Boring Old Deletes

Here lies dozens of unused files. This commit is ONLY file deletions except
for the removing of a couple of #includes and removing filenames from CmakeLists
where appropriate.
This commit is contained in:
Jeffrey 2022-03-07 17:49:11 -06:00
parent 6694597974
commit 690ce560b0
71 changed files with 0 additions and 9678 deletions

View file

@ -1,318 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _ABSTRACT_TCP_SERVER_H_
#define _ABSTRACT_TCP_SERVER_H_
#include <process.h>
#include <list>
#include <winsock2.h>
#include "winobj.h"
//#include "threads_helper.h"
#include "net_utils_base.h"
#pragma comment(lib, "Ws2_32.lib")
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace net_utils
{
/************************************************************************/
/* */
/************************************************************************/
class soket_sender: public i_service_endpoint
{
public:
soket_sender(SOCKET sock):m_sock(sock){}
private:
virtual bool handle_send(const void* ptr, size_t cb)
{
if(cb != send(m_sock, (char*)ptr, (int)cb, 0))
{
int sock_err = WSAGetLastError();
LOG_ERROR("soket_sender: Failed to send " << cb << " bytes, Error=" << sock_err);
return false;
}
return true;
}
SOCKET m_sock;
};
/************************************************************************/
/* */
/************************************************************************/
template<class THandler>
class abstract_tcp_server
{
public:
abstract_tcp_server();
bool init_server(int port_no);
bool deinit_server();
bool run_server();
bool send_stop_signal();
typename THandler::config_type& get_config_object(){return m_config;}
private:
bool invoke_connection(SOCKET hnew_sock, long ip_from, int post_from);
static unsigned __stdcall ConnectionHandlerProc(void* lpParameter);
class thread_context;
typedef std::list<thread_context> connections_container;
typedef typename connections_container::iterator connections_iterator;
struct thread_context
{
HANDLE m_htread;
SOCKET m_socket;
abstract_tcp_server* powner;
connection_context m_context;
typename connections_iterator m_self_it;
};
SOCKET m_listen_socket;
int m_port;
bool m_initialized;
volatile LONG m_stop_server;
volatile LONG m_threads_count;
typename THandler::config_type m_config;
connections_container m_connections;
critical_section m_connections_lock;
};
template<class THandler>
unsigned __stdcall abstract_tcp_server<THandler>::ConnectionHandlerProc(void* lpParameter)
{
thread_context* pthread_context = (thread_context*)lpParameter;
if(!pthread_context)
return 0;
abstract_tcp_server<THandler>* pthis = pthread_context->powner;
::InterlockedIncrement(&pthis->m_threads_count);
::CoInitialize(NULL);
LOG_PRINT("Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2);
int res = 0;
soket_sender sndr(pthread_context->m_socket);
THandler srv(&sndr, pthread_context->powner->m_config, pthread_context->m_context);
srv.after_init_connection();
char buff[1000] = {0};
std::string ansver;
while ( (res = recv(pthread_context->m_socket, (char*)buff, 1000, 0)) > 0)
{
LOG_PRINT("Data in, " << res << " bytes", LOG_LEVEL_3);
if(!srv.handle_recv(buff, res))
break;
}
shutdown(pthread_context->m_socket, SD_BOTH);
closesocket(pthread_context->m_socket);
abstract_tcp_server* powner = pthread_context->powner;
LOG_PRINT("Handler thread with socket=" << pthread_context->m_socket << " STOPPED", LOG_LEVEL_2);
powner->m_connections_lock.lock();
::CloseHandle(pthread_context->m_htread);
pthread_context->powner->m_connections.erase(pthread_context->m_self_it);
powner->m_connections_lock.unlock();
CoUninitialize();
::InterlockedDecrement(&pthis->m_threads_count);
return 1;
}
//----------------------------------------------------------------------------------------
template<class THandler>
abstract_tcp_server<THandler>::abstract_tcp_server():m_listen_socket(INVALID_SOCKET),
m_initialized(false),
m_stop_server(0), m_port(0), m_threads_count(0)
{
}
//----------------------------------------------------------------------------------------
template<class THandler>
bool abstract_tcp_server<THandler>::init_server(int port_no)
{
m_port = port_no;
WSADATA wsad = {0};
int err = ::WSAStartup(MAKEWORD(2,2), &wsad);
if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 )
{
LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
m_initialized = true;
m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if(INVALID_SOCKET == m_listen_socket)
{
err = ::WSAGetLastError();
LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
int opt = 1;
setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(int));
sockaddr_in adr = {0};
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = (u_short)htons(port_no);
err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr ));
if(SOCKET_ERROR == err )
{
err = ::WSAGetLastError();
LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2);
deinit_server();
return false;
}
::InterlockedExchange(&m_stop_server, 0);
return true;
}
//----------------------------------------------------------------------------------------
template<class THandler>
bool abstract_tcp_server<THandler>::deinit_server()
{
if(!m_initialized)
return true;
if(INVALID_SOCKET != m_listen_socket)
{
shutdown(m_listen_socket, SD_BOTH);
int res = closesocket(m_listen_socket);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
}
m_listen_socket = INVALID_SOCKET;
}
int res = ::WSACleanup();
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
}
m_initialized = false;
return true;
}
//----------------------------------------------------------------------------------------
template<class THandler>
bool abstract_tcp_server<THandler>::send_stop_signal()
{
InterlockedExchange(&m_stop_server, 1);
return true;
}
//----------------------------------------------------------------------------------------
template<class THandler>
bool abstract_tcp_server<THandler>::run_server()
{
int err = listen(m_listen_socket, 10000);
if(SOCKET_ERROR == err )
{
err = ::WSAGetLastError();
LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
LOG_PRINT("Listening port "<< m_port << "...." , LOG_LEVEL_2);
while(!m_stop_server)
{
sockaddr_in adr_from = {0};
int adr_len = sizeof(adr_from);
fd_set read_fs = {0};
read_fs.fd_count = 1;
read_fs.fd_array[0] = m_listen_socket;
TIMEVAL tv = {0};
tv.tv_usec = 100;
int select_res = select(0, &read_fs, NULL, NULL, &tv);
if(!select_res)
continue;
SOCKET new_sock = WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, NULL, NULL);
LOG_PRINT("Accepted connection on socket=" << new_sock, LOG_LEVEL_2);
invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port);
}
deinit_server();
#define ABSTR_TCP_SRV_WAIT_COUNT_MAX 5000
#define ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL 1000
int wait_count = 0;
while(m_threads_count && wait_count*1000 < ABSTR_TCP_SRV_WAIT_COUNT_MAX)
{
::Sleep(ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL);
wait_count++;
}
LOG_PRINT("abstract_tcp_server exit with wait count=" << wait_count*ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL << "(max=" << ABSTR_TCP_SRV_WAIT_COUNT_MAX <<")", LOG_LEVEL_0);
return true;
}
//----------------------------------------------------------------------------------------
template<class THandler>
bool abstract_tcp_server<THandler>::invoke_connection(SOCKET hnew_sock, const network_address &remote_address)
{
m_connections_lock.lock();
m_connections.push_back(thread_context());
m_connections_lock.unlock();
m_connections.back().m_socket = hnew_sock;
m_connections.back().powner = this;
m_connections.back().m_self_it = --m_connections.end();
m_connections.back().m_context.m_remote_address = remote_address;
m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky
return true;
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
}
}
#endif //_ABSTRACT_TCP_SERVER_H_

View file

@ -1,236 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _LEVIN_CP_SERVER_H_
#define _LEVIN_CP_SERVER_H_
#include <winsock2.h>
#include <rpc.h>
#include <string>
#include <map>
#include <boost/shared_ptr.hpp>
#include "misc_log_ex.h"
//#include "threads_helper.h"
#include "syncobj.h"
#define ENABLE_PROFILING
#include "profile_tools.h"
#include "net_utils_base.h"
#include "pragma_comp_defs.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
#define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000
namespace epee
{
namespace net_utils
{
template<class TProtocol>
class cp_server_impl//: public abstract_handler
{
public:
cp_server_impl(/*abstract_handler* phandler = NULL*/);
virtual ~cp_server_impl();
bool init_server(int port_no);
bool deinit_server();
bool run_server(int threads_count = 0);
bool send_stop_signal();
bool is_stop_signal();
virtual bool on_net_idle(){return true;}
size_t get_active_connections_num();
typename TProtocol::config_type& get_config_object(){return m_config;}
private:
enum overlapped_operation_type
{
op_type_recv,
op_type_send,
op_type_stop
};
struct io_data_base
{
OVERLAPPED m_overlapped;
WSABUF DataBuf;
overlapped_operation_type m_op_type;
DWORD TotalBuffBytes;
volatile LONG m_is_in_use;
char Buffer[1];
};
PRAGMA_WARNING_PUSH
PRAGMA_WARNING_DISABLE_VS(4355)
template<class TProtocol>
struct connection: public net_utils::i_service_endpoint
{
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)
{
}
//connection():m_sock(INVALID_SOCKET), m_tprotocol_handler(this, m_dummy_config, context), m_psend_data(NULL), m_precv_data(NULL), m_asked_to_shutdown(0), m_connection_shutwoned(0)
//{
//}
connection<TProtocol>& operator=(const connection<TProtocol>& obj)
{
return *this;
}
bool init_buffers()
{
m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1];
m_psend_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE;
m_precv_data = (io_data_base*)new char[sizeof(io_data_base) + LEVIN_DEFAULT_DATA_BUFF_SIZE-1];
m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE;
return true;
}
bool query_shutdown()
{
if(!::InterlockedCompareExchange(&m_asked_to_shutdown, 1, 0))
{
m_psend_data->m_op_type = op_type_stop;
::PostQueuedCompletionStatus(m_completion_port, 0, (ULONG_PTR)this, &m_psend_data->m_overlapped);
}
return true;
}
//bool set_config(typename TProtocol::config_type& config)
//{
// this->~connection();
// new(this) connection<TProtocol>(config);
// return true;
//}
~connection()
{
if(m_psend_data)
delete m_psend_data;
if(m_precv_data)
delete m_precv_data;
}
virtual bool handle_send(const void* ptr, size_t cb)
{
PROFILE_FUNC("[handle_send]");
if(m_psend_data->TotalBuffBytes < cb)
resize_send_buff((DWORD)cb);
ZeroMemory(&m_psend_data->m_overlapped, sizeof(OVERLAPPED));
m_psend_data->DataBuf.len = (u_long)cb;//m_psend_data->TotalBuffBytes;
m_psend_data->DataBuf.buf = m_psend_data->Buffer;
memcpy(m_psend_data->DataBuf.buf, ptr, cb);
m_psend_data->m_op_type = op_type_send;
InterlockedExchange(&m_psend_data->m_is_in_use, 1);
DWORD bytes_sent = 0;
DWORD flags = 0;
int res = 0;
{
PROFILE_FUNC("[handle_send] ::WSASend");
res = ::WSASend(m_sock, &(m_psend_data->DataBuf), 1, &bytes_sent, flags, &(m_psend_data->m_overlapped), NULL);
}
if(res == SOCKET_ERROR )
{
int err = ::WSAGetLastError();
if(WSA_IO_PENDING == err )
return true;
}
LOG_ERROR("BIG FAIL: WSASend error code not correct, res=" << res << " last_err=" << err);
::InterlockedExchange(&m_psend_data->m_is_in_use, 0);
query_shutdown();
//closesocket(m_psend_data);
return false;
}else if(0 == res)
{
::InterlockedExchange(&m_psend_data->m_is_in_use, 0);
if(!bytes_sent || bytes_sent != cb)
{
int err = ::WSAGetLastError();
LOG_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res=" << res << " last_err=" << err);
query_shutdown();
return false;
}else
{
return true;
}
}
return true;
}
bool resize_send_buff(DWORD new_size)
{
if(m_psend_data->TotalBuffBytes >= new_size)
return true;
delete m_psend_data;
m_psend_data = (io_data_base*)new char[sizeof(io_data_base) + new_size-1];
m_psend_data->TotalBuffBytes = new_size;
LOG_PRINT("Connection buffer resized up to " << new_size, LOG_LEVEL_3);
return true;
}
SOCKET m_sock;
net_utils::connection_context_base context;
TProtocol m_tprotocol_handler;
typename TProtocol::config_type m_dummy_config;
io_data_base* m_precv_data;
io_data_base* m_psend_data;
HANDLE m_completion_port;
volatile LONG m_asked_to_shutdown;
volatile LONG m_connection_shutwoned;
};
PRAGMA_WARNING_POP
bool worker_thread_member();
static unsigned CALLBACK worker_thread(void* param);
bool add_new_connection(SOCKET new_sock, long ip_from, int port_from);
bool shutdown_connection(connection<TProtocol>* pconn);
typedef std::map<SOCKET, boost::shared_ptr<connection<TProtocol> > > connections_container;
SOCKET m_listen_socket;
HANDLE m_completion_port;
connections_container m_connections;
critical_section m_connections_lock;
int m_port;
volatile LONG m_stop;
//abstract_handler* m_phandler;
bool m_initialized;
volatile LONG m_worker_thread_counter;
typename TProtocol::config_type m_config;
};
}
}
#include "abstract_tcp_server_cp.inl"
#endif //_LEVIN_SERVER_H_

View file

@ -1,607 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma comment(lib, "Ws2_32.lib")
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace net_utils
{
template<class TProtocol>
cp_server_impl<TProtocol>::cp_server_impl():
m_port(0), m_stop(false),
m_worker_thread_counter(0), m_listen_socket(INVALID_SOCKET)
{
}
//-------------------------------------------------------------
template<class TProtocol>
cp_server_impl<TProtocol>::~cp_server_impl()
{
deinit_server();
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::init_server(int port_no)
{
m_port = port_no;
WSADATA wsad = {0};
int err = ::WSAStartup(MAKEWORD(2,2), &wsad);
if ( err != 0 || LOBYTE( wsad.wVersion ) != 2 || HIBYTE( wsad.wVersion ) != 2 )
{
LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
m_initialized = true;
m_listen_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == m_listen_socket)
{
err = ::WSAGetLastError();
LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
int opt = 1;
err = setsockopt (m_listen_socket, SOL_SOCKET,SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(int));
if(SOCKET_ERROR == err )
{
err = ::WSAGetLastError();
LOG_PRINT("Failed to setsockopt(SO_REUSEADDR), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1);
deinit_server();
return false;
}
sockaddr_in adr = {0};
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = (u_short)htons(m_port);
//binding
err = bind(m_listen_socket, (const sockaddr*)&adr, sizeof(adr ));
if(SOCKET_ERROR == err )
{
err = ::WSAGetLastError();
LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1);
deinit_server();
return false;
}
m_completion_port = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if(INVALID_HANDLE_VALUE == m_completion_port)
{
err = ::WSAGetLastError();
LOG_PRINT("Failed to CreateIoCompletionPort, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_1);
deinit_server();
return false;
}
return true;
}
//-------------------------------------------------------------
//-------------------------------------------------------------
static int CALLBACK CPConditionFunc(
IN LPWSABUF lpCallerId,
IN LPWSABUF lpCallerData,
IN OUT LPQOS lpSQOS,
IN OUT LPQOS lpGQOS,
IN LPWSABUF lpCalleeId,
OUT LPWSABUF lpCalleeData,
OUT GROUP FAR *g,
IN DWORD_PTR dwCallbackData
)
{
/*cp_server_impl* pthis = (cp_server_impl*)dwCallbackData;
if(!pthis)
return CF_REJECT;*/
/*if(pthis->get_active_connections_num()>=FD_SETSIZE-1)
{
LOG_PRINT("Maximum connections count overfull.", LOG_LEVEL_2);
return CF_REJECT;
}*/
return CF_ACCEPT;
}
//-------------------------------------------------------------
template<class TProtocol>
size_t cp_server_impl<TProtocol>::get_active_connections_num()
{
return m_connections.size();
}
//-------------------------------------------------------------
template<class TProtocol>
unsigned CALLBACK cp_server_impl<TProtocol>::worker_thread(void* param)
{
if(!param)
return 0;
cp_server_impl<TProtocol>* pthis = (cp_server_impl<TProtocol>*)param;
pthis->worker_thread_member();
return 1;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::worker_thread_member()
{
LOG_PRINT("Worker thread STARTED", LOG_LEVEL_1);
bool stop_handling = false;
while(!stop_handling)
{
PROFILE_FUNC("[worker_thread]Worker Loop");
DWORD bytes_transfered = 0;
connection<TProtocol>* pconnection = 0;
io_data_base* pio_data = 0;
{
PROFILE_FUNC("[worker_thread]GetQueuedCompletionStatus");
BOOL res = ::GetQueuedCompletionStatus (m_completion_port, &bytes_transfered , (PULONG_PTR)&pconnection, (LPOVERLAPPED *)&pio_data, INFINITE);
if (res == 0)
{
// check return code for error
int err = GetLastError();
LOG_PRINT("GetQueuedCompletionStatus failed with error " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_1);
if(pio_data)
::InterlockedExchange(&pio_data->m_is_in_use, 0);
continue;
}
}
if(pio_data)
::InterlockedExchange(&pio_data->m_is_in_use, 0);
if(!bytes_transfered && !pconnection && !pio_data)
{
//signal to stop
break;
}
if(!pconnection || !pio_data)
{
LOG_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection=" << pconnection << " pio_data=" << pio_data, LOG_LEVEL_0);
break;
}
if(::InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0))
{
LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)");
//DebugBreak();
}
if(pio_data->m_op_type == op_type_stop)
{
if(!pconnection)
{
LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!");
continue;
}
shutdown_connection(pconnection);
continue;//
}
else if(pio_data->m_op_type == op_type_send)
{
continue;
//do nothing, just queuing request
}else if(pio_data->m_op_type == op_type_recv)
{
PROFILE_FUNC("[worker_thread]m_tprotocol_handler.handle_recv");
if(bytes_transfered)
{
bool res = pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_transfered);
if(!res)
pconnection->query_shutdown();
}
else
{
pconnection->query_shutdown();
continue;
}
}
//preparing new request,
{
PROFILE_FUNC("[worker_thread]RECV Request small loop");
int res = 0;
while(true)
{
LOG_PRINT("Prepearing data for WSARecv....", LOG_LEVEL_3);
ZeroMemory(&pio_data->m_overlapped, sizeof(OVERLAPPED));
pio_data->DataBuf.len = pio_data->TotalBuffBytes;
pio_data->DataBuf.buf = pio_data->Buffer;
pio_data->m_op_type = op_type_recv;
//calling WSARecv() and go to completion waiting
DWORD bytes_recvd = 0;
DWORD flags = 0;
LOG_PRINT("Calling WSARecv....", LOG_LEVEL_3);
::InterlockedExchange(&pio_data->m_is_in_use, 1);
res = WSARecv(pconnection->m_sock, &(pio_data->DataBuf), 1, &bytes_recvd , &flags, &(pio_data->m_overlapped), NULL);
if(res == SOCKET_ERROR )
{
int err = ::WSAGetLastError();
if(WSA_IO_PENDING == err )
{//go pending, ok
LOG_PRINT("WSARecv return WSA_IO_PENDING", LOG_LEVEL_3);
break;
}
LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err);
::InterlockedExchange(&pio_data->m_is_in_use, 0);
pconnection->query_shutdown();
break;
}
break;
/*else if(0 == res)
{
if(!bytes_recvd)
{
::InterlockedExchange(&pio_data->m_is_in_use, 0);
LOG_PRINT("WSARecv return 0, bytes_recvd=0, graceful close.", LOG_LEVEL_3);
int err = ::WSAGetLastError();
//LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err);
//pconnection->query_shutdown();
break;
}else
{
LOG_PRINT("WSARecv return immediatily 0, bytes_recvd=" << bytes_recvd, LOG_LEVEL_3);
//pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd);
}
}*/
}
}
}
LOG_PRINT("Worker thread STOPED", LOG_LEVEL_1);
::InterlockedDecrement(&m_worker_thread_counter);
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::shutdown_connection(connection<TProtocol>* pconn)
{
PROFILE_FUNC("[shutdown_connection]");
if(!pconn)
{
LOG_ERROR("Attempt to remove null pptr connection!");
return false;
}
else
{
LOG_PRINT("Shutting down connection ("<< pconn << ")", LOG_LEVEL_3);
}
m_connections_lock.lock();
connections_container::iterator it = m_connections.find(pconn->m_sock);
m_connections_lock.unlock();
if(it == m_connections.end())
{
LOG_ERROR("Failed to find closing socket=" << pconn->m_sock);
return false;
}
SOCKET sock = it->second->m_sock;
{
PROFILE_FUNC("[shutdown_connection] shutdown, close");
::shutdown(it->second->m_sock, SD_SEND );
}
size_t close_sock_wait_count = 0;
{
LOG_PRINT("Entered to 'in_use wait zone'", LOG_LEVEL_3);
PROFILE_FUNC("[shutdown_connection] wait for in_use");
while(::InterlockedCompareExchange(&it->second->m_precv_data->m_is_in_use, 1, 1))
{
Sleep(100);
close_sock_wait_count++;
}
LOG_PRINT("First step to 'in_use wait zone'", LOG_LEVEL_3);
while(::InterlockedCompareExchange(&it->second->m_psend_data->m_is_in_use, 1, 1))
{
Sleep(100);
close_sock_wait_count++;
}
LOG_PRINT("Leaved 'in_use wait zone'", LOG_LEVEL_3);
}
::closesocket(it->second->m_sock);
::InterlockedExchange(&it->second->m_connection_shutwoned, 1);
m_connections_lock.lock();
m_connections.erase(it);
m_connections_lock.unlock();
LOG_PRINT("Socked " << sock << " closed, wait_count=" << close_sock_wait_count, LOG_LEVEL_2);
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::run_server(int threads_count = 0)
{
int err = listen(m_listen_socket, 100);
if(SOCKET_ERROR == err )
{
err = ::WSAGetLastError();
LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
if(!threads_count)
{
SYSTEM_INFO si = {0};
::GetSystemInfo(&si);
threads_count = si.dwNumberOfProcessors + 2;
}
for(int i = 0; i != threads_count; i++)
{
boost::thread(boost::bind(&cp_server_impl::worker_thread_member, this));
//HANDLE h_thread = threads_helper::create_thread(worker_thread, this);
InterlockedIncrement(&m_worker_thread_counter);
//::CloseHandle(h_thread);
}
LOG_PRINT("Numbers of worker threads started: " << threads_count, LOG_LEVEL_1);
m_stop = false;
while(!m_stop)
{
PROFILE_FUNC("[run_server] main_loop");
TIMEVAL tv = {0};
tv.tv_sec = 0;
tv.tv_usec = 100;
fd_set sock_set;
sock_set.fd_count = 1;
sock_set.fd_array[0] = m_listen_socket;
int select_res = 0;
{
PROFILE_FUNC("[run_server] select");
select_res = select(0, &sock_set, &sock_set, NULL, &tv);
}
if(SOCKET_ERROR == select_res)
{
err = ::WSAGetLastError();
LOG_ERROR("Failed to select, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
return false;
}
if(!select_res)
{
on_net_idle();
continue;
}
else
{
sockaddr_in adr_from = {0};
int adr_len = sizeof(adr_from);
SOCKET new_sock = INVALID_SOCKET;
{
PROFILE_FUNC("[run_server] WSAAccept");
new_sock = ::WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, CPConditionFunc, (DWORD_PTR)this);
}
if(INVALID_SOCKET == new_sock)
{
if(m_stop)
break;
int err = ::WSAGetLastError();
LOG_PRINT("Failed to WSAAccept, err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2);
continue;
}
LOG_PRINT("Accepted connection (new socket=" << new_sock << ")", LOG_LEVEL_2);
{
PROFILE_FUNC("[run_server] Add new connection");
add_new_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port);
}
}
}
LOG_PRINT("Closing connections("<< m_connections.size() << ") and waiting...", LOG_LEVEL_2);
m_connections_lock.lock();
for(connections_container::iterator it = m_connections.begin(); it != m_connections.end(); it++)
{
::shutdown(it->second->m_sock, SD_BOTH);
::closesocket(it->second->m_sock);
}
m_connections_lock.unlock();
size_t wait_count = 0;
while(m_connections.size() && wait_count < 100)
{
::Sleep(100);
wait_count++;
}
LOG_PRINT("Connections closed OK (wait_count=" << wait_count << ")", LOG_LEVEL_2);
LOG_PRINT("Stopping worker threads("<< m_worker_thread_counter << ").", LOG_LEVEL_2);
for(int i = 0; i<m_worker_thread_counter; i++)
{
::PostQueuedCompletionStatus(m_completion_port, 0, 0, 0);
}
wait_count = 0;
while(InterlockedCompareExchange(&m_worker_thread_counter, 0, 0) && wait_count < 100)
{
Sleep(100);
wait_count++;
}
LOG_PRINT("Net Server STOPPED, wait_count = " << wait_count, LOG_LEVEL_1);
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::add_new_connection(SOCKET new_sock, const network_address &address_from)
{
PROFILE_FUNC("[add_new_connection]");
LOG_PRINT("Add new connection zone: entering lock", LOG_LEVEL_3);
m_connections_lock.lock();
boost::shared_ptr<connection<TProtocol> > ptr;
ptr.reset(new connection<TProtocol>(m_config));
connection<TProtocol>& conn = *ptr.get();
m_connections[new_sock] = ptr;
LOG_PRINT("Add new connection zone: leaving lock", LOG_LEVEL_3);
m_connections_lock.unlock();
conn.init_buffers();
conn.m_sock = new_sock;
conn.context.m_remote_address = address_from;
conn.m_completion_port = m_completion_port;
{
PROFILE_FUNC("[add_new_connection] CreateIoCompletionPort");
::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0);
}
//if(NULL == ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0))
//{
// int err = ::GetLastError();
// LOG_PRINT("Failed to CreateIoCompletionPort(associate socket and completion port), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2);
// return false;
//}
conn.m_tprotocol_handler.after_init_connection();
{
PROFILE_FUNC("[add_new_connection] starting loop");
int res = 0;
while(true)//res!=SOCKET_ERROR)
{
PROFILE_FUNC("[add_new_connection] in loop time");
conn.m_precv_data->TotalBuffBytes = LEVIN_DEFAULT_DATA_BUFF_SIZE;
ZeroMemory(&conn.m_precv_data->m_overlapped, sizeof(OVERLAPPED));
conn.m_precv_data->DataBuf.len = conn.m_precv_data->TotalBuffBytes;
conn.m_precv_data->DataBuf.buf = conn.m_precv_data->Buffer;
conn.m_precv_data->m_op_type = op_type_recv;
InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1);
DWORD bytes_recvd = 0;
DWORD flags = 0;
::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 1);
{
PROFILE_FUNC("[add_new_connection] ::WSARecv");
res = ::WSARecv(conn.m_sock, &(conn.m_precv_data->DataBuf), 1, &bytes_recvd , &flags, &(conn.m_precv_data->m_overlapped), NULL);
}
if(res == SOCKET_ERROR )
{
int err = ::WSAGetLastError();
if(WSA_IO_PENDING == err )
{
break;
}
LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err << " " << log_space::get_win32_err_descr(err));
::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0);
conn.query_shutdown();
//shutdown_connection(&conn);
break;
}
break;
/*else if(0 == res)
{
if(!bytes_recvd)
{
PROFILE_FUNC("[add_new_connection] shutdown_connection");
::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0);
conn.query_shutdown();
//shutdown_connection(&conn);
break;
}else
{
PROFILE_FUNC("[add_new_connection] handle_recv");
}
}*/
}
}
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::deinit_server()
{
if(!m_initialized)
return true;
if(INVALID_SOCKET != m_listen_socket)
{
shutdown(m_listen_socket, SD_BOTH);
int res = closesocket(m_listen_socket);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
}
m_listen_socket = INVALID_SOCKET;
}
int res = ::WSACleanup();
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
}
m_initialized = false;
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::send_stop_signal()
{
::InterlockedExchange(&m_stop, 1);
return true;
}
//-------------------------------------------------------------
template<class TProtocol>
bool cp_server_impl<TProtocol>::is_stop_signal()
{
return m_stop?true:false;
}
//-------------------------------------------------------------
}
}

View file

@ -1,180 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include <wininet.h>
#include <atlutil.h>
#pragma comment(lib, "Wininet.lib")
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
namespace epee
{
namespace net_utils
{
inline
bool http_ssl_invoke(const std::string& url, const std::string usr, const std::string psw, std::string& http_response_body, bool use_post = false)
{
bool final_res = false;
ATL::CUrl url_obj;
BOOL crack_rss = url_obj.CrackUrl(string_encoding::convert_to_t<std::basic_string<TCHAR> >(url).c_str());
HINTERNET hinet = ::InternetOpenA(SHARED_JOBSCOMMON_HTTP_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(!hinet)
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
return false;
}
DWORD dwFlags = 0;
DWORD dwBuffLen = sizeof(dwFlags);
if(usr.size())
{
dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID|
INTERNET_FLAG_PRAGMA_NOCACHE | SECURITY_FLAG_IGNORE_UNKNOWN_CA|INTERNET_FLAG_SECURE;
}else
{
dwFlags |= INTERNET_FLAG_PRAGMA_NOCACHE;
}
int port = url_obj.GetPortNumber();
BOOL res = FALSE;
HINTERNET hsession = ::InternetConnectA(hinet, string_encoding::convert_to_ansii(url_obj.GetHostName()).c_str(), port/*INTERNET_DEFAULT_HTTPS_PORT*/, usr.c_str(), psw.c_str(), INTERNET_SERVICE_HTTP, dwFlags, NULL);
if(hsession)
{
const std::string uri = string_encoding::convert_to_ansii(url_obj.GetUrlPath()) + string_encoding::convert_to_ansii(url_obj.GetExtraInfo());
HINTERNET hrequest = ::HttpOpenRequestA(hsession, use_post?"POST":NULL, uri.c_str(), NULL, NULL,NULL, dwFlags, NULL);
if(hrequest)
{
while(true)
{
res = ::HttpSendRequestA(hrequest, NULL, 0, NULL, 0);
if(!res)
{
//ERROR_INTERNET_INVALID_CA 45
//ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5)
int err = ::GetLastError();
LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
break;
}
DWORD code = 0;
DWORD buf_len = sizeof(code);
DWORD index = 0;
res = ::HttpQueryInfo(hrequest, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &code, &buf_len, &index);
if(!res)
{
//ERROR_INTERNET_INVALID_CA 45
//ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5)
int err = ::GetLastError();
LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
break;
}
if(code < 200 || code > 299)
{
LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code , LOG_LEVEL_0);
break;
}
char buff[100000] = {0};
DWORD readed = 0;
while(true)
{
res = ::InternetReadFile(hrequest, buff, sizeof(buff), &readed);
if(!res)
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
break;
}
if(readed)
{
http_response_body.append(buff, readed);
}
else
break;
}
if(!res)
break;
//we success
final_res = true;
res = ::InternetCloseHandle(hrequest);
if(!res)
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
}
break;
}
}
else
{
//ERROR_INTERNET_INVALID_CA
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
return false;
}
res = ::InternetCloseHandle(hsession);
if(!res)
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
}
}else
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
}
res = ::InternetCloseHandle(hinet);
if(!res)
{
int err = ::GetLastError();
LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0);
}
return final_res;
}
}
}

View file

@ -1,52 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _HTTP_SERVER_CP_H_
#define _HTTP_SERVER_CP_H_
#include "abstract_tcp_server_cp.h"
#include "http_server.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
namespace epee
{
namespace net_utils
{
typedef cp_server_impl<http::simple_http_connection_handler> cp_http_server_file_system;
typedef cp_server_impl<http::http_custom_handler> cp_http_server_custum_handling;
}
}
#endif

View file

@ -1,51 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _HTTP_SERVER_CP2_H_
#define _HTTP_SERVER_CP2_H_
#include "abstract_tcp_server2.h"
#include "http_protocol_handler.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
namespace epee
{
namespace net_utils
{
typedef boosted_tcp_server<http::simple_http_connection_handler<> > boosted_http_server_file_system;
typedef boosted_tcp_server<http::http_custom_handler<> > boosted_http_server_custum_handling;
}
}
#endif

View file

@ -1,48 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _HTTP_SERVER_CP_H_
#define _HTTP_SERVER_CP_H_
#include "abstract_tcp_server.h"
#include "http_server.h"
namespace epee
{
namespace net_utils
{
typedef abstract_tcp_server<http::simple_http_connection_handler> mt_http_server_file_system;
typedef abstract_tcp_server<http::http_custom_handler> mt_http_server_custum_handling;
}
}
#endif

View file

@ -1,167 +0,0 @@
#ifndef JSONRPC_PROTOCOL_HANDLER_H
#define JSONRPC_PROTOCOL_HANDLER_H
#include <cstdint>
#include <string>
#include "net/net_utils_base.h"
#include "jsonrpc_structs.h"
#include "storages/portable_storage.h"
#include "storages/portable_storage_template_helper.h"
namespace epee
{
namespace net_utils
{
namespace jsonrpc2
{
inline
std::string& make_error_resp_json(int64_t code, const std::string& message,
std::string& response_data,
const epee::serialization::storage_entry& id = nullptr)
{
epee::json_rpc::error_response rsp;
rsp.id = id;
rsp.jsonrpc = "2.0";
rsp.error.code = code;
rsp.error.message = message;
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_data, 0, false);
response_data += "\n";
return response_data;
}
template<class t_connection_context>
struct i_jsonrpc2_server_handler
{
virtual ~i_jsonrpc2_server_handler()
{}
virtual bool handle_rpc_request(const std::string& req_data,
std::string& resp_data,
t_connection_context& conn_context) = 0;
virtual bool init_server_thread()
{ return true; }
virtual bool deinit_server_thread()
{ return true; }
};
template<class t_connection_context>
struct jsonrpc2_server_config
{
i_jsonrpc2_server_handler<t_connection_context>* m_phandler;
critical_section m_lock;
};
template<class t_connection_context = net_utils::connection_context_base>
class jsonrpc2_connection_handler
{
public:
typedef t_connection_context connection_context;
typedef jsonrpc2_server_config<t_connection_context> config_type;
jsonrpc2_connection_handler(i_service_endpoint* psnd_hndlr,
config_type& config,
t_connection_context& conn_context)
: m_psnd_hndlr(psnd_hndlr),
m_config(config),
m_conn_context(conn_context),
m_is_stop_handling(false)
{}
virtual ~jsonrpc2_connection_handler()
{}
bool release_protocol()
{
return true;
}
virtual bool thread_init()
{
return true;
}
virtual bool thread_deinit()
{
return true;
}
void handle_qued_callback()
{}
bool after_init_connection()
{
return true;
}
virtual bool handle_recv(const void* ptr, size_t cb)
{
std::string buf((const char*)ptr, cb);
LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" << buf);
bool res = handle_buff_in(buf);
return res;
}
private:
bool handle_buff_in(std::string& buf)
{
if(m_cache.size())
m_cache += buf;
else
m_cache.swap(buf);
m_is_stop_handling = false;
while (!m_is_stop_handling) {
std::string::size_type pos = match_end_of_request(m_cache);
if (std::string::npos == pos) {
m_is_stop_handling = true;
if (m_cache.size() > 4096) {
LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request");
return false;
}
break;
} else {
extract_cached_request_and_handle(pos);
}
if (!m_cache.size()) {
m_is_stop_handling = true;
}
}
return true;
}
bool extract_cached_request_and_handle(std::string::size_type pos)
{
std::string request_data(m_cache.begin(), m_cache.begin() + pos);
m_cache.erase(0, pos);
return handle_request_and_send_response(request_data);
}
bool handle_request_and_send_response(const std::string& request_data)
{
CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!");
std::string response_data;
LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" << request_data);
bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context);
LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" << response_data);
m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size());
return rpc_result;
}
std::string::size_type match_end_of_request(const std::string& buf)
{
std::string::size_type res = buf.find("\n");
if(std::string::npos != res) {
return res + 2;
}
return res;
}
protected:
i_service_endpoint* m_psnd_hndlr;
private:
config_type& m_config;
t_connection_context& m_conn_context;
std::string m_cache;
bool m_is_stop_handling;
};
}
}
}
#endif /* JSONRPC_PROTOCOL_HANDLER_H */

View file

@ -1,86 +0,0 @@
#ifndef JSONRPC_SERVER_HANDLERS_MAP_H
#define JSONRPC_SERVER_HANDLERS_MAP_H
#include <string>
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage_template_helper.h"
#include "storages/portable_storage_base.h"
#include "jsonrpc_structs.h"
#include "jsonrpc_protocol_handler.h"
#define BEGIN_JSONRPC2_MAP(t_connection_context) \
bool handle_rpc_request(const std::string& req_data, \
std::string& resp_data, \
t_connection_context& m_conn_context) \
{ \
bool handled = false; \
uint64_t ticks = epee::misc_utils::get_tick_count(); \
epee::serialization::portable_storage ps; \
if (!ps.load_from_json(req_data)) \
{ \
epee::net_utils::jsonrpc2::make_error_resp_json(-32700, "Parse error", resp_data); \
return true; \
} \
epee::serialization::storage_entry id_; \
id_ = epee::serialization::storage_entry(std::string()); \
if (!ps.get_value("id", id_, nullptr)) \
{ \
epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data); \
return true; \
} \
std::string callback_name; \
if (!ps.get_value("method", callback_name, nullptr)) \
{ \
epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data, id_); \
return true; \
} \
if (false) return true; //just a stub to have "else if"
#define PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \
handled = true; \
boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \
epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\
if(!req.load(ps)) \
{ \
epee::net_utils::jsonrpc2::make_error_resp_json(-32602, "Invalid params", resp_data, req.id); \
return true; \
} \
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \
epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \
resp.jsonrpc = "2.0"; \
resp.id = req.id;
#define FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
epee::serialization::store_t_to_json(resp, resp_data, 0, false); \
resp_data += "\n"; \
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
LOG_PRINT("[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2);
#define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \
else if (callback_name == method_name) \
{ \
PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
fail_resp.jsonrpc = "2.0"; \
fail_resp.id = req.id; \
if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \
{ \
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), resp_data, 0, false); \
resp_data += "\n"; \
return true; \
} \
FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \
return true; \
}
#define END_JSONRPC2_MAP() \
epee::net_utils::jsonrpc2::make_error_resp_json(-32601, "Method not found", resp_data, id_); \
return true; \
}
#endif /* JSONRPC_SERVER_HANDLERS_MAP_H */

View file

@ -1,84 +0,0 @@
#ifndef JSONRPC_SERVER_IMPL_BASE_H
#define JSONRPC_SERVER_IMPL_BASE_H
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "net/jsonrpc_protocol_handler.h"
#include "net/jsonrpc_server_handlers_map.h"
#include "net/abstract_tcp_server2.h"
namespace epee
{
template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base>
class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler<t_connection_context>
{
public:
jsonrpc_server_impl_base()
: m_net_server()
{}
explicit jsonrpc_server_impl_base(boost::asio::io_service& external_io_service)
: m_net_server(external_io_service)
{}
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0")
{
//set self as callback handler
m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this);
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
bool res = m_net_server.init_server(bind_port, bind_ip);
if (!res)
{
LOG_ERROR("Failed to bind server");
return false;
}
return true;
}
bool run(size_t threads_count, bool wait = true)
{
//go to loop
LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0);
if(!m_net_server.run_server(threads_count, wait))
{
LOG_ERROR("Failed to run net tcp server!");
}
if(wait)
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
return true;
}
bool deinit()
{
return m_net_server.deinit_server();
}
bool timed_wait_server_stop(uint64_t ms)
{
return m_net_server.timed_wait_server_stop(ms);
}
bool send_stop_signal()
{
m_net_server.send_stop_signal();
return true;
}
int get_binded_port()
{
return m_net_server.get_binded_port();
}
protected:
net_utils::boosted_tcp_server<net_utils::jsonrpc2::jsonrpc2_connection_handler<t_connection_context> > m_net_server;
};
}
#endif /* JSONRPC_SERVER_IMPL_BASE_H */

View file

@ -1,89 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _LEVIN_CLIENT_H_
#define _LEVIN_CLIENT_H_
#include "net_helper.h"
#include "levin_base.h"
#ifndef MAKE_IP
#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24))
#endif
namespace epee
{
namespace levin
{
/************************************************************************/
/* */
/************************************************************************/
class levin_client_impl
{
public:
levin_client_impl();
virtual ~levin_client_impl();
bool connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0");
bool connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0");
bool is_connected();
bool disconnect();
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out);
virtual int notify(int command, const std::string& in_buff);
protected:
net_utils::blocked_mode_client m_transport;
};
/************************************************************************/
/* */
/************************************************************************/
class levin_client_impl2: public levin_client_impl
{
public:
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out);
int notify(int command, const std::string& in_buff);
};
}
namespace net_utils
{
typedef levin::levin_client_impl levin_client;
typedef levin::levin_client_impl2 levin_client2;
}
}
#include "levin_client.inl"
#endif //_LEVIN_CLIENT_H_

View file

@ -1,199 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#include "string_tools.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace levin
{
inline
bool levin_client_impl::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip)
{
return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip);
}
//------------------------------------------------------------------------------
inline
bool levin_client_impl::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip)
{
return m_transport.connect(addr, port, timeout, timeout, bind_ip);
}
//------------------------------------------------------------------------------
inline
bool levin_client_impl::is_connected()
{
return m_transport.is_connected();
}
//------------------------------------------------------------------------------
inline
bool levin_client_impl::disconnect()
{
return m_transport.disconnect();
}
//------------------------------------------------------------------------------
inline
levin_client_impl::levin_client_impl()
{
}
//------------------------------------------------------------------------------
inline
levin_client_impl::~levin_client_impl()
{
disconnect();
}
//------------------------------------------------------------------------------
inline
int levin_client_impl::invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out)
{
if(!is_connected())
return -1;
bucket_head head = {0};
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = SWAP64LE(in_buff.size());
head.m_have_to_return_data = 1;
head.m_command = SWAP32LE(command);
if(!m_transport.send(&head, sizeof(head)))
return -1;
if(!m_transport.send(in_buff))
return -1;
std::string local_buff;
if(!m_transport.recv_n(local_buff, sizeof(bucket_head)))
return -1;
head = *(bucket_head*)local_buff.data();
if(head.m_signature!=SWAP64LE(LEVIN_SIGNATURE))
{
LOG_PRINT_L1("Signature mismatch in response");
return -1;
}
if(!m_transport.recv_n(buff_out, head.m_cb))
return -1;
return head.m_return_code;
}
//------------------------------------------------------------------------------
inline
int levin_client_impl::notify(int command, const std::string& in_buff)
{
if(!is_connected())
return -1;
bucket_head head = {0};
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = SWAP64LE(in_buff.size());
head.m_have_to_return_data = 0;
head.m_command = SWAP32LE(command);
if(!m_transport.send((const char*)&head, sizeof(head)))
return -1;
if(!m_transport.send(in_buff))
return -1;
return 1;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
inline
int levin_client_impl2::invoke(int command, epee::span<const uint8_t>string& in_buff, std::string& buff_out)
{
if(!is_connected())
return -1;
bucket_head2 head = {0};
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = SWAP64LE(in_buff.size());
head.m_have_to_return_data = 1;
head.m_command = SWAP32LE(command);
head.m_return_code = SWAP32LE(0);
head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST);
head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1);
if(!m_transport.send(&head, sizeof(head)))
return -1;
if(!m_transport.send(in_buff))
return -1;
std::string local_buff;
if(!m_transport.recv_n(local_buff, sizeof(bucket_head2)))
return -1;
head = *(bucket_head2*)local_buff.data();
if(head.m_signature != SWAP64LE(LEVIN_SIGNATURE))
{
LOG_PRINT_L1("Signature mismatch in response");
return -1;
}
if(!m_transport.recv_n(buff_out, SWAP64LE(head.m_cb)))
return -1;
return head.m_return_code;
}
//------------------------------------------------------------------------------
inline
int levin_client_impl2::notify(int command, const std::string& in_buff)
{
if(!is_connected())
return -1;
bucket_head2 head = {0};
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = SWAP64LE(in_buff.size());
head.m_have_to_return_data = 0;
head.m_command = SWAP32LE(command);
head.m_return_code = SWAP32LE(0);
head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST);
head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1);
if(!m_transport.send((const char*)&head, sizeof(head)))
return -1;
if(!m_transport.send(in_buff))
return -1;
return 1;
}
}
}
//------------------------------------------------------------------------------

View file

@ -1,585 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include ""
#include "net_helper.h"
#include "levin_base.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace levin
{
/************************************************************************
* levin_client_async - probably it is not really fast implementation,
* each handler thread could make up to 30 ms latency.
* But, handling events in reader thread will cause dead locks in
* case of recursive call (call invoke() to the same connection
* on reader thread on remote invoke() handler)
***********************************************************************/
class levin_client_async
{
levin_commands_handler* m_pcommands_handler;
void (*commands_handler_destroy)(levin_commands_handler*);
volatile uint32_t m_is_stop;
volatile uint32_t m_threads_count;
::critical_section m_send_lock;
std::string m_local_invoke_buff;
::critical_section m_local_invoke_buff_lock;
volatile int m_invoke_res;
volatile uint32_t m_invoke_data_ready;
volatile uint32_t m_invoke_is_active;
boost::mutex m_invoke_event;
boost::condition_variable m_invoke_cond;
size_t m_timeout;
::critical_section m_recieved_packets_lock;
struct packet_entry
{
bucket_head m_hd;
std::string m_body;
uint32_t m_connection_index;
};
std::list<packet_entry> m_recieved_packets;
/*
m_current_connection_index needed when some connection was broken and reconnected - in this
case we could have some received packets in que, which shoud not be handled
*/
volatile uint32_t m_current_connection_index;
::critical_section m_invoke_lock;
::critical_section m_reciev_packet_lock;
::critical_section m_connection_lock;
net_utils::blocked_mode_client m_transport;
public:
levin_client_async():m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0)
{}
levin_client_async(const levin_client_async& /*v*/):m_pcommands_handler(NULL), commands_handler_destroy(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0)
{}
~levin_client_async()
{
boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);
disconnect();
while(boost::interprocess::ipcdetail::atomic_read32(&m_threads_count))
::Sleep(100);
set_handler(NULL);
}
void set_handler(levin_commands_handler* phandler, void (*destroy)(levin_commands_handler*) = NULL)
{
if (commands_handler_destroy && m_pcommands_handler)
(*commands_handler_destroy)(m_pcommands_handler);
m_pcommands_handler = phandler;
m_pcommands_handler_destroy = destroy;
}
bool connect(uint32_t ip, uint32_t port, uint32_t timeout)
{
loop_call_guard();
critical_region cr(m_connection_lock);
m_timeout = timeout;
bool res = false;
CRITICAL_REGION_BEGIN(m_reciev_packet_lock);
CRITICAL_REGION_BEGIN(m_send_lock);
res = levin_client_impl::connect(ip, port, timeout);
boost::interprocess::ipcdetail::atomic_inc32(&m_current_connection_index);
CRITICAL_REGION_END();
CRITICAL_REGION_END();
if(res && !boost::interprocess::ipcdetail::atomic_read32(&m_threads_count) )
{
//boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 0);//m_is_stop = false;
boost::thread( boost::bind(&levin_duplex_client::reciever_thread, this) );
boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) );
boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) );
}
return res;
}
bool is_connected()
{
loop_call_guard();
critical_region cr(m_cs);
return levin_client_impl::is_connected();
}
inline
bool check_connection()
{
loop_call_guard();
critical_region cr(m_cs);
if(!is_connected())
{
if( !reconnect() )
{
LOG_ERROR("Reconnect Failed. Failed to invoke() because not connected!");
return false;
}
}
return true;
}
//------------------------------------------------------------------------------
inline
bool recv_n(SOCKET s, char* pbuff, size_t cb)
{
while(cb)
{
int res = ::recv(m_socket, pbuff, (int)cb, 0);
if(SOCKET_ERROR == res)
{
if(!m_connected)
return false;
int err = ::WSAGetLastError();
LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
disconnect();
//reconnect();
return false;
}else if(res == 0)
{
disconnect();
//reconnect();
return false;
}
LOG_PRINT_L4("[" << m_socket <<"] RECV " << res);
cb -= res;
pbuff += res;
}
return true;
}
//------------------------------------------------------------------------------
inline
bool recv_n(SOCKET s, std::string& buff)
{
size_t cb_remain = buff.size();
char* m_current_ptr = (char*)buff.data();
return recv_n(s, m_current_ptr, cb_remain);
}
bool disconnect()
{
//boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);//m_is_stop = true;
loop_call_guard();
critical_region cr(m_cs);
levin_client_impl::disconnect();
CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock);
m_local_invoke_buff.clear();
m_invoke_res = LEVIN_ERROR_CONNECTION_DESTROYED;
CRITICAL_REGION_END();
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true;
m_invoke_cond.notify_all();
return true;
}
void loop_call_guard()
{
}
void on_leave_invoke()
{
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 0);
}
int invoke(const GUID& target, int command, const std::string& in_buff, std::string& buff_out)
{
critical_region cr_invoke(m_invoke_lock);
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 1);
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 0);
misc_utils::destr_ptr hdlr = misc_utils::add_exit_scope_handler(boost::bind(&levin_duplex_client::on_leave_invoke, this));
loop_call_guard();
if(!check_connection())
return LEVIN_ERROR_CONNECTION_DESTROYED;
bucket_head head = {0};
head.m_signature = LEVIN_SIGNATURE;
head.m_cb = in_buff.size();
head.m_have_to_return_data = 1;
head.m_id = target;
#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS
::UuidCreate(&head.m_id);
#endif
head.m_command = command;
head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
head.m_flags = LEVIN_PACKET_REQUEST;
LOG_PRINT("[" << m_socket <<"] Sending invoke data", LOG_LEVEL_4);
CRITICAL_REGION_BEGIN(m_send_lock);
LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head));
int res = ::send(m_socket, (const char*)&head, sizeof(head), 0);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
disconnect();
return LEVIN_ERROR_CONNECTION_DESTROYED;
}
LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size());
res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
disconnect();
return LEVIN_ERROR_CONNECTION_DESTROYED;
}
CRITICAL_REGION_END();
LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
//hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles.
boost::system_time timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100);
size_t timeout_count = 0;
boost::unique_lock<boost::mutex> lock(m_invoke_event);
while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_data_ready))
{
if(!m_invoke_cond.timed_wait(lock, timeout))
{
if(timeout_count < 10)
{
//workaround to avoid freezing at timed_wait called after notify_all.
timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100);
++timeout_count;
continue;
}else if(timeout_count == 10)
{
//workaround to avoid freezing at timed_wait called after notify_all.
timeout = boost::get_system_time()+ boost::posix_time::minutes(10);
++timeout_count;
continue;
}else
{
LOG_PRINT("[" << m_socket <<"] Timeout on waiting invoke result. ", LOG_LEVEL_0);
//disconnect();
return LEVIN_ERROR_CONNECTION_TIMEDOUT;
}
}
}
CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock);
buff_out.swap(m_local_invoke_buff);
m_local_invoke_buff.clear();
CRITICAL_REGION_END();
return m_invoke_res;
}
int notify(const GUID& target, int command, const std::string& in_buff)
{
if(!check_connection())
return LEVIN_ERROR_CONNECTION_DESTROYED;
bucket_head head = {0};
head.m_signature = LEVIN_SIGNATURE;
head.m_cb = in_buff.size();
head.m_have_to_return_data = 0;
head.m_id = target;
#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS
::UuidCreate(&head.m_id);
#endif
head.m_command = command;
head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
head.m_flags = LEVIN_PACKET_REQUEST;
CRITICAL_REGION_BEGIN(m_send_lock);
LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head));
int res = ::send(m_socket, (const char*)&head, sizeof(head), 0);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
disconnect();
return LEVIN_ERROR_CONNECTION_DESTROYED;
}
LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size());
res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0);
if(SOCKET_ERROR == res)
{
int err = ::WSAGetLastError();
LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"");
disconnect();
return LEVIN_ERROR_CONNECTION_DESTROYED;
}
CRITICAL_REGION_END();
LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
return 1;
}
private:
bool have_some_data(SOCKET sock, int interval = 1)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
fd_set fdse;
FD_ZERO(&fdse);
FD_SET(sock, &fdse);
timeval tv;
tv.tv_sec = interval;
tv.tv_usec = 0;
int sel_res = select(0, &fds, 0, &fdse, &tv);
if(0 == sel_res)
return false;
else if(sel_res == SOCKET_ERROR)
{
if(m_is_stop)
return false;
int err_code = ::WSAGetLastError();
LOG_ERROR("Filed to call select, err code = " << err_code);
disconnect();
}else
{
if(fds.fd_array[0])
{//some read operations was performed
return true;
}else if(fdse.fd_array[0])
{//some error was at the socket
return true;
}
}
return false;
}
bool reciev_and_process_incoming_data()
{
bucket_head head = {0};
uint32_t conn_index = 0;
bool is_request = false;
std::string local_buff;
CRITICAL_REGION_BEGIN(m_reciev_packet_lock);//to protect from socket reconnect between head and body
if(!recv_n(m_socket, (char*)&head, sizeof(head)))
{
if(m_is_stop)
return false;
LOG_ERROR("Failed to recv_n");
return false;
}
conn_index = boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index);
if(head.m_signature!=LEVIN_SIGNATURE)
{
LOG_ERROR("Signature mismatch in response");
return false;
}
is_request = (head.m_protocol_version == LEVIN_PROTOCOL_VER_1 && head.m_flags&LEVIN_PACKET_REQUEST);
local_buff.resize((size_t)head.m_cb);
if(!recv_n(m_socket, local_buff))
{
if(m_is_stop)
return false;
LOG_ERROR("Filed to reciev");
return false;
}
CRITICAL_REGION_END();
LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
if(is_request)
{
CRITICAL_REGION_BEGIN(m_recieved_packets_lock);
m_recieved_packets.resize(m_recieved_packets.size() + 1);
m_recieved_packets.back().m_hd = head;
m_recieved_packets.back().m_body.swap(local_buff);
m_recieved_packets.back().m_connection_index = conn_index;
CRITICAL_REGION_END();
/*
*/
}else
{//this is some response
CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock);
m_local_invoke_buff.swap(local_buff);
m_invoke_res = head.m_return_code;
CRITICAL_REGION_END();
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true;
m_invoke_cond.notify_all();
}
return true;
}
bool reciever_thread()
{
LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]");
log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER");
boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count);
while(!m_is_stop)
{
if(!m_connected)
{
Sleep(100);
continue;
}
if(have_some_data(m_socket, 1))
{
if(!reciev_and_process_incoming_data())
{
if(m_is_stop)
{
break;//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count);
//return true;
}
LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down");
//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count);
//disconnect_no_wait();
//break;
}
}
}
boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count);
LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]");
return true;
}
bool process_recieved_packet(bucket_head& head, const std::string& local_buff, uint32_t conn_index)
{
net_utils::connection_context_base conn_context;
conn_context.m_remote_address = m_address;
if(head.m_have_to_return_data)
{
std::string return_buff;
if(m_pcommands_handler)
head.m_return_code = m_pcommands_handler->invoke(head.m_id, head.m_command, local_buff, return_buff, conn_context);
else
head.m_return_code = LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED;
head.m_cb = return_buff.size();
head.m_have_to_return_data = 0;
head.m_protocol_version = LEVIN_PROTOCOL_VER_1;
head.m_flags = LEVIN_PACKET_RESPONSE;
std::string send_buff((const char*)&head, sizeof(head));
send_buff += return_buff;
CRITICAL_REGION_BEGIN(m_send_lock);
if(conn_index != boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index))
{//there was reconnect, send response back is not allowed
return true;
}
int res = ::send(m_socket, (const char*)send_buff.data(), send_buff.size(), 0);
if(res == SOCKET_ERROR)
{
int err_code = ::WSAGetLastError();
LOG_ERROR("Failed to send, err = " << err_code);
return false;
}
CRITICAL_REGION_END();
LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]");
}
else
{
if(m_pcommands_handler)
m_pcommands_handler->notify(head.m_id, head.m_command, local_buff, conn_context);
}
return true;
}
bool handler_thread()
{
LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread started.[m_threads_count=" << m_threads_count << "]");
log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER");
boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count);
while(!m_is_stop)
{
bool have_some_work = false;
std::string local_buff;
bucket_head bh = {0};
uint32_t conn_index = 0;
CRITICAL_REGION_BEGIN(m_recieved_packets_lock);
if(m_recieved_packets.size())
{
bh = m_recieved_packets.begin()->m_hd;
conn_index = m_recieved_packets.begin()->m_connection_index;
local_buff.swap(m_recieved_packets.begin()->m_body);
have_some_work = true;
m_recieved_packets.pop_front();
}
CRITICAL_REGION_END();
if(have_some_work)
{
process_recieved_packet(bh, local_buff, conn_index);
}else
{
//Idle when no work
Sleep(30);
}
}
boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count);
LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]");
return true;
}
};
}
}

View file

@ -1,161 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include "levin_base.h"
#include "serializeble_struct_helper.h"
#include "int-util.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace levin
{
template<class t_struct>
bool pack_struct_to_levin_message(const t_struct& t, std::string& buff, int command_id)
{
buff.resize(sizeof(levin::bucket_head));
levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]);
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = 0;
head.m_have_to_return_data = 1;
head.m_command = SWAP32LE(command_id);
head.m_return_code = SWAP32LE(1);
head.m_reservedA = rand(); //probably some flags in future
head.m_reservedB = rand(); //probably some check summ in future
std::string buff_strg;
if(!StorageNamed::save_struct_as_storage_to_buff_t<t_struct, StorageNamed::DefaultStorageType>(t, buff_strg))
return false;
head.m_cb = SWAP64LE(buff_strg.size());
buff.append(buff_strg);
return true;
}
bool pack_data_to_levin_message(const std::string& data, std::string& buff, int command_id)
{
buff.resize(sizeof(levin::bucket_head));
levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]);
head.m_signature = SWAP64LE(LEVIN_SIGNATURE);
head.m_cb = 0;
head.m_have_to_return_data = 1;
head.m_command = SWAP32LE(command_id);
head.m_return_code = SWAP32LE(1);
head.m_reservedA = rand(); //probably some flags in future
head.m_reservedB = rand(); //probably some check summ in future
head.m_cb = SWAP64LE(data.size());
buff.append(data);
return true;
}
bool load_levin_data_from_levin_message(std::string& levin_data, const std::string& buff, int& command)
{
if(buff.size() < sizeof(levin::bucket_head) )
{
LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message");
return false;
}
#if BYTE_ORDER == LITTLE_ENDIAN
levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]);
#else
levin::bucket_head head = *(levin::bucket_head*)(&buff[0]);
head.m_signature = SWAP64LE(head.m_signature);
head.m_cb = SWAP64LE(head.m_cb);
head.m_command = SWAP32LE(head.m_command);
head.m_return_code = SWAP32LE(head.m_return_code);
head.m_reservedA = SWAP32LE(head.m_reservedA);
head.m_reservedB = SWAP32LE(head.m_reservedB);
#endif
if(head.m_signature != LEVIN_SIGNATURE)
{
LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message");
return false;
}
if(head.m_cb != buff.size()-sizeof(levin::bucket_head))
{
LOG_PRINT_L3("sizes mismatch, at load_struct_from_levin_message");
return false;
}
//std::string buff_strg;
levin_data.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head));
command = head.m_command;
return true;
}
template<class t_struct>
bool load_struct_from_levin_message(t_struct& t, const std::string& buff, int& command)
{
if(buff.size() < sizeof(levin::bucket_head) )
{
LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message");
return false;
}
#if BYTE_ORDER == LITTLE_ENDIAN
levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]);
#else
levin::bucket_head head = *(levin::bucket_head*)(&buff[0]);
head.m_signature = SWAP64LE(head.m_signature);
head.m_cb = SWAP64LE(head.m_cb);
head.m_command = SWAP32LE(head.m_command);
head.m_return_code = SWAP32LE(head.m_return_code);
head.m_reservedA = SWAP32LE(head.m_reservedA);
head.m_reservedB = SWAP32LE(head.m_reservedB);
#endif
if(head.m_signature != LEVIN_SIGNATURE)
{
LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message");
return false;
}
if(head.m_cb != buff.size()-sizeof(levin::bucket_head))
{
LOG_ERROR("sizes mismatch, at load_struct_from_levin_message");
return false;
}
std::string buff_strg;
buff_strg.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head));
if(!StorageNamed::load_struct_from_storage_buff_t<t_struct, StorageNamed::DefaultStorageType>(t, buff_strg))
{
LOG_ERROR("Failed to read storage, at load_struct_from_levin_message");
return false;
}
command = head.m_command;
return true;
}
}
}

View file

@ -1,47 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _HTTP_SERVER_CP_H_
#define _HTTP_SERVER_CP_H_
#include "abstract_tcp_server_cp.h"
#include "levin_protocol_handler.h"
namespace epee
{
namespace net_utils
{
typedef cp_server_impl<levin::protocol_handler> cp_levin_server;
}
}
#endif

View file

@ -1,49 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _HTTP_SERVER_CP_H_
#define _HTTP_SERVER_CP_H_
#include "abstract_tcp_server2.h"
#include "levin_protocol_handler.h"
#include "levin_protocol_handler_async.h"
namespace epee
{
namespace net_utils
{
typedef boosted_tcp_server<levin::protocol_handler<> > boosted_levin_server;
typedef boosted_tcp_server<levin::async_protocol_handler<> > boosted_levin_async_server;
}
}
#endif

View file

@ -1,47 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _MULTIPROTOCOLS_SERVER_H_
#define _MULTIPROTOCOLS_SERVER_H_
//#include "abstract_tcp_server_cp.h"
#include "protocol_switcher.h"
#include "abstract_tcp_server2.h"
namespace epee
{
namespace net_utils
{
//typedef cp_server_impl<net_utils::protocol_switcher> multiprotocol_server;
typedef boosted_tcp_server<net_utils::protocol_switcher> boosted_multiprotocol_server;
}
}
#endif //_MULTIPROTOCOLS_SERVER_H_

View file

@ -1,376 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _MUNIN_CONNECTION_HANDLER_H_
#define _MUNIN_CONNECTION_HANDLER_H_
#include <string>
#include "net_utils_base.h"
#include "to_nonconst_iterator.h"
#include "http_base.h"
#include "reg_exp_definer.h"
#define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n"
#define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n"
#define MUNIN_TITLE(title_str) "graph_title " title_str "\n"
#define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n"
#define MUNIN_INFO(info_str) "graph_info " info_str "\n"
#define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n"
#define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n"
#define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n"
#define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) {
#define END_MUNIN_SERVICE() }
#define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast<std::string>(variable) + "\n"
namespace epee
{
namespace net_utils
{
namespace munin
{
/************************************************************************/
/* */
/************************************************************************/
struct munin_service;
struct munin_service_data_provider
{
virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0;
};
struct munin_service
{
std::string m_service_name;
std::string m_service_config_string;
munin_service_data_provider* m_pdata_provider;
};
struct node_server_config
{
std::list<munin_service> m_services;
//TODO:
};
struct fake_send_handler: public i_service_endpoint
{
virtual bool do_send(const void* ptr, size_t cb)
{
m_cache += std::string((const char*)ptr, cb);
return true;
}
public:
std::string m_cache;
};
/************************************************************************/
/* */
/************************************************************************/
class munin_node_server_connection_handler
{
public:
typedef node_server_config config_type;
typedef connection_context_base connection_context;
munin_node_server_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, const connection_context_base& context):m_psnd_hndlr(psnd_hndlr),
m_machine_state(http_state_retriving_comand_line),
m_config(config)
{
init();
}
virtual ~munin_node_server_connection_handler()
{
}
bool release_protocol()
{
return true;
}
bool after_init_connection()
{
std::string hello_str = "# munin node at ";
hello_str += m_host_name + "\n";
send_hook(hello_str);
return true;
}
virtual bool thread_init()
{
return true;
}
virtual bool thread_deinit()
{
return true;
}
void handle_qued_callback()
{
}
virtual bool handle_recv(const void* ptr, size_t cb)
{
const char* pbuff = (const char*)ptr;
std::string recvd_buff(pbuff, cb);
LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3);
m_cache += recvd_buff;
bool stop_handling = false;
while(!stop_handling)
{
switch(m_machine_state)
{
case http_state_retriving_comand_line:
{
std::string::size_type fpos = m_cache.find('\n');
if(std::string::npos != fpos )
{
bool res = handle_command(m_cache);
if(!res)
return false;
m_cache.erase(0, fpos+1);
continue;
}
stop_handling = true;
}
break;
case http_state_error:
stop_handling = true;
return false;
default:
LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state);
stop_handling = true;
m_machine_state = http_state_error;
return false;
}
}
return true;
}
private:
bool init()
{
char hostname[64] = {0};
int res = gethostname(hostname, 64);
hostname[63] = 0;//be happy
m_host_name = hostname;
return true;
}
bool handle_command(const std::string& command)
{
// list, nodes, config, fetch, version or quit
STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal);
// 12 3 4 5 6 7 8 9
size_t match_len = 0;
boost::smatch result;
if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched)
{
if(result[2].matched)
{//list command
return handle_list_command();
}else if(result[3].matched)
{//nodes command
return handle_nodes_command();
}else if(result[4].matched)
{//config command
if(result[9].matched)
return handle_config_command(result[9]);
else
{
send_hook("Unknown service\n");
}
}else if(result[5].matched)
{//fetch command
if(result[9].matched)
return handle_fetch_command(result[9]);
else
{
send_hook("Unknown service\n");
}
}else if(result[6].matched)
{//version command
return handle_version_command();
}else if(result[7].matched)
{//quit command
return handle_quit_command();
}
else
return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");
}
return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");
}
bool handle_list_command()
{
std::string buff_to_send;
for(std::list<munin_service>::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++)
{
buff_to_send += it->m_service_name + " ";
}
buff_to_send+='\n';
return send_hook(buff_to_send);
}
bool handle_nodes_command()
{
//supports only one node - host name
send_hook(m_host_name + "\n.\n");
return true;
}
bool handle_config_command(const std::string& service_name)
{
munin_service* psrv = get_service_by_name(service_name);
if(!psrv)
return send_hook(std::string() + "Unknown service\n");
return send_hook(psrv->m_service_config_string + ".\n");
}
bool handle_fetch_command(const std::string& service_name)
{
munin_service* psrv = get_service_by_name(service_name);
if(!psrv)
return send_hook(std::string() + "Unknown service\n");
std::string buff;
psrv->m_pdata_provider->update_service_data(psrv, buff);
buff += ".\n";
return send_hook(buff);
}
bool handle_version_command()
{
return send_hook("Munin node component by Andrey Sabelnikov\n");
}
bool handle_quit_command()
{
return false;
}
bool send_hook(const std::string& buff)
{
LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3);
if(m_psnd_hndlr)
return m_psnd_hndlr->do_send(buff.data(), buff.size());
else
return false;
}
munin_service* get_service_by_name(const std::string& srv_name)
{
std::list<munin_service>::iterator it = m_config.m_services.begin();
for(; it!=m_config.m_services.end(); it++)
if(it->m_service_name == srv_name)
break;
if(it==m_config.m_services.end())
return NULL;
return &(*it);
}
enum machine_state{
http_state_retriving_comand_line,
http_state_error
};
config_type& m_config;
machine_state m_machine_state;
std::string m_cache;
std::string m_host_name;
protected:
i_service_endpoint* m_psnd_hndlr;
};
inline bool test_self()
{
/*WSADATA w;
::WSAStartup(MAKEWORD(1, 1), &w);
node_server_config sc;
sc.m_services.push_back(munin_service());
sc.m_services.back().m_service_name = "test_service";
sc.m_services.back().m_service_config_string =
"graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n"
"graph_title REPORTS STATICTICS\n"
"graph_category bind\n"
"graph_info This graph shows how many reports came in fixed time period.\n"
"graph_order apps free swap\n"
"apps.label apps\n"
"apps.draw AREA\n"
"apps.info Memory used by user-space applications.\n"
"swap.label swap\n"
"swap.draw STACK\n"
"swap.info Swap space used.\n"
"free.label unused\n"
"free.draw STACK\n"
"free.info Wasted memory. Memory that is not used for anything at all.\n"
"committed.label committed\n"
"committed.draw LINE2\n"
"committed.warn 625410048\n"
"committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n";
sc.m_services.push_back(munin_service());
sc.m_services.back().m_service_name = "test_service1";
fake_send_handler fh;
munin_node_server_connection_handler mh(&fh, sc);
std::string buff = "list\n";
mh.handle_recv(buff.data(), buff.size());
buff = "nodes\n";
mh.handle_recv(buff.data(), buff.size());
*/
return true;
}
}
}
}
#endif//!_MUNIN_CONNECTION_HANDLER_H_

View file

@ -1,49 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _MUNIN_NODE_SERVER_H_
#define _MUNIN_NODE_SERVER_H_
#include <string>
//#include "net_utils_base.h"
#include "munin_connection_handler.h"
//#include "abstract_tcp_server.h"
//#include "abstract_tcp_server_cp.h"
#include "abstract_tcp_server2.h"
namespace epee
{
namespace net_utils
{
namespace munin
{
typedef boosted_tcp_server<munin_node_server_connection_handler> munin_node_server;
//typedef cp_server_impl<munin_node_server_connection_handler> munin_node_cp_server;
}
}
}
#endif//!_MUNIN_NODE_SERVER_H_

View file

@ -1,38 +0,0 @@
// Copyright (c) 2019-2022, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
namespace epee
{
namespace net_utils
{
struct ssl_authentication_t;
class ssl_options_t;
}
}

View file

@ -1,121 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _PROTOCOL_SWITCHER_H_
#define _PROTOCOL_SWITCHER_H_
#include "levin_base.h"
#include "http_server.h"
#include "levin_protocol_handler.h"
//#include "abstract_tcp_server.h"
namespace epee
{
namespace net_utils
{
struct protocl_switcher_config
{
http::http_custom_handler::config_type m_http_config;
levin::protocol_handler::config_type m_levin_config;
};
struct i_protocol_handler
{
virtual bool handle_recv(const void* ptr, size_t cb)=0;
};
template<class t>
class t_protocol_handler: public i_protocol_handler
{
public:
typedef t t_type;
t_protocol_handler(i_service_endpoint* psnd_hndlr, typename t_type::config_type& config, const connection_context& conn_context):m_hadler(psnd_hndlr, config, conn_context)
{}
private:
bool handle_recv(const void* ptr, size_t cb)
{
return m_hadler.handle_recv(ptr, cb);
}
t_type m_hadler;
};
class protocol_switcher
{
public:
typedef protocl_switcher_config config_type;
protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context);
virtual ~protocol_switcher(){}
virtual bool handle_recv(const void* ptr, size_t cb);
bool after_init_connection(){return true;}
private:
t_protocol_handler<http::http_custom_handler> m_http_handler;
t_protocol_handler<levin::protocol_handler> m_levin_handler;
i_protocol_handler* pcurrent_handler;
std::string m_cached_buff;
};
protocol_switcher::protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context):m_http_handler(psnd_hndlr, config.m_http_config, conn_context), m_levin_handler(psnd_hndlr, config.m_levin_config, conn_context), pcurrent_handler(NULL)
{}
bool protocol_switcher::handle_recv(const void* ptr, size_t cb)
{
if(pcurrent_handler)
return pcurrent_handler->handle_recv(ptr, cb);
else
{
m_cached_buff.append((const char*)ptr, cb);
if(m_cached_buff.size() < sizeof(uint64_t))
return true;
if(*((uint64_t*)&m_cached_buff[0]) == LEVIN_SIGNATURE)
{
pcurrent_handler = &m_levin_handler;
return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size());
}
if(m_cached_buff.substr(0, 4) == "GET " || m_cached_buff.substr(0, 4) == "POST")
{
pcurrent_handler = &m_http_handler;
return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size());
}else
{
LOG_ERROR("Wrong protocol accepted on port...");
return false;
}
}
return true;
}
}
}
#endif //_PROTOCOL_SWITCHER_H_

View file

@ -1,31 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#define RPC_METHOD_NAME(name) static inline const char* methodname(){return name;}

View file

@ -1,181 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
namespace epee
{
namespace net_utils
{
namespace smtp
{
using boost::asio::ip::tcp;
using namespace boost::archive::iterators;
typedef base64_from_binary<transform_width<const char *,6,8> > base64_text;
/************************************************************************/
/* */
/************************************************************************/
class smtp_client
{
public:
smtp_client(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword):
mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService)
{
tcp::resolver::query qry(mServer,boost::lexical_cast<std::string>( mPort ));
mResolver.async_resolve(qry,boost::bind(&smtp_client::handleResolve,this,boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
}
bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage)
{
mHasError = true;
mFrom=pFrom;
mTo=pTo;
mSubject=pSubject;
mMessage=pMessage;
mIOService.run();
return !mHasError;
}
private:
std::string encodeBase64(std::string pData)
{
std::stringstream os;
size_t sz=pData.size();
std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),std::ostream_iterator<char>(os));
return os.str();
}
void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator)
{
if(!err)
{
tcp::endpoint endpoint=*endpoint_iterator;
mSocket.async_connect(endpoint,
boost::bind(&smtp_client::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator));
}
else
{
mHasError=true;
mErrorMsg= err.message();
}
}
void writeLine(std::string pData)
{
std::ostream req_strm(&mRequest);
req_strm << pData << "\r\n";
boost::asio::write(mSocket,mRequest);
req_strm.clear();
}
void readLine(std::string& pData)
{
boost::asio::streambuf response;
boost::asio::read_until(mSocket, response, "\r\n");
std::istream response_stream(&response);
response_stream >> pData;
}
void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator)
{
if (!err)
{
std::string read_buff;
// The connection was successful. Send the request.
std::ostream req_strm(&mRequest);
writeLine("EHLO "+mServer);
readLine(read_buff);//220
writeLine("AUTH LOGIN");
readLine(read_buff);//
writeLine(encodeBase64(mUserName));
readLine(read_buff);
writeLine(encodeBase64(mPassword));
readLine(read_buff);
writeLine( "MAIL FROM:<"+mFrom+">");
writeLine( "RCPT TO:<"+mTo+">");
writeLine( "DATA");
writeLine( "SUBJECT:"+mSubject);
writeLine( "From:"+mFrom);
writeLine( "To:"+mTo);
writeLine( "");
writeLine( mMessage );
writeLine( "\r\n.\r\n");
readLine(read_buff);
if(read_buff == "250")
mHasError = false;
writeLine( "QUIT");
}
else
{
mHasError=true;
mErrorMsg= err.message();
}
}
std::string mServer;
std::string mUserName;
std::string mPassword;
std::string mFrom;
std::string mTo;
std::string mSubject;
std::string mMessage;
unsigned int mPort;
boost::asio::io_service mIOService;
tcp::resolver mResolver;
tcp::socket mSocket;
boost::asio::streambuf mRequest;
boost::asio::streambuf mResponse;
bool mHasError;
std::string mErrorMsg;
};
bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_email, /*"STIL CRAWLER",*/
const std::string& maillist, const std::string& subject, const std::string& body)
{
STD_TRY_BEGIN();
//smtp_client mailc("yoursmtpserver.com",25,"user@yourdomain.com","password");
//mailc.Send("from@yourdomain.com","to@somewhere.com","subject","Hello from C++ SMTP Client!");
smtp_client mailc(server,port,login,pass);
return mailc.Send(from_email,maillist,subject,body);
STD_TRY_CATCH("at send_mail", false);
}
}
}
}
//#include "smtp.inl"

File diff suppressed because it is too large Load diff

View file

@ -1,88 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#pragma once
#include "smtp.h"
namespace epee
{
namespace net_utils
{
namespace smtp
{
inline bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_addres, const std::string& from_name, const std::string& maillist, const std::string& subject, const std::string& mail_body)
{
net_utils::smtp::CSMTPClient smtp;
if ( !smtp.ServerConnect( server.c_str(), port ) )
{
LOG_PRINT("Reporting: Failed to connect to server " << server <<":"<< port, LOG_LEVEL_0);
return false;
}
if(login.size() && pass.size())
{
if ( !smtp.ServerLogin( login.c_str(), pass.c_str()) )
{
LOG_PRINT("Reporting: Failed to auth on server " << server <<":"<< port, LOG_LEVEL_0);
return false;
}
}
if ( !smtp.SendMessage( from_addres.c_str(),
from_name.c_str(),
maillist.c_str(),
subject.c_str(),
"bicycle-client",
(LPBYTE)mail_body.data(),
mail_body.size()))
{
char *szErrorText = smtp.GetLastErrorText();
if ( szErrorText )
{
LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0);
}
else
{
LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0);
}
return false;
}
smtp.ServerDisconnect();
return true;
}
}
}
}