# porter/libsrc/porter/protocol/packet.c

# 1 ファイル

## 1.1 porter/libsrc/porter/protocol/packet.c

パケット構築・解析モジュール。

### 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 hton64

    static uint64_t hton64 ( uint64_t v )

## 2.2 ntoh64

    static uint64_t ntoh64 ( uint64_t v )

## 2.3 fill_session_hdr

    static void fill_session_hdr ( PotrPacket *packet, const PotrPacketSessionHdr *shdr )

## 2.4 packet_build_nack

    int packet_build_nack ( PotrPacket *packet, const PotrPacketSessionHdr *shdr, uint32_t nack_num )

NACK パケットを構築します。

### 2.4.1 引数

- packet [out] 構築結果を格納するパケット構造体へのポインタ。
- shdr [in] セッション識別ヘッダーへのポインタ。
- nack_num [in] 再送要求する通番。

### 2.4.2 戻り値

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

## 2.5 packet_build_ping

    int packet_build_ping ( PotrPacket *packet, const PotrPacketSessionHdr *shdr, uint32_t seq_num, uint32_t ack_num )

PING パケットを構築します。

ヘルスチェックパケットです。ペイロードなし (payload_len=0)。
通番には送信側の next_seq（次に送出する DATA に割り当てる通番）を格納します。
PING はウィンドウに登録されません（NACK・再送の対象外）。
ack_num == 0 は PING 要求。受信者は seq_num を上限として欠番を一括 NACK します。
ack_num != 0 は PING 応答 (unicast_bidir 専用)。受信者は gap スキャンを行いません。
応答時は ack_num = req_seq_num + 1 を指定することで、req_seq_num=0 でも ack_num=0 になりません。

### 2.5.1 引数

- packet [out] 構築結果を格納するパケット構造体へのポインタ。
- shdr [in] セッション識別ヘッダーへのポインタ。
- seq_num [in] 通番 (ウィンドウ管理に使用)。
- ack_num [in] PING 要求では 0、PING 応答では要求の seq_num を指定する。

### 2.5.2 戻り値

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

## 2.6 packet_build_reject

    int packet_build_reject ( PotrPacket *packet, const PotrPacketSessionHdr *shdr, uint32_t seq_num )

再送不能通知 (REJECT) パケットを構築します。

受信者から NACK を受け取ったが、送信ウィンドウに該当パケットが存在しない場合に 送信者が返すパケットです。受信者はこのパケットを受け取ると即時 DISCONNECTED を 発火し、欠落通番をスキップして後続パケットの配信を継続します。

### 2.6.1 引数

- packet [out] 構築結果を格納するパケット構造体へのポインタ。
- shdr [in] セッション識別ヘッダーへのポインタ。
- seq_num [in] 再送不能な通番。ack_num フィールドに格納します。

### 2.6.2 戻り値

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

## 2.7 packet_build_fin

    int packet_build_fin ( PotrPacket *packet, const PotrPacketSessionHdr *shdr )

正常終了通知 (FIN) パケットを構築します。

送信者が potrCloseService 時に送出する終了通知パケットです。ペイロードなし。
受信者はこのパケットを受け取ると即座に POTR_EVENT_DISCONNECTED を発火します。

### 2.7.1 引数

- packet [out] 構築結果を格納するパケット構造体へのポインタ。
- shdr [in] セッション識別ヘッダーへのポインタ。

### 2.7.2 戻り値

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

## 2.8 packet_build_packed

    int packet_build_packed ( PotrPacket *out, const PotrPacketSessionHdr *shdr, uint32_t seq_num, const void *packed_payload, size_t payload_len )

データパケット (パックコンテナ) を構築します。

すべてのデータパケットはパックコンテナ形式で送受信します。
ペイロードエレメントが 1 件のみの場合も同じ形式を使用します。
再送・順序整列の単位は外側パケット (本関数が構築する UDP ペイロード) であり、 通番は外側パケットの seq_num フィールドで管理します。
ペイロードエレメントの形式は flags(2) + payload_len(4) + payload(N) です。
受信者は POTR_FLAG_DATA を検出後 packet_unpack_next() でペイロードエレメントを展開します。

### 2.8.1 引数

- out [out] 構築結果を格納するパケット構造体へのポインタ。
- shdr [in] セッション識別ヘッダーへのポインタ。
- seq_num [in] 外側パケットの通番。再送・順序整列に使用する。
- packed_payload [in] 送信スレッドが構築したペイロードエレメント列。
- payload_len [in] packed_payload のバイト数。

### 2.8.2 戻り値

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

## 2.9 packet_unpack_next

    int packet_unpack_next ( const PotrPacket *container, size_t *offset, PotrPacket *elem_out )

データパケットから次のペイロードエレメントを取り出します。

ペイロードエレメントの形式は flags(2) + payload_len(4) + payload(N) です。
通番は外側パケットで管理するためペイロードエレメントには含まれません。
container->payload_len はホストバイトオーダー (packet_parse() 変換済み) で参照します。
elem_out の session 情報は container から引き継ぎます。

### 2.9.1 引数

- container [in] packet_parse() 済みのデータパケット (POTR_FLAG_DATA)。
- offset [in,out] コンテナ payload 内の読み取り位置。呼び出し毎に更新。
- elem_out [out] 取り出したペイロードエレメントを格納する構造体へのポインタ。

### 2.9.2 戻り値

ペイロードエレメントを取り出せた場合は POTR_SUCCESS、 末尾に達した場合またはエラーの場合は POTR_ERROR を返します。

## 2.10 packet_parse

    int packet_parse ( PotrPacket *packet, const void *buf, size_t buf_len )

受信バイト列をパケット構造体に解析します。

各フィールドをホストバイトオーダーに変換して構造体に格納します。

### 2.10.1 引数

- packet [out] 解析結果を格納するパケット構造体へのポインタ。
- buf [in] 受信バイト列へのポインタ。
- buf_len [in] 受信バイト列の長さ。

### 2.10.2 戻り値

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

## 2.11 packet_wire_size

    size_t packet_wire_size ( const PotrPacket *packet )

パケットのヘッダー + ペイロードの合計バイト数を返します。

UDP 送信時に sendto() へ渡すバイト数を求めるために使用します。
内部で ntohs(packet->payload_len) を呼ぶため、引数は必ず NBO 状態で渡してください。

### 2.11.1 引数

- packet [in] 対象のパケット構造体へのポインタ。 packet_build_*() で構築した NBO パケットを渡すこと。 packet_parse() 済み (ホストバイトオーダー) のパケットを 渡すと payload_len の ntohs 変換が二重になり誤値を返す。

### 2.11.2 戻り値

パケットの送信サイズ (バイト)。packet が NULL の場合は 0。