OSDN Git Service

Add unix/socket_impl.hpp (とりあえずWindowsの持ってきただけ…)
authormyun2 <myun2@nwhite.info>
Mon, 9 Jul 2012 00:33:25 +0000 (09:33 +0900)
committermyun2 <myun2@nwhite.info>
Mon, 9 Jul 2012 00:33:25 +0000 (09:33 +0900)
roast/include/roast/unix/socket_impl.hpp [new file with mode: 0644]

diff --git a/roast/include/roast/unix/socket_impl.hpp b/roast/include/roast/unix/socket_impl.hpp
new file mode 100644 (file)
index 0000000..77827ef
--- /dev/null
@@ -0,0 +1,312 @@
+//     Roast+ License
+
+/*
+*/
+#ifndef __SFJP_ROAST__unix__socket_impl_HPP__
+#define __SFJP_ROAST__unix__socket_impl_HPP__
+
+#include "roast/io/socket/socket_base.hpp"
+#include <stdio.h>     //      sprintf
+#include <string>
+#include <ws2tcpip.h>
+#include <Wspiapi.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+
+#include "roast/windows/socket_startup.hpp"
+
+namespace roast
+{
+       namespace windows
+       {
+               ////////////////////////////////////////////////////////////////////////////////
+
+               class socket_impl
+               {
+               public:
+                       //      Types:
+                       typedef ::SOCKET handler_type, sock_type, socket_type;
+                       
+                       struct open_params_type {
+                               int af;
+                               int type;
+                               int protocol;
+                               const char* host;
+                               int port;
+                               
+                               open_params_type(){
+                                       host = NULL;
+                                       port = 0;
+                                       af = AF_INET;
+                                       type = SOCK_STREAM;
+                                       protocol = 0;
+                               }
+                               open_params_type(int af_in, int type_in, int protocol_in){
+                                       host = NULL;
+                                       port = 0;
+                                       af = af_in;
+                                       type = type_in;
+                                       protocol = protocol_in;
+                               }
+                               open_params_type(const char* host_in, int port_in, int af_in, int type_in, int protocol_in){
+                                       host = host_in;
+                                       port = port_in;
+                                       af = af_in;
+                                       type = type_in;
+                                       protocol = protocol_in;
+                               }
+                               open_params_type(const char* host_in, int port_in){
+                                       host = host_in;
+                                       port = port_in;
+                                       af = AF_INET;
+                                       type = SOCK_STREAM;
+                                       protocol = 0;
+                               }
+                       };
+                       struct ioctl_data {};
+       
+                       //      Const Values
+                       const static handler_type invalid_handle;
+                       
+               private:
+                       //      Private Methods
+                       static ::std::string get_last_error_msg()
+                       {
+                               char *msg_buf;
+                               ::FormatMessageA(       FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                                                                       NULL, ::WSAGetLastError(), LANG_USER_DEFAULT, (LPSTR)&msg_buf, 0, NULL );
+                               ::std::string msg;
+                               if ( msg_buf != NULL ){
+                                       msg = msg_buf;
+                                       ::LocalFree(msg_buf);
+                               }
+                               return msg;
+                       }
+                       
+                       static void nozero_assert(int code, const char* msg){
+                               if ( code != 0 )
+                                       throw socket_exception(::std::string(msg) + ' ' + get_last_error_msg(), code);
+                       }
+                       static void lasterr_assert(const char* msg){
+                               nozero_assert(::WSAGetLastError(), msg);
+                       }
+
+                       //      Private Classes
+                       class addr
+                       {
+                       private:
+                               ::addrinfo* data;
+                       public:
+                               addr(const char* host, int port, int family, int socktype) {
+                                       ::addrinfo hints;
+                                       ::memset(&hints, 0, sizeof(hints));
+                                       hints.ai_family = family;
+                                       hints.ai_socktype = socktype;
+
+#pragma warning(disable: 4996)
+                                       char port_str[12];
+                                       sprintf(port_str, "%d", port);
+#pragma warning(default: 4996)
+
+                                       nozero_assert(
+                                               ::getaddrinfo(host, port_str, &hints, &data),
+                                               "roast::windows::socket::addr() ::getaddrinfo() function was error.");
+
+                               }
+                               virtual ~addr(){
+                                       if ( data != NULL )
+                                               ::freeaddrinfo(data);
+                               }
+                               ///////////////
+                               operator ::addrinfo* (){ return data; }
+                               operator ::addrinfo* () const { return data; }
+                               ::addrinfo* operator -> (){ return data; }
+                               const ::addrinfo* operator -> () const { return data; }
+                       };
+                       
+               public:
+                       socket_impl(){}
+                       virtual ~socket_impl(){}
+                       
+                       //      Implement Methods
+                       static handler_type create(const open_params_type& params){
+                               sock_type sock = ::socket(params.af, params.type, params.protocol);
+                               lasterr_assert("roast::windows::socket::create() ::socket() function was error.");
+                               return sock;
+                       }
+                       
+                       static handler_type open(/*handler_type handler, */const open_params_type& params)
+                       {
+                               handler_type handler = create(params);
+                               
+                               addr ai(params.host, params.port, params.af, params.type);
+                               nozero_assert(
+                                       ::connect(handler, ai->ai_addr, ai->ai_addrlen),
+                                       "roast::socket::connect() ::connect() function was error.");
+                               return handler;
+                       }
+                       
+                       static void close(handler_type handler)
+                       {
+                               nozero_assert(
+                                       ::closesocket(handler),
+                                       "roast::windows::socket::close() ::closesocket() function was error.");
+                       }
+                       
+                       void shutdown(handler_type handler, int how=3)
+                       {
+                               nozero_assert(
+                                       ::shutdown(handler, how),
+                                       "roast::windows::socket::close() ::closesocket() function was error.");
+                       }
+                       
+                       void listen(handler_type handler, int max_queueing=SOMAXCONN)
+                       {
+                               nozero_assert(
+                                       ::listen(handler, max_queueing),
+                                       "roast::windows::socket::listen() ::listen() function was error.");
+                       }
+                       
+                       handler_type accept(handler_type handler, ::sockaddr* addr_out=NULL, int* len_out=NULL)
+                       {
+                               ::SOCKET accepted_socket = ::accept(handler, addr_out, len_out);
+                               nozero_assert(::WSAGetLastError(), "roast::socket::accept() ::accept() function was error.");
+                               return accepted_socket;
+                       }
+                       
+                       ///////////////////////////////////////////////////////////////////////////////////////////////
+                       
+                       static int read(handler_type handler, void *buf, size_t size){ return read(handler, buf, size, 0); }
+                       static int write(handler_type handler, const void *buf, size_t size){ return write(handler, buf, size, 0); }
+                       //int ioctl(handler_type handler, const ioctl_data& data);
+                       
+                       static int read(handler_type handler, void* buf, size_t size, int flag)
+                       {
+                               int ret = ::recv(handler, (char*)buf, size, flag);
+                               lasterr_assert("roast::windows::socket::read() ::recv() function was error.");
+                               return ret;
+                       }
+                       static int write(handler_type handler, const void* buf, size_t size, int flag)
+                       {
+                               int ret = ::send(handler, (const char*)buf, size, flag);
+                               lasterr_assert("roast::windows::socket::write() ::send() function was error.");
+                               return ret;
+                       }
+
+                       static int ioctl(handler_type handler, const ioctl_data& data){ return -1; }
+               };
+               
+               const socket_impl::handler_type socket_impl::invalid_handle = INVALID_SOCKET;
+
+               ////////////////////////////////////////////////////////////////////////////////
+               /*
+               class socket : public socket_impl_base
+               {
+               private:
+                       bool m_opened;
+                       int m_af;
+                       int m_socket_type;
+                       int m_socket_protocol;
+
+               public:
+                       socket(int af=AF_INET, int type=SOCK_STREAM, int protocol=0)
+                               : m_sock(NULL)
+                       {
+                               m_cleanup.add();
+                               m_opened = false;
+                               m_owner = true;
+
+                               m_af = af;
+                               m_socket_type = type;
+                               m_socket_protocol = protocol;
+
+                               m_sock = ::socket(af, type, protocol);
+
+                               nozero_assert(::WSAGetLastError(), "roast::socket::socket() ::socket() function was error.");
+
+                               if ( m_sock == INVALID_SOCKET )
+                                       throw socket_exception(::WSAGetLastError(), "roast::socket::socket() m_sock is INVALID_SOCKET.");
+                       }
+
+
+                       //////////////////////////////////////////////////////////////////
+
+                       void connect(const char* host, int port)
+                       {
+                               //      Already Socket was Close...?
+                               //close();
+
+                               if ( m_sock != INVALID_SOCKET && m_opened )
+                                       throw socket_exception(::WSAGetLastError(), "roast::socket::connect() Socket was already opened.");
+                               
+                               ::addrinfo hints;
+                               ::memset(&hints, 0, sizeof(hints));
+                               hints.ai_socktype = m_socket_type;
+                               hints.ai_family = m_af;
+
+#pragma warning(disable: 4996)
+                               char port_str[12];
+                               sprintf(port_str, "%d", port);
+#pragma warning(default: 4996)
+
+                               ::addrinfo *addr=NULL;
+                               nozero_assert(
+                                       ::getaddrinfo(host, port_str, &hints, &addr),
+                                       "roast::socket::connect() ::getaddrinfo() function was error.");
+
+                               try
+                               {
+                                       nozero_assert(
+                                               ::connect(m_sock, addr->ai_addr, addr->ai_addrlen),
+                                               "roast::socket::connect() ::connect() function was error.");
+                               }
+                               catch(const socket_exception& e){
+                                       ::freeaddrinfo(addr);
+                                       throw e;
+                               }
+
+                               m_opened = true;
+                               ::freeaddrinfo(addr);
+                       }
+
+                       void bind(int port, const char* host="0.0.0.0")
+                       {
+                               if ( m_sock != INVALID_SOCKET && m_opened )
+                                       throw socket_exception(::WSAGetLastError(), "roast::socket::bind() Socket was already binded.");
+                               
+                               ::addrinfo hints;
+                               ::memset(&hints, 0, sizeof(hints));
+                               hints.ai_socktype = m_socket_type;
+                               hints.ai_family = m_af;
+
+#pragma warning(disable: 4996)
+                               char port_str[12];
+                               sprintf(port_str, "%d", port);
+#pragma warning(default: 4996)
+
+                               ::addrinfo *addr=NULL;
+                               nozero_assert(
+                                       ::getaddrinfo(host, port_str, &hints, &addr),
+                                       "roast::socket::bind() ::getaddrinfo() function was error.");
+
+                               try
+                               {
+                                       nozero_assert(
+                                               ::bind(m_sock, addr->ai_addr, addr->ai_addrlen),
+                                               "roast::socket::bind() ::connect() function was error.");
+                               }
+                               catch(const socket_exception& e){
+                                       ::freeaddrinfo(addr);
+                                       throw e;
+                               }
+
+                               m_opened = true;
+                               ::freeaddrinfo(addr);
+                       }
+               };*/
+               
+               ////////////////////////////////////////////////////////////////////////////////
+       }
+}
+
+#endif//__SFJP_ROAST__unix__socket_impl_HPP__