/**
 * @file      nstdc_socket.c
 * @brief     ソケット扱うモジュール (for Windows 以外)
 * @author    Nomura Kei
 * @copyright 2003 - 2017  Nomura Kei
 * License: New BSD License (3-cclause BSD license)
 */
#include <nstdc_socket.h>

#if (nstdc_is_windows())
/* include for atexit()	*/
#include <stdlib.h>
#endif



/* -----------------------------------------------------------------------------
 *  プロトタイプ宣言
 * -----------------------------------------------------------------------------
 */
#if (nstdc_is_windows())
static bool winsock_startup(void);
static void winsock_cleanup(void);
#endif



/* -----------------------------------------------------------------------------
 *  内部変数
 * -----------------------------------------------------------------------------
 */
#if (nstdc_is_windows())
static WSADATA nstdc_winsock_wsadata;			/**< winsock 情報.				*/
#endif



/* -----------------------------------------------------------------------------
 *  for Windows
 * -----------------------------------------------------------------------------
 */
#if (nstdc_is_windows())


/**
 * ソケットを生成します.
 *
 * @param [in] domain   通信を行うドメイン(AF_INET/AF_INET6/AF_PACKET etc.).
 * @param [in] type     型 (SOCK_STREAM/SOCK_DGRAM/SOCK_SEQPACKET/SOCK_RAW/SOCK_RDM etc.).
 * @param [in] protocol ソケットによって使用されるプロトコル(通常0).
 * @return ソケットのディスクリプター
 */
int socket_win(int domain, int type, int protocol)
{
	bool ret = winsock_startup();
	if (ret)
	{
		SOCKET sockfd = socket(domain, type, protocol);
		if (sockfd != INVALID_SOCKET)
		{
			return (int) sockfd;
		}
	}
	return -1;
}



/**
 * Winsock の初期化を実施します.
 */
static
bool winsock_startup(void)
{
	static bool is_init = false;
	if (!is_init)
	{
		int ret = WSAStartup(MAKEWORD(2, 0), &nstdc_winsock_wsadata);
		if (ret == 0)
		{
			atexit(winsock_cleanup);
			is_init = true;
		}
	}
	return is_init;
}



/**
 * Winsock をクリーンアップします.
 */
static
void winsock_cleanup(void)
{
	WSACleanup();
}




#endif	/* if (nstdc_is_windows())	*/

