28#define CONFIG_LINE_MAX 256
31#define CONFIG_SECTION_MAX 64
34#define CONFIG_KEY_MAX 64
37#define CONFIG_VAL_MAX 128
50 fp = fopen(path,
"r");
52 if (fopen_s(&fp, path,
"r") != 0)
66 if (dst == NULL || dst_size == 0)
83 memcpy(dst, src, len);
88static void trim(
const char *src,
char *buf,
size_t buf_size)
94 if (src == NULL || buf == NULL || buf_size == 0)
100 while (*start !=
'\0' && isspace((
unsigned char)*start))
105 end = src + strlen(src) - 1;
106 while (end >= start && isspace((
unsigned char)*end))
111 len = (size_t)(end - start + 1);
117 memcpy(buf, start, len);
122static int parse_kv(
const char *line,
char *key_out,
size_t key_size,
123 char *val_out,
size_t val_size)
129 eq = strchr(line,
'=');
135 key_len = (size_t)(eq - line);
140 memcpy(key_raw, line, key_len);
141 key_raw[key_len] =
'\0';
143 trim(key_raw, key_out, key_size);
144 trim(eq + 1, val_out, val_size);
169 if (config_path == NULL || global == NULL)
194 while (fgets(line,
sizeof(line), fp) != NULL)
197 trim(line, trimmed,
sizeof(trimmed));
200 if (trimmed[0] ==
'\0' || trimmed[0] ==
'#' || trimmed[0] ==
';')
206 if (trimmed[0] ==
'[')
208 char *close = strchr(trimmed,
']');
211 size_t sec_len = (size_t)(close - trimmed - 1);
216 memcpy(section, trimmed + 1, sec_len);
217 section[sec_len] =
'\0';
218 if (strcmp(section,
"global") == 0)
235 if (!
parse_kv(trimmed, key,
sizeof(key), val,
sizeof(val)))
240 if (strcmp(key,
"window_size") == 0)
244 else if (strcmp(key,
"max_payload") == 0)
248 else if (strcmp(key,
"health_interval_ms") == 0 ||
249 strcmp(key,
"udp_health_interval_ms") == 0)
254 else if (strcmp(key,
"health_timeout_ms") == 0 ||
255 strcmp(key,
"udp_health_timeout_ms") == 0)
259 else if (strcmp(key,
"tcp_health_interval_ms") == 0)
263 else if (strcmp(key,
"tcp_health_timeout_ms") == 0)
267 else if (strcmp(key,
"reorder_timeout_ms") == 0)
271 else if (strcmp(key,
"max_message_size") == 0)
275 else if (strcmp(key,
"send_queue_depth") == 0)
282 "config loaded: window_size=%u max_payload=%u "
283 "max_message_size=%u send_queue_depth=%u "
284 "udp_health=%u/%u tcp_health=%u/%u reorder_timeout_ms=%u",
299 if (strcmp(key,
"type") == 0)
301 if (strcmp(val,
"unicast_raw") == 0)
305 else if (strcmp(val,
"multicast_raw") == 0)
309 else if (strcmp(val,
"broadcast_raw") == 0)
313 else if (strcmp(val,
"unicast") == 0)
317 else if (strcmp(val,
"multicast") == 0)
321 else if (strcmp(val,
"broadcast") == 0)
325 else if (strcmp(val,
"unicast_bidir") == 0)
329 else if (strcmp(val,
"unicast_bidir_n1") == 0)
333 else if (strcmp(val,
"tcp") == 0)
337 else if (strcmp(val,
"tcp_bidir") == 0)
342 else if (strcmp(key,
"dst_port") == 0)
344 current->
dst_port = (uint16_t)atoi(val);
346 else if (strcmp(key,
"src_port") == 0)
348 current->
src_port = (uint16_t)atoi(val);
350 else if (strcmp(key,
"multicast_group") == 0)
356 else if (strcmp(key,
"ttl") == 0)
358 current->
ttl = (uint8_t)atoi(val);
360 else if (strcmp(key,
"broadcast_addr") == 0)
366 else if (strncmp(key,
"src_addr", 8) == 0)
370 if (key[8] <
'1' || key[8] >
'4' || key[9] !=
'\0')
377 else if (strncmp(key,
"dst_addr", 8) == 0)
380 if (key[8] <
'1' || key[8] >
'4' || key[9] !=
'\0')
387 else if (strcmp(key,
"pack_wait_ms") == 0)
391 else if (strcmp(key,
"max_peers") == 0)
399 else if (strcmp(key,
"health_interval_ms") == 0)
403 else if (strcmp(key,
"health_timeout_ms") == 0)
407 else if (strcmp(key,
"reconnect_interval_ms") == 0)
411 else if (strcmp(key,
"connect_timeout_ms") == 0)
419 else if (strcmp(key,
"encrypt_key") == 0)
421 size_t hex_len = strlen(val);
430 if (!isxdigit((
unsigned char)val[i]))
449 unsigned long byte_val;
451 byte_str[0] = val[i * 2];
452 byte_str[1] = val[i * 2 + 1];
455 byte_val = strtoul(byte_str, &endp, 16);
460 "config: encrypt_key loaded as hex key (service_id=%" PRId64
")",
463 else if (hex_len > 0)
467 (
const uint8_t *)val, hex_len) == 0)
471 "config: encrypt_key treated as passphrase (SHA-256, service_id=%" PRId64
")",
479 "config: encrypt_key passphrase hashing failed (service_id=%" PRId64
")",
489 "config: encrypt_key is empty, ignored (service_id=%" PRId64
")",
518 if (config_path == NULL || def == NULL)
532 while (fgets(line,
sizeof(line), fp) != NULL)
535 trim(line, trimmed,
sizeof(trimmed));
537 if (trimmed[0] ==
'\0' || trimmed[0] ==
'#' || trimmed[0] ==
';')
542 if (trimmed[0] ==
'[')
554 close = strchr(trimmed,
']');
557 sec_len = (size_t)(close - trimmed - 1);
562 memcpy(section, trimmed + 1, sec_len);
563 section[sec_len] =
'\0';
566 if (strncmp(section,
"service.", 8) == 0 &&
567 strtoll(section + 8, NULL, 10) == service_id)
569 memset(def, 0,
sizeof(*def));
590 if (!
parse_kv(trimmed, key,
sizeof(key), val,
sizeof(val)))
602 "service loaded: service_id=%" PRId64
" type=%d "
603 "src_addr1=%s dst_addr1=%s dst_port=%u src_port=%u",
636 if (config_path == NULL || ids_out == NULL || count_out == NULL)
649 ids = (int64_t *)malloc((
size_t)capacity *
sizeof(int64_t));
656 while (fgets(line,
sizeof(line), fp) != NULL)
659 trim(line, trimmed,
sizeof(trimmed));
661 if (trimmed[0] !=
'[')
667 char *close = strchr(trimmed,
']');
675 sec_len = (size_t)(close - trimmed - 1);
680 memcpy(section, trimmed + 1, sec_len);
681 section[sec_len] =
'\0';
683 if (strncmp(section,
"service.", 8) != 0)
688 if (count >= capacity)
690 int new_cap = capacity * 2;
691 int64_t *new_ids = (int64_t *)realloc(ids, (
size_t)new_cap *
sizeof(int64_t));
702 ids[count++] = strtoll(section + 8, NULL, 10);
int config_list_service_ids(const char *config_path, int64_t **ids_out, int *count_out)
設定ファイルに登録されているすべてのサービス ID を列挙します。
int config_load_service(const char *config_path, int64_t service_id, PotrServiceDef *def)
設定ファイルから指定サービスの定義を読み込みます。
static void copy_cstr_trunc(char *dst, size_t dst_size, const char *src)
static void trim(const char *src, char *buf, size_t buf_size)
#define CONFIG_LINE_MAX
設定ファイル 1 行の最大長。
static int parse_kv(const char *line, char *key_out, size_t key_size, char *val_out, size_t val_size)
static FILE * open_config_file_read(const char *path)
#define CONFIG_KEY_MAX
キー名の最大長。
#define CONFIG_VAL_MAX
値文字列の最大長。
#define CONFIG_SECTION_MAX
セクション名の最大長。
static void apply_service_kv(const char *key, const char *val, PotrServiceDef *current)
int config_load_global(const char *config_path, PotrGlobalConfig *global)
設定ファイルから [global] セクションを読み込みます。
int potr_passphrase_to_key(uint8_t *key, const uint8_t *passphrase, size_t passphrase_len)
任意のパスフレーズを SHA-256 ハッシュにより AES-256 鍵に変換します。
#define POTR_CRYPTO_KEY_SIZE
AES-256-GCM 鍵サイズ (バイト)。設定ファイルの encrypt_key に 64 文字 hex で指定する。
#define POTR_DEFAULT_PACK_WAIT_MS
デフォルトパッキング待ち時間 (ミリ秒)。0 = 即時送信。
#define POTR_DEFAULT_MAX_PAYLOAD
デフォルト最大ペイロード長 (バイト)。
#define POTR_DEFAULT_HEALTH_TIMEOUT_MS
デフォルトヘルスチェックタイムアウト (ミリ秒)。0 = 無効。
#define POTR_DEFAULT_HEALTH_INTERVAL_MS
デフォルトヘルスチェック送信間隔 (ミリ秒)。0 = 無効。
#define POTR_DEFAULT_TTL
デフォルトマルチキャスト TTL。
#define POTR_DEFAULT_WINDOW_SIZE
デフォルトウィンドウサイズ (パケット数)。
#define POTR_DEFAULT_RECONNECT_INTERVAL_MS
SENDER 自動再接続間隔のデフォルト (ミリ秒)。TCP 通信種別 (POTR_TYPE_TCP / POTR_TYPE_TCP_BIDIR) のみ有効。
#define POTR_DEFAULT_CONNECT_TIMEOUT_MS
SENDER TCP 接続タイムアウトのデフォルト (ミリ秒)。0 = OS デフォルト。TCP 通信種別のみ有効。
#define POTR_SEND_QUEUE_DEPTH
非同期送信キューの最大エントリ数のデフォルト値。設定ファイルの send_queue_depth で変更可能。メッセージがフラグメント化される場合、1 メッセージが複数エントリを占有する。
#define POTR_MAX_MESSAGE_SIZE
1 回の potrSend で送信できる最大メッセージ長 (バイト) のデフォルト値。設定ファイルの max_message_size で変更可能。フラグメント化により max_payload を超える...
#define POTR_MAX_ADDR_LEN
アドレス文字列の最大長 (バイト、終端 NUL を含む)。
#define POTR_MAX_SERVICES
config_list_service_ids() の初期バッファ容量。サービス数がこれを超えた場合は realloc で自動拡張する。
#define POTR_SUCCESS
成功の戻り値を表す定数。
#define POTR_ERROR
失敗の戻り値を表す定数。
@ POTR_TRACE_INFO
情報。TRACE_LV_INFO (3) と同値。
@ POTR_TRACE_VERBOSE
詳細情報 (デバッグ)。TRACE_LV_VERBOSE (4) と同値。
@ POTR_TRACE_WARNING
警告。回復可能な異常を記録。TRACE_LV_WARNING (2) と同値。
@ POTR_TYPE_BROADCAST_RAW
1:N 通信 RAW モード (UDP ブロードキャスト)。
@ POTR_TYPE_BROADCAST
1:N 通信 (UDP ブロードキャスト)。
@ POTR_TYPE_UNICAST_BIDIR_N1
N:1 双方向通信 (UDP ユニキャスト)。
@ POTR_TYPE_UNICAST
1:1 通信 (UDP ユニキャスト)。
@ POTR_TYPE_MULTICAST_RAW
1:N 通信 RAW モード (UDP マルチキャスト)。
@ POTR_TYPE_TCP_BIDIR
TCP 双方向通信 (両端が potrSend 可)。
@ POTR_TYPE_TCP
TCP ユニキャスト通信 (単方向: SENDER のみ potrSend 可)。
@ POTR_TYPE_UNICAST_RAW
1:1 通信 RAW モード (UDP ユニキャスト)。
@ POTR_TYPE_UNICAST_BIDIR
双方向 1:1 通信 (UDP ユニキャスト)。
@ POTR_TYPE_MULTICAST
1:N 通信 (UDP マルチキャスト)。
#define POTR_LOG(level,...)
porter 内部ログ出力マクロ。
uint32_t tcp_health_interval_ms
TCP 通信種別の PING 送信間隔 (ミリ秒)。DATA 送信頻度に関わらず定期的に PING を送信。0 = 無効。設定ファイルキー: tcp_health_interval_ms。
uint16_t window_size
スライディングウィンドウサイズ (パケット数)。
uint32_t reorder_timeout_ms
受信ウィンドウ欠番検出後、NACK または切断を遅延する時間 (ミリ秒)。マルチパスや近距離 WAN での追い越し吸収用。0 = 即時 (デフォルト)。推奨値: LAN/マルチパス=10〜30 ms、遠...
uint32_t send_queue_depth
非同期送信キューの最大エントリ数。デフォルト: POTR_SEND_QUEUE_DEPTH。
uint32_t tcp_health_timeout_ms
TCP 通信種別の PING 応答待機タイムアウト (ミリ秒)。SENDER 側で使用。0 = 無効。設定ファイルキー: tcp_health_timeout_ms。
uint16_t max_payload
最大ペイロード長 (バイト)。
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。
uint32_t max_message_size
1 回の potrSend で送信できる最大メッセージ長 (バイト)。デフォルト: POTR_MAX_MESSAGE_SIZE。
uint16_t src_port
送信者の送信元 bind ポート番号。0 = OS 自動選定。(全通信種別で省略可)
uint32_t health_interval_ms
グローバルの udp/tcp_health_interval_ms をサービス単位で上書きする。0 = グローバル値を使用。
uint8_t ttl
マルチキャスト TTL。(multicast のみ)
int encrypt_enabled
非 0 のとき暗号化有効。設定ファイルに有効な encrypt_key が存在するときに 1 に設定される。
uint16_t dst_port
宛先ポート番号。サービスの識別子。受信者の bind ポート / 送信者の送信先ポート。(全通信種別で必須)
char src_addr[POTR_MAX_PATH][POTR_MAX_ADDR_LEN]
送信元アドレス [0]=src_addr1 〜 [3]=src_addr4。送信者は bind / 送信インターフェース、受信者は送信元フィルタ。(全通信種別で必須)
char multicast_group[POTR_MAX_ADDR_LEN]
マルチキャストグループアドレス。(multicast のみ)
int64_t service_id
サービス ID。
uint32_t pack_wait_ms
パッキング待ち時間 (ミリ秒)。最初の送信要求からこの時間だけ待ち合わせ、複数メッセージを 1 パケットにまとめる。0 = 即時送信 (パッキング待ちなし)。パケット容量が満杯になった場合はタイマーを無...
uint32_t connect_timeout_ms
SENDER TCP 接続タイムアウト (ms)。0 = OS デフォルト。デフォルト: POTR_DEFAULT_CONNECT_TIMEOUT_MS。
char dst_addr[POTR_MAX_PATH][POTR_MAX_ADDR_LEN]
宛先アドレス [0]=dst_addr1 〜 [3]=dst_addr4。送信者は送信先、受信者は bind アドレス。(unicast のみ)
uint32_t max_peers
N:1 モード時の最大同時接続ピア数。省略時: 1024。1:1 モードでは無視される。
char broadcast_addr[POTR_MAX_ADDR_LEN]
ブロードキャスト宛先アドレス。省略時は 255.255.255.255。(broadcast のみ)
uint8_t encrypt_key[POTR_CRYPTO_KEY_SIZE]
AES-256-GCM 事前共有鍵 (32 バイト)。encrypt_enabled が 0 の場合は未使用。
uint32_t reconnect_interval_ms
SENDER 自動再接続間隔 (ms)。0 = 再接続なし。デフォルト: POTR_DEFAULT_RECONNECT_INTERVAL_MS。
uint32_t health_timeout_ms
グローバルの udp/tcp_health_timeout_ms をサービス単位で上書きする。0 = グローバル値を使用。