29 #ifndef _ABSTRACT_TCP_SERVER_H_ 30 #define _ABSTRACT_TCP_SERVER_H_ 39 #pragma comment(lib, "Ws2_32.lib") 41 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY 42 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "net" 56 virtual bool handle_send(
const void* ptr,
size_t cb)
58 if(cb !=
send(m_sock, (
char*)ptr, (
int)cb, 0))
60 int sock_err = WSAGetLastError();
61 LOG_ERROR(
"soket_sender: Failed to send " << cb <<
" bytes, Error=" << sock_err);
76 template<
class THandler>
90 bool invoke_connection(
SOCKET hnew_sock,
long ip_from,
int post_from);
91 static unsigned __stdcall ConnectionHandlerProc(
void* lpParameter);
95 typedef typename connections_container::iterator connections_iterator;
102 connection_context m_context;
103 typename connections_iterator m_self_it;
109 volatile LONG m_stop_server;
110 volatile LONG m_threads_count;
111 typename THandler::config_type m_config;
112 connections_container m_connections;
116 template<
class THandler>
117 unsigned __stdcall abstract_tcp_server<THandler>::ConnectionHandlerProc(
void* lpParameter)
120 thread_context* pthread_context = (thread_context*)lpParameter;
123 abstract_tcp_server<THandler>* pthis = pthread_context->powner;
125 ::InterlockedIncrement(&pthis->m_threads_count);
127 ::CoInitialize(NULL);
130 LOG_PRINT(
"Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2);
133 soket_sender sndr(pthread_context->m_socket);
134 THandler srv(&sndr, pthread_context->powner->m_config, pthread_context->m_context);
137 srv.after_init_connection();
139 char buff[1000] = {0};
141 while ( (
res = recv(pthread_context->m_socket, (
char*)buff, 1000, 0)) > 0)
143 LOG_PRINT(
"Data in, " <<
res <<
" bytes", LOG_LEVEL_3);
144 if(!srv.handle_recv(buff,
res))
147 shutdown(pthread_context->m_socket, SD_BOTH);
148 closesocket(pthread_context->m_socket);
150 abstract_tcp_server* powner = pthread_context->powner;
151 LOG_PRINT(
"Handler thread with socket=" << pthread_context->m_socket <<
" STOPPED", LOG_LEVEL_2);
152 powner->m_connections_lock.lock();
153 ::CloseHandle(pthread_context->m_htread);
154 pthread_context->powner->m_connections.erase(pthread_context->m_self_it);
155 powner->m_connections_lock.unlock();
157 ::InterlockedDecrement(&pthis->m_threads_count);
161 template<
class THandler>
164 m_stop_server(0),
m_port(0), m_threads_count(0)
170 template<
class THandler>
175 int err = ::WSAStartup(MAKEWORD(2,2), &wsad);
176 if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 )
178 LOG_ERROR(
"Could not find a usable WinSock DLL, err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"");
184 m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
187 err = ::WSAGetLastError();
188 LOG_ERROR(
"Failed to create socket, err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"");
193 setsockopt (
m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast<char*>(&opt),
sizeof(
int));
195 sockaddr_in adr = {0};
196 adr.sin_family = AF_INET;
197 adr.sin_addr.s_addr = htonl(INADDR_ANY);
198 adr.sin_port = (u_short)htons(port_no);
201 if(SOCKET_ERROR == err )
203 err = ::WSAGetLastError();
204 LOG_PRINT(
"Failed to Bind, err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"", LOG_LEVEL_2);
209 ::InterlockedExchange(&m_stop_server, 0);
214 template<
class THandler>
225 if(SOCKET_ERROR ==
res)
227 int err = ::WSAGetLastError();
228 LOG_ERROR(
"Failed to closesocket(), err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"");
233 int res = ::WSACleanup();
234 if(SOCKET_ERROR ==
res)
236 int err = ::WSAGetLastError();
237 LOG_ERROR(
"Failed to WSACleanup(), err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"");
244 template<
class THandler>
247 InterlockedExchange(&m_stop_server, 1);
251 template<
class THandler>
255 if(SOCKET_ERROR == err )
257 err = ::WSAGetLastError();
258 LOG_ERROR(
"Failed to listen, err = " << err <<
" \"" << socket_errors::get_socket_error_text(err) <<
"\"");
262 LOG_PRINT(
"Listening port "<<
m_port <<
"...." , LOG_LEVEL_2);
264 while(!m_stop_server)
266 sockaddr_in adr_from = {0};
267 int adr_len =
sizeof(adr_from);
268 fd_set read_fs = {0};
269 read_fs.fd_count = 1;
273 int select_res = select(0, &read_fs, NULL, NULL, &tv);
277 LOG_PRINT(
"Accepted connection on socket=" << new_sock, LOG_LEVEL_2);
278 invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port);
283 #define ABSTR_TCP_SRV_WAIT_COUNT_MAX 5000 284 #define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL 1000 298 template<
class THandler>
307 m_connections.back().m_context.m_remote_address = remote_address;
318 #endif //_ABSTRACT_TCP_SERVER_H_
connections_container m_connections
bool init_server(int port_no)
std::map< SOCKET, boost::shared_ptr< connection< TProtocol > > > connections_container
critical_section m_connections_lock
THandler::config_type & get_config_object()
soket_sender(SOCKET sock)
#define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL
#define ABSTR_TCP_SRV_WAIT_COUNT_MAX
expect< void > send(const epee::span< const std::uint8_t > payload, void *const socket, const int flags) noexcept