MiniSock: C APIの設計
MiniSockのC APIを適当に用意する。 ... 一度適当に作ったあとPOSIXなりlwIPなりで実装してみて、合わなかったところを摺り合わせる作戦で行こうと思う。
後回し機能
- no copyなsend/receive
- scatter / gather
- マルチキャストとブロードキャスト
初期化・終了
全ての操作はコンテキスト msck_ctx_t*
を通じて操作することになるため、コンテキストの確保、開放操作が必要になる。 コンテキストの作成数に上限があっても良い 。
create
APIはバックエンドが独自拡張するケースが想定される。このため default
を含んだAPIをとりあえず定義しておく。
コンテキストの解放操作である destroy
は必ず成功する。失敗をハンドルする妥当な方法が存在しないため。
int msck_ctx_create_default(msck_ctx_t** out_ctx, void* cb, uintptr_t data);
void msck_ctx_destroy(msck_ctx_t* ctx);
void msck_ctx_step(msck_ctx_t* ctx, int waitok);
セッションの作成・破棄
MiniSockは全ての通信を接続指向で行うものと見做す。UDPであっても、通常のシチュエーションでは対話を行うため、セッションの作成が必要になる。
destroy
は明示的に行う必要がある。
int msck_session_create(msck_ctx_t* ctx,
msck_session_type_t st,
msck_name_type_t nt, const char* name, size_t namelen,
uintptr_t arg0, uintptr_t arg1,
uintptr_t data,
msck_session_t** out_session);
void msck_session_destroy(msck_ctx_t* ctx, msck_session_t* session);
セッションタイプ
セッションタイプは、 enum
で表現される。
タイプ | 内容 |
---|---|
MSCK_SESSION_TYPE_STREAM | TCP (バイトストリーム) |
MSCK_SESSION_TYPE_STREAM_SERVER | TCP (バイトストリーム、Listen) |
MSCK_SESSION_TYPE_DATAGRAM | UDP |
名前空間タイプ
名前は const char*
で表現されるが、その指す先のデータが何であるかを名前空間タイプで表現する。
タイプ | 内容 |
---|---|
MSCK_NAME_TYPE_VIRTUAL | 管理用の仮想名 |
MSCK_NAME_TYPE_IPV4 | IPv4 numeric |
MSCK_NAME_TYPE_IPV6 | IPv6 numeric |
MSCK_NAME_TYPE_DNS | DNS name |
MSCK_NAME_TYPE_DNS_IPV4 | DNS name (v4 only) |
MSCK_NAME_TYPE_DNS_IPV6 | DNS name (v6 only) |
送信
送信はブロッキングと非ブロッキングを選択できる。これは受信がイベント処理として行われる都合でイベントハンドラからブロッキング送信がブロックされるのを防ぐ必要があるため。
どちらのケースも、関数から戻ってきた後はバッファを解放して良い。no copy版はもし必要なら別途。
バッファの解放はコールバックが呼出されたタイミングで実施できる。つまり、ストリームするためにコールバックから次々とsendするということが可能である。送信処理自体はキャンセルできない。
int msck_session_send(msck_ctx_t* ctx, msck_session_t* session, const char* data, size_t datalen);
イベントと受信
イベントは初期化時に与えたコールバック関数に通知される。受信データはコールバック関数から抜けるまでに消費する必要がある。
コールバック関数の基本
void callback(msck_ctx_t* ctx, msck_event_type_t type,
msck_session_t* session,
const char* buf, int arg0,
uintptr_t data_ctx, uintptr_t data_session);
コールバック関数は コールバックタイプ、 (ctx, session)の組とそれぞれに対応した data
、1つのデータバッファを通知する。
処理のブロック
EDIT: ブロッキングは一旦仕様から外した。
msck_send
以外のAPIは、コールバック内で呼びだしても完了することが保証される(エラーになる可能性はある)。また、コールバック内で msck_send_nowait
を呼出しても コールバックは再帰しないことが保証される 。
msck_send
はコールバック内で呼出した場合の挙動は未定義となる。つまり、 msck_send
はコールバックの完了を前提として動作しても構わない。
イベントタイプ
タイプ | 概要 |
---|---|
MSCK_EVENT_TYPE_SESSION_CREATE_RESULT | create_session の成否(arg0: エラーコード) |
MSCK_EVENT_TYPE_SESSION_DATA | データの受信(arg0: バッファバイト長) |
MSCK_EVENT_TYPE_SESSION_INCOMING | サーバー接続の開始要求 |
MSCK_EVENT_TYPE_SESSION_TERMINATE | セッションの終了(arg0: エラーコード) |
(やっぱし無理だった)
- ブロッキングな
send
は一旦仕様から外した -
session_receive
API を追加。セッションの作成後、明示的にバッファを与えないと受信がkickされないようにした -
MSCK_EVENT_TYPE_SESSION_INCOMING
イベントとsession_accept
を追加 (忘れてた)
一旦ダブル(以上)バッファはやらない方向で。