Newer
Older
libkc / modules / include / kc_socket.h
/**
 * @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