From 1f058a600348e7e71080a52caeab3b738e6a1290 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Mon, 17 Oct 2016 09:16:09 -0700 Subject: [PATCH 1/3] fixed compile issues for tcpsocketclients; files referred to tcpsocketclientprivate.h, which cmake didn't add to the include directory --- .../connectors/linuxtcpsocketclient.cpp | 3 +-- .../client/connectors/linuxtcpsocketclient.h | 18 ++++++------- .../client/connectors/tcpsocketclient.h | 11 ++++---- .../connectors/tcpsocketclientprivate.h | 26 ------------------- .../connectors/windowstcpsocketclient.h | 16 ++++++------ 5 files changed, 22 insertions(+), 52 deletions(-) delete mode 100644 src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 631998dd..1b14a684 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -2,7 +2,7 @@ * libjson-rpc-cpp ************************************************************************* * @file linuxtcpsocketclient.cpp - * @date 17.07.2015 + * @date 17.10.2016 * @author Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ @@ -29,7 +29,6 @@ using namespace jsonrpc; using namespace std; LinuxTcpSocketClient::LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port) : - TcpSocketClientPrivate(), hostToConnect(hostToConnect), port(port) { diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h index 5d05315f..a46c6eb3 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -2,7 +2,7 @@ * libjson-rpc-cpp ************************************************************************* * @file linuxtcpsocketclient.h - * @date 17.07.2015 + * @date 17.10.2016 * @author Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ @@ -10,9 +10,7 @@ #ifndef JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ #define JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ -#include -#include -#include "tcpsocketclientprivate.h" +#include namespace jsonrpc { @@ -20,7 +18,7 @@ namespace jsonrpc * This class is the Linux/UNIX implementation of TCPSocketClient. * It uses the POSIX socket API to performs its job. */ - class LinuxTcpSocketClient : public TcpSocketClientPrivate + class LinuxTcpSocketClient : public IClientConnector { public: /** @@ -46,20 +44,20 @@ namespace jsonrpc unsigned int port; /*!< The port on which the client should try to connect*/ /** * @brief Connects to the host and port provided by constructor parameters. - * + * * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. * On first case it tries to connect to the ip. * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. - * + * * @returns A file descriptor to the successfully connected socket * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). */ int Connect() throw (JsonRpcException); /** * @brief Connects to provided ip and port. - * + * * This method tries to connect to the provided ip and port. - * + * * @param ip The ipv4 address to connect to * @param port The port to connect to * @returns A file descriptor to the successfully connected socket @@ -68,7 +66,7 @@ namespace jsonrpc int Connect(const std::string& ip, const int& port) throw (JsonRpcException); /** * @brief Check if provided ip is an ipv4 address. - * + * * @param ip The ipv4 address to check * @returns A boolean indicating if the provided ip is or is not an ipv4 address */ diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.h b/src/jsonrpccpp/client/connectors/tcpsocketclient.h index 66e80054..a011783b 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.h @@ -2,7 +2,7 @@ * libjson-rpc-cpp ************************************************************************* * @file unixdomainsocketclient.h - * @date 11.05.2015 + * @date 17.10.2016 * @author Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ @@ -10,10 +10,9 @@ #ifndef JSONRPC_CPP_TCPSOCKETCLIENT_H_ #define JSONRPC_CPP_TCPSOCKETCLIENT_H_ -#include "../iclientconnector.h" +#include #include #include -#include "tcpsocketclientprivate.h" namespace jsonrpc { @@ -29,9 +28,9 @@ namespace jsonrpc public: /** * @brief TcpSocketClient, constructor for the included TcpSocketClient - * + * * Instanciates the real implementation of TcpSocketClientPrivate depending on running OS. - * + * * @param ipToConnect The ipv4 address on which the client should try to connect * @param port The port on which the client should try to connect */ @@ -49,7 +48,7 @@ namespace jsonrpc virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); private: - TcpSocketClientPrivate *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ + IClientConnector *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h b/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h deleted file mode 100644 index 767eecfe..00000000 --- a/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h +++ /dev/null @@ -1,26 +0,0 @@ -/************************************************************************* - * libjson-rpc-cpp - ************************************************************************* - * @file tcpsocketclientprivate.h - * @date 17.07.2015 - * @author Alexandre Poirot - * @license See attached LICENSE.txt - ************************************************************************/ - -#ifndef JSONRPC_CPP_TCPSOCKETCLIENTPRIVATE_H_ -#define JSONRPC_CPP_TCPSOCKETCLIENTPRIVATE_H_ - -#include "../iclientconnector.h" -#include - -namespace jsonrpc -{ - /** - * This class is an interface to the real implementation of TcpSocketClient. Kind of a strategy design pattern. - */ - class TcpSocketClientPrivate : public IClientConnector - { - }; - -} /* namespace jsonrpc */ -#endif /* JSONRPC_CPP_TCPSOCKETCLIENTPRIVATE_H_ */ diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index a1da2e96..7835d699 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -2,7 +2,7 @@ * libjson-rpc-cpp ************************************************************************* * @file windowstcpsocketclient.h - * @date 17.07.2015 + * @date 17.10.2016 * @author Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ @@ -12,7 +12,7 @@ #include #include -#include "tcpsocketclientprivate.h" +#include #include namespace jsonrpc @@ -21,7 +21,7 @@ namespace jsonrpc * This class is the windows implementation of TCPSocketClient. * It uses the Winsock2 API to performs its job. */ - class WindowsTcpSocketClient : public TcpSocketClientPrivate + class WindowsTcpSocketClient : public IClientConnector { public: /** @@ -53,20 +53,20 @@ namespace jsonrpc static std::string GetErrorMessage(const int &e); /** * @brief Connects to the host and port provided by constructor parameters. - * + * * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. * On first case it tries to connect to the ip. * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. - * + * * @returns A file descriptor to the successfully connected socket * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). */ SOCKET Connect() throw (JsonRpcException); /** * @brief Connects to provided ip and port. - * + * * This method tries to connect to the provided ip and port. - * + * * @param ip The ipv4 address to connect to * @param port The port to connect to * @returns A file descriptor to the successfully connected socket @@ -75,7 +75,7 @@ namespace jsonrpc SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); /** * @brief Check if provided ip is an ipv4 address. - * + * * @param ip The ipv4 address to check * @returns A boolean indicating if the provided ip is or is not an ipv4 address */ From 3ac4398266605f66e12e6a75039adc18f5d221ab Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Mon, 17 Oct 2016 09:25:02 -0700 Subject: [PATCH 2/3] updated authors --- AUTHORS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 081b7f70..b0e238a4 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -63,3 +63,6 @@ Erik Lundin Michał Górny + bugfixes in the build system + +Trevor Vannoy ++ fixed tcp socket client compile issues From 11adbe6c895791933b80697eec264267b8d2457d Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Mon, 17 Oct 2016 09:32:29 -0700 Subject: [PATCH 3/3] converted tabs to spaces... --- .../connectors/linuxtcpsocketclient.cpp | 364 +++++++-------- .../client/connectors/linuxtcpsocketclient.h | 114 ++--- .../client/connectors/tcpsocketclient.cpp | 24 +- .../client/connectors/tcpsocketclient.h | 16 +- .../connectors/unixdomainsocketclient.cpp | 70 +-- .../connectors/unixdomainsocketclient.h | 18 +- .../connectors/windowstcpsocketclient.cpp | 436 +++++++++--------- .../connectors/windowstcpsocketclient.h | 126 ++--- .../connectors/linuxtcpsocketserver.cpp | 344 +++++++------- .../server/connectors/linuxtcpsocketserver.h | 81 ++-- .../server/connectors/tcpsocketserver.cpp | 48 +- .../server/connectors/tcpsocketserver.h | 47 +- .../connectors/unixdomainsocketserver.cpp | 272 +++++------ .../connectors/unixdomainsocketserver.h | 71 ++- .../connectors/windowstcpsocketserver.cpp | 384 +++++++-------- .../connectors/windowstcpsocketserver.h | 83 ++-- 16 files changed, 1247 insertions(+), 1251 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 1b14a684..a4022077 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -29,8 +29,8 @@ using namespace jsonrpc; using namespace std; LinuxTcpSocketClient::LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port) : - hostToConnect(hostToConnect), - port(port) + hostToConnect(hostToConnect), + port(port) { } @@ -40,197 +40,197 @@ LinuxTcpSocketClient::~LinuxTcpSocketClient() void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - int socket_fd = this->Connect(); - char buffer[BUFFER_SIZE]; - - bool fullyWritten = false; - string toSend = message; - do - { - ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten == -1) - { - string message = "send() failed"; - int err = errno; - switch(err) - { - case EACCES: - case EWOULDBLOCK: - case EBADF: - case ECONNRESET: - case EDESTADDRREQ: - case EFAULT: - case EINTR: - case EINVAL: - case EISCONN: - case EMSGSIZE: - case ENOBUFS: - case ENOMEM: - case ENOTCONN: - case ENOTSOCK: - case EOPNOTSUPP: - case EPIPE: - message = strerror(err); - break; - } - close(socket_fd); - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else if(static_cast(byteWritten) < toSend.size()) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten); - - do - { - int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); - if(nbytes == -1) - { - string message = "recv() failed"; - int err = errno; - switch(err) - { - case EWOULDBLOCK: - case EBADF: - case ECONNRESET: - case EFAULT: - case EINTR: - case EINVAL: - case ENOMEM: - case ENOTCONN: - case ENOTSOCK: - message = strerror(err); - break; - } - close(socket_fd); - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else - { - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); - } - } while(result.find(DELIMITER_CHAR) == string::npos); - - close(socket_fd); + int socket_fd = this->Connect(); + char buffer[BUFFER_SIZE]; + + bool fullyWritten = false; + string toSend = message; + do + { + ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); + if(byteWritten == -1) + { + string message = "send() failed"; + int err = errno; + switch(err) + { + case EACCES: + case EWOULDBLOCK: + case EBADF: + case ECONNRESET: + case EDESTADDRREQ: + case EFAULT: + case EINTR: + case EINVAL: + case EISCONN: + case EMSGSIZE: + case ENOBUFS: + case ENOMEM: + case ENOTCONN: + case ENOTSOCK: + case EOPNOTSUPP: + case EPIPE: + message = strerror(err); + break; + } + close(socket_fd); + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(static_cast(byteWritten) < toSend.size()) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten); + + do + { + int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + if(nbytes == -1) + { + string message = "recv() failed"; + int err = errno; + switch(err) + { + case EWOULDBLOCK: + case EBADF: + case ECONNRESET: + case EFAULT: + case EINTR: + case EINVAL: + case ENOMEM: + case ENOTCONN: + case ENOTSOCK: + message = strerror(err); + break; + } + close(socket_fd); + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else + { + string tmp; + tmp.append(buffer, nbytes); + result.append(buffer,nbytes); + } + } while(result.find(DELIMITER_CHAR) == string::npos); + + close(socket_fd); } int LinuxTcpSocketClient::Connect() throw (JsonRpcException) { - if(this->IsIpv4Address(this->hostToConnect)) - { - return this->Connect(this->hostToConnect, this->port); - } - else //We were given a hostname - { - struct addrinfo *result = NULL; - struct addrinfo hints; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + if(this->IsIpv4Address(this->hostToConnect)) + { + return this->Connect(this->hostToConnect, this->port); + } + else //We were given a hostname + { + struct addrinfo *result = NULL; + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; char port[6]; - snprintf(port, 6, "%d", this->port); - int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - if(retval != 0) - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); - bool foundValidIp = false; - int socket_fd; - for(struct addrinfo *temp = result; (temp != NULL) && !foundValidIp; temp = temp->ai_next) - { - if(temp->ai_family == AF_INET) - { - try - { - sockaddr_in* sock = reinterpret_cast(temp->ai_addr); - socket_fd = this->Connect(inet_ntoa(sock->sin_addr), ntohs(sock->sin_port)); - foundValidIp = true; - } - catch(const JsonRpcException& e) - { - foundValidIp = false; - socket_fd = -1; - } - catch(void* p) - { - foundValidIp = false; - socket_fd = -1; - } - } - } - - if(!foundValidIp) - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); - - return socket_fd; - } + snprintf(port, 6, "%d", this->port); + int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + if(retval != 0) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); + bool foundValidIp = false; + int socket_fd; + for(struct addrinfo *temp = result; (temp != NULL) && !foundValidIp; temp = temp->ai_next) + { + if(temp->ai_family == AF_INET) + { + try + { + sockaddr_in* sock = reinterpret_cast(temp->ai_addr); + socket_fd = this->Connect(inet_ntoa(sock->sin_addr), ntohs(sock->sin_port)); + foundValidIp = true; + } + catch(const JsonRpcException& e) + { + foundValidIp = false; + socket_fd = -1; + } + catch(void* p) + { + foundValidIp = false; + socket_fd = -1; + } + } + } + + if(!foundValidIp) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); + + return socket_fd; + } } int LinuxTcpSocketClient::Connect(const string& ip, const int& port) throw (JsonRpcException) { - sockaddr_in address; - int socket_fd; - socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 0) - { - string message = "socket() failed"; - int err = errno; - switch(err) - { - case EACCES: - case EAFNOSUPPORT: - case EINVAL: - case EMFILE: - case ENOBUFS: - case ENOMEM: - case EPROTONOSUPPORT: - message = strerror(err); - break; - } - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - memset(&address, 0, sizeof(sockaddr_in)); - - address.sin_family = AF_INET; - inet_aton(ip.c_str(), &(address.sin_addr)); - address.sin_port = htons(port); - - if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) - { - string message = "connect() failed"; - int err = errno; - switch(err) - { - case EACCES: - case EPERM: - case EADDRINUSE: - case EAFNOSUPPORT: - case EAGAIN: - case EALREADY: - case EBADF: - case ECONNREFUSED: - case EFAULT: - case EINPROGRESS: - case EINTR: - case EISCONN: - case ENETUNREACH: - case ENOTSOCK: - case ETIMEDOUT: - message = strerror(err); - break; - } - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - return socket_fd; + sockaddr_in address; + int socket_fd; + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) + { + string message = "socket() failed"; + int err = errno; + switch(err) + { + case EACCES: + case EAFNOSUPPORT: + case EINVAL: + case EMFILE: + case ENOBUFS: + case ENOMEM: + case EPROTONOSUPPORT: + message = strerror(err); + break; + } + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + memset(&address, 0, sizeof(sockaddr_in)); + + address.sin_family = AF_INET; + inet_aton(ip.c_str(), &(address.sin_addr)); + address.sin_port = htons(port); + + if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) + { + string message = "connect() failed"; + int err = errno; + switch(err) + { + case EACCES: + case EPERM: + case EADDRINUSE: + case EAFNOSUPPORT: + case EAGAIN: + case EALREADY: + case EBADF: + case ECONNREFUSED: + case EFAULT: + case EINPROGRESS: + case EINTR: + case EISCONN: + case ENETUNREACH: + case ENOTSOCK: + case ETIMEDOUT: + message = strerror(err); + break; + } + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + return socket_fd; } bool LinuxTcpSocketClient::IsIpv4Address(const std::string& ip) { - struct in_addr addr; - return (inet_aton(ip.c_str(), &addr) != 0); + struct in_addr addr; + return (inet_aton(ip.c_str(), &addr) != 0); } diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h index a46c6eb3..c343b9bd 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -14,64 +14,64 @@ namespace jsonrpc { - /** - * This class is the Linux/UNIX implementation of TCPSocketClient. - * It uses the POSIX socket API to performs its job. - */ - class LinuxTcpSocketClient : public IClientConnector - { - public: - /** - * @brief LinuxTcpSocketClient, constructor of the Linux/UNIX implementation of class TcpSocketClient - * @param hostToConnect The hostname or the ipv4 address on which the client should try to connect - * @param port The port on which the client should try to connect - */ - LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); - /** - * @brief ~LinuxTcpSocketClient, the destructor of LinuxTcpSocketClient - */ - virtual ~LinuxTcpSocketClient(); - /** - * @brief The real implementation of TcpSocketClient::SendRPCMessage method. - * @param message The message to send - * @param result The result of the call returned by the server - * @throw JsonRpcException Thrown when an issue is encountered with socket manipulation (see message of exception for more information about what happened). - */ - virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + /** + * This class is the Linux/UNIX implementation of TCPSocketClient. + * It uses the POSIX socket API to performs its job. + */ + class LinuxTcpSocketClient : public IClientConnector + { + public: + /** + * @brief LinuxTcpSocketClient, constructor of the Linux/UNIX implementation of class TcpSocketClient + * @param hostToConnect The hostname or the ipv4 address on which the client should try to connect + * @param port The port on which the client should try to connect + */ + LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); + /** + * @brief ~LinuxTcpSocketClient, the destructor of LinuxTcpSocketClient + */ + virtual ~LinuxTcpSocketClient(); + /** + * @brief The real implementation of TcpSocketClient::SendRPCMessage method. + * @param message The message to send + * @param result The result of the call returned by the server + * @throw JsonRpcException Thrown when an issue is encountered with socket manipulation (see message of exception for more information about what happened). + */ + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); - private: - std::string hostToConnect; /*!< The hostname or the ipv4 address on which the client should try to connect*/ - unsigned int port; /*!< The port on which the client should try to connect*/ - /** - * @brief Connects to the host and port provided by constructor parameters. - * - * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. - * On first case it tries to connect to the ip. - * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. - * - * @returns A file descriptor to the successfully connected socket - * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). - */ - int Connect() throw (JsonRpcException); - /** - * @brief Connects to provided ip and port. - * - * This method tries to connect to the provided ip and port. - * - * @param ip The ipv4 address to connect to - * @param port The port to connect to - * @returns A file descriptor to the successfully connected socket - * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). - */ - int Connect(const std::string& ip, const int& port) throw (JsonRpcException); - /** - * @brief Check if provided ip is an ipv4 address. - * - * @param ip The ipv4 address to check - * @returns A boolean indicating if the provided ip is or is not an ipv4 address - */ - bool IsIpv4Address(const std::string& ip); - }; + private: + std::string hostToConnect; /*!< The hostname or the ipv4 address on which the client should try to connect*/ + unsigned int port; /*!< The port on which the client should try to connect*/ + /** + * @brief Connects to the host and port provided by constructor parameters. + * + * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. + * On first case it tries to connect to the ip. + * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. + * + * @returns A file descriptor to the successfully connected socket + * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). + */ + int Connect() throw (JsonRpcException); + /** + * @brief Connects to provided ip and port. + * + * This method tries to connect to the provided ip and port. + * + * @param ip The ipv4 address to connect to + * @param port The port to connect to + * @returns A file descriptor to the successfully connected socket + * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). + */ + int Connect(const std::string& ip, const int& port) throw (JsonRpcException); + /** + * @brief Check if provided ip is an ipv4 address. + * + * @param ip The ipv4 address to check + * @returns A boolean indicating if the provided ip is or is not an ipv4 address + */ + bool IsIpv4Address(const std::string& ip); + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ */ diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp index 874e0faa..be3c1d5f 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp @@ -21,27 +21,27 @@ using namespace std; TcpSocketClient::TcpSocketClient(const std::string& ipToConnect, const unsigned int &port) { #ifdef __WIN32__ - this->realSocket = new WindowsTcpSocketClient(ipToConnect, port); + this->realSocket = new WindowsTcpSocketClient(ipToConnect, port); #elif __unix__ - this->realSocket = new LinuxTcpSocketClient(ipToConnect, port); + this->realSocket = new LinuxTcpSocketClient(ipToConnect, port); #else - this->realSocket = NULL; + this->realSocket = NULL; #endif } TcpSocketClient::~TcpSocketClient() { - if(this->realSocket != NULL) - { - delete this->realSocket; - this->realSocket = NULL; - } + if(this->realSocket != NULL) + { + delete this->realSocket; + this->realSocket = NULL; + } } void TcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - if(this->realSocket != NULL) - { - this->realSocket->SendRPCMessage(message, result); - } + if(this->realSocket != NULL) + { + this->realSocket->SendRPCMessage(message, result); + } } diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.h b/src/jsonrpccpp/client/connectors/tcpsocketclient.h index a011783b..65b48245 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.h @@ -23,9 +23,9 @@ namespace jsonrpc * This class hides OS specific features in real implementation of this client. Currently it has implementation for * both Linux and Windows. */ - class TcpSocketClient : public IClientConnector - { - public: + class TcpSocketClient : public IClientConnector + { + public: /** * @brief TcpSocketClient, constructor for the included TcpSocketClient * @@ -34,7 +34,7 @@ namespace jsonrpc * @param ipToConnect The ipv4 address on which the client should try to connect * @param port The port on which the client should try to connect */ - TcpSocketClient(const std::string& ipToConnect, const unsigned int &port); + TcpSocketClient(const std::string& ipToConnect, const unsigned int &port); /** * @brief ~TcpSocketClient, the destructor of TcpSocketClient */ @@ -45,11 +45,11 @@ namespace jsonrpc * @param result The result of the call returned by the servsr * @throw JsonRpcException Thrown when an issue is encounter with socket manipulation (see message of exception for more information about what happened). */ - virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); - private: - IClientConnector *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ - }; + private: + IClientConnector *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_TCPSOCKETCLIENT_H_ */ diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index 585e88d8..363fcfcb 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -27,7 +27,7 @@ using namespace jsonrpc; using namespace std; - UnixDomainSocketClient::UnixDomainSocketClient(const std::string& path) + UnixDomainSocketClient::UnixDomainSocketClient(const std::string& path) : path(path) { } @@ -38,47 +38,47 @@ UnixDomainSocketClient::~UnixDomainSocketClient() void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - sockaddr_un address; - int socket_fd, nbytes; - char buffer[BUFFER_SIZE]; - socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (socket_fd < 0) - { - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not created unix domain socket"); - } + sockaddr_un address; + int socket_fd, nbytes; + char buffer[BUFFER_SIZE]; + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (socket_fd < 0) + { + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not created unix domain socket"); + } - memset(&address, 0, sizeof(sockaddr_un)); + memset(&address, 0, sizeof(sockaddr_un)); address.sun_family = AF_UNIX; snprintf(address.sun_path, PATH_MAX, "%s", this->path.c_str()); - if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) - { - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not connect to: " + this->path); - } + if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) + { + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not connect to: " + this->path); + } - bool fullyWritten = false; - string toSend = message; - do - { - ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); - if(static_cast(byteWritten) < toSend.size()) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten); + bool fullyWritten = false; + string toSend = message; + do + { + ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); + if(static_cast(byteWritten) < toSend.size()) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten); - do - { - nbytes = read(socket_fd, buffer, BUFFER_SIZE); - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); + do + { + nbytes = read(socket_fd, buffer, BUFFER_SIZE); + string tmp; + tmp.append(buffer, nbytes); + result.append(buffer,nbytes); - } while(result.find(DELIMITER_CHAR) == string::npos); + } while(result.find(DELIMITER_CHAR) == string::npos); - close(socket_fd); + close(socket_fd); } diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h index 78bfbe28..b1250c32 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h @@ -15,16 +15,16 @@ namespace jsonrpc { - class UnixDomainSocketClient : public IClientConnector - { - public: - UnixDomainSocketClient(const std::string& path); - virtual ~UnixDomainSocketClient(); - virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + class UnixDomainSocketClient : public IClientConnector + { + public: + UnixDomainSocketClient(const std::string& path); + virtual ~UnixDomainSocketClient(); + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); - private: - std::string path; - }; + private: + std::string path; + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_HTTPCLIENT_H_ */ diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index 4ebdf6f3..81e85a7f 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -24,8 +24,8 @@ using namespace jsonrpc; using namespace std; WindowsTcpSocketClient::WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port) : - hostToConnect(hostToConnect), - port(port) + hostToConnect(hostToConnect), + port(port) { } @@ -35,256 +35,256 @@ WindowsTcpSocketClient::~WindowsTcpSocketClient() void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - SOCKET socket_fd = this->Connect(); - char buffer[BUFFER_SIZE]; - bool fullyWritten = false; - string toSend = message; - do - { - int byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten == -1) - { - string message = "send() failed"; - int err = WSAGetLastError(); - switch(err) - { - case WSANOTINITIALISED: - case WSAENETDOWN: - case WSAEACCES: - case WSAEINTR: - case WSAEINPROGRESS: - case WSAEFAULT: - case WSAENETRESET: - case WSAENOBUFS: - case WSAENOTCONN: - case WSAENOTSOCK: - case WSAEOPNOTSUPP: - case WSAESHUTDOWN: - case WSAEWOULDBLOCK: - case WSAEMSGSIZE: - case WSAEHOSTUNREACH: - case WSAEINVAL: - case WSAECONNABORTED: - case WSAECONNRESET: - case WSAETIMEDOUT: - message = GetErrorMessage(err); - break; - } - closesocket(socket_fd); - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else if(static_cast(byteWritten) < toSend.size()) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten); + SOCKET socket_fd = this->Connect(); + char buffer[BUFFER_SIZE]; + bool fullyWritten = false; + string toSend = message; + do + { + int byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); + if(byteWritten == -1) + { + string message = "send() failed"; + int err = WSAGetLastError(); + switch(err) + { + case WSANOTINITIALISED: + case WSAENETDOWN: + case WSAEACCES: + case WSAEINTR: + case WSAEINPROGRESS: + case WSAEFAULT: + case WSAENETRESET: + case WSAENOBUFS: + case WSAENOTCONN: + case WSAENOTSOCK: + case WSAEOPNOTSUPP: + case WSAESHUTDOWN: + case WSAEWOULDBLOCK: + case WSAEMSGSIZE: + case WSAEHOSTUNREACH: + case WSAEINVAL: + case WSAECONNABORTED: + case WSAECONNRESET: + case WSAETIMEDOUT: + message = GetErrorMessage(err); + break; + } + closesocket(socket_fd); + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(static_cast(byteWritten) < toSend.size()) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten); - do - { - int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); - if(nbytes == -1) - { - string message = "recv() failed"; - int err = WSAGetLastError(); - switch(err) - { - case WSANOTINITIALISED: - case WSAENETDOWN: - case WSAEFAULT: - case WSAENOTCONN: - case WSAEINTR: - case WSAEINPROGRESS: - case WSAENETRESET: - case WSAENOTSOCK: - case WSAEOPNOTSUPP: - case WSAESHUTDOWN: - case WSAEWOULDBLOCK: - case WSAEMSGSIZE: - case WSAEINVAL: - case WSAECONNABORTED: - case WSAETIMEDOUT: - case WSAECONNRESET: - message = GetErrorMessage(err); - break; - } - closesocket(socket_fd); - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else - { - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); - } + do + { + int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + if(nbytes == -1) + { + string message = "recv() failed"; + int err = WSAGetLastError(); + switch(err) + { + case WSANOTINITIALISED: + case WSAENETDOWN: + case WSAEFAULT: + case WSAENOTCONN: + case WSAEINTR: + case WSAEINPROGRESS: + case WSAENETRESET: + case WSAENOTSOCK: + case WSAEOPNOTSUPP: + case WSAESHUTDOWN: + case WSAEWOULDBLOCK: + case WSAEMSGSIZE: + case WSAEINVAL: + case WSAECONNABORTED: + case WSAETIMEDOUT: + case WSAECONNRESET: + message = GetErrorMessage(err); + break; + } + closesocket(socket_fd); + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else + { + string tmp; + tmp.append(buffer, nbytes); + result.append(buffer,nbytes); + } - } while(result.find(DELIMITER_CHAR) == string::npos); + } while(result.find(DELIMITER_CHAR) == string::npos); - closesocket(socket_fd); + closesocket(socket_fd); } string WindowsTcpSocketClient::GetErrorMessage(const int& e) { - LPVOID lpMsgBuf; - lpMsgBuf = (LPVOID)"Unknown error"; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, e, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, 0, NULL); - string message(static_cast(lpMsgBuf)); - LocalFree(lpMsgBuf); - return message; + LPVOID lpMsgBuf; + lpMsgBuf = (LPVOID)"Unknown error"; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, 0, NULL); + string message(static_cast(lpMsgBuf)); + LocalFree(lpMsgBuf); + return message; } SOCKET WindowsTcpSocketClient::Connect() throw (JsonRpcException) { - if(this->IsIpv4Address(this->hostToConnect)) - { - return this->Connect(this->hostToConnect, this->port); - } - else //We were given a hostname - { - struct addrinfo *result = NULL; - struct addrinfo hints; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + if(this->IsIpv4Address(this->hostToConnect)) + { + return this->Connect(this->hostToConnect, this->port); + } + else //We were given a hostname + { + struct addrinfo *result = NULL; + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; char port[6]; - port = itoa(this->port, port, 10); - DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - if(retval != 0) - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); + port = itoa(this->port, port, 10); + DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + if(retval != 0) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); - bool foundValidIp = false; - SOCKET socket_fd = INVALID_SOCKET; - for(struct addrinfo *temp = result; (temp != NULL) && !foundValidIp; temp = temp->ai_next) - { - if(temp->ai_family == AF_INET) - { - try - { - SOCKADDR_IN* sock = reinterpret_cast(temp->ai_addr); - socket_fd = this->Connect(inet_ntoa(sock->sin_addr), ntohs(sock->sin_port)); - foundValidIp = true; - } - catch(const JsonRpcException& e) - { - foundValidIp = false; - socket_fd = INVALID_SOCKET; - } - catch(void* p) - { - foundValidIp = false; - socket_fd = INVALID_SOCKET; - } - } - } + bool foundValidIp = false; + SOCKET socket_fd = INVALID_SOCKET; + for(struct addrinfo *temp = result; (temp != NULL) && !foundValidIp; temp = temp->ai_next) + { + if(temp->ai_family == AF_INET) + { + try + { + SOCKADDR_IN* sock = reinterpret_cast(temp->ai_addr); + socket_fd = this->Connect(inet_ntoa(sock->sin_addr), ntohs(sock->sin_port)); + foundValidIp = true; + } + catch(const JsonRpcException& e) + { + foundValidIp = false; + socket_fd = INVALID_SOCKET; + } + catch(void* p) + { + foundValidIp = false; + socket_fd = INVALID_SOCKET; + } + } + } - if(!foundValidIp) - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); + if(!foundValidIp) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); - return socket_fd; - } + return socket_fd; + } } SOCKET WindowsTcpSocketClient::Connect(const string& ip, const int& port) throw (JsonRpcException) { - SOCKADDR_IN address; - SOCKET socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd == INVALID_SOCKET) - { - string message = "socket() failed"; - int err = WSAGetLastError(); - switch(err) - { - case WSANOTINITIALISED: - case WSAENETDOWN: - case WSAEAFNOSUPPORT: - case WSAEINPROGRESS: - case WSAEMFILE: - case WSAEINVAL: - case WSAEINVALIDPROVIDER: - case WSAEINVALIDPROCTABLE: - case WSAENOBUFS: - case WSAEPROTONOSUPPORT: - case WSAEPROTOTYPE: - case WSAEPROVIDERFAILEDINIT: - case WSAESOCKTNOSUPPORT: - message = GetErrorMessage(err); - break; - } - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - memset(&address, 0, sizeof(SOCKADDR_IN)); + SOCKADDR_IN address; + SOCKET socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd == INVALID_SOCKET) + { + string message = "socket() failed"; + int err = WSAGetLastError(); + switch(err) + { + case WSANOTINITIALISED: + case WSAENETDOWN: + case WSAEAFNOSUPPORT: + case WSAEINPROGRESS: + case WSAEMFILE: + case WSAEINVAL: + case WSAEINVALIDPROVIDER: + case WSAEINVALIDPROCTABLE: + case WSAENOBUFS: + case WSAEPROTONOSUPPORT: + case WSAEPROTOTYPE: + case WSAEPROVIDERFAILEDINIT: + case WSAESOCKTNOSUPPORT: + message = GetErrorMessage(err); + break; + } + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + memset(&address, 0, sizeof(SOCKADDR_IN)); - address.sin_family = AF_INET; - address.sin_addr.s_addr = inet_addr(ip.c_str()); - address.sin_port = htons(port); - if(connect(socket_fd, reinterpret_cast(&address), sizeof(SOCKADDR_IN)) != 0) - { - string message = "connect() failed"; - int err = WSAGetLastError(); - switch(err) - { - case WSANOTINITIALISED: - case WSAENETDOWN: - case WSAEADDRINUSE: - case WSAEINTR: - case WSAEINPROGRESS: - case WSAEALREADY: - case WSAEADDRNOTAVAIL: - case WSAEAFNOSUPPORT: - case WSAECONNREFUSED: - case WSAEFAULT: - case WSAEINVAL: - case WSAEISCONN: - case WSAENETUNREACH: - case WSAEHOSTUNREACH: - case WSAENOBUFS: - case WSAENOTSOCK: - case WSAETIMEDOUT: - case WSAEWOULDBLOCK: - case WSAEACCES: - message = GetErrorMessage(err); - break; - } - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - return socket_fd; + address.sin_family = AF_INET; + address.sin_addr.s_addr = inet_addr(ip.c_str()); + address.sin_port = htons(port); + if(connect(socket_fd, reinterpret_cast(&address), sizeof(SOCKADDR_IN)) != 0) + { + string message = "connect() failed"; + int err = WSAGetLastError(); + switch(err) + { + case WSANOTINITIALISED: + case WSAENETDOWN: + case WSAEADDRINUSE: + case WSAEINTR: + case WSAEINPROGRESS: + case WSAEALREADY: + case WSAEADDRNOTAVAIL: + case WSAEAFNOSUPPORT: + case WSAECONNREFUSED: + case WSAEFAULT: + case WSAEINVAL: + case WSAEISCONN: + case WSAENETUNREACH: + case WSAEHOSTUNREACH: + case WSAENOBUFS: + case WSAENOTSOCK: + case WSAETIMEDOUT: + case WSAEWOULDBLOCK: + case WSAEACCES: + message = GetErrorMessage(err); + break; + } + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + return socket_fd; } bool WindowsTcpSocketClient::IsIpv4Address(const std::string& ip) { - return (inet_addr(ip.c_str()) != INADDR_NONE); + return (inet_addr(ip.c_str()) != INADDR_NONE); } //This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). struct ClientSocketInitializer { - ClientSocketInitializer() + ClientSocketInitializer() - { - WSADATA init; - if(WSAStartup(MAKEWORD(2, 2), &init) != 0) - { + { + WSADATA init; + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) + { throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); - } - } + } + } - ~ClientSocketInitializer() + ~ClientSocketInitializer() - { - if(WSACleanup() != 0) - { + { + if(WSACleanup() != 0) + { cerr << "An issue occured while WSAClean executed." << endl; - } - } + } + } }; struct ClientSocketInitializer clientGlobalInitializer; diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index 7835d699..ef0b4023 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -17,70 +17,70 @@ namespace jsonrpc { - /** - * This class is the windows implementation of TCPSocketClient. - * It uses the Winsock2 API to performs its job. - */ - class WindowsTcpSocketClient : public IClientConnector - { - public: - /** - * @brief WindowsTcpSocketClient, constructor of the Windows implementation of class TcpSocketClient - * @param hostToConnect The hostname or the ipv4 address on which the client should try to connect - * @param port The port on which the client should try to connect - */ - WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); - /** - * @brief ~WindowsTcpSocketClient, the destructor of WindowsTcpSocketClient - */ - virtual ~WindowsTcpSocketClient(); - /** - * @brief The real implementation of TcpSocketClient::SendRPCMessage method. - * @param message The message to send - * @param result The result of the call returned by the server - * @throw JsonRpcException Thrown when an issue is encounter with socket manipulation (see message of exception for more information about what happened). - */ - virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + /** + * This class is the windows implementation of TCPSocketClient. + * It uses the Winsock2 API to performs its job. + */ + class WindowsTcpSocketClient : public IClientConnector + { + public: + /** + * @brief WindowsTcpSocketClient, constructor of the Windows implementation of class TcpSocketClient + * @param hostToConnect The hostname or the ipv4 address on which the client should try to connect + * @param port The port on which the client should try to connect + */ + WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); + /** + * @brief ~WindowsTcpSocketClient, the destructor of WindowsTcpSocketClient + */ + virtual ~WindowsTcpSocketClient(); + /** + * @brief The real implementation of TcpSocketClient::SendRPCMessage method. + * @param message The message to send + * @param result The result of the call returned by the server + * @throw JsonRpcException Thrown when an issue is encounter with socket manipulation (see message of exception for more information about what happened). + */ + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); - private: - std::string hostToConnect; /*!< The hostname or the ipv4 address on which the client should try to connect*/ - unsigned int port; /*!< The port on which the client should try to connect*/ - /** - * @brief A method to produce human readable messages from Winsock2 error values. - * @param e A Winsock2 error value - * @return The message matching the error value - */ - static std::string GetErrorMessage(const int &e); - /** - * @brief Connects to the host and port provided by constructor parameters. - * - * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. - * On first case it tries to connect to the ip. - * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. - * - * @returns A file descriptor to the successfully connected socket - * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). - */ - SOCKET Connect() throw (JsonRpcException); - /** - * @brief Connects to provided ip and port. - * - * This method tries to connect to the provided ip and port. - * - * @param ip The ipv4 address to connect to - * @param port The port to connect to - * @returns A file descriptor to the successfully connected socket - * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). - */ - SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); - /** - * @brief Check if provided ip is an ipv4 address. - * - * @param ip The ipv4 address to check - * @returns A boolean indicating if the provided ip is or is not an ipv4 address - */ - bool IsIpv4Address(const std::string& ip); - }; + private: + std::string hostToConnect; /*!< The hostname or the ipv4 address on which the client should try to connect*/ + unsigned int port; /*!< The port on which the client should try to connect*/ + /** + * @brief A method to produce human readable messages from Winsock2 error values. + * @param e A Winsock2 error value + * @return The message matching the error value + */ + static std::string GetErrorMessage(const int &e); + /** + * @brief Connects to the host and port provided by constructor parameters. + * + * This method detects if the hostToConnect attribute is either an IPv4 or a hostname. + * On first case it tries to connect to the ip. + * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful. + * + * @returns A file descriptor to the successfully connected socket + * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). + */ + SOCKET Connect() throw (JsonRpcException); + /** + * @brief Connects to provided ip and port. + * + * This method tries to connect to the provided ip and port. + * + * @param ip The ipv4 address to connect to + * @param port The port to connect to + * @returns A file descriptor to the successfully connected socket + * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened). + */ + SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); + /** + * @brief Check if provided ip is an ipv4 address. + * + * @param ip The ipv4 address to check + * @returns A boolean indicating if the provided ip is or is not an ipv4 address + */ + bool IsIpv4Address(const std::string& ip); + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_ */ diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index d25edc04..5ef0ba96 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -35,229 +35,229 @@ using namespace std; LinuxTcpSocketServer::LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : AbstractServerConnector(), running(false), - ipToBind(ipToBind), + ipToBind(ipToBind), port(port) { } bool LinuxTcpSocketServer::StartListening() { - if(!this->running) - { - //Create and bind socket here. - //Then launch the listenning loop. - this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if(this->socket_fd < 0) - { - return false; - } + if(!this->running) + { + //Create and bind socket here. + //Then launch the listenning loop. + this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if(this->socket_fd < 0) + { + return false; + } - fcntl(this->socket_fd, F_SETFL, FNDELAY); - int reuseaddr = 1; - setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); + fcntl(this->socket_fd, F_SETFL, FNDELAY); + int reuseaddr = 1; + setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); - /* start with a clean address structure */ - memset(&(this->address), 0, sizeof(struct sockaddr_in)); + /* start with a clean address structure */ + memset(&(this->address), 0, sizeof(struct sockaddr_in)); - this->address.sin_family = AF_INET; - inet_aton(this->ipToBind.c_str(), &(this->address.sin_addr)); - this->address.sin_port = htons(this->port); + this->address.sin_family = AF_INET; + inet_aton(this->ipToBind.c_str(), &(this->address.sin_addr)); + this->address.sin_port = htons(this->port); - if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_in)) != 0) - { - return false; - } + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_in)) != 0) + { + return false; + } - if(listen(this->socket_fd, 5) != 0) - { - return false; - } - //Launch listening loop there - this->running = true; - int ret = pthread_create(&(this->listenning_thread), NULL, LinuxTcpSocketServer::LaunchLoop, this); - if(ret != 0) - { - pthread_detach(this->listenning_thread); - shutdown(this->socket_fd, 2); - close(this->socket_fd); - } - this->running = static_cast(ret==0); - return this->running; - } - else - { - return false; - } + if(listen(this->socket_fd, 5) != 0) + { + return false; + } + //Launch listening loop there + this->running = true; + int ret = pthread_create(&(this->listenning_thread), NULL, LinuxTcpSocketServer::LaunchLoop, this); + if(ret != 0) + { + pthread_detach(this->listenning_thread); + shutdown(this->socket_fd, 2); + close(this->socket_fd); + } + this->running = static_cast(ret==0); + return this->running; + } + else + { + return false; + } } bool LinuxTcpSocketServer::StopListening() { - if(this->running) - { - this->running = false; - pthread_join(this->listenning_thread, NULL); - shutdown(this->socket_fd, 2); - close(this->socket_fd); - return !(this->running); - } - else - { - return false; - } + if(this->running) + { + this->running = false; + pthread_join(this->listenning_thread, NULL); + shutdown(this->socket_fd, 2); + close(this->socket_fd); + return !(this->running); + } + else + { + return false; + } } bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) { - bool result = false; - int connection_fd = reinterpret_cast(addInfo); + bool result = false; + int connection_fd = reinterpret_cast(addInfo); - string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) - { - temp.append(1, DELIMITER_CHAR); - } - if(DELIMITER_CHAR != '\n') - { - char eot = DELIMITER_CHAR; - string toSend = temp.substr(0, toSend.find_last_of('\n')); - toSend += eot; - result = this->WriteToSocket(connection_fd, toSend); - } - else - { - result = this->WriteToSocket(connection_fd, temp); - } - CleanClose(connection_fd); - return result; + string temp = response; + if(temp.find(DELIMITER_CHAR) == string::npos) + { + temp.append(1, DELIMITER_CHAR); + } + if(DELIMITER_CHAR != '\n') + { + char eot = DELIMITER_CHAR; + string toSend = temp.substr(0, toSend.find_last_of('\n')); + toSend += eot; + result = this->WriteToSocket(connection_fd, toSend); + } + else + { + result = this->WriteToSocket(connection_fd, temp); + } + CleanClose(connection_fd); + return result; } void* LinuxTcpSocketServer::LaunchLoop(void *p_data) { - pthread_detach(pthread_self()); - LinuxTcpSocketServer *instance = reinterpret_cast(p_data);; - instance->ListenLoop(); - return NULL; + pthread_detach(pthread_self()); + LinuxTcpSocketServer *instance = reinterpret_cast(p_data);; + instance->ListenLoop(); + return NULL; } void LinuxTcpSocketServer::ListenLoop() { - int connection_fd = 0; - struct sockaddr_in connection_address; - memset(&connection_address, 0, sizeof(struct sockaddr_in)); - socklen_t address_length = sizeof(connection_address); - while(this->running) - { - if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(connection_address)), &address_length)) > 0) - { - pthread_t client_thread; - struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); - params->instance = this; - params->connection_fd = connection_fd; - int ret = pthread_create(&client_thread, NULL, LinuxTcpSocketServer::GenerateResponse, params); - if(ret != 0) - { - pthread_detach(client_thread); - delete params; - params = NULL; - CleanClose(connection_fd); - } - } - else - { - usleep(2500); - } - } + int connection_fd = 0; + struct sockaddr_in connection_address; + memset(&connection_address, 0, sizeof(struct sockaddr_in)); + socklen_t address_length = sizeof(connection_address); + while(this->running) + { + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(connection_address)), &address_length)) > 0) + { + pthread_t client_thread; + struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); + params->instance = this; + params->connection_fd = connection_fd; + int ret = pthread_create(&client_thread, NULL, LinuxTcpSocketServer::GenerateResponse, params); + if(ret != 0) + { + pthread_detach(client_thread); + delete params; + params = NULL; + CleanClose(connection_fd); + } + } + else + { + usleep(2500); + } + } } void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { - pthread_detach(pthread_self()); - struct GenerateResponseParameters* params = reinterpret_cast(p_data); - LinuxTcpSocketServer *instance = params->instance; - int connection_fd = params->connection_fd; - delete params; - params = NULL; - int nbytes; - char buffer[BUFFER_SIZE]; - string request; - do - { //The client sends its json formatted request and a delimiter request. - nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); - if(nbytes == -1) - { - instance->CleanClose(connection_fd); - return NULL; - } - else - { - request.append(buffer,nbytes); - } - } while(request.find(DELIMITER_CHAR) == string::npos); - instance->OnRequest(request, reinterpret_cast(connection_fd)); - return NULL; + pthread_detach(pthread_self()); + struct GenerateResponseParameters* params = reinterpret_cast(p_data); + LinuxTcpSocketServer *instance = params->instance; + int connection_fd = params->connection_fd; + delete params; + params = NULL; + int nbytes; + char buffer[BUFFER_SIZE]; + string request; + do + { //The client sends its json formatted request and a delimiter request. + nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); + if(nbytes == -1) + { + instance->CleanClose(connection_fd); + return NULL; + } + else + { + request.append(buffer,nbytes); + } + } while(request.find(DELIMITER_CHAR) == string::npos); + instance->OnRequest(request, reinterpret_cast(connection_fd)); + return NULL; } bool LinuxTcpSocketServer::WriteToSocket(const int& fd, const string& toWrite) { - bool fullyWritten = false; - bool errorOccured = false; - string toSend = toWrite; - do - { - ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 0) - { - errorOccured = true; - CleanClose(fd); - } - else if(static_cast(byteWritten) < toSend.size()) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten && !errorOccured); + bool fullyWritten = false; + bool errorOccured = false; + string toSend = toWrite; + do + { + ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); + if(byteWritten < 0) + { + errorOccured = true; + CleanClose(fd); + } + else if(static_cast(byteWritten) < toSend.size()) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten && !errorOccured); - return fullyWritten && !errorOccured; + return fullyWritten && !errorOccured; } bool LinuxTcpSocketServer::WaitClientClose(const int& fd, const int &timeout) { - bool ret = false; - int i = 0; - while((recv(fd, NULL, 0, 0) != 0) && i < timeout) - { - usleep(1); - ++i; - ret = true; - } + bool ret = false; + int i = 0; + while((recv(fd, NULL, 0, 0) != 0) && i < timeout) + { + usleep(1); + ++i; + ret = true; + } - return ret; + return ret; } int LinuxTcpSocketServer::CloseByReset(const int& fd) { - struct linger so_linger; - so_linger.l_onoff = 1; - so_linger.l_linger = 0; + struct linger so_linger; + so_linger.l_onoff = 1; + so_linger.l_linger = 0; - int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)); - if(ret != 0) - return ret; + int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)); + if(ret != 0) + return ret; - return close(fd); + return close(fd); } int LinuxTcpSocketServer::CleanClose(const int& fd) { - if(WaitClientClose(fd)) - { - return close(fd); - } - else - { - return CloseByReset(fd); - } + if(WaitClientClose(fd)) + { + return close(fd); + } + else + { + return CloseByReset(fd); + } } diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index d9461d0b..22bc4b2e 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -24,121 +24,120 @@ namespace jsonrpc { - /** + /** * This class is the Linux/UNIX implementation of TCPSocketServer. * It uses the POSIX socket API and POSIX thread API to performs its job. * Each client request is handled in a new thread. */ class LinuxTcpSocketServer: public AbstractServerConnector - { - public: - /** + { + public: + /** * @brief LinuxTcpSocketServer, constructor of the Linux/UNIX implementation of class TcpSocketServer * @param ipToBind The ipv4 address on which the server should bind and listen * @param port The port on which the server should bind and listen */ - LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port); + LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port); /** * @brief The real implementation TcpSocketServer::StartListening method. - * - * This method launches the listening loop that will handle client connections. + * + * This method launches the listening loop that will handle client connections. * The return value depends on the current listening states : * - not listening and no error come up while bind and listen returns true * - not listening but error happen on bind or listen returns false * - is called while listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StartListening(); + bool StartListening(); /** * @brief The real implementation TcpSocketServer::StopListening method. - * - * This method stops the listening loop that will handle client connections. + * + * This method stops the listening loop that will handle client connections. * The return value depends on the current listening states : * - listening and successfuly stops the listen loop returns true * - is called while not listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StopListening(); + bool StopListening(); /** * @brief The real implementation TcpSocketServer::SendResponse method. - * + * * This method sends the result of the RPC Call over the tcp socket that the client has used to perform its request. * @param response The response to send to the client * @param addInfo Additionnal parameters (mainly client socket file descriptor) * @return A boolean that indicates the success or the failure of the operation. */ - bool SendResponse(const std::string& response, void* addInfo = NULL); + bool SendResponse(const std::string& response, void* addInfo = NULL); - private: - bool running; /*!< A boolean that is used to know the listening state*/ - std::string ipToBind; /*!< The ipv4 address on which the server should bind and listen*/ - unsigned int port; /*!< The port on which the server should bind and listen*/ - int socket_fd; /*!< The file descriptior of the listening socket*/ - struct sockaddr_in address; /*!< The listening socket*/ + private: + bool running; /*!< A boolean that is used to know the listening state*/ + std::string ipToBind; /*!< The ipv4 address on which the server should bind and listen*/ + unsigned int port; /*!< The port on which the server should bind and listen*/ + int socket_fd; /*!< The file descriptior of the listening socket*/ + struct sockaddr_in address; /*!< The listening socket*/ - pthread_t listenning_thread; /*!< The identifier of the listen loop thread*/ + pthread_t listenning_thread; /*!< The identifier of the listen loop thread*/ /** * @brief The static method that is used as listening thread entry point * @param p_data The parameters for the thread entry point method */ - static void* LaunchLoop(void *p_data); + static void* LaunchLoop(void *p_data); /** * @brief The method that launches the listenning loop */ - void ListenLoop(); - struct GenerateResponseParameters - { - LinuxTcpSocketServer *instance; - int connection_fd; - }; /*!< The structure used to give parameters to the Response generating method*/ + void ListenLoop(); + struct GenerateResponseParameters + { + LinuxTcpSocketServer *instance; + int connection_fd; + }; /*!< The structure used to give parameters to the Response generating method*/ /** * @brief The static method that is used as client request handling entry point * @param p_data The parameters for the thread entry point method */ - static void* GenerateResponse(void *p_data); + static void* GenerateResponse(void *p_data); /** * @brief A method that write a message to socket - * + * * Tries to send the full message. * @param fd The file descriptor of the socket message should be sent * @param toSend The message to send over socket * @returns A boolean indicating the success or the failure of the operation */ - bool WriteToSocket(const int& fd, const std::string& toSend); + bool WriteToSocket(const int& fd, const std::string& toSend); /** * @brief A method that wait for the client to close the tcp session - * + * * This method wait for the client to close the tcp session in order to avoid the server to enter in TIME_WAIT status. - * Entering in TIME_WAIT status with too many clients may occur in a DOS attack + * Entering in TIME_WAIT status with too many clients may occur in a DOS attack * since server will not be able to use a new socket when a new client connects. * @param fd The file descriptor of the socket that should be closed by the client * @param timeout The maximum time the server will wait for the client to close the tcp session in microseconds. * @returns A boolean indicating the success or the failure of the operation */ - bool WaitClientClose(const int& fd, const int &timeout = 100000); + bool WaitClientClose(const int& fd, const int &timeout = 100000); /** * @brief A method that close a socket by reseting it - * + * * This method reset the tcp session in order to avoid enter in TIME_WAIT state. * @param fd The file descriptor of the socket that should be reset * @returns The return value of POSIX close() method */ - int CloseByReset(const int& fd); + int CloseByReset(const int& fd); /** * @brief A method that cleanly close a socket by avoid TIME_WAIT state - * + * * This method uses WaitClientClose and ClodeByReset to clenly close a tcp session with a client * (avoiding TIME_WAIT to avoid DOS attacks). * @param fd The file descriptor of the socket that should be cleanly closed * @returns The return value of POSIX close() method */ - int CleanClose(const int& fd); - }; + int CleanClose(const int& fd); + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_LINUXTCPSOCKETSERVERCONNECTOR_H_ */ - diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp index e6c23c79..a4e05a0f 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp @@ -19,49 +19,49 @@ using namespace jsonrpc; using namespace std; TcpSocketServer::TcpSocketServer(const std::string& ipToBind, const unsigned int &port) : - AbstractServerConnector() + AbstractServerConnector() { #ifdef __WIN32__ - this->realSocket = new WindowsTcpSocketServer(ipToBind, port); + this->realSocket = new WindowsTcpSocketServer(ipToBind, port); #elif __unix__ - this->realSocket = new LinuxTcpSocketServer(ipToBind, port); + this->realSocket = new LinuxTcpSocketServer(ipToBind, port); #else - this->realSocket = NULL; + this->realSocket = NULL; #endif } TcpSocketServer::~TcpSocketServer() { - if(this->realSocket != NULL) - { - delete this->realSocket; - this->realSocket = NULL; - } + if(this->realSocket != NULL) + { + delete this->realSocket; + this->realSocket = NULL; + } } bool TcpSocketServer::StartListening() { - if(this->realSocket != NULL) - { - this->realSocket->SetHandler(this->GetHandler()); - return this->realSocket->StartListening(); - } - else - return false; + if(this->realSocket != NULL) + { + this->realSocket->SetHandler(this->GetHandler()); + return this->realSocket->StartListening(); + } + else + return false; } bool TcpSocketServer::StopListening() { - if(this->realSocket != NULL) - return this->realSocket->StopListening(); - else - return false; + if(this->realSocket != NULL) + return this->realSocket->StopListening(); + else + return false; } bool TcpSocketServer::SendResponse(const string& response, void* addInfo) { - if(this->realSocket != NULL) - return this->realSocket->SendResponse(response, addInfo); - else - return false; + if(this->realSocket != NULL) + return this->realSocket->SendResponse(response, addInfo); + else + return false; } diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.h b/src/jsonrpccpp/server/connectors/tcpsocketserver.h index 2c9c69f7..5321dcff 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.h @@ -14,67 +14,66 @@ namespace jsonrpc { - /** + /** * This class provides an embedded TCP Socket Server that handle incoming Requests and send result over same socket. * It uses the delimiter character to distinct a full RPC Message over the tcp flow. This character is parametered on * compilation time in implementation files. The default value for this delimiter is 0x0A a.k.a. "new line". * This class hides OS specific features in real implementation of this server. Currently it has implementation for * both Linux and Windows. */ - class TcpSocketServer: public AbstractServerConnector - { - public: - /** + class TcpSocketServer: public AbstractServerConnector + { + public: + /** * @brief TcpSocketServer, constructor for the included TcpSocketServer - * + * * Instanciates the real implementation of TcpSocketServerPrivate depending on running OS. - * + * * @param ipToBind The ipv4 address on which the server should bind and listen * @param port The port on which the server should bind and listen */ - TcpSocketServer(const std::string& ipToBind, const unsigned int &port); - /** + TcpSocketServer(const std::string& ipToBind, const unsigned int &port); + /** * @brief ~TcpSocketServer, the destructor of TcpSocketServer */ - ~TcpSocketServer(); + ~TcpSocketServer(); /** * @brief The AbstractServerConnector::StartListening method overload. - * - * This method launches the listening loop that will handle client connections. + * + * This method launches the listening loop that will handle client connections. * The return value depends on the current listening states : * - not listening and no error come up while bind and listen returns true * - not listening but error happen on bind or listen returns false * - is called while listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StartListening(); + bool StartListening(); /** * @brief The AbstractServerConnector::StopListening method overload. - * - * This method stops the listening loop that will handle client connections. + * + * This method stops the listening loop that will handle client connections. * The return value depends on the current listening states : * - listening and successfuly stops the listen loop returns true * - is called while not listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StopListening(); - + bool StopListening(); + /** * @brief The AbstractServerConnector::SendResponse method overload. - * + * * This method sends the result of the RPC Call over the tcp socket that the client has used to perform its request. * @param response The response to send to the client * @param addInfo Additionnal parameters (mainly client socket file descriptor) * @return A boolean that indicates the success or the failure of the operation. */ - bool SendResponse(const std::string& response, void* addInfo = NULL); + bool SendResponse(const std::string& response, void* addInfo = NULL); - private: + private: AbstractServerConnector *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ - }; + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ */ - diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 9fca57b6..37a83b6d 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -28,180 +28,180 @@ using namespace std; #endif UnixDomainSocketServer::UnixDomainSocketServer(const string &socket_path) : - running(false), - socket_path(socket_path.substr(0, PATH_MAX)) + running(false), + socket_path(socket_path.substr(0, PATH_MAX)) { } bool UnixDomainSocketServer::StartListening() { - if(!this->running) - { - //Create and bind socket here. - //Then launch the listenning loop. - if (access(this->socket_path.c_str(), F_OK) != -1) - return false; + if(!this->running) + { + //Create and bind socket here. + //Then launch the listenning loop. + if (access(this->socket_path.c_str(), F_OK) != -1) + return false; - this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(this->socket_fd < 0) - { - return false; - } + if(this->socket_fd < 0) + { + return false; + } - unlink(this->socket_path.c_str()); + unlink(this->socket_path.c_str()); - fcntl(this->socket_fd, F_SETFL, FNDELAY); + fcntl(this->socket_fd, F_SETFL, FNDELAY); - /* start with a clean address structure */ - memset(&(this->address), 0, sizeof(struct sockaddr_un)); + /* start with a clean address structure */ + memset(&(this->address), 0, sizeof(struct sockaddr_un)); - this->address.sun_family = AF_UNIX; - snprintf(this->address.sun_path, PATH_MAX, "%s", this->socket_path.c_str()); + this->address.sun_family = AF_UNIX; + snprintf(this->address.sun_path, PATH_MAX, "%s", this->socket_path.c_str()); - if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)) != 0) - { - return false; - } + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)) != 0) + { + return false; + } - if(listen(this->socket_fd, 5) != 0) + if(listen(this->socket_fd, 5) != 0) { return false; - } - - //Launch listening loop there - this->running = true; - int ret = pthread_create(&(this->listenning_thread), NULL, UnixDomainSocketServer::LaunchLoop, this); - if(ret != 0) - { - pthread_detach(this->listenning_thread); - } - this->running = static_cast(ret==0); - - return this->running; - } - else - { - return false; - } + } + + //Launch listening loop there + this->running = true; + int ret = pthread_create(&(this->listenning_thread), NULL, UnixDomainSocketServer::LaunchLoop, this); + if(ret != 0) + { + pthread_detach(this->listenning_thread); + } + this->running = static_cast(ret==0); + + return this->running; + } + else + { + return false; + } } bool UnixDomainSocketServer::StopListening() { - if(this->running) - { - this->running = false; - pthread_join(this->listenning_thread, NULL); - close(this->socket_fd); - unlink(this->socket_path.c_str()); - return !(this->running); - } - else - { - return false; - } + if(this->running) + { + this->running = false; + pthread_join(this->listenning_thread, NULL); + close(this->socket_fd); + unlink(this->socket_path.c_str()); + return !(this->running); + } + else + { + return false; + } } bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) { - bool result = false; - int connection_fd = reinterpret_cast(addInfo); - - string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) - { - temp.append(1, DELIMITER_CHAR); - } - if(DELIMITER_CHAR != '\n') - { - char eot = DELIMITER_CHAR; - string toSend = temp.substr(0, toSend.find_last_of('\n')); - toSend += eot; - result = this->WriteToSocket(connection_fd, toSend); - } - else - { - result = this->WriteToSocket(connection_fd, temp); - } - close(connection_fd); - return result; + bool result = false; + int connection_fd = reinterpret_cast(addInfo); + + string temp = response; + if(temp.find(DELIMITER_CHAR) == string::npos) + { + temp.append(1, DELIMITER_CHAR); + } + if(DELIMITER_CHAR != '\n') + { + char eot = DELIMITER_CHAR; + string toSend = temp.substr(0, toSend.find_last_of('\n')); + toSend += eot; + result = this->WriteToSocket(connection_fd, toSend); + } + else + { + result = this->WriteToSocket(connection_fd, temp); + } + close(connection_fd); + return result; } void* UnixDomainSocketServer::LaunchLoop(void *p_data) { - pthread_detach(pthread_self()); - UnixDomainSocketServer *instance = reinterpret_cast(p_data);; - instance->ListenLoop(); - return NULL; + pthread_detach(pthread_self()); + UnixDomainSocketServer *instance = reinterpret_cast(p_data);; + instance->ListenLoop(); + return NULL; } void UnixDomainSocketServer::ListenLoop() { - int connection_fd; - socklen_t address_length = sizeof(this->address); - while(this->running) - { - if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->address)), &address_length)) > 0) - { - pthread_t client_thread; - struct ClientConnection *params = new struct ClientConnection(); - params->instance = this; - params->connection_fd = connection_fd; - int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); - if(ret != 0) - { - pthread_detach(client_thread); - delete params; - params = NULL; - } - } - else - { - usleep(25000); - } - } + int connection_fd; + socklen_t address_length = sizeof(this->address); + while(this->running) + { + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->address)), &address_length)) > 0) + { + pthread_t client_thread; + struct ClientConnection *params = new struct ClientConnection(); + params->instance = this; + params->connection_fd = connection_fd; + int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); + if(ret != 0) + { + pthread_detach(client_thread); + delete params; + params = NULL; + } + } + else + { + usleep(25000); + } + } } void* UnixDomainSocketServer::GenerateResponse(void *p_data) { - pthread_detach(pthread_self()); - struct ClientConnection* params = reinterpret_cast(p_data); - UnixDomainSocketServer *instance = params->instance; - int connection_fd = params->connection_fd; - delete params; - params = NULL; - int nbytes; - char buffer[BUFFER_SIZE]; - string request; - do - { //The client sends its json formatted request and a delimiter request. - nbytes = read(connection_fd, buffer, BUFFER_SIZE); - request.append(buffer,nbytes); - } while(request.find(DELIMITER_CHAR) == string::npos); - - instance->OnRequest(request, reinterpret_cast(connection_fd)); - return NULL; + pthread_detach(pthread_self()); + struct ClientConnection* params = reinterpret_cast(p_data); + UnixDomainSocketServer *instance = params->instance; + int connection_fd = params->connection_fd; + delete params; + params = NULL; + int nbytes; + char buffer[BUFFER_SIZE]; + string request; + do + { //The client sends its json formatted request and a delimiter request. + nbytes = read(connection_fd, buffer, BUFFER_SIZE); + request.append(buffer,nbytes); + } while(request.find(DELIMITER_CHAR) == string::npos); + + instance->OnRequest(request, reinterpret_cast(connection_fd)); + return NULL; } bool UnixDomainSocketServer::WriteToSocket(int fd, const string& toWrite) { - bool fullyWritten = false; - bool errorOccured = false; - string toSend = toWrite; - do - { - ssize_t byteWritten = write(fd, toSend.c_str(), toSend.size()); - if(byteWritten < 0) - errorOccured = true; - else if(byteWritten < static_cast(toSend.size())) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten && !errorOccured); - - return fullyWritten && !errorOccured; + bool fullyWritten = false; + bool errorOccured = false; + string toSend = toWrite; + do + { + ssize_t byteWritten = write(fd, toSend.c_str(), toSend.size()); + if(byteWritten < 0) + errorOccured = true; + else if(byteWritten < static_cast(toSend.size())) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten && !errorOccured); + + return fullyWritten && !errorOccured; } diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h index 2d2072b0..c54f91b1 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -23,42 +23,41 @@ namespace jsonrpc { - /** - * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. - */ - class UnixDomainSocketServer: public AbstractServerConnector - { - public: - /** - * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer - * @param socket_path, a string containing the path to the unix socket - */ - UnixDomainSocketServer(const std::string& socket_path); - - virtual bool StartListening(); - virtual bool StopListening(); - - bool virtual SendResponse(const std::string& response, void* addInfo = NULL); - - private: - bool running; - std::string socket_path; - int socket_fd; - struct sockaddr_un address; - - pthread_t listenning_thread; - - static void* LaunchLoop(void *p_data); - void ListenLoop(); - struct ClientConnection - { - UnixDomainSocketServer *instance; - int connection_fd; - }; - static void* GenerateResponse(void *p_data); - bool WriteToSocket(int fd, const std::string& toSend); - }; + /** + * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. + */ + class UnixDomainSocketServer: public AbstractServerConnector + { + public: + /** + * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer + * @param socket_path, a string containing the path to the unix socket + */ + UnixDomainSocketServer(const std::string& socket_path); + + virtual bool StartListening(); + virtual bool StopListening(); + + bool virtual SendResponse(const std::string& response, void* addInfo = NULL); + + private: + bool running; + std::string socket_path; + int socket_fd; + struct sockaddr_un address; + + pthread_t listenning_thread; + + static void* LaunchLoop(void *p_data); + void ListenLoop(); + struct ClientConnection + { + UnixDomainSocketServer *instance; + int connection_fd; + }; + static void* GenerateResponse(void *p_data); + bool WriteToSocket(int fd, const std::string& toSend); + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_HTTPSERVERCONNECTOR_H_ */ - diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 95dcbc2d..4057cdd1 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -30,9 +30,9 @@ using namespace std; WindowsTcpSocketServer::WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : AbstractServerConnector(), - ipToBind(ipToBind), - port(port), - running(false) + ipToBind(ipToBind), + port(port), + running(false) { } @@ -42,251 +42,251 @@ WindowsTcpSocketServer::~WindowsTcpSocketServer() bool WindowsTcpSocketServer::StartListening() { - if(!this->running) - { - //Create and bind socket here. - //Then launch the listenning loop. - this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if(this->socket_fd < 0) - { - return false; - } - unsigned long nonBlocking = 1; - ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking + if(!this->running) + { + //Create and bind socket here. + //Then launch the listenning loop. + this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if(this->socket_fd < 0) + { + return false; + } + unsigned long nonBlocking = 1; + ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking int reuseaddr = 1; setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reuseaddr), sizeof(reuseaddr)); - /* start with a clean address structure */ - memset(&(this->address), 0, sizeof(SOCKADDR_IN)); + /* start with a clean address structure */ + memset(&(this->address), 0, sizeof(SOCKADDR_IN)); - this->address.sin_family = AF_INET; - this->address.sin_addr.s_addr = inet_addr(this->ipToBind.c_str()); - this->address.sin_port = htons(this->port); + this->address.sin_family = AF_INET; + this->address.sin_addr.s_addr = inet_addr(this->ipToBind.c_str()); + this->address.sin_port = htons(this->port); - if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(SOCKADDR_IN)) != 0) - { - return false; - } + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(SOCKADDR_IN)) != 0) + { + return false; + } - if(listen(this->socket_fd, 5) != 0) - { - return false; - } - //Launch listening loop there - this->running = true; - HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::LaunchLoop)), reinterpret_cast(this), 0, &(this->listenning_thread)); - if(ret == NULL) - { - ExitProcess(3); - } - else - { - CloseHandle(ret); - } - this->running = static_cast(ret!=NULL); - return this->running; - } - else - { - return false; - } + if(listen(this->socket_fd, 5) != 0) + { + return false; + } + //Launch listening loop there + this->running = true; + HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::LaunchLoop)), reinterpret_cast(this), 0, &(this->listenning_thread)); + if(ret == NULL) + { + ExitProcess(3); + } + else + { + CloseHandle(ret); + } + this->running = static_cast(ret!=NULL); + return this->running; + } + else + { + return false; + } } bool WindowsTcpSocketServer::StopListening() { - if(this->running) - { - this->running = false; - WaitForSingleObject(OpenThread(THREAD_ALL_ACCESS, FALSE,this->listenning_thread), INFINITE); - closesocket(this->socket_fd); - return !(this->running); - } - else - { - return false; - } + if(this->running) + { + this->running = false; + WaitForSingleObject(OpenThread(THREAD_ALL_ACCESS, FALSE,this->listenning_thread), INFINITE); + closesocket(this->socket_fd); + return !(this->running); + } + else + { + return false; + } } bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) { - bool result = false; - int connection_fd = reinterpret_cast(addInfo); + bool result = false; + int connection_fd = reinterpret_cast(addInfo); - string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) - { - temp.append(1, DELIMITER_CHAR); - } - if(DELIMITER_CHAR != '\n') - { - char eot = DELIMITER_CHAR; - string toSend = temp.substr(0, toSend.find_last_of('\n')); - toSend += eot; - result = this->WriteToSocket(connection_fd, toSend); - } - else - { - result = this->WriteToSocket(connection_fd, temp); - } - CleanClose(connection_fd); - return result; + string temp = response; + if(temp.find(DELIMITER_CHAR) == string::npos) + { + temp.append(1, DELIMITER_CHAR); + } + if(DELIMITER_CHAR != '\n') + { + char eot = DELIMITER_CHAR; + string toSend = temp.substr(0, toSend.find_last_of('\n')); + toSend += eot; + result = this->WriteToSocket(connection_fd, toSend); + } + else + { + result = this->WriteToSocket(connection_fd, temp); + } + CleanClose(connection_fd); + return result; } DWORD WINAPI WindowsTcpSocketServer::LaunchLoop(LPVOID lp_data) { - WindowsTcpSocketServer *instance = reinterpret_cast(lp_data);; - instance->ListenLoop(); - CloseHandle(GetCurrentThread()); - return 0; //DO NOT USE ExitThread function here! ExitThread does not call destructors for allocated objects and therefore it would lead to a memory leak. + WindowsTcpSocketServer *instance = reinterpret_cast(lp_data);; + instance->ListenLoop(); + CloseHandle(GetCurrentThread()); + return 0; //DO NOT USE ExitThread function here! ExitThread does not call destructors for allocated objects and therefore it would lead to a memory leak. } void WindowsTcpSocketServer::ListenLoop() { - while(this->running) - { - SOCKET connection_fd = INVALID_SOCKET; - SOCKADDR_IN connection_address; - memset(&connection_address, 0, sizeof(SOCKADDR_IN)); - int address_length = sizeof(connection_address); - if((connection_fd = accept(this->socket_fd, reinterpret_cast(&connection_address), &address_length)) != INVALID_SOCKET) - { - unsigned long nonBlocking = 0; - ioctlsocket(connection_fd, FIONBIO, &nonBlocking); //Set blocking - DWORD client_thread; - struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); - params->instance = this; - params->connection_fd = connection_fd; - HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::GenerateResponse)), reinterpret_cast(params), 0, &client_thread); - if(ret == NULL) - { - delete params; - params = NULL; - CleanClose(connection_fd); - } - else - { - CloseHandle(ret); - } - } - else - { - Sleep(2.5); - } - } + while(this->running) + { + SOCKET connection_fd = INVALID_SOCKET; + SOCKADDR_IN connection_address; + memset(&connection_address, 0, sizeof(SOCKADDR_IN)); + int address_length = sizeof(connection_address); + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&connection_address), &address_length)) != INVALID_SOCKET) + { + unsigned long nonBlocking = 0; + ioctlsocket(connection_fd, FIONBIO, &nonBlocking); //Set blocking + DWORD client_thread; + struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); + params->instance = this; + params->connection_fd = connection_fd; + HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::GenerateResponse)), reinterpret_cast(params), 0, &client_thread); + if(ret == NULL) + { + delete params; + params = NULL; + CleanClose(connection_fd); + } + else + { + CloseHandle(ret); + } + } + else + { + Sleep(2.5); + } + } } DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) { - struct GenerateResponseParameters* params = reinterpret_cast(lp_data); - WindowsTcpSocketServer *instance = params->instance; - int connection_fd = params->connection_fd; - delete params; - params = NULL; - int nbytes = 0; - char buffer[BUFFER_SIZE]; - memset(&buffer, 0, BUFFER_SIZE); - string request = ""; - do - { //The client sends its json formatted request and a delimiter request. - nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); - if(nbytes == -1) - { - instance->CleanClose(connection_fd); - } - else - { - request.append(buffer,nbytes); - } - } while(request.find(DELIMITER_CHAR) == string::npos); - instance->OnRequest(request, reinterpret_cast(connection_fd)); - CloseHandle(GetCurrentThread()); - return 0; //DO NOT USE ExitThread function here! ExitThread does not call destructors for allocated objects and therefore it would lead to a memory leak. + struct GenerateResponseParameters* params = reinterpret_cast(lp_data); + WindowsTcpSocketServer *instance = params->instance; + int connection_fd = params->connection_fd; + delete params; + params = NULL; + int nbytes = 0; + char buffer[BUFFER_SIZE]; + memset(&buffer, 0, BUFFER_SIZE); + string request = ""; + do + { //The client sends its json formatted request and a delimiter request. + nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); + if(nbytes == -1) + { + instance->CleanClose(connection_fd); + } + else + { + request.append(buffer,nbytes); + } + } while(request.find(DELIMITER_CHAR) == string::npos); + instance->OnRequest(request, reinterpret_cast(connection_fd)); + CloseHandle(GetCurrentThread()); + return 0; //DO NOT USE ExitThread function here! ExitThread does not call destructors for allocated objects and therefore it would lead to a memory leak. } bool WindowsTcpSocketServer::WriteToSocket(const SOCKET& fd, const string& toWrite) { - bool fullyWritten = false; - bool errorOccured = false; - string toSend = toWrite; - do - { - ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 0) - { - errorOccured = true; - CleanClose(fd); - } - else if(byteWritten < toSend.size()) - { - int len = toSend.size() - byteWritten; - toSend = toSend.substr(byteWritten + sizeof(char), len); - } - else - fullyWritten = true; - } while(!fullyWritten && !errorOccured); + bool fullyWritten = false; + bool errorOccured = false; + string toSend = toWrite; + do + { + ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); + if(byteWritten < 0) + { + errorOccured = true; + CleanClose(fd); + } + else if(byteWritten < toSend.size()) + { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten && !errorOccured); - return fullyWritten && !errorOccured; + return fullyWritten && !errorOccured; } bool WindowsTcpSocketServer::WaitClientClose(const SOCKET& fd, const int &timeout) { - bool ret = false; - int i = 0; - while((recv(fd, NULL, 0, 0) != 0) && i < timeout) - { - Sleep(1); - ++i; - ret = true; - } + bool ret = false; + int i = 0; + while((recv(fd, NULL, 0, 0) != 0) && i < timeout) + { + Sleep(1); + ++i; + ret = true; + } - return ret; + return ret; } int WindowsTcpSocketServer::CloseByReset(const SOCKET& fd) { - struct linger so_linger; - so_linger.l_onoff = 1; - so_linger.l_linger = 0; + struct linger so_linger; + so_linger.l_onoff = 1; + so_linger.l_linger = 0; - int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, reinterpret_cast(&so_linger), sizeof(so_linger)); - if(ret != 0) - return ret; + int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, reinterpret_cast(&so_linger), sizeof(so_linger)); + if(ret != 0) + return ret; - return closesocket(fd); + return closesocket(fd); } int WindowsTcpSocketServer::CleanClose(const SOCKET& fd) { - if(WaitClientClose(fd)) - { - return closesocket(fd); - } - else - { - return CloseByReset(fd); - } + if(WaitClientClose(fd)) + { + return closesocket(fd); + } + else + { + return CloseByReset(fd); + } } //This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). struct ServerSocketInitializer { - ServerSocketInitializer() - { - WSADATA init; - if(WSAStartup(MAKEWORD(2, 2), &init) != 0) - { + ServerSocketInitializer() + { + WSADATA init; + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) + { JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); - } - } + } + } - ~ServerSocketInitializer() - { - if(WSACleanup() != 0) - { + ~ServerSocketInitializer() + { + if(WSACleanup() != 0) + { cerr << "An issue occured while WSAClean executed." << endl; - } - } + } + } }; struct ServerSocketInitializer serverGlobalInitializer; diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index 88f0e80e..6bb8c75c 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -18,125 +18,124 @@ namespace jsonrpc { - /** + /** * This class is the Windows implementation of TCPSocketServer. * It uses the Winsock2 socket API and Windows thread API to performs its job. * Each client request is handled in a new thread. */ class WindowsTcpSocketServer: public AbstractServerConnector - { - public: - /** + { + public: + /** * @brief WindowsTcpSocketServer, constructor of the Windows implementation of class TcpSocketServer * @param ipToBind The ipv4 address on which the server should bind and listen * @param port The port on which the server should bind and listen */ - WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port); + WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port); /** * @brief ~WindowsTcpSocketServer, the destructor of WindowsTcpSocketServer */ - ~WindowsTcpSocketServer(); + ~WindowsTcpSocketServer(); /** * @brief The real implementation TcpSocketServer::StartListening method. - * - * This method launches the listening loop that will handle client connections. + * + * This method launches the listening loop that will handle client connections. * The return value depends on the current listening states : * - not listening and no error come up while bind and listen returns true * - not listening but error happen on bind or listen returns false * - is called while listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StartListening(); + bool StartListening(); /** * @brief The real implementation TcpSocketServer::StopListening method. - * - * This method stops the listening loop that will handle client connections. + * + * This method stops the listening loop that will handle client connections. * The return value depends on the current listening states : * - listening and successfuly stops the listen loop returns true * - is called while not listening returns false - * + * * @return A boolean that indicates the success or the failure of the operation. */ - bool StopListening(); + bool StopListening(); /** * @brief The real implementation TcpSocketServer::SendResponse method. - * + * * This method sends the result of the RPC Call over the tcp socket that the client has used to perform its request. * @param response The response to send to the client * @param addInfo Additionnal parameters (mainly client socket file descriptor) * @return A boolean that indicates the success or the failure of the operation. */ - bool SendResponse(const std::string& response, void* addInfo = NULL); + bool SendResponse(const std::string& response, void* addInfo = NULL); - private: - bool running; /*!< A boolean that is used to know the listening state*/ - std::string ipToBind; /*!< The ipv4 address on which the server should bind and listen*/ - unsigned int port; /*!< The port on which the server should bind and listen*/ - SOCKET socket_fd; /*!< The file descriptior of the listening socket*/ - SOCKADDR_IN address; /*!< The listening socket*/ + private: + bool running; /*!< A boolean that is used to know the listening state*/ + std::string ipToBind; /*!< The ipv4 address on which the server should bind and listen*/ + unsigned int port; /*!< The port on which the server should bind and listen*/ + SOCKET socket_fd; /*!< The file descriptior of the listening socket*/ + SOCKADDR_IN address; /*!< The listening socket*/ - DWORD listenning_thread; /*!< The identifier of the listen loop thread*/ + DWORD listenning_thread; /*!< The identifier of the listen loop thread*/ /** * @brief The static method that is used as listening thread entry point * @param lp_data The parameters for the thread entry point method */ - static DWORD WINAPI LaunchLoop(LPVOID lp_data); + static DWORD WINAPI LaunchLoop(LPVOID lp_data); /** * @brief The method that launches the listenning loop */ - void ListenLoop(); - struct GenerateResponseParameters - { - WindowsTcpSocketServer *instance; - SOCKET connection_fd; - }; /*!< The structure used to give parameters to the Response generating method*/ - /** + void ListenLoop(); + struct GenerateResponseParameters + { + WindowsTcpSocketServer *instance; + SOCKET connection_fd; + }; /*!< The structure used to give parameters to the Response generating method*/ + /** * @brief The static method that is used as client request handling entry point * @param lp_data The parameters for the thread entry point method */ static DWORD WINAPI GenerateResponse(LPVOID lp_data); /** * @brief A method that write a message to socket - * + * * Tries to send the full message. * @param fd The file descriptor of the socket message should be sent * @param toSend The message to send over socket * @returns A boolean indicating the success or the failure of the operation */ - bool WriteToSocket(const SOCKET& fd, const std::string& toSend); + bool WriteToSocket(const SOCKET& fd, const std::string& toSend); /** * @brief A method that wait for the client to close the tcp session - * + * * This method wait for the client to close the tcp session in order to avoid the server to enter in TIME_WAIT status. - * Entering in TIME_WAIT status with too many clients may occur in a DOS attack + * Entering in TIME_WAIT status with too many clients may occur in a DOS attack * since server will not be able to use a new socket when a new client connects. * @param fd The file descriptor of the socket that should be closed by the client * @param timeout The maximum time the server will wait for the client to close the tcp session in milliseconds. * @returns A boolean indicating the success or the failure of the operation */ - bool WaitClientClose(const SOCKET& fd, const int &timeout = 100); + bool WaitClientClose(const SOCKET& fd, const int &timeout = 100); /** * @brief A method that close a socket by reseting it - * + * * This method reset the tcp session in order to avoid enter in TIME_WAIT state. * @param fd The file descriptor of the socket that should be reset * @returns The return value of POSIX close() method */ - int CloseByReset(const SOCKET& fd); + int CloseByReset(const SOCKET& fd); /** * @brief A method that cleanly close a socket by avoid TIME_WAIT state - * + * * This method uses WaitClientClose and ClodeByReset to clenly close a tcp session with a client * (avoiding TIME_WAIT to avoid DOS attacks). * @param fd The file descriptor of the socket that should be cleanly closed * @returns The return value of POSIX close() method */ - int CleanClose(const SOCKET& fd); - }; + int CleanClose(const SOCKET& fd); + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_WINDOWSTCPSOCKETSERVERCONNECTOR_H_ */ -