--- /dev/null
+// Roast+ License
+
+/*
+*/
+#ifndef __SFJP_ROAST__windows__net__socket_windows_impl_HPP__
+#define __SFJP_ROAST__windows__net__socket_windows_impl_HPP__
+
+#include <string>
+#include <ws2tcpip.h>
+#include <Wspiapi.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+
+//////////////////////////////////////////////////
+
+namespace roast
+{
+ class _socket_windows_impl_default_option
+ {
+ public:
+ static unsigned char GetWsockMajorVersion(){ return 2; }
+ static unsigned char GetWsockMinerVersion(){ return 0; }
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////
+
+ class _socket_windows_impl_constant
+ {
+ public:
+ typedef ::SOCKET socket_t;
+ static const socket_t invalid_socket;
+ };
+ const _socket_windows_impl_constant::socket_t _socket_windows_impl_constant::invalid_socket = INVALID_SOCKET;
+
+ ////////////////////
+
+ class _socket_windows_instance_count
+ {
+ protected:
+ static int m_instance_count;
+ };
+ int _socket_windows_instance_count::m_instance_count = 0;
+
+ ////////////////////
+
+ template <typename _OptionT = _socket_windows_impl_default_option>
+ class socket_windows_impl_ : public _socket_windows_impl_constant, _socket_windows_instance_count
+ {
+ public:
+ typedef ::u_long in_addr_t; // Linux: in_addr_t
+ typedef struct ::sockaddr sockaddr_t;
+ typedef struct ::sockaddr_in sockaddr_in_t;
+ typedef struct ::addrinfo addrinfo_t;
+ typedef ::SOCKET socket_t;
+ //typedef ::fd_set fd_set_t, fdset_t;
+
+ private:
+ //WSADATA* m_wsaInfo;
+ ::WSADATA* m_pWsaInfo;
+ int m_last_error;
+ ::std::string m_last_error_msg;
+ //static int m_instance_count;
+
+ void _last_error_zero()
+ {
+ m_last_error = 0;
+ }
+ void _WSAle_update()
+ {
+ m_last_error = ::WSAGetLastError();
+ }
+
+ bool _apiret_0true(int apiret)
+ {
+ m_last_error = apiret;
+ return ( apiret == 0 ? true : false );
+ }
+
+ bool _apiret_WSAle(int apiret)
+ {
+ _WSAle_update();
+ return ( apiret == SOCKET_ERROR ? false : true );
+ }
+
+ int _myselect(socket_t s,
+ ::fd_set *readfds, ::fd_set *writefds, ::fd_set *exceptfds,
+ long timeout_sec, long timeout_usec)
+ {
+ struct ::timeval tv;
+ tv.tv_sec = timeout_sec;
+ tv.tv_usec = timeout_usec;
+
+ int ret = ::select(0/*Winsock always zero.*/, readfds, writefds, exceptfds, &tv);
+ _WSAle_update();
+ return ret;
+ }
+
+ public:
+ socket_windows_impl_()
+ {
+ //ZeroMemory(&m_wsaInfo,sizeof(m_wsaInfo));
+ m_pWsaInfo = NULL;
+ m_last_error = 0;
+
+ if ( m_instance_count == 0 )
+ init();
+ m_instance_count++;
+ }
+ virtual ~socket_windows_impl_()
+ {
+ m_instance_count--;
+ if ( m_instance_count == 0 )
+ term();
+
+ if ( m_pWsaInfo != NULL )
+ delete m_pWsaInfo;
+ }
+
+ ///////////////////////////////////////////////
+
+ // init()
+ bool init()
+ {
+ //ZeroMemory(m_wsaInfo,sizeof(m_wsaInfo));
+ if ( m_pWsaInfo == NULL )
+ m_pWsaInfo = new ::WSADATA();
+ ZeroMemory(m_pWsaInfo,sizeof(::WSADATA));
+
+ WORD wVersionRequested = MAKEWORD(
+ _OptionT::GetWsockMajorVersion(),
+ _OptionT::GetWsockMinerVersion());
+
+ //return _apiret_0true( ::WSAStartup(wVersionRequested, &m_wsaInfo) );
+ return _apiret_0true( ::WSAStartup(wVersionRequested, m_pWsaInfo) );
+ }
+ //WSADATA* get_wsadata(){ return &m_wsaInfo; }
+ ::WSADATA* get_wsadata(){ return m_pWsaInfo; }
+
+ // term()
+ bool term()
+ {
+ return _apiret_0true( ::WSACleanup() );
+ }
+
+ ///////////////////////////////////////////
+
+ // socket()
+ socket_t socket(int af, int type, int protocol)
+ {
+ socket_t s = ::socket(af, type, protocol);
+ _WSAle_update();
+ return s;
+ }
+
+ bool getaddrinfo(const char *node, const char *service,
+ const addrinfo_t *hints, addrinfo_t **res)
+ {
+ return _apiret_0true( ::getaddrinfo(node, service, hints, res) );
+ }
+
+ void freeaddrinfo(addrinfo_t *ai)
+ {
+ ::freeaddrinfo(ai);
+ }
+
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+ {
+ return _apiret_0true( ::getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) );
+ }
+
+ // connect()
+ bool connect(socket_t s, const sockaddr_t *addr, int addrlen)
+ {
+ return _apiret_WSAle( ::connect(s, addr, addrlen) );
+ }
+
+ // bind
+ bool bind(socket_t s, const sockaddr_t *addr, int len )
+ {
+ return _apiret_WSAle( ::bind(s, addr, len) );
+ }
+
+ // listen
+ bool listen(socket_t s, int max_queueing)
+ {
+ return _apiret_WSAle( ::listen(s, max_queueing) );
+ }
+
+ // accept
+ socket_t accept(socket_t s, sockaddr_t *addr_out, int *len_out )
+ {
+ socket_t accepted_socket = ::accept(s, addr_out, len_out);
+ _WSAle_update();
+ return accepted_socket;
+ }
+
+ // shutdown()
+ // \82±\82Ì\8aÖ\90\94\82Å\83\\83P\83b\83g\82Ì\91\97\90M\82©\8eó\90M\82ð\82Å\82«\82È\82\82µ\82Ü\82·\81B
+ // closesocket \8aÖ\90\94\82Å\83\\83P\83b\83g\82ð\95Â\82¶\82é\91O\82É\81A\82±\82Ì\8aÖ\90\94\82Å\90Ú\91±\82ð\92â\8e~\81i\83V\83\83\83b\83g\83_\83E\83\93\81j\82µ\82Ä\82\82¾\82³\82¢\81B
+ /*
+ WSAAsyncSelect \8aÖ\90\94\82ð\8eg\82Á\82Ä FD_CLOSE \92Ê\92m\82ð\93o\98^\82µ\82Ä\82\82¾\82³\82¢\81B
+ shutdown \82Ì how \82É SD_SEND \82ð\93n\82µ\82Ä\82\82¾\82³\82¢\81B
+
+ \93Á\82É\81AWindows Sockets \83v\83\8d\83o\83C\83_\82Í\81A\8eÕ\92f\82³\82ê\82½\83\\83P\83b\83g\82Ì connect \82Ì\8eg\97p\82É\91Î\89\9e\82·\82é\95K\97v\82Í\82 \82è\82Ü\82¹\82ñ\81B
+ */
+ bool shutdown(socket_t s, int how=3)
+ {
+ return _apiret_WSAle( ::shutdown(s, how) );
+ }
+
+ // close()
+ bool close(socket_t s)
+ {
+ return _apiret_WSAle( ::closesocket(s) );
+ }
+
+ /*
+ // select()
+ int select(socket_t s,
+ fdset_t *readfds, fdset_t *writefds, fdset_t *exceptfds,
+ long timeout_sec, long timeout_usec)
+ {
+ struct ::timeval tv;
+ tv.tv_sec = timeout_sec;
+ tv.tv_usec = timeout_usec;
+
+ int ret = ::select(s, readfds, writefds, exceptfds, tv);
+ _WSAle_update();
+ return ret;
+ }
+ */
+ bool wait_readable(socket_t s, int timeout_ms)
+ {
+ ::fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+
+ int ret = _myselect(s, &readfds, NULL, NULL, timeout_ms/1000, timeout_ms*1000);
+ _WSAle_update();
+ //return FD_ISSET(m_socket, &readfds);
+ return (ret > 0);
+ }
+ bool is_connected(socket_t s)
+ {
+ ::fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+
+ int ret = _myselect(s, &readfds, NULL, NULL, 0,0);
+ _WSAle_update();
+ //return FD_ISSET(m_socket, &readfds);
+ return (ret != -1);
+ }
+
+ ////////////////////////////////////////////////////////////////
+
+ // recv
+ // \8ew\92è\82³\82ê\82½\83\\83P\83b\83g\83f\83B\83X\83N\83\8a\83v\83^\82ª\83X\83g\83\8a\81[\83\80\83\\83P\83b\83g\82Ì\8fê\8d\87\81A
+ // \8aÖ\90\94\82Í\83o\83b\83t\83@\82É\8eó\90M\8dÏ\82Ý\83f\81[\83^\82ð\93ü\82ê\82ç\82ê\82é\82¾\82¯\93ü\82ê\81A
+ // \8ec\82è\82Ì\83f\81[\83^\82Í\8e\9f\89ñ\82Ì\8cÄ\82Ñ\8fo\82µ\82Å\8eæ\93¾\82·\82é\8e\96\82ª\82Å\82«\82Ü\82·\81B
+ // \83f\81[\83^\83O\83\89\83\80\83\\83P\83b\83g\82Ì\8fê\8d\87\82É\82Í\8eó\90M\82µ\82½\83f\81[\83^\83O\83\89\83\80\82Ì\82Å\82«\82é\82¾\82¯\91½\82\82ð
+ // \83o\83b\83t\83@\82É\95Û\91¶\82µ\82Ü\82·\82ª\81A\83o\83b\83t\83@\82É\93ü\82è\82«\82ç\82È\82©\82Á\82½\95ª\82Í\94j\8aü\82³\82ê\82Ü\82·\81B
+ // \82±\82Ì\8e\9e\81A\8aÖ\90\94\82Í WSEMSGSIZE \83G\83\89\81[\82ð\94\90¶\82µ\82Ü\82·\81B
+ // \82±\82Ì\8aÖ\90\94\82Å\96â\91è\82ª\94\90¶\82µ\82È\82¯\82ê\82Î\81A\8eó\90M\82µ\82½\83o\83C\83g\90\94\82ð\95Ô\82µ\82Ü\82·\81B
+ // \90Ú\91±\82ª\90³\8fí\82É\95Â\82¶\82ç\82ê\82Ä\82¢\82½\8fê\8d\87\82Í\83[\83\8d\82ð\95Ô\82µ\82Ü\82·\81B
+ // \83G\83\89\81[\82Í-1
+ int recv(socket_t s, void* buf, int len, int flag)
+ {
+ int ret = ::recv(s, (char*)buf, len, flag);
+ _WSAle_update();
+ if ( ret == SOCKET_ERROR )
+ return -1;
+ return ret;
+ }
+
+ // send()
+ // \8aÖ\90\94\8cÄ\82Ñ\8fo\82µ\8cã\82·\82®\82É\83f\81[\83^\82ª\91\97\90M\82³\82ê\82é\82Æ\8c¾\82¤\95Û\8fØ\82Í\82 \82è\82Ü\82¹\82ñ\81B
+ // \82à\82µ\91\97\90M\83o\83b\83t\83@\82ª\82¢\82Á\82Ï\82¢\82Å\81A\90V\82µ\82¢\83f\81[\83^\82ð\83o\83b\83t\83@\82É\95Û\91¶\82Å\82«\82È\82¢\8fê\8d\87\81A
+ // \8aÖ\90\94\82Í\95Û\91¶\82ª\89Â\94\\82É\82È\82é\82Ü\82Å\8f\88\97\9d\82ð\92\86\92f\82µ\82Ü\82·\81B
+ // \82±\82Ì\8aÖ\90\94\82Å\96â\91è\82ª\94\90¶\82µ\82È\82¯\82ê\82Î\81A\91\97\90M\82µ\82½\91S\83o\83C\83g\90\94\82ð\95Ô\82µ\82Ü\82·\81B
+ // \83G\83\89\81[\82Í-1
+ int send(socket_t s, const char* buf, int len, int flag)
+ {
+ int ret = ::send(s, buf, len, flag);
+ _WSAle_update();
+ if ( ret == SOCKET_ERROR )
+ return -1;
+ return ret;
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ int get_last_error(){ return m_last_error; }
+ const char* get_last_error_msg()
+ {
+ m_last_error_msg = "";
+ char *msg_buf;
+ ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, m_last_error, LANG_USER_DEFAULT, (LPSTR)&msg_buf, 0, NULL );
+ if ( msg_buf != NULL ){
+ m_last_error_msg = msg_buf;
+ LocalFree(msg_buf);
+ }
+ return m_last_error_msg.c_str();
+ }
+
+ bool is_invalid_socket(::SOCKET s){
+ return ( s == invalid_socket ? true : false );
+ }
+ bool is_valid_socket(::SOCKET s){
+ return ( s == invalid_socket ? false : true );
+ }
+ };
+ typedef socket_windows_impl_<> socket_windows_impl;
+
+ //static int m_instance_count = 0;
+}
+
+#endif//__SFJP_ROAST__windows__net__socket_windows_impl_HPP__