--- /dev/null
+// 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__