5 #ifndef __SFJP_ROAST__unix__socket_impl_HPP__
6 #define __SFJP_ROAST__unix__socket_impl_HPP__
8 #include "roast/io/socket/socket_base.hpp"
9 #include <stdio.h> // sprintf
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
22 ////////////////////////////////////////////////////////////////////////////////
28 typedef int handler_type, sock_type, socket_type;
30 struct open_params_type {
44 open_params_type(int af_in, int type_in, int protocol_in){
49 protocol = protocol_in;
51 open_params_type(const char* host_in, int port_in, int af_in, int type_in, int protocol_in){
56 protocol = protocol_in;
58 open_params_type(const char* host_in, int port_in){
69 const static handler_type invalid_handle;
73 /*static ::std::string get_last_error_msg()
76 ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
77 NULL, ::WSAGetLastError(), LANG_USER_DEFAULT, (LPSTR)&msg_buf, 0, NULL );
79 if ( msg_buf != NULL ){
86 static void nozero_assert(int code, const char* msg){
88 throw socket_exception(::std::string(msg) /*+ ' ' + get_last_error_msg()*/, code);
90 static void lasterr_assert(const char* msg){
91 nozero_assert(errno, msg);
100 addr(const char* host, int port, int family, int socktype) {
102 ::memset(&hints, 0, sizeof(hints));
103 hints.ai_family = family;
104 hints.ai_socktype = socktype;
106 #pragma warning(disable: 4996)
108 sprintf(port_str, "%d", port);
109 #pragma warning(default: 4996)
112 ::getaddrinfo(host, port_str, &hints, &data),
113 "roast::unix::socket::addr() ::getaddrinfo() function was error.");
118 ::freeaddrinfo(data);
121 operator ::addrinfo* (){ return data; }
122 operator ::addrinfo* () const { return data; }
123 ::addrinfo* operator -> (){ return data; }
124 const ::addrinfo* operator -> () const { return data; }
129 virtual ~socket_impl(){}
132 static handler_type create(const open_params_type& params){
133 sock_type sock = ::socket(params.af, params.type, params.protocol);
134 lasterr_assert("roast::unix::socket::create() ::socket() function was error.");
138 static handler_type open(/*handler_type handler, */const open_params_type& params)
140 handler_type handler = create(params);
142 addr ai(params.host, params.port, params.af, params.type);
144 ::connect(handler, ai->ai_addr, ai->ai_addrlen),
145 "roast::socket::connect() ::connect() function was error.");
149 static void close(handler_type handler)
152 ::closesocket(handler),
153 "roast::unix::socket::close() ::closesocket() function was error.");
156 void shutdown(handler_type handler, int how=3)
159 ::shutdown(handler, how),
160 "roast::unix::socket::close() ::closesocket() function was error.");
163 void listen(handler_type handler, int max_queueing=SOMAXCONN)
166 ::listen(handler, max_queueing),
167 "roast::unix::socket::listen() ::listen() function was error.");
170 handler_type accept(handler_type handler, ::sockaddr* addr_out=NULL, int* len_out=NULL)
172 handler_type accepted_socket = ::accept(handler, addr_out, len_out);
173 nozero_assert(errno, "roast::socket::accept() ::accept() function was error.");
174 return accepted_socket;
177 ///////////////////////////////////////////////////////////////////////////////////////////////
179 static int read(handler_type handler, void *buf, size_t size){ return read(handler, buf, size, 0); }
180 static int write(handler_type handler, const void *buf, size_t size){ return write(handler, buf, size, 0); }
181 //int ioctl(handler_type handler, const ioctl_data& data);
183 static int read(handler_type handler, void* buf, size_t size, int flag)
185 int ret = ::recv(handler, (char*)buf, size, flag);
186 lasterr_assert("roast::unix::socket::read() ::recv() function was error.");
189 static int write(handler_type handler, const void* buf, size_t size, int flag)
191 int ret = ::send(handler, (const char*)buf, size, flag);
192 lasterr_assert("roast::unix::socket::write() ::send() function was error.");
196 static int ioctl(handler_type handler, const ioctl_data& data){ return -1; }
199 const socket_impl::handler_type socket_impl::invalid_handle = INVALID_SOCKET;
201 ////////////////////////////////////////////////////////////////////////////////
203 class socket : public socket_impl_base
209 int m_socket_protocol;
212 socket(int af=AF_INET, int type=SOCK_STREAM, int protocol=0)
220 m_socket_type = type;
221 m_socket_protocol = protocol;
223 m_sock = ::socket(af, type, protocol);
225 nozero_assert(errno, "roast::socket::socket() ::socket() function was error.");
227 if ( m_sock == INVALID_SOCKET )
228 throw socket_exception(errno, "roast::socket::socket() m_sock is INVALID_SOCKET.");
232 //////////////////////////////////////////////////////////////////
234 void connect(const char* host, int port)
236 // Already Socket was Close...?
239 if ( m_sock != INVALID_SOCKET && m_opened )
240 throw socket_exception(errno, "roast::socket::connect() Socket was already opened.");
243 ::memset(&hints, 0, sizeof(hints));
244 hints.ai_socktype = m_socket_type;
245 hints.ai_family = m_af;
247 #pragma warning(disable: 4996)
249 sprintf(port_str, "%d", port);
250 #pragma warning(default: 4996)
252 ::addrinfo *addr=NULL;
254 ::getaddrinfo(host, port_str, &hints, &addr),
255 "roast::socket::connect() ::getaddrinfo() function was error.");
260 ::connect(m_sock, addr->ai_addr, addr->ai_addrlen),
261 "roast::socket::connect() ::connect() function was error.");
263 catch(const socket_exception& e){
264 ::freeaddrinfo(addr);
269 ::freeaddrinfo(addr);
272 void bind(int port, const char* host="0.0.0.0")
274 if ( m_sock != INVALID_SOCKET && m_opened )
275 throw socket_exception(errno, "roast::socket::bind() Socket was already binded.");
278 ::memset(&hints, 0, sizeof(hints));
279 hints.ai_socktype = m_socket_type;
280 hints.ai_family = m_af;
282 #pragma warning(disable: 4996)
284 sprintf(port_str, "%d", port);
285 #pragma warning(default: 4996)
287 ::addrinfo *addr=NULL;
289 ::getaddrinfo(host, port_str, &hints, &addr),
290 "roast::socket::bind() ::getaddrinfo() function was error.");
295 ::bind(m_sock, addr->ai_addr, addr->ai_addrlen),
296 "roast::socket::bind() ::connect() function was error.");
298 catch(const socket_exception& e){
299 ::freeaddrinfo(addr);
304 ::freeaddrinfo(addr);
308 ////////////////////////////////////////////////////////////////////////////////
312 #endif//__SFJP_ROAST__unix__socket_impl_HPP__