OSDN Git Service

unix/socket_impl.hpp: 大体直して、みた、ような…?
[roast/roast.git] / roast / include / roast / unix / socket_impl.hpp
1 //      Roast+ License
2
3 /*
4 */
5 #ifndef __SFJP_ROAST__unix__socket_impl_HPP__
6 #define __SFJP_ROAST__unix__socket_impl_HPP__
7
8 #include "roast/io/socket/socket_base.hpp"
9 #include <stdio.h>      //      sprintf
10 #include <string>
11
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <netdb.h>
17
18 namespace roast
19 {
20         namespace unix
21         {
22                 ////////////////////////////////////////////////////////////////////////////////
23
24                 class socket_impl
25                 {
26                 public:
27                         //      Types:
28                         typedef int handler_type, sock_type, socket_type;
29                         
30                         struct open_params_type {
31                                 int af;
32                                 int type;
33                                 int protocol;
34                                 const char* host;
35                                 int port;
36                                 
37                                 open_params_type(){
38                                         host = NULL;
39                                         port = 0;
40                                         af = AF_INET;
41                                         type = SOCK_STREAM;
42                                         protocol = 0;
43                                 }
44                                 open_params_type(int af_in, int type_in, int protocol_in){
45                                         host = NULL;
46                                         port = 0;
47                                         af = af_in;
48                                         type = type_in;
49                                         protocol = protocol_in;
50                                 }
51                                 open_params_type(const char* host_in, int port_in, int af_in, int type_in, int protocol_in){
52                                         host = host_in;
53                                         port = port_in;
54                                         af = af_in;
55                                         type = type_in;
56                                         protocol = protocol_in;
57                                 }
58                                 open_params_type(const char* host_in, int port_in){
59                                         host = host_in;
60                                         port = port_in;
61                                         af = AF_INET;
62                                         type = SOCK_STREAM;
63                                         protocol = 0;
64                                 }
65                         };
66                         struct ioctl_data {};
67         
68                         //      Const Values
69                         const static handler_type invalid_handle;
70                         
71                 private:
72                         //      Private Methods
73                         /*static ::std::string get_last_error_msg()
74                         {
75                                 char *msg_buf;
76                                 ::FormatMessageA(       FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
77                                                                         NULL, ::WSAGetLastError(), LANG_USER_DEFAULT, (LPSTR)&msg_buf, 0, NULL );
78                                 ::std::string msg;
79                                 if ( msg_buf != NULL ){
80                                         msg = msg_buf;
81                                         ::LocalFree(msg_buf);
82                                 }
83                                 return msg;
84                         }*/
85                         
86                         static void nozero_assert(int code, const char* msg){
87                                 if ( code != 0 )
88                                         throw socket_exception(::std::string(msg) /*+ ' ' + get_last_error_msg()*/, code);
89                         }
90                         static void lasterr_assert(const char* msg){
91                                 nozero_assert(errno, msg);
92                         }
93
94                         //      Private Classes
95                         class addr
96                         {
97                         private:
98                                 ::addrinfo* data;
99                         public:
100                                 addr(const char* host, int port, int family, int socktype) {
101                                         ::addrinfo hints;
102                                         ::memset(&hints, 0, sizeof(hints));
103                                         hints.ai_family = family;
104                                         hints.ai_socktype = socktype;
105
106 #pragma warning(disable: 4996)
107                                         char port_str[12];
108                                         sprintf(port_str, "%d", port);
109 #pragma warning(default: 4996)
110
111                                         nozero_assert(
112                                                 ::getaddrinfo(host, port_str, &hints, &data),
113                                                 "roast::unix::socket::addr() ::getaddrinfo() function was error.");
114
115                                 }
116                                 virtual ~addr(){
117                                         if ( data != NULL )
118                                                 ::freeaddrinfo(data);
119                                 }
120                                 ///////////////
121                                 operator ::addrinfo* (){ return data; }
122                                 operator ::addrinfo* () const { return data; }
123                                 ::addrinfo* operator -> (){ return data; }
124                                 const ::addrinfo* operator -> () const { return data; }
125                         };
126                         
127                 public:
128                         socket_impl(){}
129                         virtual ~socket_impl(){}
130                         
131                         //      Implement Methods
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.");
135                                 return sock;
136                         }
137                         
138                         static handler_type open(/*handler_type handler, */const open_params_type& params)
139                         {
140                                 handler_type handler = create(params);
141                                 
142                                 addr ai(params.host, params.port, params.af, params.type);
143                                 nozero_assert(
144                                         ::connect(handler, ai->ai_addr, ai->ai_addrlen),
145                                         "roast::socket::connect() ::connect() function was error.");
146                                 return handler;
147                         }
148                         
149                         static void close(handler_type handler)
150                         {
151                                 nozero_assert(
152                                         ::closesocket(handler),
153                                         "roast::unix::socket::close() ::closesocket() function was error.");
154                         }
155                         
156                         void shutdown(handler_type handler, int how=3)
157                         {
158                                 nozero_assert(
159                                         ::shutdown(handler, how),
160                                         "roast::unix::socket::close() ::closesocket() function was error.");
161                         }
162                         
163                         void listen(handler_type handler, int max_queueing=SOMAXCONN)
164                         {
165                                 nozero_assert(
166                                         ::listen(handler, max_queueing),
167                                         "roast::unix::socket::listen() ::listen() function was error.");
168                         }
169                         
170                         handler_type accept(handler_type handler, ::sockaddr* addr_out=NULL, int* len_out=NULL)
171                         {
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;
175                         }
176                         
177                         ///////////////////////////////////////////////////////////////////////////////////////////////
178                         
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);
182                         
183                         static int read(handler_type handler, void* buf, size_t size, int flag)
184                         {
185                                 int ret = ::recv(handler, (char*)buf, size, flag);
186                                 lasterr_assert("roast::unix::socket::read() ::recv() function was error.");
187                                 return ret;
188                         }
189                         static int write(handler_type handler, const void* buf, size_t size, int flag)
190                         {
191                                 int ret = ::send(handler, (const char*)buf, size, flag);
192                                 lasterr_assert("roast::unix::socket::write() ::send() function was error.");
193                                 return ret;
194                         }
195
196                         static int ioctl(handler_type handler, const ioctl_data& data){ return -1; }
197                 };
198                 
199                 const socket_impl::handler_type socket_impl::invalid_handle = INVALID_SOCKET;
200
201                 ////////////////////////////////////////////////////////////////////////////////
202                 /*
203                 class socket : public socket_impl_base
204                 {
205                 private:
206                         bool m_opened;
207                         int m_af;
208                         int m_socket_type;
209                         int m_socket_protocol;
210
211                 public:
212                         socket(int af=AF_INET, int type=SOCK_STREAM, int protocol=0)
213                                 : m_sock(NULL)
214                         {
215                                 m_cleanup.add();
216                                 m_opened = false;
217                                 m_owner = true;
218
219                                 m_af = af;
220                                 m_socket_type = type;
221                                 m_socket_protocol = protocol;
222
223                                 m_sock = ::socket(af, type, protocol);
224
225                                 nozero_assert(errno, "roast::socket::socket() ::socket() function was error.");
226
227                                 if ( m_sock == INVALID_SOCKET )
228                                         throw socket_exception(errno, "roast::socket::socket() m_sock is INVALID_SOCKET.");
229                         }
230
231
232                         //////////////////////////////////////////////////////////////////
233
234                         void connect(const char* host, int port)
235                         {
236                                 //      Already Socket was Close...?
237                                 //close();
238
239                                 if ( m_sock != INVALID_SOCKET && m_opened )
240                                         throw socket_exception(errno, "roast::socket::connect() Socket was already opened.");
241                                 
242                                 ::addrinfo hints;
243                                 ::memset(&hints, 0, sizeof(hints));
244                                 hints.ai_socktype = m_socket_type;
245                                 hints.ai_family = m_af;
246
247 #pragma warning(disable: 4996)
248                                 char port_str[12];
249                                 sprintf(port_str, "%d", port);
250 #pragma warning(default: 4996)
251
252                                 ::addrinfo *addr=NULL;
253                                 nozero_assert(
254                                         ::getaddrinfo(host, port_str, &hints, &addr),
255                                         "roast::socket::connect() ::getaddrinfo() function was error.");
256
257                                 try
258                                 {
259                                         nozero_assert(
260                                                 ::connect(m_sock, addr->ai_addr, addr->ai_addrlen),
261                                                 "roast::socket::connect() ::connect() function was error.");
262                                 }
263                                 catch(const socket_exception& e){
264                                         ::freeaddrinfo(addr);
265                                         throw e;
266                                 }
267
268                                 m_opened = true;
269                                 ::freeaddrinfo(addr);
270                         }
271
272                         void bind(int port, const char* host="0.0.0.0")
273                         {
274                                 if ( m_sock != INVALID_SOCKET && m_opened )
275                                         throw socket_exception(errno, "roast::socket::bind() Socket was already binded.");
276                                 
277                                 ::addrinfo hints;
278                                 ::memset(&hints, 0, sizeof(hints));
279                                 hints.ai_socktype = m_socket_type;
280                                 hints.ai_family = m_af;
281
282 #pragma warning(disable: 4996)
283                                 char port_str[12];
284                                 sprintf(port_str, "%d", port);
285 #pragma warning(default: 4996)
286
287                                 ::addrinfo *addr=NULL;
288                                 nozero_assert(
289                                         ::getaddrinfo(host, port_str, &hints, &addr),
290                                         "roast::socket::bind() ::getaddrinfo() function was error.");
291
292                                 try
293                                 {
294                                         nozero_assert(
295                                                 ::bind(m_sock, addr->ai_addr, addr->ai_addrlen),
296                                                 "roast::socket::bind() ::connect() function was error.");
297                                 }
298                                 catch(const socket_exception& e){
299                                         ::freeaddrinfo(addr);
300                                         throw e;
301                                 }
302
303                                 m_opened = true;
304                                 ::freeaddrinfo(addr);
305                         }
306                 };*/
307                 
308                 ////////////////////////////////////////////////////////////////////////////////
309         }
310 }
311
312 #endif//__SFJP_ROAST__unix__socket_impl_HPP__