Drafts of specifications of the OpenXM standard socket functions. 1. connect(2) connect(2) の代わりに ox_connet を使うべし. int ox_connect(const char *hostname, int port, struct ox_sockopt *opt); hostname - 接続先のホスト名 port - 接続先のポート番号 opt - setsockopt(2) へ渡したいオプション群 setsockopt(2) の第一引数は生成されたソケット番号を渡すが, これは ox_connect 内で生成される. struct ox_sockopt { ... int level; /* setsockopt(2) の第二引数 */ int option_name; /* setsockopt(2) の第三引数 */ void *option_value; /* setsockopt(2) の第四引数 */ socklen_t option_len; /* setsockopt(2) の第五引数 */ ... }; 成功すれば生成されたソケット番号を, 失敗すれば -1 を返す. 2. listen(2) listen(2) の代わりに ox_listen を使うべし. struct listen_socks * ox_listen(const char *hostname, int *port, int backlog, struct ox_sockopt *opt); hostname - 接続先のホスト名 port - 接続先のポート番号 backlog - listen(2) の第二引数 opt - setsockopt(2) へ渡したいオプション群 (ox_connect と同様) 成功すれば listen(2) しているソケットの数と配列への構造体への ポインタを, 失敗すれば NULL を返す. struct listen_socks { int nsocks; int listen_sock[nsocks]; /* 動的に割り当てられる */ }; 理由: 待ち受けているソケットは必ずしもひとつではない. IPv4 と IPv6 双方が利用可能な (デュアルスタックな) マシンにおいて, IPv4 および IPv6 をサポートしている sshd (OpenSSH など) をワイルドカードアドレスで待ち受けている 場合は, 以下のようになっている. # sockstat | grep sshd root sshd 177 4 tcp4 *:22 *:* root sshd 177 3 tcp46 *:22 *:* 3. accept(2) accept(2) の代わりに ox_accept を使うべし. int ox_accept(struct listen_socks *socks); socks - ox_listen の戻り値 成功すれば accept(2) されたソケット番号を, 失敗すれば -1 を返す. 4. getsockname(2) getsockname(2) の代わりに ox_getsockname を使うべし. int ox_getsockname(int socket, struct sockaddr **addr, socklen_t *addrlen); socket - 有効なソケット番号 addr - sockaddr 構造体へのポインタのポインタ addrlen - sockaddr 構造体の長さ 成功すれば 0 を, 失敗すれば -1 を返す. 取得できた sockaddr 構造体は addr に格納され, 長さは addrlen に格納される. 理由: sockaddr 構造体は, 今日では汎用的なインターフェイスを 提供しているにしかすぎない. 実際のサイズはそれぞれの アドレスファミリごとに違うので, 現在では, 実質的な sockaddr 構造体の placeholder として, sockaddr_storage 構造体が定義されている. ただし, この構造体は, 事実上 IPv6 登場以降の OS にしか実装されておらず, OpenXM として 実装を仮定するのはよくない. そこで, ox_getsockname という wrapper を用意し, 実際の挙動を隠蔽することにした. 中身が必要となる場合として, ポート番号の取得があるが, これについては, ox_getport という wrapper を用意し, sockaddr 構造体をさらに隠蔽できるようにしてある. ox_getsockname で取得した sockaddr 構造体へ割り当てたメモリは, 必要がなくなった時点で確実に free(2) されるべきである. GC を用いている場合は, この限りではない. 5. ポート番号の取得 ポート番号の取得に関する汎用的なインターフェイスは存在しない. それぞれのアドレスファミリごとに個別に対処する必要がある. この操作を OpenXM として用意したのが, ox_getport である. int ox_getport(int socket); socket - 有効なソケット番号 成功すればポート番号を, 失敗すれば -1 を返す. 現在サポートされているのは, IPv4 および IPv6 だけである. 事実上これで十分であるが, ox_getport は容易に拡張可能である. 注意事項: 一部の OS には socklen_t が宣言されていない. Single UNIX Specification, version 2 あるいは, POSIX に基づいて 32 ビット符号無し整数と仮定してよいだろう. これ以上のサイズが必要となるときと, 我々の死とどちらが早いだろうか...