00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _terimber_aiosock_h_
00029 #define _terimber_aiosock_h_
00030
00031 #include "base/primitives.h"
00032 #include "base/stack.h"
00033 #include "base/list.h"
00034 #include "base/map.h"
00035 #include "threadpool/threadpool.h"
00036 #include "threadpool/thread.h"
00037 #include "aiosock/aiosockfactory.h"
00038 #include "aiocomport/aiocomport.h"
00039
00040 BEGIN_TERIMBER_NAMESPACE
00041
00042 #pragma pack(4)
00043
00046 class aiosock_block : public OVERLAPPED
00047 {
00048 public:
00050 aiosock_block();
00052 aiosock_block(const aiosock_block& x);
00054 aiosock_block& operator=(const aiosock_block& x);
00055
00057 void
00058 clear();
00060 void
00061 settimeout( size_t timeout
00062 );
00063
00064 public:
00065 aiosock_type _type;
00066 char* _buf;
00067 size_t _len;
00068 size_t _socket_ident;
00069 size_t _processed;
00070 int _err;
00071 void* _userdata;
00072 size_t _accept_ident;
00073 size_t _flags;
00074 ub1_t _accept_buf[2*(sizeof(struct sockaddr_in) + 16)];
00075 sockaddr_in _address;
00076 #if OS_TYPE == OS_WIN32
00077 size_t
00078 #else
00079 timeval
00080 #endif
00081 _timeout;
00082 sb8_t _expired;
00083 };
00084
00087 typedef SOCKET aio_sock_handle;
00088
00091 class aiosock : public terimber_thread_employer,
00092 public terimber_aiosock
00093 {
00096 typedef node_allocator< base_list< aiosock_block* >::_node > aiosock_pblock_allocator_t;
00099 typedef _list< aiosock_block*, aiosock_pblock_allocator_t > aiosock_pblock_alloc_list_t;
00102 typedef list< aiosock_block* > aiosock_pblock_list_t;
00105 typedef node_allocator< aiosock_block > aiosock_block_allocator_t;
00106
00109 class listener_info
00110 {
00111 public:
00113 listener_info( size_t curr_count,
00114 size_t max_count,
00115 void* userdata
00116 ) :
00117 _curr_count(curr_count),
00118 _max_count(max_count),
00119 _userdata(userdata)
00120 {
00121 }
00122 size_t _curr_count;
00123 size_t _max_count;
00124 void* _userdata;
00125 };
00126
00129 typedef map< size_t, listener_info > aiosock_listener_map_t;
00130
00133 class aiosock_socket
00134 {
00135 public:
00137 aiosock_socket(bool tcp_udp,
00138 aio_sock_handle handle,
00139 terimber_aiosock_callback* callback
00140
00141 ) : _handle(handle), _client_obj(callback), _callback_invoking(0), _tcp_udp(tcp_udp)
00142 {
00143 }
00145 aiosock_socket(const aiosock_socket& x) : _handle(x._handle), _client_obj(x._client_obj), _callback_invoking(x._callback_invoking), _tcp_udp(x._tcp_udp) {}
00147 ~aiosock_socket()
00148 {
00149 assert(_incoming_list.empty());
00150 }
00151
00152
00153
00154 aio_sock_handle _handle;
00155 terimber_aiosock_callback* _client_obj;
00156 aiosock_pblock_alloc_list_t _incoming_list;
00157 size_t _callback_invoking;
00158 bool _tcp_udp;
00159 };
00160
00163 typedef map< size_t, aiosock_socket > aiosock_socket_map_t;
00166 typedef map< size_t, aiosock_socket >::iterator aiosock_socket_map_iterator_t;
00169 typedef map< aio_sock_handle, aiosock_socket_map_iterator_t > aiosock_reverse_map_t;
00172 typedef map< aio_sock_handle, aiosock_socket_map_iterator_t >::iterator aiosock_reverse_map_iterator_t;
00175 typedef map< size_t, size_t > aiosock_delay_key_t;
00176
00178 void
00179 _clear_block_lists()
00180 {
00181 if (!_outgoing_list.empty())
00182 {
00183 for (aiosock_pblock_list_t::iterator out_iter = _outgoing_list.begin(); out_iter != _outgoing_list.end(); ++out_iter)
00184 {
00185 aiosock_block* block = *out_iter;
00186 _put_block(block);
00187 }
00188
00189 _outgoing_list.clear();
00190 }
00191
00192 #if OS_TYPE == OS_WIN32
00193
00194 if (!_abounded_list.empty())
00195 {
00196 for (aiosock_pblock_list_t::iterator tm_iter = _abounded_list.begin(); tm_iter != _abounded_list.end(); ++tm_iter)
00197 {
00198 aiosock_block* block = *tm_iter;
00199 _put_block(block);
00200 }
00201
00202 _abounded_list.clear();
00203 }
00204
00205 #endif
00206 if (!_initial_list.empty())
00207 {
00208 for (aiosock_pblock_list_t::iterator in_iter = _initial_list.begin(); in_iter != _initial_list.end(); ++in_iter)
00209 {
00210 aiosock_block* block = *in_iter;
00211 _put_block(block);
00212 }
00213
00214 _initial_list.clear();
00215 }
00216 }
00217
00219 inline
00220 aiosock_block*
00221 _get_block()
00222 {
00223 aiosock_block* ptr = _block_allocator.allocate();
00224 if (ptr)
00225 {
00226 new(ptr) aiosock_block();
00227 }
00228
00229 return ptr;
00230 }
00231
00233 inline
00234 void
00235 _put_block(aiosock_block* block)
00236 {
00237 block->~aiosock_block();
00238 _block_allocator.deallocate(block);
00239 }
00240
00241
00242 public:
00244 aiosock(size_t capacity,
00245 size_t deactivate_time_msec
00246 );
00248 ~aiosock();
00249
00251 bool
00252 on();
00254 void
00255 off();
00256
00258 virtual
00259 size_t
00260 create( terimber_aiosock_callback* callback,
00261 bool tcp_udp
00262 );
00264 virtual
00265 void
00266 close( size_t ident
00267 );
00269 virtual
00270 int
00271 send( size_t ident,
00272 const void* buf,
00273 size_t len,
00274 size_t timeout,
00275 const sockaddr_in* toaddr,
00276 void* userdata
00277 );
00279 virtual
00280 int
00281 receive(size_t ident,
00282 void* buf,
00283 size_t len,
00284 size_t timeout,
00285 const sockaddr_in* fromaddr,
00286 void* userdata
00287 );
00289 virtual
00290 int
00291 connect(size_t ident,
00292 const char* address,
00293 unsigned short port,
00294 size_t timeout,
00295 void* userdata
00296 );
00298 virtual
00299 int
00300 listen( size_t ident,
00301 unsigned short port,
00302 size_t max_connection,
00303 const char* address,
00304 unsigned short accept_pool,
00305 void* userdata
00306 );
00307
00309 virtual
00310 int
00311 bind( size_t ident,
00312 const char* address,
00313 unsigned short port
00314 );
00315
00317 virtual
00318 int
00319 getpeeraddr(size_t ident,
00320 sockaddr_in& addr
00321 );
00323 virtual
00324 int
00325 getsockaddr(size_t ident,
00326 sockaddr_in& addr
00327 );
00328
00330 virtual
00331 bool
00332 get_error_description(
00333 int err,
00334 char* buf,
00335 size_t len
00336 ) const
00337 {
00338 return resolve_sock_error_code(err, buf, len);
00339 }
00340
00342 virtual
00343 void
00344 doxray();
00345
00347 static
00348 bool
00349 resolve_sock_error_code(
00350 int err,
00351 char* buf,
00352 size_t len
00353 );
00354 protected:
00356 virtual
00357 bool
00358 v_has_job( size_t ident,
00359 void* data
00360 );
00362 virtual
00363 void
00364 v_do_job( size_t ident,
00365 void* data
00366 );
00367
00368 private:
00370 bool
00371 resolve_socket_address(const char* address,
00372 unsigned short port,
00373 sockaddr_in& addr
00374 );
00375
00377 aio_sock_handle
00378 find_socket_handle( size_t ident
00379 );
00380
00382 void
00383 process_timeouted_blocks();
00384
00386 bool
00387 process_accept_blocks();
00388
00390 void
00391 complete_block( size_t sock_key,
00392 aiosock_block* ov,
00393 int err,
00394 size_t processed
00395 );
00396
00398 int
00399 _activate_block( size_t ident,
00400 aiosock_block* block,
00401 const sockaddr_in* pddr
00402 );
00403
00405 void
00406 _cancel_socket( aio_sock_handle handle
00407 );
00408
00409 #if OS_TYPE != OS_WIN32
00410
00412 void
00413 _cancel_aio( aio_sock_handle handle,
00414 OVERLAPPED* overlapped
00415 );
00416 #endif
00417
00419 size_t
00420 _assign_socket( aio_sock_handle handle,
00421 terimber_aiosock_callback* callback,
00422 bool tcp_udp
00423 );
00424
00426 void
00427 _close_socket( aio_sock_handle handle,
00428 bool tcp_udp
00429 );
00430
00431
00433 int
00434 _process_block( aiosock_block* block
00435 );
00436
00437
00439 int
00440 _process_connect( aio_sock_handle handle,
00441 aiosock_block* block
00442 );
00444 int
00445 _process_accept( aio_sock_handle handle,
00446 terimber_aiosock_callback* client,
00447 aiosock_block* block
00448 );
00450 int
00451 _process_send( aio_sock_handle handle,
00452 aiosock_block* block,
00453 bool tcp_udp
00454 );
00456 int
00457 _process_recv( aio_sock_handle handle,
00458 aiosock_block* block,
00459 bool tcp_udp
00460 );
00461
00463 void
00464 wait_for_io_completion();
00465
00466 public:
00467
00468 mutex _mtx;
00469 aiosock_socket_map_t _socket_map;
00470 aiosock_reverse_map_t _reverse_map;
00471 aiosock_listener_map_t _listeners_map;
00472 aiosock_delay_key_t _delay_key_map;
00473 unique_key_generator _socket_generator;
00474 aiosock_pblock_allocator_t _incoming_list_allocator;
00475 aiosock_block_allocator_t _block_allocator;
00476 aiosock_pblock_list_t _initial_list;
00477 aiosock_pblock_list_t _outgoing_list;
00478
00479 #if OS_TYPE == OS_WIN32
00480 aiosock_pblock_list_t _abounded_list;
00481 #endif
00482
00483 private:
00484 HANDLE _aiosock_io_handle;
00485 threadpool _thread_pool;
00486 size_t _capacity;
00487 thread _in_thread;
00488 static bool _port_init;
00489 bool _on;
00490 bool _flag_io_port;
00491 event _start_io_port;
00492 event _stop_io_port;
00493 };
00494
00495
00496
00497 #pragma pack()
00498 END_TERIMBER_NAMESPACE
00499
00500 #endif // _terimber_aioport_h_