/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_long_t tb_aioo_rtor_select_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout) { // check tb_assert_and_check_return_val(sock, -1); // fd tb_long_t fd = tb_sock2fd(sock); tb_assert_and_check_return_val(fd >= 0, -1); // init time struct timeval t = {0}; if (timeout > 0) { #ifdef TB_CONFIG_OS_WINDOWS t.tv_sec = (LONG)(timeout / 1000); #else t.tv_sec = (timeout / 1000); #endif t.tv_usec = (timeout % 1000) * 1000; } // init fds fd_set rfds; fd_set wfds; fd_set* prfds = (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT)? &rfds : tb_null; fd_set* pwfds = (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN)? &wfds : tb_null; if (prfds) { FD_ZERO(prfds); FD_SET(fd, prfds); } if (pwfds) { FD_ZERO(pwfds); FD_SET(fd, pwfds); } // select #ifdef TB_CONFIG_OS_WINDOWS tb_long_t r = tb_ws2_32()->select((tb_int_t)fd + 1, prfds, pwfds, tb_null, timeout >= 0? &t : tb_null); #else tb_long_t r = select(fd + 1, prfds, pwfds, tb_null, timeout >= 0? &t : tb_null); #endif tb_assert_and_check_return_val(r >= 0, -1); // timeout? tb_check_return_val(r, 0); // error? tb_int_t o = 0; #ifdef TB_CONFIG_OS_WINDOWS tb_int_t n = sizeof(tb_int_t); tb_ws2_32()->getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n); #else socklen_t n = sizeof(socklen_t); getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n); #endif if (o) return -1; // ok tb_long_t e = 0; if (prfds && FD_ISSET(fd, &rfds)) { e |= TB_AIOE_CODE_RECV; if (code & TB_AIOE_CODE_ACPT) e |= TB_AIOE_CODE_ACPT; } if (pwfds && FD_ISSET(fd, &wfds)) { e |= TB_AIOE_CODE_SEND; if (code & TB_AIOE_CODE_CONN) e |= TB_AIOE_CODE_CONN; } return e; }
static tb_long_t tb_aiop_rtor_select_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) { // check tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor; tb_assert_and_check_return_val(impl && rtor->aiop && list && maxn, -1); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, tb_false); // init time struct timeval t = {0}; if (timeout > 0) { #ifdef TB_CONFIG_OS_WINDOWS t.tv_sec = (LONG)(timeout / 1000); #else t.tv_sec = (timeout / 1000); #endif t.tv_usec = (timeout % 1000) * 1000; } // loop tb_long_t wait = 0; tb_bool_t stop = tb_false; tb_hong_t time = tb_mclock(); while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout)) { // enter tb_spinlock_enter(&impl->lock.pfds); // init fdo tb_size_t sfdm = impl->sfdm; tb_memcpy(&impl->rfdo, &impl->rfdi, sizeof(fd_set)); tb_memcpy(&impl->wfdo, &impl->wfdi, sizeof(fd_set)); // leave tb_spinlock_leave(&impl->lock.pfds); // wait #ifdef TB_CONFIG_OS_WINDOWS tb_long_t sfdn = tb_ws2_32()->select((tb_int_t)sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #else tb_long_t sfdn = select(sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #endif tb_assert_and_check_return_val(sfdn >= 0, -1); // timeout? tb_check_return_val(sfdn, 0); // enter tb_spinlock_enter(&impl->lock.hash); // sync tb_size_t itor = tb_iterator_head(impl->hash); tb_size_t tail = tb_iterator_tail(impl->hash); for (; itor != tail && wait >= 0 && (tb_size_t)wait < maxn; itor = tb_iterator_next(impl->hash, itor)) { tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)tb_iterator_item(impl->hash, itor); if (item) { // the sock tb_socket_ref_t sock = (tb_socket_ref_t)item->name; tb_assert_and_check_return_val(sock, -1); // spak? if (sock == aiop->spak[1] && FD_ISSET(((tb_long_t)aiop->spak[1] - 1), &impl->rfdo)) { // read spak tb_char_t spak = '\0'; if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) wait = -1; // killed? if (spak == 'k') wait = -1; tb_check_break(wait >= 0); // stop to wait stop = tb_true; // continue it continue ; } // filter spak tb_check_continue(sock != aiop->spak[1]); // the fd tb_long_t fd = (tb_long_t)item->name - 1; // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)item->data; tb_assert_and_check_return_val(aioo && aioo->sock == sock, -1); // init aioe tb_aioe_t aioe = {0}; aioe.priv = aioo->priv; aioe.aioo = (tb_aioo_ref_t)aioo; if (FD_ISSET(fd, &impl->rfdo)) { aioe.code |= TB_AIOE_CODE_RECV; if (aioo->code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT; } if (FD_ISSET(fd, &impl->wfdo)) { aioe.code |= TB_AIOE_CODE_SEND; if (aioo->code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN; } // ok? if (aioe.code) { // save aioe list[wait++] = aioe; // oneshot? clear it if (aioo->code & TB_AIOE_CODE_ONESHOT) { // clear aioo aioo->code = TB_AIOE_CODE_NONE; aioo->priv = tb_null; // clear events tb_spinlock_enter(&impl->lock.pfds); FD_CLR(fd, &impl->rfdi); FD_CLR(fd, &impl->wfdi); tb_spinlock_leave(&impl->lock.pfds); } } } } // leave tb_spinlock_leave(&impl->lock.hash); } // ok return wait; }
tb_bool_t tb_hostname(tb_char_t* name, tb_size_t size) { return !tb_ws2_32()->gethostname(name, (DWORD)size)? tb_true : tb_false; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_bool_t tb_mswsock_instance_init(tb_handle_t instance) { // check tb_mswsock_ref_t mswsock = (tb_mswsock_ref_t)instance; tb_assert_and_check_return_val(mswsock, tb_false); // done tb_socket_ref_t sock = tb_null; do { // init sock sock = tb_socket_init(TB_SOCKET_TYPE_TCP); tb_assert_and_check_break(sock); // init AcceptEx DWORD AcceptEx_real = 0; GUID AcceptEx_guid = TB_MSWSOCK_WSAID_ACCEPTEX; tb_ws2_32()->WSAIoctl( (SOCKET)sock - 1 , SIO_GET_EXTENSION_FUNCTION_POINTER , &AcceptEx_guid , sizeof(GUID) , &mswsock->AcceptEx , sizeof(tb_mswsock_AcceptEx_t) , &AcceptEx_real , tb_null , tb_null); // init ConnectEx DWORD ConnectEx_real = 0; GUID ConnectEx_guid = TB_MSWSOCK_WSAID_CONNECTEX; tb_ws2_32()->WSAIoctl( (SOCKET)sock - 1 , SIO_GET_EXTENSION_FUNCTION_POINTER , &ConnectEx_guid , sizeof(GUID) , &mswsock->ConnectEx , sizeof(tb_mswsock_ConnectEx_t) , &ConnectEx_real , tb_null , tb_null); // init DisconnectEx DWORD DisconnectEx_real = 0; GUID DisconnectEx_guid = TB_MSWSOCK_WSAID_DISCONNECTEX; tb_ws2_32()->WSAIoctl( (SOCKET)sock - 1 , SIO_GET_EXTENSION_FUNCTION_POINTER , &DisconnectEx_guid , sizeof(GUID) , &mswsock->DisconnectEx , sizeof(tb_mswsock_DisconnectEx_t) , &DisconnectEx_real , tb_null , tb_null); // init TransmitFile DWORD TransmitFile_real = 0; GUID TransmitFile_guid = TB_MSWSOCK_WSAID_TRANSMITFILE; tb_ws2_32()->WSAIoctl( (SOCKET)sock - 1 , SIO_GET_EXTENSION_FUNCTION_POINTER , &TransmitFile_guid , sizeof(GUID) , &mswsock->TransmitFile , sizeof(tb_mswsock_TransmitFile_t) , &TransmitFile_real , tb_null , tb_null); // init GetAcceptExSockaddrs DWORD GetAcceptExSockaddrs_real = 0; GUID GetAcceptExSockaddrs_guid = TB_MSWSOCK_WSAID_GETACCEPTEXSOCKADDRS; tb_ws2_32()->WSAIoctl( (SOCKET)sock - 1 , SIO_GET_EXTENSION_FUNCTION_POINTER , &GetAcceptExSockaddrs_guid , sizeof(GUID) , &mswsock->GetAcceptExSockaddrs , sizeof(tb_mswsock_GetAcceptExSockaddrs_t) , &GetAcceptExSockaddrs_real , tb_null , tb_null); } while (0); // exit sock if (sock) tb_socket_exit(sock); // ok return tb_true; }