/** * @file kc_socket.h * @brief ソケットモジュールヘッダファイル * @copyright 2002 - 2023 Nomura Kei * @depends * kc.h */ #ifndef KC_SOCKET_H #define KC_SOCKET_H #include <kc.h> #if (KC_IS_WINDOWS) typedef SOCKET socket_t; #define SHUT_RD SD_RECEIVE #define SHUT_WR SD_SEND #define SHUT_RDWR SD_BOTH #define sockclose(sockfd) closesocket(sockfd) #else #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <net/if.h> #include <netdb.h> #include <stdlib.h> #include <unistd.h> typedef int socket_t; #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) #define sockclose(sockfd) close(sockfd) #endif // KC_IS_WINDOWS #ifdef __cplusplus extern "C" { namespace kc { using namespace std; #endif typedef struct KcSocket_ { /** * ソケットの接続先アドレスを返します。 * アドレスが取得できない場合(未接続状態など)、NULL を返します。 * * @param sock 対象ソケット * @return ソケットの接続先アドレス */ const char *(*get_remote_addr)(struct KcSocket_ *sock); /** * ソケットの接続先ポート番号を返します。 * 接続先ポート番号が取得できなかった場合、-1 を返します。 * * @param sock 対象ソケット * @return ポート番号 */ int (*get_remote_port)(struct KcSocket_ *sock); /** * ソケットのローカルアドレスを返します。 * アドレスが取得できない場合、NULL を返します。 * * @param sock 対象ソケット * @return ソケットのローカルアドレス */ const char *(*get_local_addr)(struct KcSocket_ *sock); /** * ソケットのローカルポート番号を返します。 * ローカルポート番号が取得できなかった場合、-1 を返します。 * * @param sock 対象ソケット * @return ポート番号 */ int (*get_local_port)(struct KcSocket_ *sock); /** * ソケットディスクリプタを返します。 * 通常は、ソケットディスクリプタを直接操作しないでください。 * * @param sock 対象ソケット * @return ソケットディスクリプタ */ socket_t (*get_socket)(struct KcSocket_ *sock); /** * ソケットタイプを返します。 * * @param sock 対象ソケット * @return ソケットタイプ */ int (*get_type)(struct KcSocket_ *sock); /** * ソケットファミリを返します。 * 実際にバインド、あるいは接続されているソケットファミリを返します。 * * @param sock 対象ソケット * @return ソケットファミリ */ int (*get_family)(struct KcSocket_ *sock); /** * 指定されたアドレス、サービスのアドレス情報を取得します。 * * @param sock 対象ソケット * @param result アドレス情報格納用ポインタ * @param addr アドレス * @param service サービス * @param is_passive サーバソケットの場合、true を指定ください。 */ bool (*get_addrinfo)( struct KcSocket_ *sock, struct addrinfo **result, const char *addr, const char *service, bool is_passive); /** * 指定されたアドレス、サービスにバインドします。 * 指定されたアドレスとサービスにより、複数候補がある場合は、 * 最初に見つかったアドレスとポートにバインドします。 * * @param sock 対象ソケット * @param addr アドレス * @param service サービス (例: "80", "http", "ssh" など) * @return true/false (bind 成功/失敗) */ bool (*bind)(struct KcSocket_ *sock, const char *addr, const char *service); /** * ソケットを接続待ちソケットとしてマークをつけます。 * 保留中の接続のキュー最大長を指定します。 * * @param sock 対象ソケット * @param backlog バックログ * @return true/false (成功/失敗) */ bool (*listen)(struct KcSocket_ *sock, int backlog); /** * ソケットへの接続を受け付けます。 * * @param sock 対象ソケット * @return 受け付けたソケット */ struct KcSocket_ *(*accept)(struct KcSocket_ *sock); /** * 指定されたアドレス、サービス接続します。 * local_addr に NULL を指定した場合、自動的にローカルのアドレスが設定されます。 * local_service に -1 を指定した場合、自動的にローカルのポート番号が割りつけられます。 * * @param sock 対象ソケット * @param addr アドレス * @param service サービス * @param local_addr ローカルアドレス * @param local_service ローカルサービス * @return true/false (成功/失敗) */ bool (*connect)(struct KcSocket_ *sock, const char *addr, const char *service, const char *local_addr, const char *local_port); /** * ソケットをクローズします。 * * @param sock 対象ソケット * @return true/false (成功/失敗) */ bool (*close)(struct KcSocket_ *sock); /** * メッセージを送信します。 * * @param sock 対象ソケット * @param buff メッセージ * @param size サイズ * @param flags フラグ (MSG_CONFIRM/MSG_DONTROUTE/MSG_DONTWAIT/MSG_EOR/MSG_MORE/MSG_NOSIGNAL/MSG_OOB) * @return 送信されたデータサイズ */ ssize_t (*send)(struct KcSocket_ *sock, const char *buff, size_t size, int flags); /** * メッセージを受信します。 * 受信したメッセージは指定されたバッファに格納されます。 * * @param sock 対象ソケット * @param buff メッセージ受信用バッファ * @param size バッファサイズ * @param flags フラグ (MSG_CONFIRM/MSG_DONTROUTE/MSG_DONTWAIT/MSG_EOR/MSG_MORE/MSG_NOSIGNAL/MSG_OOB) * @return 読み取ったデータサイズ */ ssize_t (*recv)(struct KcSocket_ *sock, char *buff, size_t size, int flags); /** * 指定されたアドレス、サービスにメッセージを送信します。 * * @param sock 対象ソケット * @param buff メッセージ * @param size サイズ * @param flags フラグ (MSG_CONFIRM/MSG_DONTROUTE/MSG_DONTWAIT/MSG_EOR/MSG_MORE/MSG_NOSIGNAL/MSG_OOB) * @param addr アドレス * @param service サービス * @return 送信メッセージサイズ、エラー発生時は -1 */ ssize_t (*sendto)( struct KcSocket_ *sock, const char *buff, size_t size, int flags, const char *addr, const char *service); /** * メッセージを受信します。 * src_addr, src_service がいずれも NULL 出ない場合、 * 送信元のアドレスとサービスが格納されます。 * * @param sock 対象ソケット * @param buff メッセージ受信用バッファ * @param size バッファサイズ * @param flags フラグ (MSG_CONFIRM/MSG_DONTROUTE/MSG_DONTWAIT/MSG_EOR/MSG_MORE/MSG_NOSIGNAL/MSG_OOB) * @param src_addr 送信元アドレス格納用バッファ * @param src_addrlen 送信元アドレス格納用バッファサイズ * @param src_service 送信元サービス格納用バッファ * @param src_servicelen 送信元サービス格納用バッファサイズ * @return 受信メッセージサイズ、エラー発生時は -1 */ ssize_t (*recvfrom)( struct KcSocket_ *sock, char *buff, size_t size, int flags, char *src_addr, size_t src_addrlen, char *src_service, size_t src_servicelen); /** * TTL を設定します。 * * @param sock 対象ソケット * @param val 設定する TTL * @return true/false (成功/失敗) */ bool (*set_ttl)(struct KcSocket_ *sock, int val); /** * マルチキャストグループに参加するために JOIN します。 * IPv4 の場合、ifname に、IPアドレスを指定ください。 * IPv6 の場合、ifname にインタフェース名 (例: eth0 など)を指定ください。 * ifname に NULL が指定された場合、任意のインタフェースとなります。 * * @param sock 対象ソケット * @param addr マルチキャストアドレス * @param ifname インタフェース名 * @return true/false (成功/失敗) */ bool (*join)(struct KcSocket_ *sock, const char *addr, const char *ifname); /** * マルチキャストグループから離脱します。 * * @param sock 対象ソケット * @param addr マルチキャストアドレス * @param ifname インタフェース名 * @return true/false (成功/失敗) */ bool (*leave)(struct KcSocket_ *sock, const char *addr, const char *ifname); /** * マルチキャストを送信するインタフェースを指定します。 * * @param sock 対象ソケット * @param v4_ifname インタフェース名(IPアドレス) * @param v6_ifname インタフェース名(eth0 など) * @return true/false (成功/失敗) */ void (*set_ifname)(struct KcSocket_ *sock, const char *v4_ifname, const char *v6_ifname); /** * 指定されたソケットの情報を指定されたバッファに出力します。 * * @param buff バッファ * @param size バッファサイズ * @param sock 対象ソケット */ void (*print_info)(struct KcSocket_ *sock, char *buff, size_t size); /** * Socket 管理情報 */ void *_info; } KcSocket; /** * 指定されたタイプ、ファミリのSocket オブジェクトを構築します。 * * @param type タイプ(SOCK_STREAM/SOCK_DGRAM/SOCK_RAW) * @param family ファミリ(AF_UNSPEC/AF_INET/AF_INET6) */ KcSocket *KcSocket_new(int type, int family); /** * Socket を破棄します。 */ void KcSocket_delete(KcSocket *socket); #ifdef __cplusplus } // namespace kc } // extern "C" #endif #endif // KC_SOCKET_H