19 #include <arpa/inet.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
44 #define POTR_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
45 #define POTR_MUTEX_DESTROY(m) pthread_mutex_destroy(m)
47 #define POTR_MUTEX_INIT(m) InitializeCriticalSection(m)
48 #define POTR_MUTEX_DESTROY(m) DeleteCriticalSection(m)
57 srand((
unsigned)((
unsigned long)time(NULL) ^ (
unsigned long)getpid()));
60 clock_gettime(CLOCK_REALTIME, &ts);
67 srand((
unsigned)(GetTickCount() ^ GetCurrentProcessId()));
70 GetSystemTimeAsFileTime(&ft);
71 uli.LowPart = ft.dwLowDateTime;
72 uli.HighPart = ft.dwHighDateTime;
73 peer->
session_tv_sec = (int64_t)(uli.QuadPart / 10000000ULL) - 11644473600LL;
74 peer->
session_tv_nsec = (int32_t)((uli.QuadPart % 10000000ULL) * 100ULL);
145 memcpy(nonce + 4, &fin_pkt.
flags, 2);
146 memset(nonce + 6, 0, 4);
147 memset(nonce + 10, 0, 2);
162 if (peer->
dest_addr[i].sin_family == 0)
continue;
165 sendto(ctx->
sock[i], wire_buf, wire_len, 0,
166 (
const struct sockaddr *)&peer->
dest_addr[i],
169 sendto(ctx->
sock[i], (
const char *)wire_buf, (
int)wire_len, 0,
170 (
const struct sockaddr *)&peer->
dest_addr[i],
181 if (peer->
dest_addr[i].sin_family == 0)
continue;
184 sendto(ctx->
sock[i], &fin_pkt, wire_len, 0,
185 (
const struct sockaddr *)&peer->
dest_addr[i],
188 sendto(ctx->
sock[i], (
const char *)&fin_pkt, (
int)wire_len, 0,
189 (
const struct sockaddr *)&peer->
dest_addr[i],
203 if (ctx->
peers == NULL)
206 "peer_table_init: service_id=%" PRId64
" calloc failed (max_peers=%d)",
221 "peer_table_init: service_id=%" PRId64
" max_peers=%d",
232 if (ctx->
peers == NULL)
238 "peer_table_destroy: service_id=%" PRId64
" n_peers=%d",
270 int64_t session_tv_sec,
271 int32_t session_tv_nsec)
285 return &ctx->
peers[i];
300 return &ctx->
peers[i];
308 const struct sockaddr_in *sender_addr,
317 char ip_str[INET_ADDRSTRLEN];
318 inet_ntop(AF_INET, &sender_addr->sin_addr, ip_str,
sizeof(ip_str));
320 "peer_create: service_id=%" PRId64
" max_peers=%d reached, "
321 "rejecting new connection from %s:%u",
323 ip_str, (
unsigned)ntohs(sender_addr->sin_port));
332 peer = &ctx->
peers[i];
341 "peer_create: service_id=%" PRId64
" no free slot (internal error)",
347 memset(peer, 0,
sizeof(*peer));
361 "peer_create: service_id=%" PRId64
" send_window init failed",
372 "peer_create: service_id=%" PRId64
" recv_window init failed",
388 "peer_create: service_id=%" PRId64
" frag_buf alloc failed",
396 peer->
dest_addr[path_idx] = *sender_addr;
403 "peer_create: service_id=%" PRId64
" peer_id=%u created (n_peers=%d)",
412 if (peer->
dest_addr[path_idx].sin_family == 0)
418 "peer_path_clear: service_id=%" PRId64
" peer=%u path %d cleared",
430 if (peer == NULL || !peer->
active)
436 "peer_free: service_id=%" PRId64
" peer_id=%u freed",
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_PEER_ALL
全接続ピアへの一斉送信を指示する予約ピア ID。 N:1 モードでは全アクティブピアへユニキャスト送信する。 1:1 モードでは唯一のピアへの送信として動作する。
#define POTR_SUCCESS
成功の戻り値を表す定数。
#define POTR_ERROR
失敗の戻り値を表す定数。
int packet_build_fin(PotrPacket *packet, const PotrPacketSessionHdr *shdr)
正常終了通知 (FIN) パケットを構築します。
size_t packet_wire_size(const PotrPacket *packet)
パケットのヘッダー + ペイロードの合計バイト数を返します。
#define PACKET_HEADER_SIZE
パケットヘッダーの固定長 (バイト)。payload フィールドの開始オフセット。
通信ライブラリ (動的リンク用) のヘッダーファイル。
@ POTR_TRACE_ERROR
エラー。操作の失敗を記録。TRACE_LV_ERROR (1) と同値。
@ POTR_TRACE_INFO
情報。TRACE_LV_INFO (3) と同値。
@ POTR_TRACE_VERBOSE
詳細情報 (デバッグ)。TRACE_LV_VERBOSE (4) と同値。
@ POTR_TRACE_WARNING
警告。回復可能な異常を記録。TRACE_LV_WARNING (2) と同値。
uint32_t PotrPeerId
ピア識別子。
struct PotrPeerContext_ PotrPeerContext
N:1 モードにおける個別ピアのコンテキスト。
#define POTR_INVALID_SOCKET
#define POTR_LOG(level,...)
porter 内部ログ出力マクロ。
PotrPeerContext * peer_find_by_session(struct PotrContext_ *ctx, uint32_t session_id, int64_t session_tv_sec, int32_t session_tv_nsec)
session_triplet でピアを検索する。
void peer_send_fin(struct PotrContext_ *ctx, PotrPeerContext *peer)
ピアの全パスへ FIN パケットを送信する。
#define POTR_MUTEX_INIT(m)
void peer_path_clear(struct PotrContext_ *ctx, PotrPeerContext *peer, int path_idx)
ピアの特定パスをクリアしてスロットを未使用に戻す。
PotrPeerContext * peer_find_by_id(struct PotrContext_ *ctx, PotrPeerId peer_id)
peer_id でピアを検索する。
void peer_table_destroy(struct PotrContext_ *ctx)
ピアテーブルを破棄する。
PotrPeerContext * peer_create(struct PotrContext_ *ctx, const struct sockaddr_in *sender_addr, int path_idx)
新規ピアを作成する。
void peer_free(struct PotrContext_ *ctx, PotrPeerContext *peer)
ピアリソースを解放してスロットをクリアする。
static PotrPeerId allocate_peer_id(struct PotrContext_ *ctx)
#define POTR_MUTEX_DESTROY(m)
int peer_table_init(struct PotrContext_ *ctx)
ピアテーブルを初期化する。
static void peer_generate_session(PotrPeerContext *peer)
N:1 モード用ピアテーブル管理モジュールの内部ヘッダー。
セッションコンテキスト構造体。PotrHandle の実体。
PotrGlobalConfig global
グローバル設定。
PotrServiceDef service
サービス定義。
PotrMutex peers_mutex
ピアテーブル保護用ミューテックス。
PotrSocket sock[POTR_MAX_PATH]
各パスの UDP ソケット。
int max_peers
ピアテーブルサイズ (service.max_peers から取得)。
uint32_t next_peer_id
次に発行するピア ID (単調増加、初期値 1)。
PotrPeerContext * peers
ピアテーブル (動的確保。max_peers エントリ)。
uint16_t window_size
スライディングウィンドウサイズ (パケット数)。
uint16_t max_payload
最大ペイロード長 (バイト)。
uint32_t max_message_size
1 回の potrSend で送信できる最大メッセージ長 (バイト)。デフォルト: POTR_MAX_MESSAGE_SIZE。
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)。
uint16_t payload_len
ペイロード長 (バイト) (NBO)。
PotrWindow send_window
送信ウィンドウ (NACK 再送用)。
size_t frag_buf_len
現在のデータ長。
int frag_compressed
圧縮フラグ (非 0: 圧縮あり)。
int32_t session_tv_nsec
自セッション開始時刻 ナノ秒部。
int64_t session_tv_sec
自セッション開始時刻 秒部。
int active
1: 有効スロット, 0: 空き。
uint8_t * frag_buf
フラグメント結合バッファ (動的確保)。
PotrWindow recv_window
受信ウィンドウ (順序整列)。
int n_paths
アクティブパス数。ループ境界には使わず管理カウンタとして使用する。
int64_t peer_session_tv_sec
追跡中のピアセッション開始時刻 秒部。
struct sockaddr_in dest_addr[POTR_MAX_PATH]
送信先ソケットアドレス (インデックス = ctx->sock[] の添字)。未使用スロットは sin_family == 0。
uint32_t peer_session_id
追跡中のピアセッション識別子。
uint32_t session_id
自セッション識別子 (乱数)。
PotrPeerId peer_id
外部公開用ピア識別子 (単調増加カウンタから付与)。
int64_t path_last_recv_sec[POTR_MAX_PATH]
パスごとの最終受信時刻 秒部。未使用スロットは 0。
PotrMutex send_window_mutex
send_window 保護 (送信・受信・ヘルスチェックスレッド競合)。
int32_t peer_session_tv_nsec
追跡中のピアセッション開始時刻 ナノ秒部。
int32_t path_last_recv_nsec[POTR_MAX_PATH]
パスごとの最終受信時刻 ナノ秒部。
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 の場合は未使用。
int window_init(PotrWindow *win, uint32_t initial_seq, uint16_t window_size, uint16_t max_payload)
ウィンドウを初期化します。
void window_destroy(PotrWindow *win)
ウィンドウが保持する動的確保バッファを解放します。
スライディングウィンドウ管理モジュールの内部ヘッダー。