23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
46 #define POTR_MUTEX_LOCK_LOCAL(m) pthread_mutex_lock(m)
47 #define POTR_MUTEX_UNLOCK_LOCAL(m) pthread_mutex_unlock(m)
50 #define POTR_MUTEX_LOCK_LOCAL(m) EnterCriticalSection(m)
51 #define POTR_MUTEX_UNLOCK_LOCAL(m) LeaveCriticalSection(m)
68 struct timespec abs_ts;
69 clock_gettime(CLOCK_REALTIME, &abs_ts);
70 abs_ts.tv_sec += (time_t)(interval_ms / 1000U);
71 abs_ts.tv_nsec += (long)((interval_ms % 1000U) * 1000000UL);
72 if (abs_ts.tv_nsec >= 1000000000L)
75 abs_ts.tv_nsec -= 1000000000L;
100 clock_gettime(CLOCK_MONOTONIC, &ts);
101 return (uint64_t)ts.tv_sec * 1000ULL + (uint64_t)ts.tv_nsec / 1000000ULL;
103 return (uint64_t)GetTickCount64();
157 "health[service_id=%" PRId64
"]: PING timer reset",
209 memcpy(nonce + 4, &ping_pkt.
flags, 2);
210 memcpy(nonce + 6, &ping_pkt.
seq_num, 4);
211 memset(nonce + 10, 0, 2);
228 sendto(ctx->
sock[k], wire_buf, wire_len, 0,
232 sendto(ctx->
sock[k], (
const char *)wire_buf, (
int)wire_len, 0,
246 sendto(ctx->
sock[k], &ping_pkt, wire_len, 0,
250 sendto(ctx->
sock[k], (
const char *)&ping_pkt, (
int)wire_len, 0,
258 "health[service_id=%" PRId64
"]: PING peer=%u seq=%u",
281 "health[service_id=%" PRId64
"]: PING seq=%u",
295 memcpy(nonce + 4, &ping_pkt.
flags, 2);
296 memcpy(nonce + 6, &ping_pkt.
seq_num, 4);
297 memset(nonce + 10, 0, 2);
307 for (k = 0; k < ctx->
n_path; k++)
310 sendto(ctx->
sock[k], wire_buf, wire_len, 0,
311 (
const struct sockaddr *)&ctx->
dest_addr[k],
314 sendto(ctx->
sock[k], (
const char *)wire_buf, (
int)wire_len, 0,
315 (
const struct sockaddr *)&ctx->
dest_addr[k],
325 for (k = 0; k < ctx->
n_path; k++)
328 sendto(ctx->
sock[k], &ping_pkt, wire_len, 0,
329 (
const struct sockaddr *)&ctx->
dest_addr[k],
332 sendto(ctx->
sock[k], (
const char *)&ping_pkt, (
int)wire_len, 0,
333 (
const struct sockaddr *)&ctx->
dest_addr[k],
370 "tcp_health[service_id=%" PRId64
" path=%d]: starting",
393 "tcp_health[service_id=%" PRId64
" path=%d]: PING timeout"
394 " (%llu ms), closing connection",
430 "tcp_health[service_id=%" PRId64
" path=%d]: PING seq=%u",
443 memcpy(nonce + 4, &ping_pkt.
flags, 2);
444 memcpy(nonce + 6, &ping_pkt.
seq_num, 4);
445 memset(nonce + 10, 0, 2);
461 const uint8_t *p = wire_buf;
462 while (sent < wire_len)
465 p + sent, wire_len - sent, 0);
472 (
const char *)wire_buf, (
int)wire_len, 0);
487 const uint8_t *p = (
const uint8_t *)&ping_pkt;
488 while (sent < wire_len)
491 p + sent, wire_len - sent, 0);
498 (
const char *)&ping_pkt, (
int)wire_len, 0);
506 "tcp_health[service_id=%" PRId64
" path=%d]: exited",
533 "health_thread[service_id=%" PRId64
"]: disabled (health_interval_ms=0)",
539 "health_thread[service_id=%" PRId64
"]: starting (interval=%ums)",
558 "health_thread[service_id=%" PRId64
"]: pthread_create failed",
568 "health_thread[service_id=%" PRId64
"]: CreateThread failed",
636 "tcp_health_thread[service_id=%" PRId64
" path=%d]: disabled",
652 "tcp_health_thread[service_id=%" PRId64
" path=%d]: pthread_create failed",
664 "tcp_health_thread[service_id=%" PRId64
" path=%d]: CreateThread failed",
int potr_encrypt(uint8_t *dst, size_t *dst_len, const uint8_t *src, size_t src_len, const uint8_t *key, const uint8_t *nonce, const uint8_t *aad, size_t aad_len)
AES-256-GCM でデータを暗号化します。
#define POTR_CRYPTO_NONCE_SIZE
AES-256-GCM ノンスサイズ (バイト)。session_id (4B NBO) + flags (2B NBO) + seq_or_ack_num (4B NBO) + padding (2B...
#define POTR_CRYPTO_TAG_SIZE
AES-256-GCM 認証タグサイズ (バイト)。暗号文の直後に付加する。
#define POTR_MAX_PATH
マルチパスの最大パス数。
#define POTR_FLAG_ENCRYPTED
AES-256-GCM 認証タグが付与されていることを示す外側パケットフラグ。 POTR_FLAG_DATA と組み合わせる場合: [ヘッダー 32B][暗号文: packed_len B][GCM ...
#define POTR_SUCCESS
成功の戻り値を表す定数。
#define POTR_ERROR
失敗の戻り値を表す定数。
int packet_build_ping(PotrPacket *packet, const PotrPacketSessionHdr *shdr, uint32_t seq_num, uint32_t ack_num)
PING パケットを構築します。
size_t packet_wire_size(const PotrPacket *packet)
パケットのヘッダー + ペイロードの合計バイト数を返します。
#define PACKET_HEADER_SIZE
パケットヘッダーの固定長 (バイト)。payload フィールドの開始オフセット。
通信ライブラリ (動的リンク用) のヘッダーファイル。
@ POTR_TRACE_ERROR
エラー。操作の失敗を記録。TRACE_LV_ERROR (1) と同値。
@ POTR_TRACE_VERBOSE
詳細情報 (デバッグ)。TRACE_LV_VERBOSE (4) と同値。
@ POTR_TRACE_WARNING
警告。回復可能な異常を記録。TRACE_LV_WARNING (2) と同値。
#define POTR_INVALID_SOCKET
pthread_mutex_t PotrMutexLocal
static void health_sleep(struct PotrContext_ *ctx, int path_idx, uint32_t interval_ms)
#define POTR_MUTEX_LOCK_LOCAL(m)
int potr_tcp_health_thread_stop(struct PotrContext_ *ctx, int path_idx)
TCP ヘルスチェックスレッドを停止します。
#define POTR_MUTEX_UNLOCK_LOCAL(m)
static void * health_thread_func(void *arg)
int potr_health_thread_start(struct PotrContext_ *ctx)
非 TCP ヘルスチェックスレッドを起動します。
int potr_health_thread_stop(struct PotrContext_ *ctx)
非 TCP ヘルスチェックスレッドを停止します。
static HealthArg s_health_args[POTR_MAX_PATH]
static void * tcp_health_thread_func(void *arg)
static uint64_t health_get_ms(void)
int potr_tcp_health_thread_start(struct PotrContext_ *ctx, int path_idx)
TCP ヘルスチェックスレッドを path ごとに起動します。
#define POTR_LOG(level,...)
porter 内部ログ出力マクロ。
N:1 モード用ピアテーブル管理モジュールの内部ヘッダー。
struct PotrContext_ * ctx
セッションコンテキスト構造体。PotrHandle の実体。
uint32_t session_id
自セッション識別子 (乱数)。
volatile int tcp_active_paths
アクティブ TCP path 数 (0 = 全切断)。
PotrGlobalConfig global
グローバル設定。
volatile uint64_t tcp_last_ping_recv_ms[POTR_MAX_PATH]
TCP PING 応答最終受信時刻 (ms, CLOCK_MONOTONIC 基準)。path ごと。接続確立時に現在時刻で初期化。
PotrCondVar health_wakeup[POTR_MAX_PATH]
ヘルスチェックスレッドを即時起床させる条件変数 (path ごと)。
PotrMutex send_window_mutex
send_window 保護用ミューテックス (送信スレッド・ヘルスチェックスレッド・受信スレッドが競合するため)。
int32_t session_tv_nsec
自セッション開始時刻 ナノ秒部。
volatile uint64_t last_send_ms
最終パケット送信時刻 (データ or PING、ms、単調増加)。0 = 未送信。
PotrMutex tcp_send_mutex[POTR_MAX_PATH]
TCP send() 排他制御 (path ごと)。送信スレッド・ヘルスチェックスレッド・recv スレッド競合防止。
int is_multi_peer
1: N:1 モード (src_addr/src_port 省略), 0: 1:1 モード。
PotrServiceDef service
サービス定義。
PotrThread health_thread[POTR_MAX_PATH]
ヘルスチェックスレッドハンドル (path ごと、送信者のみ)。
PotrMutex health_mutex[POTR_MAX_PATH]
ヘルスチェックスレッド停止用ミューテックス (path ごと)。
PotrMutex peers_mutex
ピアテーブル保護用ミューテックス。
PotrSocket sock[POTR_MAX_PATH]
各パスの UDP ソケット。
volatile int health_running[POTR_MAX_PATH]
ヘルスチェックスレッド実行フラグ (1: 実行中, 0: 停止)。path ごと。
PotrWindow send_window
送信バッファ (過去 N パケット保持。NACK 再送・REJECT 判定に使用)。
int max_peers
ピアテーブルサイズ (service.max_peers から取得)。
struct sockaddr_in dest_addr[POTR_MAX_PATH]
送信先ソケットアドレス (送信者が sendto に使用)。
int64_t session_tv_sec
自セッション開始時刻 秒部。
PotrPeerContext * peers
ピアテーブル (動的確保。max_peers エントリ)。
PotrSocket tcp_conn_fd[POTR_MAX_PATH]
アクティブ TCP 接続 fd (path ごと)。
uint32_t health_interval_ms
UDP 通信種別の PING 送信間隔 (ミリ秒)。最終 DATA/PING 送信から本値が経過したら PING 送信。0 = 無効。設定ファイルキー: udp_health_interval_ms。
uint32_t health_timeout_ms
UDP 通信種別の受信タイムアウト (ミリ秒)。RECEIVER 側で使用。0 = 無効。設定ファイルキー: udp_health_timeout_ms。
int32_t session_tv_nsec
セッション開始時刻 ナノ秒部。
int64_t service_id
サービス識別子。
uint32_t session_id
セッション識別子 (乱数)。
int64_t session_tv_sec
セッション開始時刻 秒部。
uint32_t session_id
セッション識別子 (NBO)。potrOpenService 時に決定する乱数。
uint16_t flags
パケット種別フラグ (POTR_FLAG_*) (NBO)。
uint32_t seq_num
通番。送信側が付与する連番 (NBO)。
uint16_t payload_len
ペイロード長 (バイト) (NBO)。
PotrWindow send_window
送信ウィンドウ (NACK 再送用)。
int32_t session_tv_nsec
自セッション開始時刻 ナノ秒部。
int64_t session_tv_sec
自セッション開始時刻 秒部。
int active
1: 有効スロット, 0: 空き。
struct sockaddr_in dest_addr[POTR_MAX_PATH]
送信先ソケットアドレス (インデックス = ctx->sock[] の添字)。未使用スロットは sin_family == 0。
uint32_t session_id
自セッション識別子 (乱数)。
PotrPeerId peer_id
外部公開用ピア識別子 (単調増加カウンタから付与)。
PotrMutex send_window_mutex
send_window 保護 (送信・受信・ヘルスチェックスレッド競合)。
int encrypt_enabled
非 0 のとき暗号化有効。設定ファイルに有効な encrypt_key が存在するときに 1 に設定される。
int64_t service_id
サービス ID。
uint8_t encrypt_key[POTR_CRYPTO_KEY_SIZE]
AES-256-GCM 事前共有鍵 (32 バイト)。encrypt_enabled が 0 の場合は未使用。
uint32_t next_seq
送信側: 次に割り当てる通番。受信側: 次に期待する通番。
スライディングウィンドウ管理モジュールの内部ヘッダー。