# porter/libsrc/porter/api/potrOpenService.c

# 1 ファイル

## 1.1 porter/libsrc/porter/api/potrOpenService.c

potrOpenService 関数の実装。

### 1.1.1 作者

c-modernization-kit sample team

### 1.1.2 バージョン

1.0.0

### 1.1.3 日付

2026/03/04

### 1.1.4 著作権

Copyright (C) CompanyName, Ltd. 2026. All rights reserved.

# 2 関数

## 2.1 open_socket_unicast

    static PotrSocket open_socket_unicast ( struct in_addr bind_addr, uint16_t port )

## 2.2 generate_session

    static void generate_session ( struct PotrContext_ *ctx )

## 2.3 open_socket_multicast

    static PotrSocket open_socket_multicast ( const PotrServiceDef *def, struct in_addr src_if, int is_receiver )

## 2.4 open_socket_broadcast

    static PotrSocket open_socket_broadcast ( uint16_t src_port, uint16_t dst_port, struct in_addr src_if, int is_receiver )

## 2.5 cleanup_sockets

    static void cleanup_sockets ( struct PotrContext_ *ctx )

## 2.6 ctx_cleanup

    static void ctx_cleanup ( struct PotrContext_ *ctx )

## 2.7 open_socket_tcp_receiver

    static int open_socket_tcp_receiver ( struct PotrContext_ *ctx, int path_idx )

## 2.8 open_socket_tcp_sender

    static int open_socket_tcp_sender ( struct PotrContext_ *ctx, int path_idx )

## 2.9 potrOpenService

    POTR_EXPORT int POTR_API potrOpenService ( const PotrGlobalConfig *global, const PotrServiceDef *service, PotrRole role, PotrRecvCallback callback, PotrHandle *handle )

設定構造体から指定サービスを開きます。

設定構造体からサービス定義を取得し、UDP ソケットを初期化します。
role と callback の組み合わせが不正な場合は POTR_ERROR を返します。
role と設定の IP アドレスが不整合 (bind 失敗など) の場合も POTR_ERROR を返します。
通信種別・役割に応じて以下のソケット設定を行います。

通信種別 | 役割 | bind アドレス | bind ポート
--- | --- | --- | ---
POTR_TYPE_UNICAST | 送信者 | src_addr | src_port
POTR_TYPE_UNICAST | 受信者 | dst_addr | dst_port
POTR_TYPE_MULTICAST | 送信者 | INADDR_ANY | src_port
POTR_TYPE_MULTICAST | 受信者 | INADDR_ANY | dst_port
POTR_TYPE_BROADCAST | 送信者 | src_addr | src_port
POTR_TYPE_BROADCAST | 受信者 | INADDR_ANY | dst_port

POTR_ROLE_RECEIVER の場合、内部で受信スレッドを起動します。

### 2.9.1 引数

- global [in] グローバル設定構造体へのポインタ。
- service [in] サービス定義構造体へのポインタ。
- role [in] 役割種別。POTR_ROLE_SENDER または POTR_ROLE_RECEIVER。
- callback [in] イベント発生時に呼び出されるコールバック関数 (PotrRecvCallback)。 POTR_ROLE_RECEIVER の場合は必須。データ受信・接続検知・切断検知を受け取る。 POTR_ROLE_SENDER の場合は通常 NULL を指定すること。
  ただし POTR_TYPE_TCP_BIDIR および POTR_TYPE_UNICAST_BIDIR では SENDER にもコールバックが必須。これらの種別では POTR_ROLE_SENDER でも callback が NULL の場合は失敗を返します。
- handle [out] 成功時にセッションハンドルを格納するポインタ。

### 2.9.2 戻り値

成功時は POTR_SUCCESS、失敗時は POTR_ERROR を返します。

### 2.9.3 警告

global が NULL の場合は失敗を返します。
service が NULL の場合は失敗を返します。
handle が NULL の場合は失敗を返します。
POTR_ROLE_RECEIVER かつ callback が NULL の場合は失敗を返します。
POTR_ROLE_SENDER かつ callback が NULL でない場合は失敗を返します。
ただし POTR_TYPE_TCP_BIDIR および POTR_TYPE_UNICAST_BIDIR では SENDER にも
コールバックが必須であり、この場合 callback が NULL の場合は失敗を返します。

### 2.9.4 使用例 (受信者)

    void on_recv(int64_t service_id, PotrPeerId peer_id,
                 PotrEvent event, const void *data, size_t len) {
        (void)peer_id;  // 1:1 モードでは常に POTR_PEER_NA
        if (event == POTR_EVENT_CONNECTED)
            printf("service %" PRId64 ": connected\n", service_id);
        else if (event == POTR_EVENT_DISCONNECTED)
            printf("service %" PRId64 ": disconnected\n", service_id);
        else
            printf("service %" PRId64 ": received %zu bytes\n", service_id, len);
    }

    PotrGlobalConfig global = {0};
    global.window_size        = 16;
    global.max_payload        = 1400;
    global.max_message_size   = 65535;
    global.send_queue_depth   = 64;

    PotrServiceDef service = {0};
    service.service_id = 1001;
    service.type       = POTR_TYPE_UNICAST;
    service.dst_port   = 49001;
    strncpy(service.src_addr[0], "127.0.0.1", POTR_MAX_ADDR_LEN - 1);
    strncpy(service.dst_addr[0], "127.0.0.1", POTR_MAX_ADDR_LEN - 1);

    PotrHandle handle;
    if (potrOpenService(&global, &service,
                        POTR_ROLE_RECEIVER, on_recv, &handle) == POTR_SUCCESS) {
        // 受信待機中 (受信スレッドが動作)
        potrCloseService(handle);
    }

### 2.9.5 使用例 (送信者)

    PotrGlobalConfig global = {0};
    global.window_size        = 16;
    global.max_payload        = 1400;
    global.max_message_size   = 65535;
    global.send_queue_depth   = 64;

    PotrServiceDef service = {0};
    service.service_id = 1001;
    service.type       = POTR_TYPE_UNICAST;
    service.dst_port   = 49001;
    strncpy(service.src_addr[0], "127.0.0.1", POTR_MAX_ADDR_LEN - 1);
    strncpy(service.dst_addr[0], "127.0.0.1", POTR_MAX_ADDR_LEN - 1);

    PotrHandle handle;
    if (potrOpenService(&global, &service,
                        POTR_ROLE_SENDER, NULL, &handle) == POTR_SUCCESS) {
        potrSend(handle, POTR_PEER_NA, "hello", 5, 0);
        potrCloseService(handle);
    }

### 2.9.6 スレッド セーフティ

本関数はスレッドセーフです。
異なるスレッドから独立したハンドルを取得するために並行して呼び出すことができます。
ただし取得したハンドルはスレッドセーフではありません。
同一ハンドルに対する操作は 1 スレッドから行ってください。