28 #ifndef _LEVIN_CP_SERVER_H_ 29 #define _LEVIN_CP_SERVER_H_ 35 #include <boost/shared_ptr.hpp> 40 #define ENABLE_PROFILING 45 #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY 46 #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "net" 48 #define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000 55 template<
class TProtocol>
71 enum overlapped_operation_type
80 OVERLAPPED m_overlapped;
82 overlapped_operation_type m_op_type;
84 volatile LONG m_is_in_use;
89 PRAGMA_WARNING_DISABLE_VS(4355)
90 template<class TProtocol>
91 struct
connection: public net_utils::i_service_endpoint
93 connection(
typename TProtocol::config_type& ref_config):m_sock(
INVALID_SOCKET), m_tprotocol_handler(
this, ref_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0)
101 connection<TProtocol>&
operator=(
const connection<TProtocol>& obj)
117 if(!::InterlockedCompareExchange(&m_asked_to_shutdown, 1, 0))
119 m_psend_data->m_op_type = op_type_stop;
120 ::PostQueuedCompletionStatus(m_completion_port, 0, (ULONG_PTR)
this, &m_psend_data->m_overlapped);
139 virtual bool handle_send(
const void* ptr,
size_t cb)
142 if(m_psend_data->TotalBuffBytes < cb)
143 resize_send_buff((DWORD)cb);
145 ZeroMemory(&m_psend_data->m_overlapped,
sizeof(OVERLAPPED));
146 m_psend_data->DataBuf.len = (u_long)cb;
147 m_psend_data->DataBuf.buf = m_psend_data->Buffer;
148 memcpy(m_psend_data->DataBuf.buf, ptr, cb);
149 m_psend_data->m_op_type = op_type_send;
150 InterlockedExchange(&m_psend_data->m_is_in_use, 1);
151 DWORD bytes_sent = 0;
156 res = ::WSASend(m_sock, &(m_psend_data->DataBuf), 1, &bytes_sent, flags, &(m_psend_data->m_overlapped), NULL);
159 if(
res == SOCKET_ERROR )
161 int err = ::WSAGetLastError();
162 if(WSA_IO_PENDING == err )
165 LOG_ERROR(
"BIG FAIL: WSASend error code not correct, res=" <<
res <<
" last_err=" << err);
166 ::InterlockedExchange(&m_psend_data->m_is_in_use, 0);
172 ::InterlockedExchange(&m_psend_data->m_is_in_use, 0);
173 if(!bytes_sent || bytes_sent != cb)
175 int err = ::WSAGetLastError();
176 LOG_ERROR(
"BIG FAIL: WSASend immediatly complete? but bad results, res=" <<
res <<
" last_err=" << err);
187 bool resize_send_buff(DWORD new_size)
189 if(m_psend_data->TotalBuffBytes >= new_size)
193 m_psend_data = (io_data_base*)
new char[
sizeof(io_data_base) + new_size-1];
194 m_psend_data->TotalBuffBytes = new_size;
195 LOG_PRINT(
"Connection buffer resized up to " << new_size, LOG_LEVEL_3);
202 TProtocol m_tprotocol_handler;
203 typename TProtocol::config_type m_dummy_config;
204 io_data_base* m_precv_data;
205 io_data_base* m_psend_data;
206 HANDLE m_completion_port;
207 volatile LONG m_asked_to_shutdown;
208 volatile LONG m_connection_shutwoned;
213 static unsigned CALLBACK worker_thread(
void* param);
233 #include "abstract_tcp_server_cp.inl" 236 #endif //_LEVIN_SERVER_H_
bool add_new_connection(SOCKET new_sock, long ip_from, int port_from)
virtual bool handle_send(const void *ptr, size_t cb)
#define LEVIN_DEFAULT_DATA_BUFF_SIZE
bool run_server(int threads_count=0)
connection(typename TProtocol::config_type &ref_config)
connections_container m_connections
PRAGMA_WARNING_POP bool worker_thread_member()
std::map< SOCKET, boost::shared_ptr< connection< TProtocol > > > connections_container
critical_section m_connections_lock
bool shutdown_connection(connection< TProtocol > *pconn)
virtual bool on_net_idle()
TProtocol::config_type & get_config_object()
volatile LONG m_worker_thread_counter
bool init_server(int port_no)
void * memcpy(void *a, const void *b, size_t c)
virtual ~cp_server_impl()
TProtocol::config_type m_config
connection< TProtocol > & operator=(const connection< TProtocol > &obj)
size_t get_active_connections_num()