From: myun2 Date: Mon, 9 Jul 2012 00:33:25 +0000 (+0900) Subject: Add unix/socket_impl.hpp (とりあえずWindowsの持ってきただけ…) X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a35b8f3f4884fa72ca0cb1da6549d6da1414d87f;p=roast%2Froast.git Add unix/socket_impl.hpp (とりあえずWindowsの持ってきただけ…) --- diff --git a/roast/include/roast/unix/socket_impl.hpp b/roast/include/roast/unix/socket_impl.hpp new file mode 100644 index 00000000..77827ef3 --- /dev/null +++ b/roast/include/roast/unix/socket_impl.hpp @@ -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 // sprintf +#include +#include +#include +#include +#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__