From 77ecb82e491535968c41d9b305afdf009b04f35c Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 1 Jul 2015 21:02:42 +0200 Subject: [PATCH 001/114] Fixing multiarch support for libjsonrpccpp-stub.so --- src/stubgenerator/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stubgenerator/CMakeLists.txt b/src/stubgenerator/CMakeLists.txt index a5e55647..2dbf7450 100644 --- a/src/stubgenerator/CMakeLists.txt +++ b/src/stubgenerator/CMakeLists.txt @@ -64,8 +64,9 @@ install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/stubgenerator/ DESTINATION include/jsonrpccpp/stubgen FILES_MATCHING PATTERN "*.h") -install(TARGETS jsonrpcstub ${ALL_LIBS} LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX} - RUNTIME DESTINATION bin +install(TARGETS ${ALL_LIBS} jsonrpcstub + LIBRARY DESTINATION lib/${CMAKE_LIBRARY_PATH} + ARCHIVE DESTINATION lib/${CMAKE_LIBRARY_PATH} + RUNTIME DESTINATION bin ) From 2cdebba6e539015a6d680c7b33dd26d9535def96 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 1 Jul 2015 21:02:50 +0200 Subject: [PATCH 002/114] Fixing security warnings --- src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp | 2 +- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index 1d3dce7b..4e923e3b 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -47,7 +47,7 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str memset(&address, 0, sizeof(sockaddr_un)); address.sun_family = AF_UNIX; - snprintf(address.sun_path, PATH_MAX, this->path.c_str()); + 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); diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 2f1cdb6c..ca23a0ae 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -46,7 +46,7 @@ bool UnixDomainSocketServer::StartListening() memset(&(this->address), 0, sizeof(struct sockaddr_un)); this->address.sun_family = AF_UNIX; - snprintf(this->address.sun_path, PATH_MAX, this->socket_path.c_str()); + snprintf(this->address.sun_path, PATH_MAX, "%s", this->socket_path.c_str()); bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)); From 827c876c159cc067f21aad79e39a09dccb853be6 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 1 Jul 2015 23:11:55 +0200 Subject: [PATCH 003/114] make interface more public --- src/stubgenerator/client/cppclientstubgenerator.h | 1 - src/stubgenerator/server/cppserverstubgenerator.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/stubgenerator/client/cppclientstubgenerator.h b/src/stubgenerator/client/cppclientstubgenerator.h index 2dc60353..7900eb0f 100755 --- a/src/stubgenerator/client/cppclientstubgenerator.h +++ b/src/stubgenerator/client/cppclientstubgenerator.h @@ -25,7 +25,6 @@ namespace jsonrpc virtual void generateStub(); - private: void generateMethod(Procedure& proc); void generateAssignments(Procedure& proc); void generateProcCall(Procedure &proc); diff --git a/src/stubgenerator/server/cppserverstubgenerator.h b/src/stubgenerator/server/cppserverstubgenerator.h index bac2d52e..1351155c 100755 --- a/src/stubgenerator/server/cppserverstubgenerator.h +++ b/src/stubgenerator/server/cppserverstubgenerator.h @@ -23,7 +23,6 @@ namespace jsonrpc virtual void generateStub(); - private: void generateBindings(); void generateProcedureDefinitions(); void generateAbstractDefinitions(); From d13f03e73a3accf60a3ef2bebb8fb9407d6c4921 Mon Sep 17 00:00:00 2001 From: JugglerShu Date: Wed, 15 Jul 2015 14:22:48 +0900 Subject: [PATCH 004/114] Include CURL_INCLUDE_DIRS when compiling client This is required when you specify CURL_INCLUDE_DIR via commandline to point curl include directory which is not localed at stardard directories --- src/jsonrpccpp/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 4c1126d5..758210f8 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -37,6 +37,7 @@ if (HTTP_CLIENT) list(APPEND client_connector_header "client/connectors/httpclient.h") list(APPEND client_connector_source "client/connectors/httpclient.cpp") list(APPEND client_connector_libs ${CURL_LIBRARIES}) + include_directories(${CURL_INCLUDE_DIRS}) endif() if (HTTP_SERVER) From e63e2ec9bccbef8cb7f5ffd717e07e3a31eae337 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 10 Apr 2015 19:47:48 +0200 Subject: [PATCH 005/114] appveyor CI --- appveyor.yml | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..2982e6ca --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,75 @@ +version: 0.5.0.{build} + +branches: + only: + - master + - develop + +os: Windows Server 2012 R2 + +clone_folder: c:\projects\libjson-rpc-cpp + +#platform: Any CPU +#configuration: Debug + +install: + # by default, all script lines are interpreted as batch + +# scripts to run before build +before_build: + + # setup dependency directory + - mkdir c:\projects\libjson-rpc-cpp\deps + - mkdir c:\projects\libjson-rpc-cpp\deps\install + - cd c:\projects\libjson-rpc-cpp\deps + + # get boost + - echo "Downloading boost..." + - curl -O https://build.ethdev.com/builds/windows-precompiled/boost.tar.gz + - echo "Unzipping boost..." + - 7z x boost.tar.gz > nul + - 7z x boost.tar > nul + - echo "boost unzipped!" + - cmake -E copy_directory boost install + + # get curl + - echo "Downloading curl..." + - curl -O https://build.ethdev.com/builds/windows-precompiled/curl.tar.gz + - echo "Unzipping curl..." + - 7z x curl.tar.gz > nul + - 7z x curl.tar > nul + - echo "curl unzipped!" + - cmake -E copy_directory curl install + + # get microhttpd + - echo "Downloading microhttpd..." + - curl -O https://build.ethdev.com/builds/windows-precompiled/microhttpd.tar.gz + - echo "Unzipping microhttpd..." + - 7z x microhttpd.tar.gz > nul + - 7z x microhttpd.tar > nul + - echo "microhttpd unzipped!" + - cmake -E copy_directory microhttpd install + + # get jsoncpp + - echo "Downloading jsoncpp..." + - curl -O https://build.ethdev.com/builds/windows-precompiled/jsoncpp.tar.gz + - echo "Unzipping jsoncpp..." + - 7z x jsoncpp.tar.gz > nul + - 7z x jsoncpp.tar > nul + - echo "jsoncpp unzipped!" + - cmake -E copy_directory jsoncpp install + + # argtable not supported + + - ls + - echo "Running cmake..." + - cd c:\projects\libjson-rpc-cpp + - cmake -DCMAKE_PREFIX_PATH="c:/projects/libjson-rpc-cpp/deps/install" -DCOMPILE_STUBGEN=NO . + +build: + project: ALL_BUILD.vcxproj # path to Visual Studio solution or project + +after_build: + - echo "Running tests..." + - echo "Finished!" + From b7ccdecf091ebc573ab85c96ac9ea75e8f4cedeb Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 10 Apr 2015 20:12:09 +0200 Subject: [PATCH 006/114] running tests on appveyor CI after successfull build --- appveyor.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2982e6ca..44b96e0c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -60,8 +60,7 @@ before_build: - cmake -E copy_directory jsoncpp install # argtable not supported - - - ls + - echo "Running cmake..." - cd c:\projects\libjson-rpc-cpp - cmake -DCMAKE_PREFIX_PATH="c:/projects/libjson-rpc-cpp/deps/install" -DCOMPILE_STUBGEN=NO . @@ -70,6 +69,12 @@ build: project: ALL_BUILD.vcxproj # path to Visual Studio solution or project after_build: + # copy missing dlls + - cd c:\projects\libjson-rpc-cpp\bin\Debug + - cmake -E copy c:\projects\libjson-rpc-cpp\deps\install\bin\libmicrohttpd-dll_d.dll . + + # run tests - echo "Running tests..." + - unit_testsuite.exe - echo "Finished!" From 0008834b7fce9bde5396108108767994038e7934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Tue, 28 Apr 2015 20:24:59 +0200 Subject: [PATCH 007/114] Add Gentoo install instructions --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index da786f61..074270ab 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ For Arch Linux there is a [PKGBUILD provided in the AUR](https://aur.archlinux.o sudo aura -A libjson-rpc-cpp ``` +**Gentoo Linux** + +```sh +sudo emerge dev-cpp/libjson-rpc-cpp +``` + **Mac OS X** For OS X a [Brew](http://brew.sh) package is available: From 1cc3bd8f341a844279f6db4213eb3462f6d4ddba Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Wed, 6 May 2015 16:41:40 +0200 Subject: [PATCH 008/114] Added a way to make the http server to listen only to local loop. --- .../server/connectors/httpserver.cpp | 95 ++++++++++++++++++- src/jsonrpccpp/server/connectors/httpserver.h | 6 +- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/httpserver.cpp b/src/jsonrpccpp/server/connectors/httpserver.cpp index bb494c45..0ea2104e 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.cpp +++ b/src/jsonrpccpp/server/connectors/httpserver.cpp @@ -26,14 +26,15 @@ struct mhd_coninfo { int code; }; -HttpServer::HttpServer(int port, const std::string &sslcert, const std::string &sslkey, int threads) : +HttpServer::HttpServer(int port, const std::string &sslcert, const std::string &sslkey, int threads, const bool listenLocalhostOnly) : AbstractServerConnector(), port(port), threads(threads), running(false), path_sslcert(sslcert), path_sslkey(sslkey), - daemon(NULL) + daemon(NULL), + listenLocalhostOnly(listenLocalhostOnly) { } @@ -57,7 +58,52 @@ bool HttpServer::StartListening() SpecificationParser::GetFileContent(this->path_sslcert, this->sslcert); SpecificationParser::GetFileContent(this->path_sslkey, this->sslkey); - this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, this->port, NULL, NULL, HttpServer::callback, this, MHD_OPTION_HTTPS_MEM_KEY, this->sslkey.c_str(), MHD_OPTION_HTTPS_MEM_CERT, this->sslcert.c_str(), MHD_OPTION_THREAD_POOL_SIZE, this->threads, MHD_OPTION_END); + if(this->listenLocalhostOnly) { + this->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(this->sockfd < 0) + cerr << "can't open stream socket" << endl; + + this->addr.sin_family = AF_INET; + this->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + this->addr.sin_port = htons(8385); + + if (bind(this->sockfd, (struct sockaddr *) &(this->addr), sizeof(this->addr)) < 0) + cerr << "server: can't bind local address" << endl; + + listen(sockfd, 5); + cout << "Using own socket (" << this->addr.sin_addr.s_addr << ", " << this->addr.sin_port << ")" << endl; + + this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, + this->port, + NULL, + NULL, + HttpServer::callback, + this, + MHD_OPTION_HTTPS_MEM_KEY, + this->sslkey.c_str(), + MHD_OPTION_HTTPS_MEM_CERT, + this->sslcert.c_str(), + MHD_OPTION_THREAD_POOL_SIZE, + this->threads, + MHD_OPTION_LISTEN_SOCKET, + this->sockfd, + MHD_OPTION_END); + } + else { + this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, + this->port, + NULL, + NULL, + HttpServer::callback, + this, + MHD_OPTION_HTTPS_MEM_KEY, + this->sslkey.c_str(), + MHD_OPTION_HTTPS_MEM_CERT, + this->sslcert.c_str(), + MHD_OPTION_THREAD_POOL_SIZE, + this->threads, + MHD_OPTION_END); + } } catch (JsonRpcException& ex) { @@ -66,7 +112,48 @@ bool HttpServer::StartListening() } else { - this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, this->port, NULL, NULL, HttpServer::callback, this, MHD_OPTION_THREAD_POOL_SIZE, this->threads, MHD_OPTION_END); + if(this->listenLocalhostOnly) { + this->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(this->sockfd < 0) + cerr << "can't open stream socket" << endl; + + this->addr.sin_family = AF_INET; + this->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + this->addr.sin_port = htons(8385); + + if (bind(this->sockfd, (struct sockaddr *) &(this->addr), sizeof(this->addr)) < 0) + cerr << "server: can't bind local address" << endl; + + listen(sockfd, 5); + cout << "Using own socket (" << this->addr.sin_addr.s_addr << ", " << this->addr.sin_port << ")" << endl; + + this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, + this->port, + NULL, + NULL, + HttpServer::callback, + this, + MHD_OPTION_THREAD_POOL_SIZE, + this->threads, + MHD_OPTION_LISTEN_SOCKET, + this->sockfd, + MHD_OPTION_END); + } + else { + this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, + this->port, + NULL, + NULL, + HttpServer::callback, + this, + MHD_OPTION_HTTPS_MEM_KEY, + this->sslkey.c_str(), + MHD_OPTION_HTTPS_MEM_CERT, + this->sslcert.c_str(), + MHD_OPTION_THREAD_POOL_SIZE, + this->threads, + MHD_OPTION_END); + } } if (this->daemon != NULL) this->running = true; diff --git a/src/jsonrpccpp/server/connectors/httpserver.h b/src/jsonrpccpp/server/connectors/httpserver.h index 075962c8..72b57c34 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.h +++ b/src/jsonrpccpp/server/connectors/httpserver.h @@ -23,6 +23,7 @@ typedef intptr_t ssize_t; #include #include #include +#include #endif #include @@ -47,7 +48,7 @@ namespace jsonrpc * @param enableSpecification - defines if the specification is returned in case of a GET request * @param sslcert - defines the path to a SSL certificate, if this path is != "", then SSL/HTTPS is used with the given certificate. */ - HttpServer(int port, const std::string& sslcert = "", const std::string& sslkey = "", int threads = 50); + HttpServer(int port, const std::string& sslcert = "", const std::string& sslkey = "", int threads = 50, const bool listenLocalhostOnly = false); virtual bool StartListening(); virtual bool StopListening(); @@ -62,6 +63,9 @@ namespace jsonrpc int port; int threads; bool running; + bool listenLocalhostOnly; + int sockfd; + struct sockaddr_in addr; std::string path_sslcert; std::string path_sslkey; std::string sslcert; From 9302eb9c36fa5a1f9e8c42fd0def79538790648f Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Wed, 6 May 2015 16:43:40 +0200 Subject: [PATCH 009/114] Updated author information/metadata. --- src/jsonrpccpp/server/connectors/httpserver.cpp | 2 +- src/jsonrpccpp/server/connectors/httpserver.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/httpserver.cpp b/src/jsonrpccpp/server/connectors/httpserver.cpp index 0ea2104e..1714b3c2 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.cpp +++ b/src/jsonrpccpp/server/connectors/httpserver.cpp @@ -3,7 +3,7 @@ ************************************************************************* * @file httpserver.cpp * @date 31.12.2012 - * @author Peter Spiess-Knafl + * @author Peter Spiess-Knafl , Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ diff --git a/src/jsonrpccpp/server/connectors/httpserver.h b/src/jsonrpccpp/server/connectors/httpserver.h index 72b57c34..78ab2345 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.h +++ b/src/jsonrpccpp/server/connectors/httpserver.h @@ -3,7 +3,7 @@ ************************************************************************* * @file httpserver.h * @date 31.12.2012 - * @author Peter Spiess-Knafl + * @author Peter Spiess-Knafl , Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ From f50ff15c8eb688214b67b0014dcf178f46ee3523 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 7 May 2015 10:46:58 +0200 Subject: [PATCH 010/114] deactivate appveyor build. --- appveyor.yml | 80 ---------------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 44b96e0c..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,80 +0,0 @@ -version: 0.5.0.{build} - -branches: - only: - - master - - develop - -os: Windows Server 2012 R2 - -clone_folder: c:\projects\libjson-rpc-cpp - -#platform: Any CPU -#configuration: Debug - -install: - # by default, all script lines are interpreted as batch - -# scripts to run before build -before_build: - - # setup dependency directory - - mkdir c:\projects\libjson-rpc-cpp\deps - - mkdir c:\projects\libjson-rpc-cpp\deps\install - - cd c:\projects\libjson-rpc-cpp\deps - - # get boost - - echo "Downloading boost..." - - curl -O https://build.ethdev.com/builds/windows-precompiled/boost.tar.gz - - echo "Unzipping boost..." - - 7z x boost.tar.gz > nul - - 7z x boost.tar > nul - - echo "boost unzipped!" - - cmake -E copy_directory boost install - - # get curl - - echo "Downloading curl..." - - curl -O https://build.ethdev.com/builds/windows-precompiled/curl.tar.gz - - echo "Unzipping curl..." - - 7z x curl.tar.gz > nul - - 7z x curl.tar > nul - - echo "curl unzipped!" - - cmake -E copy_directory curl install - - # get microhttpd - - echo "Downloading microhttpd..." - - curl -O https://build.ethdev.com/builds/windows-precompiled/microhttpd.tar.gz - - echo "Unzipping microhttpd..." - - 7z x microhttpd.tar.gz > nul - - 7z x microhttpd.tar > nul - - echo "microhttpd unzipped!" - - cmake -E copy_directory microhttpd install - - # get jsoncpp - - echo "Downloading jsoncpp..." - - curl -O https://build.ethdev.com/builds/windows-precompiled/jsoncpp.tar.gz - - echo "Unzipping jsoncpp..." - - 7z x jsoncpp.tar.gz > nul - - 7z x jsoncpp.tar > nul - - echo "jsoncpp unzipped!" - - cmake -E copy_directory jsoncpp install - - # argtable not supported - - - echo "Running cmake..." - - cd c:\projects\libjson-rpc-cpp - - cmake -DCMAKE_PREFIX_PATH="c:/projects/libjson-rpc-cpp/deps/install" -DCOMPILE_STUBGEN=NO . - -build: - project: ALL_BUILD.vcxproj # path to Visual Studio solution or project - -after_build: - # copy missing dlls - - cd c:\projects\libjson-rpc-cpp\bin\Debug - - cmake -E copy c:\projects\libjson-rpc-cpp\deps\install\bin\libmicrohttpd-dll_d.dll . - - # run tests - - echo "Running tests..." - - unit_testsuite.exe - - echo "Finished!" - From 06032e84e643d93236340a868fd52f13a00a7948 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 16:55:23 +0200 Subject: [PATCH 011/114] Created a unix domain socket server class that serves request over unix domain sockets --- .../connectors/unixdomainsocketserver.cpp | 155 ++++++++++++++++++ .../connectors/unixdomainsocketserver.h | 66 ++++++++ 2 files changed, 221 insertions(+) create mode 100644 src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp create mode 100644 src/jsonrpccpp/server/connectors/unixdomainsocketserver.h diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp new file mode 100644 index 00000000..78cac4b7 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -0,0 +1,155 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file unixdomainsocketserver.cpp + * @date 07.05.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "unixdomainsocketserver.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace jsonrpc; +using namespace std; + +#define BUFFER_SIZE 64 + +UnixDomainSocketServer::UnixDomainSocketServer(const std::string &socket_path) : + AbstractServerConnector(), + socket_path(socket_path), + running(false) +{ +} + +bool UnixDomainSocketServer::StartListening() +{ + if(!this->running) + { + //Create and bind socket here. + //Then launch the listenning loop. + this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(this->socket_fd < 0) + { + cerr << "socket() failed" << endl; + return false; + } + + unlink(this->socket_path.c_str()); + + /* 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, this->socket_path.size(), this->socket_path.c_str()); + + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)) != 0) + { + cerr << "bind() failed" << endl; + return false; + } + + if(listen(this->socket_fd, 5) != 0) + { + cerr << "listen() failed" << endl; + return false; + } + //Launch listening loop there + cout << "(" << pthread_self() << ") " << "Will launch the thread for the loop" << endl; + 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); + } + cout << "(" << pthread_self() << ") " << "Returning " << this->running << endl; + return this->running; +} + +bool UnixDomainSocketServer::StopListening() +{ + if(this->running) + { + close(this->socket_fd); + unlink(this->socket_path.c_str()); + this->running = false; + } + return true; +} + +bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) +{ + cout << "(" << pthread_self() << ") " << "Entered in send response" << endl; + int connection_fd = reinterpret_cast(addInfo); + + cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; + write(connection_fd, response.c_str(), response.size()); + + cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; + close(connection_fd); + return true; +} + +void* UnixDomainSocketServer::LaunchLoop(void *p_data) { + UnixDomainSocketServer *instance = reinterpret_cast(p_data);; + instance->ListenLoop(); +} + +void UnixDomainSocketServer::ListenLoop() { + int connection_fd; + socklen_t address_length; + cout << "(" << pthread_self() << ") " << "Will launch the loop" << endl; + while((connection_fd = accept(this->socket_fd, (struct sockaddr *) &(this->address), &address_length)) > -1) + { + cout << "(" << pthread_self() << ") " << "Client connected" << endl; + pthread_t client_thread; + struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); + params->instance = this; + params->connection_fd = connection_fd; + cout << "(" << pthread_self() << ") " << "Will launch the thread to handle the request" << endl; + cout << "Sending instance=" << this << endl; + cout << "Sending connection_fd=" << connection_fd << endl; + int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); + if(ret != 0) { + pthread_detach(client_thread); + delete params; + params = NULL; + } + } +} + +void* UnixDomainSocketServer::GenerateResponse(void *p_data) { + cout << "(" << pthread_self() << ") " << "Entrered in generate response" << endl; + struct GenerateResponseParameters* params = reinterpret_cast(p_data); + UnixDomainSocketServer *instance = params->instance; + cout << "Got instance=" << instance << endl; + int connection_fd = params->connection_fd; + cout << "Got connection_fd=" << connection_fd << endl; + cout << "(" << pthread_self() << ") " << "Obtained params" << endl; + delete params; + params = NULL; + int nbytes; + char buffer[BUFFER_SIZE]; + cout << "(" << pthread_self() << ") " << "Will read the request" << endl; + string request; + do { //The client sends its json formatted request and an \0. + cout << "(" << pthread_self() << ") " << "Current request state: #" << request << "#"; + nbytes = read(connection_fd, buffer, BUFFER_SIZE); + cout << "(" << pthread_self() << ") " << "Received part of request: #" << buffer << "#"; + if(request.empty()) + request = string(buffer); + else + request.append(buffer,nbytes); + } while(request.find(char(0x04)) == string::npos); + + cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; + + cout << "(" << pthread_self() << ") " << "Will launch OnRequest" << endl; + instance->OnRequest(request, reinterpret_cast(connection_fd)); +} diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h new file mode 100644 index 00000000..72c41845 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -0,0 +1,66 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file unixdomainsocketserver.h + * @date 07.05.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ +#ifndef __WIN32__ //Unix domain sockets have meaning only on unix-like systems +#ifndef JSONRPC_CPP_UNIXDOMAINSOCKETSERVERCONNECTOR_H_ +#define JSONRPC_CPP_UNIXDOMAINSOCKETSERVERCONNECTOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../abstractserverconnector.h" + +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; + std::set client_thread_pool; + + static void* LaunchLoop(void *p_data); + void ListenLoop(); + struct GenerateResponseParameters { + UnixDomainSocketServer *instance; + int connection_fd; + }; + static void* GenerateResponse(void *p_data); + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_HTTPSERVERCONNECTOR_H_ */ +#endif /*Not def __WIN32__*/ From e3af5e22f622a3d89bae4c47707945e86fc90c33 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 16:55:54 +0200 Subject: [PATCH 012/114] Added option for Unix Domain Socket Server compilation --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12ce44a5..42b427db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) endif() # defaults for modules that can be enabled/disabled +set(UNIX_DOMAIN_SOCKET_SERVER YES CACHE BOOL "Include Unix Domain Socket server") set(HTTP_SERVER YES CACHE BOOL "Include HTTP server using libmicrohttpd") set(HTTP_CLIENT YES CACHE BOOL "Include HTTP client support using curl") set(COMPILE_TESTS YES CACHE BOOL "Compile test framework") From b23bfec88d28a6c3713421aaed316ae2ed79820c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 16:56:46 +0200 Subject: [PATCH 013/114] Added the files and libs needed to compile the Unix Domain Socket Server --- src/jsonrpccpp/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 32de5997..162707b7 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -45,6 +45,13 @@ if (HTTP_SERVER) list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT} ${MHD_LIBRARIES}) endif() +# setup sources for unix domain socket connectors +if (UNIX_DOMAIN_SOCKET_SERVER) + list(APPEND server_connector_header "server/connectors/unixdomainsocketserver.h") + list(APPEND server_connector_source "server/connectors/unixdomainsocketserver.cpp") + list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) +endif() + # configure a header file to pass some of the CMake settings to the source code # TODO: move it to custom build step? file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/gen/jsonrpccpp/common") From f162c307b7c6a862950439f83346396b7df74e2a Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 16:59:19 +0200 Subject: [PATCH 014/114] Commented out debug purpose couts --- .../connectors/unixdomainsocketserver.cpp | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 78cac4b7..c604317f 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -61,14 +61,14 @@ bool UnixDomainSocketServer::StartListening() return false; } //Launch listening loop there - cout << "(" << pthread_self() << ") " << "Will launch the thread for the loop" << endl; + //cout << "(" << pthread_self() << ") " << "Will launch the thread for the loop" << endl; 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); } - cout << "(" << pthread_self() << ") " << "Returning " << this->running << endl; + //cout << "(" << pthread_self() << ") " << "Returning " << this->running << endl; return this->running; } @@ -85,13 +85,13 @@ bool UnixDomainSocketServer::StopListening() bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) { - cout << "(" << pthread_self() << ") " << "Entered in send response" << endl; + //cout << "(" << pthread_self() << ") " << "Entered in send response" << endl; int connection_fd = reinterpret_cast(addInfo); - cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; + //cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; write(connection_fd, response.c_str(), response.size()); - cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; + //cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; close(connection_fd); return true; } @@ -104,17 +104,17 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { void UnixDomainSocketServer::ListenLoop() { int connection_fd; socklen_t address_length; - cout << "(" << pthread_self() << ") " << "Will launch the loop" << endl; + //cout << "(" << pthread_self() << ") " << "Will launch the loop" << endl; while((connection_fd = accept(this->socket_fd, (struct sockaddr *) &(this->address), &address_length)) > -1) { - cout << "(" << pthread_self() << ") " << "Client connected" << endl; + //cout << "(" << pthread_self() << ") " << "Client connected" << endl; pthread_t client_thread; struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); params->instance = this; params->connection_fd = connection_fd; - cout << "(" << pthread_self() << ") " << "Will launch the thread to handle the request" << endl; - cout << "Sending instance=" << this << endl; - cout << "Sending connection_fd=" << connection_fd << endl; + //cout << "(" << pthread_self() << ") " << "Will launch the thread to handle the request" << endl; + //cout << "Sending instance=" << this << endl; + //cout << "Sending connection_fd=" << connection_fd << endl; int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); if(ret != 0) { pthread_detach(client_thread); @@ -125,31 +125,31 @@ void UnixDomainSocketServer::ListenLoop() { } void* UnixDomainSocketServer::GenerateResponse(void *p_data) { - cout << "(" << pthread_self() << ") " << "Entrered in generate response" << endl; + //cout << "(" << pthread_self() << ") " << "Entrered in generate response" << endl; struct GenerateResponseParameters* params = reinterpret_cast(p_data); UnixDomainSocketServer *instance = params->instance; - cout << "Got instance=" << instance << endl; + //cout << "Got instance=" << instance << endl; int connection_fd = params->connection_fd; - cout << "Got connection_fd=" << connection_fd << endl; - cout << "(" << pthread_self() << ") " << "Obtained params" << endl; + //cout << "Got connection_fd=" << connection_fd << endl; + //cout << "(" << pthread_self() << ") " << "Obtained params" << endl; delete params; params = NULL; int nbytes; char buffer[BUFFER_SIZE]; - cout << "(" << pthread_self() << ") " << "Will read the request" << endl; + //cout << "(" << pthread_self() << ") " << "Will read the request" << endl; string request; do { //The client sends its json formatted request and an \0. - cout << "(" << pthread_self() << ") " << "Current request state: #" << request << "#"; + //cout << "(" << pthread_self() << ") " << "Current request state: #" << request << "#"; nbytes = read(connection_fd, buffer, BUFFER_SIZE); - cout << "(" << pthread_self() << ") " << "Received part of request: #" << buffer << "#"; + //cout << "(" << pthread_self() << ") " << "Received part of request: #" << buffer << "#"; if(request.empty()) request = string(buffer); else request.append(buffer,nbytes); } while(request.find(char(0x04)) == string::npos); - cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; + //cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; - cout << "(" << pthread_self() << ") " << "Will launch OnRequest" << endl; + //cout << "(" << pthread_self() << ") " << "Will launch OnRequest" << endl; instance->OnRequest(request, reinterpret_cast(connection_fd)); } From c5ecd496fa2b0f52b0cad5e43455edff7647e34c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 17:13:40 +0200 Subject: [PATCH 015/114] Revert "Updated author information/metadata." This reverts commit 63a558950f6072317475948a27053dbeb0f0afe0. --- src/jsonrpccpp/server/connectors/httpserver.cpp | 2 +- src/jsonrpccpp/server/connectors/httpserver.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/httpserver.cpp b/src/jsonrpccpp/server/connectors/httpserver.cpp index 1714b3c2..0ea2104e 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.cpp +++ b/src/jsonrpccpp/server/connectors/httpserver.cpp @@ -3,7 +3,7 @@ ************************************************************************* * @file httpserver.cpp * @date 31.12.2012 - * @author Peter Spiess-Knafl , Alexandre Poirot + * @author Peter Spiess-Knafl * @license See attached LICENSE.txt ************************************************************************/ diff --git a/src/jsonrpccpp/server/connectors/httpserver.h b/src/jsonrpccpp/server/connectors/httpserver.h index 78ab2345..72b57c34 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.h +++ b/src/jsonrpccpp/server/connectors/httpserver.h @@ -3,7 +3,7 @@ ************************************************************************* * @file httpserver.h * @date 31.12.2012 - * @author Peter Spiess-Knafl , Alexandre Poirot + * @author Peter Spiess-Knafl * @license See attached LICENSE.txt ************************************************************************/ From 6d415951497a78ef3f46cec961ae1478831dc878 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 17:14:06 +0200 Subject: [PATCH 016/114] Revert "Added a way to make the http server to listen only to local loop." This reverts commit 3489a3ee13cea7d2a8d46b2519c5dcfaac515d2f. --- .../server/connectors/httpserver.cpp | 95 +------------------ src/jsonrpccpp/server/connectors/httpserver.h | 6 +- 2 files changed, 5 insertions(+), 96 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/httpserver.cpp b/src/jsonrpccpp/server/connectors/httpserver.cpp index 0ea2104e..bb494c45 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.cpp +++ b/src/jsonrpccpp/server/connectors/httpserver.cpp @@ -26,15 +26,14 @@ struct mhd_coninfo { int code; }; -HttpServer::HttpServer(int port, const std::string &sslcert, const std::string &sslkey, int threads, const bool listenLocalhostOnly) : +HttpServer::HttpServer(int port, const std::string &sslcert, const std::string &sslkey, int threads) : AbstractServerConnector(), port(port), threads(threads), running(false), path_sslcert(sslcert), path_sslkey(sslkey), - daemon(NULL), - listenLocalhostOnly(listenLocalhostOnly) + daemon(NULL) { } @@ -58,52 +57,7 @@ bool HttpServer::StartListening() SpecificationParser::GetFileContent(this->path_sslcert, this->sslcert); SpecificationParser::GetFileContent(this->path_sslkey, this->sslkey); - if(this->listenLocalhostOnly) { - this->sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(this->sockfd < 0) - cerr << "can't open stream socket" << endl; - - this->addr.sin_family = AF_INET; - this->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - this->addr.sin_port = htons(8385); - - if (bind(this->sockfd, (struct sockaddr *) &(this->addr), sizeof(this->addr)) < 0) - cerr << "server: can't bind local address" << endl; - - listen(sockfd, 5); - cout << "Using own socket (" << this->addr.sin_addr.s_addr << ", " << this->addr.sin_port << ")" << endl; - - this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, - this->port, - NULL, - NULL, - HttpServer::callback, - this, - MHD_OPTION_HTTPS_MEM_KEY, - this->sslkey.c_str(), - MHD_OPTION_HTTPS_MEM_CERT, - this->sslcert.c_str(), - MHD_OPTION_THREAD_POOL_SIZE, - this->threads, - MHD_OPTION_LISTEN_SOCKET, - this->sockfd, - MHD_OPTION_END); - } - else { - this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, - this->port, - NULL, - NULL, - HttpServer::callback, - this, - MHD_OPTION_HTTPS_MEM_KEY, - this->sslkey.c_str(), - MHD_OPTION_HTTPS_MEM_CERT, - this->sslcert.c_str(), - MHD_OPTION_THREAD_POOL_SIZE, - this->threads, - MHD_OPTION_END); - } + this->daemon = MHD_start_daemon(MHD_USE_SSL | MHD_USE_SELECT_INTERNALLY, this->port, NULL, NULL, HttpServer::callback, this, MHD_OPTION_HTTPS_MEM_KEY, this->sslkey.c_str(), MHD_OPTION_HTTPS_MEM_CERT, this->sslcert.c_str(), MHD_OPTION_THREAD_POOL_SIZE, this->threads, MHD_OPTION_END); } catch (JsonRpcException& ex) { @@ -112,48 +66,7 @@ bool HttpServer::StartListening() } else { - if(this->listenLocalhostOnly) { - this->sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(this->sockfd < 0) - cerr << "can't open stream socket" << endl; - - this->addr.sin_family = AF_INET; - this->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - this->addr.sin_port = htons(8385); - - if (bind(this->sockfd, (struct sockaddr *) &(this->addr), sizeof(this->addr)) < 0) - cerr << "server: can't bind local address" << endl; - - listen(sockfd, 5); - cout << "Using own socket (" << this->addr.sin_addr.s_addr << ", " << this->addr.sin_port << ")" << endl; - - this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, - this->port, - NULL, - NULL, - HttpServer::callback, - this, - MHD_OPTION_THREAD_POOL_SIZE, - this->threads, - MHD_OPTION_LISTEN_SOCKET, - this->sockfd, - MHD_OPTION_END); - } - else { - this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, - this->port, - NULL, - NULL, - HttpServer::callback, - this, - MHD_OPTION_HTTPS_MEM_KEY, - this->sslkey.c_str(), - MHD_OPTION_HTTPS_MEM_CERT, - this->sslcert.c_str(), - MHD_OPTION_THREAD_POOL_SIZE, - this->threads, - MHD_OPTION_END); - } + this->daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, this->port, NULL, NULL, HttpServer::callback, this, MHD_OPTION_THREAD_POOL_SIZE, this->threads, MHD_OPTION_END); } if (this->daemon != NULL) this->running = true; diff --git a/src/jsonrpccpp/server/connectors/httpserver.h b/src/jsonrpccpp/server/connectors/httpserver.h index 72b57c34..075962c8 100644 --- a/src/jsonrpccpp/server/connectors/httpserver.h +++ b/src/jsonrpccpp/server/connectors/httpserver.h @@ -23,7 +23,6 @@ typedef intptr_t ssize_t; #include #include #include -#include #endif #include @@ -48,7 +47,7 @@ namespace jsonrpc * @param enableSpecification - defines if the specification is returned in case of a GET request * @param sslcert - defines the path to a SSL certificate, if this path is != "", then SSL/HTTPS is used with the given certificate. */ - HttpServer(int port, const std::string& sslcert = "", const std::string& sslkey = "", int threads = 50, const bool listenLocalhostOnly = false); + HttpServer(int port, const std::string& sslcert = "", const std::string& sslkey = "", int threads = 50); virtual bool StartListening(); virtual bool StopListening(); @@ -63,9 +62,6 @@ namespace jsonrpc int port; int threads; bool running; - bool listenLocalhostOnly; - int sockfd; - struct sockaddr_in addr; std::string path_sslcert; std::string path_sslkey; std::string sslcert; From eaa228858cd5bcfb0b95155f8004177521f5d30c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 18:08:54 +0200 Subject: [PATCH 017/114] Improved socket name handling to improving socket clean up --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index c604317f..d95a6fa6 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -20,10 +20,11 @@ using namespace jsonrpc; using namespace std; #define BUFFER_SIZE 64 +#define PATH_MAX 108 UnixDomainSocketServer::UnixDomainSocketServer(const std::string &socket_path) : AbstractServerConnector(), - socket_path(socket_path), + socket_path(socket_path.substr(0, PATH_MAX)), running(false) { } @@ -47,7 +48,7 @@ bool UnixDomainSocketServer::StartListening() memset(&(this->address), 0, sizeof(struct sockaddr_un)); this->address.sun_family = AF_UNIX; - snprintf(this->address.sun_path, this->socket_path.size(), this->socket_path.c_str()); + snprintf(this->address.sun_path, PATH_MAX, this->socket_path.c_str()); if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)) != 0) { From 7e22e9e717a2567a0d58418a34af76fedc612818 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 7 May 2015 18:43:47 +0200 Subject: [PATCH 018/114] Replaced \n char by EOT char at the end of response --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index d95a6fa6..a7f1fc47 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -90,7 +90,10 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) int connection_fd = reinterpret_cast(addInfo); //cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; - write(connection_fd, response.c_str(), response.size()); + char eot = 0x04; + string toSend = response.substr(0, toSend.find_last_of('\n')); + toSend += eot; + write(connection_fd, toSend.c_str(), toSend.size()); //cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; close(connection_fd); From 5eb3ab3de477067f3779a5976030add26031af8c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 10:48:51 +0200 Subject: [PATCH 019/114] Added a way to customize the delimiter char in the socket stream (to delimit json objects) --- .../connectors/unixdomainsocketserver.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index a7f1fc47..01aac211 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -21,6 +21,9 @@ using namespace std; #define BUFFER_SIZE 64 #define PATH_MAX 108 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR UnixDomainSocketServer::UnixDomainSocketServer(const std::string &socket_path) : AbstractServerConnector(), @@ -90,10 +93,15 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) int connection_fd = reinterpret_cast(addInfo); //cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; - char eot = 0x04; - string toSend = response.substr(0, toSend.find_last_of('\n')); - toSend += eot; - write(connection_fd, toSend.c_str(), toSend.size()); + if(DELIMITER_CHAR != '\n') { + char eot = DELIMITER_CHAR; + string toSend = response.substr(0, toSend.find_last_of('\n')); + toSend += eot; + write(connection_fd, toSend.c_str(), toSend.size()); + } + else { + write(connection_fd, response.c_str(), response.size()); + } //cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; close(connection_fd); @@ -150,7 +158,7 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { request = string(buffer); else request.append(buffer,nbytes); - } while(request.find(char(0x04)) == string::npos); + } while(request.find(DELIMITER_CHAR) == string::npos); //cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; From 096c011080fb9ea4890363c6e6a8f62f7b5ce1e9 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 15:26:57 +0200 Subject: [PATCH 020/114] Corrected some buffer wrong reading/writing. --- .../connectors/unixdomainsocketserver.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 01aac211..6ce0e811 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -92,17 +92,22 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) //cout << "(" << pthread_self() << ") " << "Entered in send response" << endl; int connection_fd = reinterpret_cast(addInfo); - //cout << "(" << pthread_self() << ") " << "Will write response #" << response << "#"; + string temp = response; + if(temp.find(DELIMITER_CHAR) == string::npos) { + //cout << "Appending delimited char" << endl; + temp.append(1, DELIMITER_CHAR); + //cout << "Temp is #" << temp << "#" << endl; + } + //cout << "Sending #" << temp << "#" << endl; if(DELIMITER_CHAR != '\n') { char eot = DELIMITER_CHAR; - string toSend = response.substr(0, toSend.find_last_of('\n')); + string toSend = temp.substr(0, toSend.find_last_of('\n')); toSend += eot; write(connection_fd, toSend.c_str(), toSend.size()); - } + } else { - write(connection_fd, response.c_str(), response.size()); + write(connection_fd, temp.c_str(), temp.size()); } - //cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; close(connection_fd); return true; @@ -150,14 +155,11 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { char buffer[BUFFER_SIZE]; //cout << "(" << pthread_self() << ") " << "Will read the request" << endl; string request; - do { //The client sends its json formatted request and an \0. + do { //The client sends its json formatted request and a delimiter request. //cout << "(" << pthread_self() << ") " << "Current request state: #" << request << "#"; nbytes = read(connection_fd, buffer, BUFFER_SIZE); //cout << "(" << pthread_self() << ") " << "Received part of request: #" << buffer << "#"; - if(request.empty()) - request = string(buffer); - else - request.append(buffer,nbytes); + request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); //cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; From bcf34dcf745d7c6d8848ebd924566e34a6dd9f84 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 15:27:49 +0200 Subject: [PATCH 021/114] Added unix domain socket client to talk with unix domain socket server. --- .../connectors/unixdomainsocketclient.cpp | 74 +++++++++++++++++++ .../connectors/unixdomainsocketclient.h | 32 ++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp create mode 100644 src/jsonrpccpp/client/connectors/unixdomainsocketclient.h diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp new file mode 100644 index 00000000..d3278014 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -0,0 +1,74 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file unixdomainsocketclient.cpp + * @date 11.05.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "unixdomainsocketclient.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BUFFER_SIZE 64 +#define PATH_MAX 108 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR + +using namespace jsonrpc; +using namespace std; + +UnixDomainSocketClient::UnixDomainSocketClient(const std::string& path) + : path(path) +{ +} + +UnixDomainSocketClient::~UnixDomainSocketClient() +{ +} + +void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) +{ + //cout << "Will call " << message << endl; + sockaddr_un address; + int socket_fd, nbytes; + char buffer[BUFFER_SIZE]; + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (socket_fd < 0) { + cerr << "Socket failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + + memset(&address, 0, sizeof(sockaddr_un)); + + address.sun_family = AF_UNIX; + snprintf(address.sun_path, PATH_MAX, this->path.c_str()); + + if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) { + cerr << "connect failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + //cout << "Will send #" << message << "#" << endl; + write(socket_fd, message.c_str(), message.size()); + + do { + nbytes = read(socket_fd, buffer, BUFFER_SIZE); + string tmp; + tmp.append(buffer, nbytes); + //cout << "Received: #" << tmp << "#("<< nbytes << ")" << endl; + result.append(buffer,nbytes); + + } while(result.find(DELIMITER_CHAR) == string::npos); + + close(socket_fd); + //cout << "Got " << result << endl; +} diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h new file mode 100644 index 00000000..87343da7 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h @@ -0,0 +1,32 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file unixdomainsocketclient.h + * @date 11.05.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef __WIN32__ //Unix domain sockets have meaning only on unix-like systems +#ifndef JSONRPC_CPP_UNIXDOMAINSOCKETCLIENT_H_ +#define JSONRPC_CPP_UNIXDOMAINSOCKETCLIENT_H_ + +#include "../iclientconnector.h" +#include + +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); + + private: + std::string path; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_HTTPCLIENT_H_ */ +#endif /*Not def __WIND32__*/ From 6c53a8282e7528846c7810eaf35f27cfe571ca2f Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 15:29:01 +0200 Subject: [PATCH 022/114] Added CMake specific content to build unix domain socket client. Also restricted those build option to UNIXes only. --- CMakeLists.txt | 5 ++++- src/jsonrpccpp/CMakeLists.txt | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42b427db..44b982d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,10 @@ if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) endif() # defaults for modules that can be enabled/disabled -set(UNIX_DOMAIN_SOCKET_SERVER YES CACHE BOOL "Include Unix Domain Socket server") +if(UNIX) + set(UNIX_DOMAIN_SOCKET_SERVER YES CACHE BOOL "Include Unix Domain Socket server") + set(UNIX_DOMAIN_SOCKET_CLIENT YES CACHE BOOL "Include Unix Domain Socket client") +endif(UNIX) set(HTTP_SERVER YES CACHE BOOL "Include HTTP server using libmicrohttpd") set(HTTP_CLIENT YES CACHE BOOL "Include HTTP client support using curl") set(COMPILE_TESTS YES CACHE BOOL "Compile test framework") diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 162707b7..7b136f6d 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -52,6 +52,11 @@ if (UNIX_DOMAIN_SOCKET_SERVER) list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) endif() +if (UNIX_DOMAIN_SOCKET_CLIENT) + list(APPEND client_connector_header "client/connectors/unixdomainsocketclient.h") + list(APPEND client_connector_source "client/connectors/unixdomainsocketclient.cpp") +endif() + # configure a header file to pass some of the CMake settings to the source code # TODO: move it to custom build step? file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/gen/jsonrpccpp/common") From 63fedaa8e6262614310db335f49ed82aaa90c0fd Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 15:47:18 +0200 Subject: [PATCH 023/114] Cleaned some debug-purpose cout. --- .../connectors/unixdomainsocketclient.cpp | 4 ---- .../connectors/unixdomainsocketserver.cpp | 22 ------------------- 2 files changed, 26 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index d3278014..84f5fca2 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -38,7 +38,6 @@ UnixDomainSocketClient::~UnixDomainSocketClient() void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - //cout << "Will call " << message << endl; sockaddr_un address; int socket_fd, nbytes; char buffer[BUFFER_SIZE]; @@ -57,18 +56,15 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str cerr << "connect failed" << endl; throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); } - //cout << "Will send #" << message << "#" << endl; write(socket_fd, message.c_str(), message.size()); do { nbytes = read(socket_fd, buffer, BUFFER_SIZE); string tmp; tmp.append(buffer, nbytes); - //cout << "Received: #" << tmp << "#("<< nbytes << ")" << endl; result.append(buffer,nbytes); } while(result.find(DELIMITER_CHAR) == string::npos); close(socket_fd); - //cout << "Got " << result << endl; } diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 6ce0e811..e00971ff 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -65,14 +65,12 @@ bool UnixDomainSocketServer::StartListening() return false; } //Launch listening loop there - //cout << "(" << pthread_self() << ") " << "Will launch the thread for the loop" << endl; 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); } - //cout << "(" << pthread_self() << ") " << "Returning " << this->running << endl; return this->running; } @@ -89,16 +87,12 @@ bool UnixDomainSocketServer::StopListening() bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) { - //cout << "(" << pthread_self() << ") " << "Entered in send response" << endl; int connection_fd = reinterpret_cast(addInfo); string temp = response; if(temp.find(DELIMITER_CHAR) == string::npos) { - //cout << "Appending delimited char" << endl; temp.append(1, DELIMITER_CHAR); - //cout << "Temp is #" << temp << "#" << endl; } - //cout << "Sending #" << temp << "#" << endl; if(DELIMITER_CHAR != '\n') { char eot = DELIMITER_CHAR; string toSend = temp.substr(0, toSend.find_last_of('\n')); @@ -108,7 +102,6 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) else { write(connection_fd, temp.c_str(), temp.size()); } - //cout << "(" << pthread_self() << ") " << "Will close client socket" << endl; close(connection_fd); return true; } @@ -121,17 +114,12 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { void UnixDomainSocketServer::ListenLoop() { int connection_fd; socklen_t address_length; - //cout << "(" << pthread_self() << ") " << "Will launch the loop" << endl; while((connection_fd = accept(this->socket_fd, (struct sockaddr *) &(this->address), &address_length)) > -1) { - //cout << "(" << pthread_self() << ") " << "Client connected" << endl; pthread_t client_thread; struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); params->instance = this; params->connection_fd = connection_fd; - //cout << "(" << pthread_self() << ") " << "Will launch the thread to handle the request" << endl; - //cout << "Sending instance=" << this << endl; - //cout << "Sending connection_fd=" << connection_fd << endl; int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); if(ret != 0) { pthread_detach(client_thread); @@ -142,28 +130,18 @@ void UnixDomainSocketServer::ListenLoop() { } void* UnixDomainSocketServer::GenerateResponse(void *p_data) { - //cout << "(" << pthread_self() << ") " << "Entrered in generate response" << endl; struct GenerateResponseParameters* params = reinterpret_cast(p_data); UnixDomainSocketServer *instance = params->instance; - //cout << "Got instance=" << instance << endl; int connection_fd = params->connection_fd; - //cout << "Got connection_fd=" << connection_fd << endl; - //cout << "(" << pthread_self() << ") " << "Obtained params" << endl; delete params; params = NULL; int nbytes; char buffer[BUFFER_SIZE]; - //cout << "(" << pthread_self() << ") " << "Will read the request" << endl; string request; do { //The client sends its json formatted request and a delimiter request. - //cout << "(" << pthread_self() << ") " << "Current request state: #" << request << "#"; nbytes = read(connection_fd, buffer, BUFFER_SIZE); - //cout << "(" << pthread_self() << ") " << "Received part of request: #" << buffer << "#"; request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); - //cout << "(" << pthread_self() << ") " << "Received request #" << request << "#" << endl; - - //cout << "(" << pthread_self() << ") " << "Will launch OnRequest" << endl; instance->OnRequest(request, reinterpret_cast(connection_fd)); } From f31e34812926ac76f6e48ad7e5890e8e2d04f51a Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 16:12:29 +0200 Subject: [PATCH 024/114] Added simple client and server over unix domain sockets instead of http. --- src/examples/unixdomainsocketclient.cpp | 33 +++++++++++++ src/examples/unixdomainsocketserver.cpp | 63 +++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/examples/unixdomainsocketclient.cpp create mode 100644 src/examples/unixdomainsocketserver.cpp diff --git a/src/examples/unixdomainsocketclient.cpp b/src/examples/unixdomainsocketclient.cpp new file mode 100644 index 00000000..c459c924 --- /dev/null +++ b/src/examples/unixdomainsocketclient.cpp @@ -0,0 +1,33 @@ +/** + * @file unixdomainsocketclient.cpp + * @date 11.05.2015 + * @author Alexandre Poirot + * @brief unixdomainsocketclient.cpp + */ + +#include +#include +#include + +using namespace jsonrpc; +using namespace std; + +int main() +{ + UnixDomainSocketClient client("/tmp/unixdomainsocketexample"); + Client c(client); + + Json::Value params; + params["name"] = "Peter"; + + try + { + cout << c.CallMethod("sayHello", params) << endl; + } + catch (JsonRpcException& e) + { + cerr << e.what() << endl; + } + + +} diff --git a/src/examples/unixdomainsocketserver.cpp b/src/examples/unixdomainsocketserver.cpp new file mode 100644 index 00000000..e198efea --- /dev/null +++ b/src/examples/unixdomainsocketserver.cpp @@ -0,0 +1,63 @@ +/** + * @file unixdomainsocketserver.cpp + * @date 11.05.2015 + * @author Alexandre Poirot + * @brief unixdomainsocketserver.cpp + */ + +#include +#include +#include +#include +#include + + +using namespace jsonrpc; +using namespace std; + +class SampleServer : public AbstractServer +{ + public: + SampleServer(UnixDomainSocketServer &server) : + AbstractServer(server) + { + this->bindAndAddMethod(Procedure("sayHello", PARAMS_BY_NAME, JSON_STRING, "name", JSON_STRING, NULL), &SampleServer::sayHello); + this->bindAndAddNotification(Procedure("notifyServer", PARAMS_BY_NAME, NULL), &SampleServer::notifyServer); + } + + //method + void sayHello(const Json::Value& request, Json::Value& response) + { + response = "Hello: " + request["name"].asString(); + } + + //notification + void notifyServer(const Json::Value& request) + { + (void)request; + cout << "server received some Notification" << endl; + } +}; + +int main() +{ + try + { + UnixDomainSocketServer server("/tmp/unixdomainsocketexample"); + SampleServer serv(server); + if (serv.StartListening()) + { + cout << "Server started successfully" << endl; + getchar(); + serv.StopListening(); + } + else + { + cout << "Error starting Server" << endl; + } + } + catch (jsonrpc::JsonRpcException& e) + { + cerr << e.what() << endl; + } +} From e4d8fa8f510a4ad51a5aadd314dc7f16219eb601 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 16:12:56 +0200 Subject: [PATCH 025/114] Modified cmake files to build previously added examples --- CMakeLists.txt | 11 ++++++++++ src/examples/CMakeLists.txt | 44 ++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44b982d4..9660ceaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,10 @@ set(COMPILE_STUBGEN YES CACHE BOOL "Compile the stubgenerator") set(COMPILE_EXAMPLES YES CACHE BOOL "Compile example programs") # print actual settings +if(UNIX) + message(STATUS "UNIX_DOMAIN_SOCKET_SERVER: ${UNIX_DOMAIN_SOCKET_SERVER}") + message(STATUS "UNIX_DOMAIN_SOCKET_CLIENT: ${UNIX_DOMAIN_SOCKET_CLIENT}") +endif(UNIX) message(STATUS "HTTP_SERVER: ${HTTP_SERVER}") message(STATUS "HTTP_CLIENT: ${HTTP_CLIENT}") message(STATUS "COMPILE_TESTS: ${COMPILE_TESTS}") @@ -74,6 +78,13 @@ if (HTTP_SERVER AND HTTP_CLIENT) add_subdirectory(src/examples) endif() +if(UNIX) + if (UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) + add_subdirectory(src/examples) + endif() +endif(UNIX) + + # setup test suite if (Boost_FOUND AND COMPILE_TESTS) enable_testing() diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index ed399962..ce90ec47 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -37,20 +37,34 @@ include_directories(${JSONCPP_INCLUDE_DIRS}) include_directories(${MHD_INCLUDE_DIRS}) if (COMPILE_EXAMPLES) - add_executable(simpleserversample simpleserver.cpp) - target_link_libraries(simpleserversample jsonrpcserver) + if (HTTP_SERVER AND HTTP_CLIENT) + add_executable(simpleserversample simpleserver.cpp) + target_link_libraries(simpleserversample jsonrpcserver) + + add_executable(simpleclientsample simpleclient.cpp) + target_link_libraries(simpleclientsample jsonrpcclient) + + if (COMPILE_STUBGEN) + add_executable(stubclientsample stubclient.cpp ${CMAKE_BINARY_DIR}/gen/stubclient.h) + target_link_libraries(stubclientsample jsonrpcclient) + + add_executable(stubserversample stubserver.cpp ${CMAKE_BINARY_DIR}/gen/abstractstubserver.h) + target_link_libraries(stubserversample jsonrpcserver) + + add_executable(xbmcremote xbmcremote.cpp ${CMAKE_BINARY_DIR}/gen/xbmcremote.h) + target_link_libraries(xbmcremote jsonrpcclient) + endif() + endif (HTTP_SERVER AND HTTP_CLIENT) + + if(UNIX) + if (UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) + add_executable(unixdomainsocketserversample unixdomainsocketserver.cpp) + target_link_libraries(unixdomainsocketserversample jsonrpcserver) + + add_executable(unixdomainsocketclientsample unixdomainsocketclient.cpp) + target_link_libraries(unixdomainsocketclientsample jsonrpcclient) + endif (UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) + endif(UNIX) - add_executable(simpleclientsample simpleclient.cpp) - target_link_libraries(simpleclientsample jsonrpcclient) - - if (COMPILE_STUBGEN) - add_executable(stubclientsample stubclient.cpp ${CMAKE_BINARY_DIR}/gen/stubclient.h) - target_link_libraries(stubclientsample jsonrpcclient) - - add_executable(stubserversample stubserver.cpp ${CMAKE_BINARY_DIR}/gen/abstractstubserver.h) - target_link_libraries(stubserversample jsonrpcserver) - - add_executable(xbmcremote xbmcremote.cpp ${CMAKE_BINARY_DIR}/gen/xbmcremote.h) - target_link_libraries(xbmcremote jsonrpcclient) - endif() + endif() From 9e25aa93494473586333634de9e9bb0e0c9a0cb0 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 16:29:32 +0200 Subject: [PATCH 026/114] Corrected incompatible include in case where both http and unix domain sokcet example should be compiled --- CMakeLists.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9660ceaa..dac76a0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,17 +74,10 @@ if (COMPILE_STUBGEN) endif () # setup examples -if (HTTP_SERVER AND HTTP_CLIENT) +if ((HTTP_SERVER AND HTTP_CLIENT) OR (UNIX AND UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT)) add_subdirectory(src/examples) endif() -if(UNIX) - if (UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) - add_subdirectory(src/examples) - endif() -endif(UNIX) - - # setup test suite if (Boost_FOUND AND COMPILE_TESTS) enable_testing() From dc28d8fe891bc4f62fa525a7c2f8e00e0ac24c32 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 11 May 2015 16:33:59 +0200 Subject: [PATCH 027/114] Removed not __WIN32__ macro from source code since CMake checks the os and only compile those file on unix-like operating systems. --- src/jsonrpccpp/client/connectors/unixdomainsocketclient.h | 2 -- src/jsonrpccpp/server/connectors/unixdomainsocketserver.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h index 87343da7..cec64f87 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h @@ -7,7 +7,6 @@ * @license See attached LICENSE.txt ************************************************************************/ -#ifndef __WIN32__ //Unix domain sockets have meaning only on unix-like systems #ifndef JSONRPC_CPP_UNIXDOMAINSOCKETCLIENT_H_ #define JSONRPC_CPP_UNIXDOMAINSOCKETCLIENT_H_ @@ -29,4 +28,3 @@ namespace jsonrpc } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_HTTPCLIENT_H_ */ -#endif /*Not def __WIND32__*/ diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h index 72c41845..0f649053 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -6,7 +6,7 @@ * @author Alexandre Poirot * @license See attached LICENSE.txt ************************************************************************/ -#ifndef __WIN32__ //Unix domain sockets have meaning only on unix-like systems + #ifndef JSONRPC_CPP_UNIXDOMAINSOCKETSERVERCONNECTOR_H_ #define JSONRPC_CPP_UNIXDOMAINSOCKETSERVERCONNECTOR_H_ @@ -63,4 +63,4 @@ namespace jsonrpc } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_HTTPSERVERCONNECTOR_H_ */ -#endif /*Not def __WIN32__*/ + From 2f63d516ef2b6f5220519985e60a450552d886ae Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 19 May 2015 11:20:27 +0200 Subject: [PATCH 028/114] Corrected bug: uninitialized address_lenght variable made accept fails. --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index e00971ff..37d21fd4 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -113,7 +113,7 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { void UnixDomainSocketServer::ListenLoop() { int connection_fd; - socklen_t address_length; + socklen_t address_length = sizeof(this->address); while((connection_fd = accept(this->socket_fd, (struct sockaddr *) &(this->address), &address_length)) > -1) { pthread_t client_thread; @@ -142,6 +142,5 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { 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)); } From 4e894e5e5770569d05508ce8b3d18c2af3d213c0 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 21 May 2015 17:27:47 +0200 Subject: [PATCH 029/114] Improved writing of request in socket : now it ensure to fully write the request in the socket (before it could have been wrote partially). --- .../client/connectors/unixdomainsocketclient.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index 84f5fca2..3be47c79 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -56,7 +56,18 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str cerr << "connect failed" << endl; throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); } - write(socket_fd, message.c_str(), message.size()); + + bool fullyWritten = false; + string toSend = message; + do { + ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); + if(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); From 0733aaf7ec83585041c5a39583eb90337bcf5eff Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 21 May 2015 17:28:29 +0200 Subject: [PATCH 030/114] Added and implemented a safer way to write in socket --- .../connectors/unixdomainsocketserver.cpp | 30 ++++++++++++++++--- .../connectors/unixdomainsocketserver.h | 1 + 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 37d21fd4..cae707a7 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -15,6 +15,7 @@ #include #include #include +#include using namespace jsonrpc; using namespace std; @@ -25,7 +26,7 @@ using namespace std; #define DELIMITER_CHAR char(0x0A) #endif //DELIMITER_CHAR -UnixDomainSocketServer::UnixDomainSocketServer(const std::string &socket_path) : +UnixDomainSocketServer::UnixDomainSocketServer(const string &socket_path) : AbstractServerConnector(), socket_path(socket_path.substr(0, PATH_MAX)), running(false) @@ -87,6 +88,7 @@ bool UnixDomainSocketServer::StopListening() bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) { + bool result = false; int connection_fd = reinterpret_cast(addInfo); string temp = response; @@ -97,13 +99,13 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) char eot = DELIMITER_CHAR; string toSend = temp.substr(0, toSend.find_last_of('\n')); toSend += eot; - write(connection_fd, toSend.c_str(), toSend.size()); + result = this->WriteToSocket(connection_fd, toSend); } else { - write(connection_fd, temp.c_str(), temp.size()); + result = this->WriteToSocket(connection_fd, temp); } close(connection_fd); - return true; + return result; } void* UnixDomainSocketServer::LaunchLoop(void *p_data) { @@ -144,3 +146,23 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { } while(request.find(DELIMITER_CHAR) == string::npos); instance->OnRequest(request, reinterpret_cast(connection_fd)); } + + +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 < 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 0f649053..8ff2b8db 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -59,6 +59,7 @@ namespace jsonrpc int connection_fd; }; static void* GenerateResponse(void *p_data); + bool WriteToSocket(int fd, const std::string& toSend); }; } /* namespace jsonrpc */ From 2694f1b799d2c70ee92af56c1a1f633918836cd8 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 22 May 2015 14:54:08 +0200 Subject: [PATCH 031/114] Added pkg-config generation files. It makes the library easier to integrate with autotools on Unix like systems. --- CMakeLists.txt | 17 ++++++++++++++++- libjson-rpc-cpp.pc.cmake | 11 +++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 libjson-rpc-cpp.pc.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index dac76a0e..b303251a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,22 @@ endif() include_directories("${CMAKE_BINARY_DIR}/gen/") include_directories("${CMAKE_BINARY_DIR}/gen/jsonrpccpp/common") +#set pkg-config +find_package(PkgConfig) +get_filename_component(FULL_PATH_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} ABSOLUTE) +set(PROJECT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") +set(PKG_CONFIG_REQUIRES jsoncpp) +set(FULL_PATH_EXEC_PREFIX "${FULL_PATH_INSTALL_PREFIX}") +set(FULL_PATH_INCLUDEDIR "${FULL_PATH_INSTALL_PREFIX}/include") +set(FULL_PATH_LIBDIR "${FULL_PATH_INSTALL_PREFIX}/lib") + +CONFIGURE_FILE( + "${CMAKE_CURRENT_SOURCE_DIR}/libjson-rpc-cpp.pc.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/libjson-rpc-cpp.pc" +) + +INSTALL(FILES "${CMAKE_BINARY_DIR}/libjson-rpc-cpp.pc" + DESTINATION lib/pkgconfig) # the core framework add_subdirectory(src/jsonrpccpp) @@ -123,4 +139,3 @@ if (WIN32 AND NOT UNIX) set(CPACK_NSIS_MODIFY_PATH ON) endif(WIN32 AND NOT UNIX) include(CPack) - diff --git a/libjson-rpc-cpp.pc.cmake b/libjson-rpc-cpp.pc.cmake new file mode 100644 index 00000000..3008b3a0 --- /dev/null +++ b/libjson-rpc-cpp.pc.cmake @@ -0,0 +1,11 @@ +prefix=${FULL_PATH_INSTALL_PREFIX} +exec_prefix=${FULL_PATH_EXEC_PREFIX} +includedir=${FULL_PATH_INCLUDEDIR} +libdir=${FULL_PATH_LIBDIR} + +Name: libjson-rpc-cpp +Description: A C++ implementation of json-rpc. +Version: ${PROJECT_VERSION} +Requires: ${PKG_CONFIG_REQUIRES} +Libs: -L${FULL_PATH_LIBDIR} -ljsonrpccpp-common -ljsonrpccpp-server -ljsonrpccpp-client +Cflags: -I${FULL_PATH_INCLUDEDIR} From c533fe69508909c5b7c3c2471812d89411dc76c9 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 22 May 2015 15:05:58 +0200 Subject: [PATCH 032/114] Used vim to autoindent those modified files (indetation was not pretty clean). --- src/examples/unixdomainsocketclient.cpp | 24 +++--- src/examples/unixdomainsocketserver.cpp | 74 +++++++++---------- .../connectors/unixdomainsocketserver.cpp | 36 ++++----- .../connectors/unixdomainsocketserver.h | 38 +++++----- 4 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/examples/unixdomainsocketclient.cpp b/src/examples/unixdomainsocketclient.cpp index c459c924..80ac0f40 100644 --- a/src/examples/unixdomainsocketclient.cpp +++ b/src/examples/unixdomainsocketclient.cpp @@ -14,20 +14,20 @@ using namespace std; int main() { - UnixDomainSocketClient client("/tmp/unixdomainsocketexample"); - Client c(client); + UnixDomainSocketClient client("/tmp/unixdomainsocketexample"); + Client c(client); - Json::Value params; - params["name"] = "Peter"; + Json::Value params; + params["name"] = "Peter"; - try - { - cout << c.CallMethod("sayHello", params) << endl; - } - catch (JsonRpcException& e) - { - cerr << e.what() << endl; - } + try + { + cout << c.CallMethod("sayHello", params) << endl; + } + catch (JsonRpcException& e) + { + cerr << e.what() << endl; + } } diff --git a/src/examples/unixdomainsocketserver.cpp b/src/examples/unixdomainsocketserver.cpp index e198efea..04d694ab 100644 --- a/src/examples/unixdomainsocketserver.cpp +++ b/src/examples/unixdomainsocketserver.cpp @@ -17,47 +17,47 @@ using namespace std; class SampleServer : public AbstractServer { - public: - SampleServer(UnixDomainSocketServer &server) : - AbstractServer(server) - { - this->bindAndAddMethod(Procedure("sayHello", PARAMS_BY_NAME, JSON_STRING, "name", JSON_STRING, NULL), &SampleServer::sayHello); - this->bindAndAddNotification(Procedure("notifyServer", PARAMS_BY_NAME, NULL), &SampleServer::notifyServer); - } + public: + SampleServer(UnixDomainSocketServer &server) : + AbstractServer(server) + { + this->bindAndAddMethod(Procedure("sayHello", PARAMS_BY_NAME, JSON_STRING, "name", JSON_STRING, NULL), &SampleServer::sayHello); + this->bindAndAddNotification(Procedure("notifyServer", PARAMS_BY_NAME, NULL), &SampleServer::notifyServer); + } - //method - void sayHello(const Json::Value& request, Json::Value& response) - { - response = "Hello: " + request["name"].asString(); - } + //method + void sayHello(const Json::Value& request, Json::Value& response) + { + response = "Hello: " + request["name"].asString(); + } - //notification - void notifyServer(const Json::Value& request) - { - (void)request; - cout << "server received some Notification" << endl; - } + //notification + void notifyServer(const Json::Value& request) + { + (void)request; + cout << "server received some Notification" << endl; + } }; int main() { - try - { - UnixDomainSocketServer server("/tmp/unixdomainsocketexample"); - SampleServer serv(server); - if (serv.StartListening()) - { - cout << "Server started successfully" << endl; - getchar(); - serv.StopListening(); - } - else - { - cout << "Error starting Server" << endl; - } - } - catch (jsonrpc::JsonRpcException& e) - { - cerr << e.what() << endl; - } + try + { + UnixDomainSocketServer server("/tmp/unixdomainsocketexample"); + SampleServer serv(server); + if (serv.StartListening()) + { + cout << "Server started successfully" << endl; + getchar(); + serv.StopListening(); + } + else + { + cout << "Error starting Server" << endl; + } + } + catch (jsonrpc::JsonRpcException& e) + { + cerr << e.what() << endl; + } } diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index cae707a7..cd7b7f1b 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -27,19 +27,19 @@ using namespace std; #endif //DELIMITER_CHAR UnixDomainSocketServer::UnixDomainSocketServer(const string &socket_path) : - AbstractServerConnector(), - socket_path(socket_path.substr(0, PATH_MAX)), - running(false) + AbstractServerConnector(), + socket_path(socket_path.substr(0, PATH_MAX)), + running(false) { } bool UnixDomainSocketServer::StartListening() { - if(!this->running) - { - //Create and bind socket here. - //Then launch the listenning loop. - this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(!this->running) + { + //Create and bind socket here. + //Then launch the listenning loop. + this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); if(this->socket_fd < 0) { cerr << "socket() failed" << endl; @@ -71,19 +71,19 @@ bool UnixDomainSocketServer::StartListening() pthread_detach(this->listenning_thread); } this->running = static_cast(ret==0); - } - return this->running; + } + return this->running; } bool UnixDomainSocketServer::StopListening() { - if(this->running) - { - close(this->socket_fd); - unlink(this->socket_path.c_str()); - this->running = false; - } - return true; + if(this->running) + { + close(this->socket_fd); + unlink(this->socket_path.c_str()); + this->running = false; + } + return true; } bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) @@ -155,7 +155,7 @@ bool UnixDomainSocketServer::WriteToSocket(int fd, const string& toWrite) { do { ssize_t byteWritten = write(fd, toSend.c_str(), toSend.size()); if(byteWritten < 0) - errorOccured = true; + errorOccured = true; else if(byteWritten < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h index 8ff2b8db..ca0a637a 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -24,29 +24,29 @@ namespace jsonrpc { - /** - * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. - */ - class UnixDomainSocketServer: public AbstractServerConnector - { - public: + /** + * 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); + /** + * @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(); + virtual bool StartListening(); + virtual bool StopListening(); - bool virtual SendResponse(const std::string& response, void* addInfo = NULL); + bool virtual SendResponse(const std::string& response, void* addInfo = NULL); - private: - bool running; - std::string socket_path; - int socket_fd; + private: + bool running; + std::string socket_path; + int socket_fd; struct sockaddr_un address; pthread_t listenning_thread; @@ -60,7 +60,7 @@ namespace jsonrpc }; static void* GenerateResponse(void *p_data); bool WriteToSocket(int fd, const std::string& toSend); - }; + }; } /* namespace jsonrpc */ #endif /* JSONRPC_CPP_HTTPSERVERCONNECTOR_H_ */ From 4b2ba6fdb1afd849a5c3a540a565ba784386e5d7 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 26 May 2015 09:36:09 +0200 Subject: [PATCH 033/114] Updated AUTHORS.md --- AUTHORS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index f54ad418..0d95cd08 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -28,6 +28,10 @@ Veselin Rachev Marek Kotewicz + msvc support +Alexandre Poirot ++ added client and server connectors that use Unix Domain Sockets ++ adapted build file to generate pkg-config file for this lib. + Bugfixes (chronological order) ============================== From b60889a2db9d6c7e98724ce5b14d6114c25fe4f6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 23 Jun 2015 18:03:18 +0200 Subject: [PATCH 034/114] Fixed memory leak induced by threads (autocleanud with pthread_detach when thread finishes) on UnixDomainSocketServer. --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index cd7b7f1b..5cef74c0 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -109,6 +109,7 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) } void* UnixDomainSocketServer::LaunchLoop(void *p_data) { + pthread_detach(pthread_self()); UnixDomainSocketServer *instance = reinterpret_cast(p_data);; instance->ListenLoop(); } @@ -132,6 +133,7 @@ void UnixDomainSocketServer::ListenLoop() { } void* UnixDomainSocketServer::GenerateResponse(void *p_data) { + pthread_detach(pthread_self()); struct GenerateResponseParameters* params = reinterpret_cast(p_data); UnixDomainSocketServer *instance = params->instance; int connection_fd = params->connection_fd; From d63ce96ff52f1885255130393d0ba11ca9251347 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Wed, 24 Jun 2015 14:07:14 +0200 Subject: [PATCH 035/114] Removed useless set of client socket in UnixDomainSocketServer. --- .../server/connectors/unixdomainsocketserver.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h index ca0a637a..1c38951a 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -18,7 +18,6 @@ #include #include #include -#include #include "../abstractserverconnector.h" @@ -30,18 +29,16 @@ namespace jsonrpc 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); + bool StartListening(); + bool StopListening(); + bool SendResponse(const std::string& response, void* addInfo = NULL); private: bool running; @@ -50,7 +47,6 @@ namespace jsonrpc struct sockaddr_un address; pthread_t listenning_thread; - std::set client_thread_pool; static void* LaunchLoop(void *p_data); void ListenLoop(); From 5e0a21cbbd0190b080f45488936477f5f74efc13 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 25 Jun 2015 17:29:34 +0200 Subject: [PATCH 036/114] Improved way to stop listenning (non blocking accept and looping only when running is true). --- .../connectors/unixdomainsocketserver.cpp | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 5cef74c0..298fdbf8 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using namespace jsonrpc; using namespace std; @@ -48,6 +49,8 @@ bool UnixDomainSocketServer::StartListening() unlink(this->socket_path.c_str()); + fcntl(this->socket_fd, F_SETFL, FNDELAY); + /* start with a clean address structure */ memset(&(this->address), 0, sizeof(struct sockaddr_un)); @@ -66,6 +69,7 @@ bool UnixDomainSocketServer::StartListening() 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); @@ -79,11 +83,12 @@ 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()); - this->running = false; } - return true; + return !(this->running); } bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) @@ -112,22 +117,28 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { 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((connection_fd = accept(this->socket_fd, (struct sockaddr *) &(this->address), &address_length)) > -1) - { - 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, UnixDomainSocketServer::GenerateResponse, params); - if(ret != 0) { - pthread_detach(client_thread); - delete params; - params = NULL; + while(this->running) { + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->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, UnixDomainSocketServer::GenerateResponse, params); + if(ret != 0) { + pthread_detach(client_thread); + delete params; + params = NULL; + } + } + else { + usleep(2500); } } } @@ -147,6 +158,7 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); instance->OnRequest(request, reinterpret_cast(connection_fd)); + return NULL; } From c49618fb7623245c65e5787fc843d73f72a6ec1a Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:04:42 +0200 Subject: [PATCH 037/114] Added Tcp Socket Client Connector architecture. --- .../client/connectors/tcpsocketclient.cpp | 41 +++++++++++++++++++ .../client/connectors/tcpsocketclient.h | 32 +++++++++++++++ .../connectors/tcpsocketclientprivate.h | 23 +++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/jsonrpccpp/client/connectors/tcpsocketclient.cpp create mode 100644 src/jsonrpccpp/client/connectors/tcpsocketclient.h create mode 100644 src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp new file mode 100644 index 00000000..24688d33 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp @@ -0,0 +1,41 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file tcpsocketclient.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "tcpsocketclient.h" + +#ifdef __WIN32__ +#include "windowstcpsocketclient.h" +#elif __unix__ +#include "linuxtcpsocketclient.h" +#endif + +using namespace jsonrpc; +using namespace std; + +TcpSocketClient::TcpSocketClient(const std::string& ipToConnect, const unsigned int &port) +{ +#ifdef __WIN32__ + this->realSocket = new WindowsTcpSocketClient(ipToConnect, port); +#elif __unix__ + this->realSocket = new LinuxTcpSocketClient(ipToConnect, port); +#else + this->realSocket = NULL; +#endif +} + +TcpSocketClient::~TcpSocketClient() +{ +} + +void TcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) +{ + 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 new file mode 100644 index 00000000..26fff40b --- /dev/null +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.h @@ -0,0 +1,32 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file unixdomainsocketclient.h + * @date 11.05.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_TCPSOCKETCLIENT_H_ +#define JSONRPC_CPP_TCPSOCKETCLIENT_H_ + +#include "../iclientconnector.h" +#include +#include +#include "tcpsocketclientprivate.h" + +namespace jsonrpc +{ + class TcpSocketClient : public IClientConnector + { + public: + TcpSocketClient(const std::string& ipToConnect, const unsigned int &port); + virtual ~TcpSocketClient(); + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + + private: + TcpSocketClientPrivate *realSocket; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_TCPSOCKETCLIENT_H_ */ diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h b/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h new file mode 100644 index 00000000..e97f679d --- /dev/null +++ b/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h @@ -0,0 +1,23 @@ +/************************************************************************* + * 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 +{ + class TcpSocketClientPrivate : public IClientConnector + { + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_TCPSOCKETCLIENTPRIVATE_H_ */ From 52b3f4c1c0b8ca4370503497d5bbbe5bb973ac7b Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:05:17 +0200 Subject: [PATCH 038/114] Implemented Linux Tcp Socket Client Connector that matches previous architecture. --- .../connectors/linuxtcpsocketclient.cpp | 81 +++++++++++++++++++ .../client/connectors/linuxtcpsocketclient.h | 32 ++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp create mode 100644 src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp new file mode 100644 index 00000000..d8d44680 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -0,0 +1,81 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file linuxtcpsocketclient.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "linuxtcpsocketclient.h" +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 64 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR + +using namespace jsonrpc; +using namespace std; + +LinuxTcpSocketClient::LinuxTcpSocketClient(const std::string& ipToConnect, const unsigned int &port) : + TcpSocketClientPrivate(), + ipToConnect(ipToConnect), + port(port) +{ +} + +LinuxTcpSocketClient::~LinuxTcpSocketClient() +{ +} + +void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) +{ + sockaddr_in address; + int socket_fd, nbytes; + char buffer[BUFFER_SIZE]; + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) { + cerr << "Socket failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + + memset(&address, 0, sizeof(sockaddr_in)); + + address.sin_family = AF_INET; + inet_aton(this->ipToConnect.c_str(), &(address.sin_addr)); + address.sin_port = htons(this->port); + + if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) { + cerr << "connect failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + + bool fullyWritten = false; + string toSend = message; + do { + ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); + if(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); + + } while(result.find(DELIMITER_CHAR) == string::npos); + + close(socket_fd); +} diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h new file mode 100644 index 00000000..9b8a7c16 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -0,0 +1,32 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file linuxtcpsocketclient.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ +#define JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ + +#include +#include +#include "tcpsocketclientprivate.h" + +namespace jsonrpc +{ + class LinuxTcpSocketClient : public TcpSocketClientPrivate + { + public: + LinuxTcpSocketClient(const std::string& ipToConnect, const unsigned int &port); + virtual ~LinuxTcpSocketClient(); + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + + private: + std::string ipToConnect; + unsigned int port; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_LINUXTCPSOCKETCLIENT_H_ */ From e46de2b442b2cda8a96388072f4a4965e4a73dde Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:08:06 +0200 Subject: [PATCH 039/114] Added Tcp Socket Server Connector architecture. --- .../server/connectors/tcpsocketserver.cpp | 65 +++++++++++++++++++ .../server/connectors/tcpsocketserver.h | 46 +++++++++++++ .../connectors/tcpsocketserverprivate.h | 27 ++++++++ 3 files changed, 138 insertions(+) create mode 100644 src/jsonrpccpp/server/connectors/tcpsocketserver.cpp create mode 100644 src/jsonrpccpp/server/connectors/tcpsocketserver.h create mode 100644 src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp new file mode 100644 index 00000000..a80505a3 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp @@ -0,0 +1,65 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file tcpsocketserver.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "tcpsocketserver.h" +#ifdef __WIN32__ +#include "windowstcpsocketserver.h" +#elif __unix__ +#include "linuxtcpsocketserver.h" +#endif +#include + +using namespace jsonrpc; +using namespace std; + +TcpSocketServer::TcpSocketServer(const std::string& ipToBind, const unsigned int &port) : + AbstractServerConnector() +{ +#ifdef __WIN32__ + this->realSocket = new WindowsTcpSocketServer(ipToBind, port); +#elif __unix__ + this->realSocket = new LinuxTcpSocketServer(ipToBind, port); +#else + this->realSocket = NULL; +#endif +} + +TcpSocketServer::~TcpSocketServer() +{ + 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; +} + +bool TcpSocketServer::StopListening() +{ + 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; +} diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.h b/src/jsonrpccpp/server/connectors/tcpsocketserver.h new file mode 100644 index 00000000..54870aee --- /dev/null +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.h @@ -0,0 +1,46 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file tcpsocketserver.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ +#define JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ + +#include "tcpsocketserverprivate.h" + +#include "../abstractserverconnector.h" + +namespace jsonrpc +{ + /** + * This class provides an embedded Tcp Socket Server,to handle incoming Requests. + */ + class TcpSocketServer: public AbstractServerConnector + { + public: + /** + * @brief TcpSocketServer, constructor for the included TcpSocketServer + * @param ipToBind, a string containing the ip of the interface to bind to. + * @param port, the port that the server will listen to. + */ + TcpSocketServer(const std::string& ipToBind, const unsigned int &port); + /** + * @brief ~TcpSocketServer, destructor for the included TcpSocketServer + */ + ~TcpSocketServer(); + bool StartListening(); + bool StopListening(); + + bool SendResponse(const std::string& response, void* addInfo = NULL); + + private: + TcpSocketServerPrivate *realSocket; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ */ + diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h b/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h new file mode 100644 index 00000000..53150a06 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h @@ -0,0 +1,27 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file tcpsocketserverprivate.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ +#define JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ + +#include "tcpsocketserverprivate.h" + +#include "../abstractserverconnector.h" + +namespace jsonrpc +{ + /** + * This interface allows to abstract the real TcpSocketServer, either it be Windows, Linux or else. + */ + class TcpSocketServerPrivate : public AbstractServerConnector + { + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ */ From d1ac604777e67d5fc8b3a54a200806cc970e3550 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:08:18 +0200 Subject: [PATCH 040/114] Implemented Linux Tcp Socket Server Connector that matches previous architecture. --- .../connectors/linuxtcpsocketserver.cpp | 187 ++++++++++++++++++ .../server/connectors/linuxtcpsocketserver.h | 65 ++++++ 2 files changed, 252 insertions(+) create mode 100644 src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp create mode 100644 src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp new file mode 100644 index 00000000..cf69ad62 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -0,0 +1,187 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file linuxtcpsocketserver.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "linuxtcpsocketserver.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +using namespace jsonrpc; +using namespace std; + +#define BUFFER_SIZE 64 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR + +LinuxTcpSocketServer::LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : + TcpSocketServerPrivate(), + ipToBind(ipToBind), + port(port), + running(false) +{ +} + +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) + { + cerr << "socket() failed" << endl; + return false; + } + + fcntl(this->socket_fd, F_SETFL, FNDELAY); + + /* 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); + + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_in)) != 0) + { + cerr << "bind() failed" << endl; + return false; + } + + if(listen(this->socket_fd, 5) != 0) + { + cerr << "listen() failed" << endl; + 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); + } + this->running = static_cast(ret==0); + } + return this->running; +} + +bool LinuxTcpSocketServer::StopListening() +{ + if(this->running) + { + this->running = false; + pthread_join(this->listenning_thread, NULL); + close(this->socket_fd); + } + return !(this->running); +} + +bool LinuxTcpSocketServer::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; +} + +void* LinuxTcpSocketServer::LaunchLoop(void *p_data) { + pthread_detach(pthread_self()); + LinuxTcpSocketServer *instance = reinterpret_cast(p_data);; + instance->ListenLoop(); + return NULL; +} + +void LinuxTcpSocketServer::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 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; + } + } + 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 = 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 LinuxTcpSocketServer::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 < 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/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h new file mode 100644 index 00000000..cee40865 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -0,0 +1,65 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file linuxtcpsocketserver.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_LINUXTCPSOCKETSERVERCONNECTOR_H_ +#define JSONRPC_CPP_LINUXTCPSOCKETSERVERCONNECTOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tcpsocketserverprivate.h" + +namespace jsonrpc +{ + /** + * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. + */ + class LinuxTcpSocketServer: public TcpSocketServerPrivate + { + public: + /** + * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer + * @param socket_path, a string containing the path to the unix socket + */ + LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port); + + bool StartListening(); + bool StopListening(); + + bool SendResponse(const std::string& response, void* addInfo = NULL); + + private: + bool running; + std::string ipToBind; + unsigned int port; + int socket_fd; + struct sockaddr_in address; + + pthread_t listenning_thread; + + static void* LaunchLoop(void *p_data); + void ListenLoop(); + struct GenerateResponseParameters { + LinuxTcpSocketServer *instance; + int connection_fd; + }; + static void* GenerateResponse(void *p_data); + bool WriteToSocket(int fd, const std::string& toSend); + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_LINUXTCPSOCKETSERVERCONNECTOR_H_ */ + From d8fcce378e191b41a546b8f9ba0d5802bc65b70f Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:08:55 +0200 Subject: [PATCH 041/114] Added simple server and client example over Tcp Socket Connectors. --- src/examples/tcpsocketclient.cpp | 33 +++++++++++++++++ src/examples/tcpsocketserver.cpp | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/examples/tcpsocketclient.cpp create mode 100644 src/examples/tcpsocketserver.cpp diff --git a/src/examples/tcpsocketclient.cpp b/src/examples/tcpsocketclient.cpp new file mode 100644 index 00000000..653c79e6 --- /dev/null +++ b/src/examples/tcpsocketclient.cpp @@ -0,0 +1,33 @@ +/** + * @file tcpsocketclient.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @brief tcpsocketclient.cpp + */ + +#include +#include +#include + +using namespace jsonrpc; +using namespace std; + +int main() +{ + TcpSocketClient client("127.0.0.1", 6543); + Client c(client); + + Json::Value params; + params["name"] = "Peter"; + + try + { + cout << c.CallMethod("sayHello", params) << endl; + } + catch (JsonRpcException& e) + { + cerr << e.what() << endl; + } + + +} diff --git a/src/examples/tcpsocketserver.cpp b/src/examples/tcpsocketserver.cpp new file mode 100644 index 00000000..c7b5a845 --- /dev/null +++ b/src/examples/tcpsocketserver.cpp @@ -0,0 +1,63 @@ +/** + * @file unixdomainsocketserver.cpp + * @date 11.05.2015 + * @author Alexandre Poirot + * @brief unixdomainsocketserver.cpp + */ + +#include +#include +#include +#include +#include + + +using namespace jsonrpc; +using namespace std; + +class SampleServer : public AbstractServer +{ + public: + SampleServer(TcpSocketServer &server) : + AbstractServer(server) + { + this->bindAndAddMethod(Procedure("sayHello", PARAMS_BY_NAME, JSON_STRING, "name", JSON_STRING, NULL), &SampleServer::sayHello); + this->bindAndAddNotification(Procedure("notifyServer", PARAMS_BY_NAME, NULL), &SampleServer::notifyServer); + } + + //method + void sayHello(const Json::Value& request, Json::Value& response) + { + response = "Hello: " + request["name"].asString(); + } + + //notification + void notifyServer(const Json::Value& request) + { + (void)request; + cout << "server received some Notification" << endl; + } +}; + +int main() +{ + try + { + TcpSocketServer server("127.0.0.1", 6543); + SampleServer serv(server); + if (serv.StartListening()) + { + cout << "Server started successfully" << endl; + getchar(); + serv.StopListening(); + } + else + { + cout << "Error starting Server" << endl; + } + } + catch (jsonrpc::JsonRpcException& e) + { + cerr << e.what() << endl; + } +} From 8d199f4344d7454959395da27dfa03f7be95dac6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 17 Jul 2015 17:09:31 +0200 Subject: [PATCH 042/114] Modified CMake files to build Tcp Sockets connectors. --- CMakeLists.txt | 4 ++++ src/jsonrpccpp/CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b303251a..9dcc251c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ if(UNIX) set(UNIX_DOMAIN_SOCKET_SERVER YES CACHE BOOL "Include Unix Domain Socket server") set(UNIX_DOMAIN_SOCKET_CLIENT YES CACHE BOOL "Include Unix Domain Socket client") endif(UNIX) + set(TCP_SOCKET_SERVER YES CACHE BOOL "Include Tcp Socket server") + set(TCP_SOCKET_CLIENT YES CACHE BOOL "Include Tcp Socket client") set(HTTP_SERVER YES CACHE BOOL "Include HTTP server using libmicrohttpd") set(HTTP_CLIENT YES CACHE BOOL "Include HTTP client support using curl") set(COMPILE_TESTS YES CACHE BOOL "Compile test framework") @@ -39,6 +41,8 @@ if(UNIX) message(STATUS "UNIX_DOMAIN_SOCKET_SERVER: ${UNIX_DOMAIN_SOCKET_SERVER}") message(STATUS "UNIX_DOMAIN_SOCKET_CLIENT: ${UNIX_DOMAIN_SOCKET_CLIENT}") endif(UNIX) +message(STATUS "TCP_SOCKET_SERVER: ${TCP_SOCKET_SERVER}") +message(STATUS "TCP_SOCKET_CLIENT: ${TCP_SOCKET_CLIENT}") message(STATUS "HTTP_SERVER: ${HTTP_SERVER}") message(STATUS "HTTP_CLIENT: ${HTTP_CLIENT}") message(STATUS "COMPILE_TESTS: ${COMPILE_TESTS}") diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 7b136f6d..199579a7 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -57,6 +57,39 @@ if (UNIX_DOMAIN_SOCKET_CLIENT) list(APPEND client_connector_source "client/connectors/unixdomainsocketclient.cpp") endif() +# setup sources for tcp socket connectors +if (TCP_SOCKET_SERVER) + list(APPEND server_connector_header "server/connectors/tcpsocketserver.h") + list(APPEND server_connector_source "server/connectors/tcpsocketserver.cpp") + list(APPEND server_connector_header "server/connectors/tcpsocketserverprivate.h") + if (WIN32) + list(APPEND server_connector_header "server/connectors/windowstcpsocketserver.h") + list(APPEND server_connector_source "server/connectors/windowstcpsocketserver.cpp") + endif() + if(UNIX) + list(APPEND server_connector_header "server/connectors/linuxtcpsocketserver.h") + list(APPEND server_connector_source "server/connectors/linuxtcpsocketserver.cpp") + endif() + list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) + list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) +endif() + +if (TCP_SOCKET_CLIENT) + list(APPEND client_connector_header "client/connectors/tcpsocketclient.h") + list(APPEND client_connector_source "client/connectors/tcpsocketclient.cpp") + list(APPEND client_connector_header "client/connectors/tcpsocketclientprivate.h") + if (WIN32) + list(APPEND client_connector_header "client/connectors/windowstcpsocketclient.h") + list(APPEND client_connector_source "client/connectors/windowstcpsocketclient.cpp") + endif() + if(UNIX) + list(APPEND client_connector_header "client/connectors/linuxtcpsocketclient.h") + list(APPEND client_connector_source "client/connectors/linuxtcpsocketclient.cpp") + endif() + list(APPEND client_connector_libs ${CMAKE_THREAD_LIBS_INIT}) + list(APPEND client_connector_libs ${CMAKE_THREAD_LIBS_INIT}) +endif() + # configure a header file to pass some of the CMake settings to the source code # TODO: move it to custom build step? file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/gen/jsonrpccpp/common") From afdbbe24129ed30f456cfa5eecc30aec8234eeec Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 20 Jul 2015 12:01:48 +0200 Subject: [PATCH 043/114] A bit of cleanup --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index cf69ad62..836dfb5f 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -125,7 +125,6 @@ void* LinuxTcpSocketServer::LaunchLoop(void *p_data) { } void LinuxTcpSocketServer::ListenLoop() { - int connection_fd; socklen_t address_length = sizeof(this->address); while(this->running) { From 28f4445ccb862a505889ad1ab1b0dfe28ee5a300 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 20 Jul 2015 12:03:45 +0200 Subject: [PATCH 044/114] Added tcp socket server implementation for windows. --- .../connectors/windowstcpsocketserver.cpp | 196 ++++++++++++++++++ .../connectors/windowstcpsocketserver.h | 62 ++++++ 2 files changed, 258 insertions(+) create mode 100644 src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp create mode 100644 src/jsonrpccpp/server/connectors/windowstcpsocketserver.h diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp new file mode 100644 index 00000000..ef82d718 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -0,0 +1,196 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file windowstcpsocketserver.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "windowstcpsocketserver.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +using namespace jsonrpc; +using namespace std; + +#define BUFFER_SIZE 64 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR + +WindowsTcpSocketServer::WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : + TcpSocketServerPrivate(), + ipToBind(ipToBind), + port(port), + running(false) +{ + //if(nbInstances == 0) { + WSADATA WSAData; + WSAStartup(MAKEWORD(2,0), &WSAData); + /*} + nbInstances++;//*/ +} + +WindowsTcpSocketServer::~WindowsTcpSocketServer() { + /*nbInstances--; + if(nbInstances == 0) { + WSACleanup(); + }//*/ +} + +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) + { + cerr << "socket() failed" << endl; + return false; + } + + ioctlsocket(this->socket_fd, FIONBIO, 1); //Set non blocking + + /* start with a clean address structure */ + memset(&(this->address), 0, sizeof(struct 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); + + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct SOCKADDR_IN)) != 0) + { + cerr << "bind() failed" << endl; + return false; + } + + if(listen(this->socket_fd, 5) != 0) + { + cerr << "listen() failed" << endl; + return false; + } + //Launch listening loop there + this->running = true; + HANDLE ret = CreateThread(NULL, 0, static_cast(WindowsTcpSocketServer::LaunchLoop), this, 0, &(this->listenning_thread)); + if(ret == NULL) { + CloseHandle(this->listenning_thread); + } + this->running = static_cast(ret!=NULL); + } + return this->running; +} + +bool WindowsTcpSocketServer::StopListening() +{ + if(this->running) + { + this->running = false; + WaitForSingleObject(this->listenning_thread, INFINITE); + closesocket(this->socket_fd); + } + return !(this->running); +} + +bool WindowsTcpSocketServer::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); + } + closesocket(connection_fd); + return result; +} + +void* WindowsTcpSocketServer::LaunchLoop(void *p_data) { + CloseHandle(GetCurrentThreadId()); + WindowsTcpSocketServer *instance = reinterpret_cast(p_data);; + instance->ListenLoop(); + return NULL; +} + +void WindowsTcpSocketServer::ListenLoop() { + int connection_fd; + unsigned int address_length = sizeof(this->address); + while(this->running) { + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->address)), &address_length)) > 0) + { + DWORD client_thread; + struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); + params->instance = this; + params->connection_fd = connection_fd; + HANDLE ret = CreateThread(NULL, 0, static_cast(WindowsTcpSocketServer::GenerateResponse), params, 0, &client_thread); + if(ret == NULL) { + CloseHandle(client_thread); + delete params; + params = NULL; + } + } + else { + Sleep(2.5); + } + } +} + +void* WindowsTcpSocketServer::GenerateResponse(void *p_data) { + CloseHandle(GetCurrentThreadId()); + struct GenerateResponseParameters* params = reinterpret_cast(p_data); + WindowsTcpSocketServer *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); + request.append(buffer,nbytes); + } while(request.find(DELIMITER_CHAR) == string::npos); + instance->OnRequest(request, reinterpret_cast(connection_fd)); + return NULL; +} + + +bool WindowsTcpSocketServer::WriteToSocket(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; + 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; +} diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h new file mode 100644 index 00000000..0cbbf542 --- /dev/null +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -0,0 +1,62 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file windowstcpsocketserver.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_WINDOWSTCPSOCKETSERVERCONNECTOR_H_ +#define JSONRPC_CPP_WINDOWSTCPSOCKETSERVERCONNECTOR_H_ + +#include +#include +#include +#include + +#include "tcpsocketserverprivate.h" + +namespace jsonrpc +{ + /** + * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. + */ + class WindowsTcpSocketServer: public TcpSocketServerPrivate + { + public: + /** + * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer + * @param socket_path, a string containing the path to the unix socket + */ + WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port); + ~WindowsTcpSocketServer(); + + bool StartListening(); + bool StopListening(); + + bool SendResponse(const std::string& response, void* addInfo = NULL); + + private: + bool running; + std::string ipToBind; + unsigned int port; + SOCKET socket_fd; + SOCKADDR_IN address; + + DWORD listenning_thread; + + DWORD WINAPI LaunchLoop(LPVOID lp_data); + void ListenLoop(); + struct GenerateResponseParameters { + WindowsTcpSocketServer *instance; + SOCKET connection_fd; + }; + DWORD WINAPI GenerateResponse(LPVOID lp_data); + bool WriteToSocket(SOCK fd, const std::string& toSend); + //static unsigned int nbInstances = 0; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_WINDOWSTCPSOCKETSERVERCONNECTOR_H_ */ + From 164d0d7821054deebdcb2a87baf0c1ffdc4580d6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 20 Jul 2015 12:08:13 +0200 Subject: [PATCH 045/114] Added tcp socket client implementation for windows. --- .../connectors/windowstcpsocketclient.cpp | 79 +++++++++++++++++++ .../connectors/windowstcpsocketclient.h | 32 ++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp create mode 100644 src/jsonrpccpp/client/connectors/windowstcpsocketclient.h diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp new file mode 100644 index 00000000..5f06b1cd --- /dev/null +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -0,0 +1,79 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file windowstcpsocketclient.cpp + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#include "windowstcpsocketclient.h" +#include +#include +#include +#include + +#define BUFFER_SIZE 64 +#ifndef DELIMITER_CHAR +#define DELIMITER_CHAR char(0x0A) +#endif //DELIMITER_CHAR + +using namespace jsonrpc; +using namespace std; + +WindowsTcpSocketClient::WindowsTcpSocketClient(const std::string& ipToConnect, const unsigned int &port) : + ipToConnect(ipToConnect), + port(port) +{ + WSADATA WSAData; + WSAStartup(MAKEWORD(2,0), &WSAData); +} + +WindowsTcpSocketClient::~WindowsTcpSocketClient() +{ +} + +void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) +{ + SOCKADDR_IN address; + int socket_fd, nbytes; + char buffer[BUFFER_SIZE]; + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) { + cerr << "Socket failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + + memset(&address, 0, sizeof(SOCKADDR_IN)); + + address.sin_family = AF_INET; + inet_aton(this->ipToConnect.c_str(), &(address.sin_addr)); + address.sin_port = htons(this->port); + + if(connect(socket_fd, (struct SOCKADDR *) &address, sizeof(SOCKADDR_IN)) != 0) { + cerr << "connect failed" << endl; + throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + } + + bool fullyWritten = false; + string toSend = message; + do { + ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); + if(byteWritten < toSend.size()) { + int len = toSend.size() - byteWritten; + toSend = toSend.substr(byteWritten + sizeof(char), len); + } + else + fullyWritten = true; + } while(!fullyWritten); + + do { + nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + string tmp; + tmp.append(buffer, nbytes); + result.append(buffer,nbytes); + + } while(result.find(DELIMITER_CHAR) == string::npos); + + closesocket(socket_fd); +} diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h new file mode 100644 index 00000000..1bfc4297 --- /dev/null +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -0,0 +1,32 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file windowstcpsocketclient.h + * @date 17.07.2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifndef JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_ +#define JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_ + +#include +#include +#include "tcpsocketclientprivate.h" + +namespace jsonrpc +{ + class WindowsTcpSocketClient : public TcpSocketClientPrivate + { + public: + WindowsTcpSocketClient(const std::string& ipToConnect, const unsigned int &port); + virtual ~WindowsTcpSocketClient(); + virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); + + private: + std::string ipToConnect; + unsigned int port; + }; + +} /* namespace jsonrpc */ +#endif /* JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_ */ From b421e3fd0d494af9f3d7b971902b9c3e96ca76b2 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 21 Jul 2015 16:19:54 +0200 Subject: [PATCH 046/114] Added a better way to initialize Winsock. Also corrected somme header and code issues. --- .../connectors/windowstcpsocketclient.cpp | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index 5f06b1cd..faec6a2a 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #define BUFFER_SIZE 64 #ifndef DELIMITER_CHAR @@ -25,8 +26,6 @@ WindowsTcpSocketClient::WindowsTcpSocketClient(const std::string& ipToConnect, c ipToConnect(ipToConnect), port(port) { - WSADATA WSAData; - WSAStartup(MAKEWORD(2,0), &WSAData); } WindowsTcpSocketClient::~WindowsTcpSocketClient() @@ -47,10 +46,10 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str memset(&address, 0, sizeof(SOCKADDR_IN)); address.sin_family = AF_INET; - inet_aton(this->ipToConnect.c_str(), &(address.sin_addr)); + address.sin_addr.s_addr = inet_addr(this->ipToConnect.c_str()); address.sin_port = htons(this->port); - if(connect(socket_fd, (struct SOCKADDR *) &address, sizeof(SOCKADDR_IN)) != 0) { + if(connect(socket_fd, reinterpret_cast(&address), sizeof(SOCKADDR_IN)) != 0) { cerr << "connect failed" << endl; throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); } @@ -77,3 +76,24 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str closesocket(socket_fd); } + +//This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). +struct ClientSocketInitializer +{ + ClientSocketInitializer() + { + WSADATA init; + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { + cerr << "An issue occured while WSAStartup executed." << endl; + } + } + + ~ClientSocketInitializer() + { + if(WSACleanup() != 0) { + cerr << "An issue occured while WSAClean executed." << endl; + } + } +}; + +struct ClientSocketInitializer clientGlobalInitializer; \ No newline at end of file From ccd6595ace800212505b949aa0296669863523f6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 21 Jul 2015 16:22:15 +0200 Subject: [PATCH 047/114] Improved Windows implementation of TcpSocketServer. --- .../connectors/windowstcpsocketserver.cpp | 94 +++++++++++-------- .../connectors/windowstcpsocketserver.h | 10 +- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index ef82d718..45d1db78 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -20,8 +20,6 @@ #include -#include - using namespace jsonrpc; using namespace std; @@ -36,18 +34,9 @@ WindowsTcpSocketServer::WindowsTcpSocketServer(const std::string& ipToBind, cons port(port), running(false) { - //if(nbInstances == 0) { - WSADATA WSAData; - WSAStartup(MAKEWORD(2,0), &WSAData); - /*} - nbInstances++;//*/ } WindowsTcpSocketServer::~WindowsTcpSocketServer() { - /*nbInstances--; - if(nbInstances == 0) { - WSACleanup(); - }//*/ } bool WindowsTcpSocketServer::StartListening() @@ -62,17 +51,17 @@ bool WindowsTcpSocketServer::StartListening() cerr << "socket() failed" << endl; return false; } - - ioctlsocket(this->socket_fd, FIONBIO, 1); //Set non blocking + unsigned long nonBlocking = 1; + ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking /* start with a clean address structure */ - memset(&(this->address), 0, sizeof(struct SOCKADDR_IN)); + 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); - if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct SOCKADDR_IN)) != 0) + if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(SOCKADDR_IN)) != 0) { cerr << "bind() failed" << endl; return false; @@ -85,10 +74,13 @@ bool WindowsTcpSocketServer::StartListening() } //Launch listening loop there this->running = true; - HANDLE ret = CreateThread(NULL, 0, static_cast(WindowsTcpSocketServer::LaunchLoop), this, 0, &(this->listenning_thread)); + HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::LaunchLoop)), reinterpret_cast(this), 0, &(this->listenning_thread)); if(ret == NULL) { - CloseHandle(this->listenning_thread); + ExitProcess(3); } + else { + CloseHandle(ret); + } this->running = static_cast(ret!=NULL); } return this->running; @@ -99,7 +91,7 @@ bool WindowsTcpSocketServer::StopListening() if(this->running) { this->running = false; - WaitForSingleObject(this->listenning_thread, INFINITE); + WaitForSingleObject(OpenThread(THREAD_ALL_ACCESS, FALSE,this->listenning_thread), INFINITE); closesocket(this->socket_fd); } return !(this->running); @@ -127,56 +119,61 @@ bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) return result; } -void* WindowsTcpSocketServer::LaunchLoop(void *p_data) { - CloseHandle(GetCurrentThreadId()); - WindowsTcpSocketServer *instance = reinterpret_cast(p_data);; +DWORD WINAPI WindowsTcpSocketServer::LaunchLoop(LPVOID lp_data) { + WindowsTcpSocketServer *instance = reinterpret_cast(lp_data);; instance->ListenLoop(); - return NULL; + 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() { - int connection_fd; - unsigned int address_length = sizeof(this->address); while(this->running) { - if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->address)), &address_length)) > 0) + 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) { - DWORD client_thread; + DWORD client_thread; struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); params->instance = this; params->connection_fd = connection_fd; - HANDLE ret = CreateThread(NULL, 0, static_cast(WindowsTcpSocketServer::GenerateResponse), params, 0, &client_thread); + HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::GenerateResponse)), reinterpret_cast(params), 0, &client_thread); if(ret == NULL) { - CloseHandle(client_thread); delete params; params = NULL; + ExitProcess(3); + } + else { + CloseHandle(ret); } } else { - Sleep(2.5); + Sleep(2.5); } } } -void* WindowsTcpSocketServer::GenerateResponse(void *p_data) { - CloseHandle(GetCurrentThreadId()); - struct GenerateResponseParameters* params = reinterpret_cast(p_data); - WindowsTcpSocketServer *instance = params->instance; +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; + int nbytes = 0; char buffer[BUFFER_SIZE]; - string request; + 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); request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); instance->OnRequest(request, reinterpret_cast(connection_fd)); - return NULL; + 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(int fd, const string& toWrite) { +bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) { bool fullyWritten = false; bool errorOccured = false; string toSend = toWrite; @@ -194,3 +191,24 @@ bool WindowsTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { return fullyWritten && !errorOccured; } + +//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) { + cerr << "An issue occured while WSAStartup executed." << endl; + } + } + + ~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 0cbbf542..05a16380 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -12,14 +12,13 @@ #include #include -#include #include #include "tcpsocketserverprivate.h" namespace jsonrpc { - /** + /** * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. */ class WindowsTcpSocketServer: public TcpSocketServerPrivate @@ -46,15 +45,14 @@ namespace jsonrpc DWORD listenning_thread; - DWORD WINAPI LaunchLoop(LPVOID lp_data); + static DWORD WINAPI LaunchLoop(LPVOID lp_data); void ListenLoop(); struct GenerateResponseParameters { WindowsTcpSocketServer *instance; SOCKET connection_fd; }; - DWORD WINAPI GenerateResponse(LPVOID lp_data); - bool WriteToSocket(SOCK fd, const std::string& toSend); - //static unsigned int nbInstances = 0; + static DWORD WINAPI GenerateResponse(LPVOID lp_data); + bool WriteToSocket(SOCKET fd, const std::string& toSend); }; } /* namespace jsonrpc */ From 9b4f622b90e2fa0c8ea2a2d7ffdf5dbb586cdc41 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 21 Jul 2015 16:24:14 +0200 Subject: [PATCH 048/114] Improved tcpsocket connectors examples (now takes parameters for ip and port). --- src/examples/tcpsocketclient.cpp | 20 ++++++++++++++++++-- src/examples/tcpsocketserver.cpp | 22 +++++++++++++++++++--- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/examples/tcpsocketclient.cpp b/src/examples/tcpsocketclient.cpp index 653c79e6..cdaea952 100644 --- a/src/examples/tcpsocketclient.cpp +++ b/src/examples/tcpsocketclient.cpp @@ -8,13 +8,29 @@ #include #include #include +#include using namespace jsonrpc; using namespace std; -int main() +int main(int argc, char** argv) { - TcpSocketClient client("127.0.0.1", 6543); + string ip; + unsigned int port; + + if(argc == 3) { + ip = string(argv[1]); + port = atoi(argv[2]); + cout << "Params are :" << endl; + cout << "\t ip: " << ip << endl; + cout << "\t port: " << port << endl; + } + else { + ip = "127.0.0.1"; + port = 6543; + } + + TcpSocketClient client(ip, port); Client c(client); Json::Value params; diff --git a/src/examples/tcpsocketserver.cpp b/src/examples/tcpsocketserver.cpp index c7b5a845..6cf238d9 100644 --- a/src/examples/tcpsocketserver.cpp +++ b/src/examples/tcpsocketserver.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace jsonrpc; @@ -39,11 +40,26 @@ class SampleServer : public AbstractServer } }; -int main() +int main(int argc, char** argv) { try - { - TcpSocketServer server("127.0.0.1", 6543); + { + string ip; + unsigned int port; + + if(argc == 3) { + ip = string(argv[1]); + port = atoi(argv[2]); + cout << "Params are :" << endl; + cout << "\t ip: " << ip << endl; + cout << "\t port: " << port << endl; + } + else { + ip = "127.0.0.1"; + port = 6543; + } + + TcpSocketServer server(ip, port); SampleServer serv(server); if (serv.StartListening()) { From a8ae92f6f9a85779f09a6f06eb24ceb096a2c514 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 24 Jul 2015 17:24:25 +0200 Subject: [PATCH 049/114] Improved way to handle end of tcp session on Linux : Server waits for client to close the socket fist, so the client enters TIME_WAIT. If the client does not close, the server closes first by using tcp RST which avoid enters in TIME_WAIT. --- .../connectors/linuxtcpsocketserver.cpp | 43 ++++++++++++++++--- .../server/connectors/linuxtcpsocketserver.h | 2 + 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 836dfb5f..3fc1eab9 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -78,6 +78,8 @@ bool LinuxTcpSocketServer::StartListening() 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); } @@ -90,6 +92,7 @@ bool LinuxTcpSocketServer::StopListening() { this->running = false; pthread_join(this->listenning_thread, NULL); + shutdown(this->socket_fd, 2); close(this->socket_fd); } return !(this->running); @@ -113,7 +116,8 @@ bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) else { result = this->WriteToSocket(connection_fd, temp); } - close(connection_fd); + WaitClientClose(connection_fd); + CloseByReset(connection_fd); return result; } @@ -125,11 +129,14 @@ void* LinuxTcpSocketServer::LaunchLoop(void *p_data) { } void LinuxTcpSocketServer::ListenLoop() { - int connection_fd; - socklen_t address_length = sizeof(this->address); + 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(&(this->address)), &address_length)) > 0) + if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(connection_address)), &address_length)) > 0) { + cout << "Got a new client " << inet_ntoa(connection_address.sin_addr) << ":" << htons(connection_address.sin_port) << endl; pthread_t client_thread; struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); params->instance = this; @@ -139,6 +146,8 @@ void LinuxTcpSocketServer::ListenLoop() { pthread_detach(client_thread); delete params; params = NULL; + WaitClientClose(connection_fd); + CloseByReset(connection_fd); } } else { @@ -158,7 +167,7 @@ void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { 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); + nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); instance->OnRequest(request, reinterpret_cast(connection_fd)); @@ -171,7 +180,7 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { bool errorOccured = false; string toSend = toWrite; do { - ssize_t byteWritten = write(fd, toSend.c_str(), toSend.size()); + ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); if(byteWritten < 0) errorOccured = true; else if(byteWritten < toSend.size()) { @@ -184,3 +193,25 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { return fullyWritten && !errorOccured; } + +bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) { + int i = 0; + while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { + usleep(1); + ++i; + } + + return (i == timeout); +} + +int LinuxTcpSocketServer::CloseByReset(int fd) { + 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; + + return close(fd); +} diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index cee40865..4fcc0fe6 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -58,6 +58,8 @@ namespace jsonrpc }; static void* GenerateResponse(void *p_data); bool WriteToSocket(int fd, const std::string& toSend); + bool WaitClientClose(int fd, const int &timeout = 100000); + int CloseByReset(int fd); }; } /* namespace jsonrpc */ From a51505d14e471233aa0f3a522f98fcd36b5ffa00 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 24 Jul 2015 17:49:31 +0200 Subject: [PATCH 050/114] Improved Client close detection and usage. --- .../connectors/linuxtcpsocketserver.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 3fc1eab9..3dee273a 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -116,8 +116,12 @@ bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) else { result = this->WriteToSocket(connection_fd, temp); } - WaitClientClose(connection_fd); - CloseByReset(connection_fd); + if(WaitClientClose(connection_fd)) { + close(connection_fd); + } + else { + CloseByReset(connection_fd); + } return result; } @@ -146,8 +150,12 @@ void LinuxTcpSocketServer::ListenLoop() { pthread_detach(client_thread); delete params; params = NULL; - WaitClientClose(connection_fd); - CloseByReset(connection_fd); + if(WaitClientClose(connection_fd)) { + close(connection_fd); + } + else { + CloseByReset(connection_fd); + } } } else { @@ -195,13 +203,15 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { } bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) { + bool ret = false; int i = 0; while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { usleep(1); ++i; + ret = true; } - return (i == timeout); + return ret; } int LinuxTcpSocketServer::CloseByReset(int fd) { From e68b1ad94970af1b3a7cc9542c54645fd55aa1f6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 24 Jul 2015 17:51:54 +0200 Subject: [PATCH 051/114] Improved indentation. Improved way to handle end of tcp session on Linux. Now havethe same behavior that Linux implementation. --- .../connectors/windowstcpsocketserver.cpp | 110 ++++++++++++------ .../connectors/windowstcpsocketserver.h | 6 +- 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 45d1db78..5af0a778 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -51,7 +51,7 @@ bool WindowsTcpSocketServer::StartListening() cerr << "socket() failed" << endl; return false; } - unsigned long nonBlocking = 1; + unsigned long nonBlocking = 1; ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking /* start with a clean address structure */ @@ -76,11 +76,11 @@ bool WindowsTcpSocketServer::StartListening() this->running = true; HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::LaunchLoop)), reinterpret_cast(this), 0, &(this->listenning_thread)); if(ret == NULL) { - ExitProcess(3); + ExitProcess(3); + } + else { + CloseHandle(ret); } - else { - CloseHandle(ret); - } this->running = static_cast(ret!=NULL); } return this->running; @@ -115,61 +115,71 @@ bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) else { result = this->WriteToSocket(connection_fd, temp); } - closesocket(connection_fd); + if(WaitClientClose(connection_fd)) { + closesocket(connection_fd); + } + else { + CloseByReset(connection_fd); + } return result; } DWORD WINAPI WindowsTcpSocketServer::LaunchLoop(LPVOID lp_data) { WindowsTcpSocketServer *instance = reinterpret_cast(lp_data);; instance->ListenLoop(); - CloseHandle(GetCurrentThread()); + 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); + 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) { - DWORD client_thread; + 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; + HANDLE ret = CreateThread(NULL, 0, reinterpret_cast(&(WindowsTcpSocketServer::GenerateResponse)), reinterpret_cast(params), 0, &client_thread); + if(ret == NULL) { + delete params; params = NULL; - ExitProcess(3); - } - else { - CloseHandle(ret); - } + if(WaitClientClose(connection_fd)) { + closesocket(connection_fd); + } + else { + CloseByReset(connection_fd); + } + } + else { + CloseHandle(ret); + } } else { - Sleep(2.5); + Sleep(2.5); } } } DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) { struct GenerateResponseParameters* params = reinterpret_cast(lp_data); - WindowsTcpSocketServer *instance = params->instance; + 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); + 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); request.append(buffer,nbytes); } while(request.find(DELIMITER_CHAR) == string::npos); instance->OnRequest(request, reinterpret_cast(connection_fd)); - CloseHandle(GetCurrentThread()); + 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. } @@ -192,23 +202,47 @@ bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) { return fullyWritten && !errorOccured; } +bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) { + bool ret = false; + int i = 0; + while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { + Sleep(1); + ++i; + ret = true; + } + + return ret; +} + +int WindowsTcpSocketServer::CloseByReset(int fd) { + 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; + + return closesocket(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) { - cerr << "An issue occured while WSAStartup executed." << endl; - } - } - - ~ServerSocketInitializer() - { - if(WSACleanup() != 0) { - cerr << "An issue occured while WSAClean executed." << endl; - } - } + ServerSocketInitializer() + { + WSADATA init; + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { + cerr << "An issue occured while WSAStartup executed." << endl; + } + } + + ~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 05a16380..d25820dc 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -18,7 +18,7 @@ namespace jsonrpc { - /** + /** * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. */ class WindowsTcpSocketServer: public TcpSocketServerPrivate @@ -29,7 +29,7 @@ namespace jsonrpc * @param socket_path, a string containing the path to the unix socket */ WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port); - ~WindowsTcpSocketServer(); + ~WindowsTcpSocketServer(); bool StartListening(); bool StopListening(); @@ -53,6 +53,8 @@ namespace jsonrpc }; static DWORD WINAPI GenerateResponse(LPVOID lp_data); bool WriteToSocket(SOCKET fd, const std::string& toSend); + bool WaitClientClose(SOCKET fd, const int &timeout = 100); + int CloseByReset(SOCKET fd); }; } /* namespace jsonrpc */ From e68e986d4b6728e766f3f016ec8b622a7ba6ff63 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 24 Jul 2015 18:20:07 +0200 Subject: [PATCH 052/114] Corrected errors in windows tcp socket server. --- src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 5af0a778..a083fd24 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -214,12 +214,12 @@ bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) { return ret; } -int WindowsTcpSocketServer::CloseByReset(int fd) { +int WindowsTcpSocketServer::CloseByReset(SOCKET fd) { 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)); + int ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, reinterpret_cast(&so_linger), sizeof(so_linger)); if(ret != 0) return ret; From fe44ed8eb8db00099119af66479bc182e4d92e70 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Fri, 24 Jul 2015 19:10:19 +0200 Subject: [PATCH 053/114] Bugfix for string id handling in client module. (Closes #119) --- src/examples/stubclient.cpp | 19 ++++++++++++++++ src/jsonrpccpp/client/batchresponse.cpp | 24 ++++++++++++++++----- src/jsonrpccpp/client/batchresponse.h | 14 +++++++----- src/jsonrpccpp/client/client.cpp | 4 ++-- src/jsonrpccpp/client/rpcprotocolclient.cpp | 4 ++-- src/jsonrpccpp/client/rpcprotocolclient.h | 2 +- src/test/test_client.cpp | 10 +++++++++ 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/examples/stubclient.cpp b/src/examples/stubclient.cpp index e0a99b09..014ab434 100644 --- a/src/examples/stubclient.cpp +++ b/src/examples/stubclient.cpp @@ -17,6 +17,25 @@ using namespace std; int main() { + Json::Value a = 3; + Json::Value b = "3"; + + std::map responses; + + responses[a] = b; + responses[b] = "asölfj"; + + cout << responses[b] << endl; + + if (a == b) + { + cout << a.toStyledString() << " == " << b.toStyledString() << endl; + } + else + { + cout << a.toStyledString() << " != " << b.toStyledString() << endl; + } + HttpClient httpclient("http://localhost:8383"); //StubClient c(httpclient, JSONRPC_CLIENT_V1); //json-rpc 1.0 StubClient c(httpclient, JSONRPC_CLIENT_V2); //json-rpc 2.0 diff --git a/src/jsonrpccpp/client/batchresponse.cpp b/src/jsonrpccpp/client/batchresponse.cpp index 8628fd88..6e59d78f 100644 --- a/src/jsonrpccpp/client/batchresponse.cpp +++ b/src/jsonrpccpp/client/batchresponse.cpp @@ -18,7 +18,7 @@ BatchResponse::BatchResponse() { } -void BatchResponse::addResponse(int id, Json::Value response, bool isError) +void BatchResponse::addResponse(Json::Value &id, Json::Value response, bool isError) { if (isError) { errorResponses.push_back(id); @@ -26,14 +26,22 @@ void BatchResponse::addResponse(int id, Json::Value response, bool isError) responses[id] = response; } -Json::Value BatchResponse::getResult(int id) +Json::Value BatchResponse::getResult(Json::Value& id) { Json::Value result; getResult(id, result); return result; } -void BatchResponse::getResult(int id, Json::Value &result) +Json::Value BatchResponse::getResult(int id) +{ + Json::Value result; + Json::Value i = id; + getResult(i, result); + return result; +} + +void BatchResponse::getResult(Json::Value& id, Json::Value &result) { if (getErrorCode(id) == 0) result = responses[id]; @@ -41,7 +49,7 @@ void BatchResponse::getResult(int id, Json::Value &result) result = Json::nullValue; } -int BatchResponse::getErrorCode(int id) +int BatchResponse::getErrorCode(Json::Value& id) { if(std::find(errorResponses.begin(), errorResponses.end(), id) != errorResponses.end()) { @@ -50,7 +58,7 @@ int BatchResponse::getErrorCode(int id) return 0; } -string BatchResponse::getErrorMessage(int id) +string BatchResponse::getErrorMessage(Json::Value& id) { if(std::find(errorResponses.begin(), errorResponses.end(), id) != errorResponses.end()) { @@ -59,6 +67,12 @@ string BatchResponse::getErrorMessage(int id) return ""; } +string BatchResponse::getErrorMessage(int id) +{ + Json::Value i = id; + return getErrorMessage(i); +} + bool BatchResponse::hasErrors() { return !errorResponses.empty(); diff --git a/src/jsonrpccpp/client/batchresponse.h b/src/jsonrpccpp/client/batchresponse.h index 6480cce0..fa44be9a 100644 --- a/src/jsonrpccpp/client/batchresponse.h +++ b/src/jsonrpccpp/client/batchresponse.h @@ -29,7 +29,7 @@ namespace jsonrpc { * @param response * @param isError */ - void addResponse(int id, Json::Value response, bool isError = false); + void addResponse(Json::Value& id, Json::Value response, bool isError = false); /** * @brief getResult method gets the result for a given request id (returned by BatchCall::addCall. @@ -37,29 +37,33 @@ namespace jsonrpc { * @param id * @return */ + Json::Value getResult(Json::Value& id); + Json::Value getResult(int id); - void getResult(int id, Json::Value &result); + void getResult(Json::Value& id, Json::Value &result); /** * @brief getErrorCode method checks if for a given id, an error occurred in the batch request. * @param id */ - int getErrorCode(int id); + int getErrorCode(Json::Value& id); /** * @brief getErrorMessage method gets the corresponding error message. * @param id * @return the error message in case of an error, an empty string if no error was found for the provided id. */ + std::string getErrorMessage(Json::Value& id); + std::string getErrorMessage(int id); bool hasErrors(); private: - std::map responses; - std::vector errorResponses; + std::map responses; + std::vector errorResponses; }; diff --git a/src/jsonrpccpp/client/client.cpp b/src/jsonrpccpp/client/client.cpp index 0f09e64c..ea370ee3 100644 --- a/src/jsonrpccpp/client/client.cpp +++ b/src/jsonrpccpp/client/client.cpp @@ -49,11 +49,11 @@ void Client::CallProcedures(const BatchCall &calls, BatchResponse &result) throw if (tmpresult[i].isObject()) { Json::Value singleResult; try { - int id = this->protocol->HandleResponse(tmpresult[i], singleResult); + Json::Value id = this->protocol->HandleResponse(tmpresult[i], singleResult); result.addResponse(id, singleResult, false); } catch (JsonRpcException& ex) { - int id = -1; + Json::Value id = -1; if(tmpresult[i].isMember("id") && tmpresult[i]["id"].isInt()) id = tmpresult[i]["id"].asInt(); result.addResponse(id, tmpresult[i]["error"], true); diff --git a/src/jsonrpccpp/client/rpcprotocolclient.cpp b/src/jsonrpccpp/client/rpcprotocolclient.cpp index dfa9c757..83564422 100644 --- a/src/jsonrpccpp/client/rpcprotocolclient.cpp +++ b/src/jsonrpccpp/client/rpcprotocolclient.cpp @@ -50,7 +50,7 @@ void RpcProtocolClient::HandleResponse(const std::string &response, Json::Value& } } -int RpcProtocolClient::HandleResponse(const Json::Value &value, Json::Value &result) throw(JsonRpcException) +Json::Value RpcProtocolClient::HandleResponse(const Json::Value &value, Json::Value &result) throw(JsonRpcException) { if(this->ValidateResponse(value)) { @@ -67,7 +67,7 @@ int RpcProtocolClient::HandleResponse(const Json::Value &value, Json::Value &res { throw JsonRpcException(Errors::ERROR_CLIENT_INVALID_RESPONSE, " " + value.toStyledString()); } - return value[KEY_ID].asInt(); + return value[KEY_ID]; } void RpcProtocolClient::BuildRequest(int id, const std::string &method, const Json::Value ¶meter, Json::Value &result, bool isNotification) diff --git a/src/jsonrpccpp/client/rpcprotocolclient.h b/src/jsonrpccpp/client/rpcprotocolclient.h index 268f423c..aa5104be 100644 --- a/src/jsonrpccpp/client/rpcprotocolclient.h +++ b/src/jsonrpccpp/client/rpcprotocolclient.h @@ -58,7 +58,7 @@ namespace jsonrpc { * @param result * @return response id */ - int HandleResponse(const Json::Value &response, Json::Value &result) throw (JsonRpcException); + Json::Value HandleResponse(const Json::Value &response, Json::Value &result) throw (JsonRpcException); static const std::string KEY_PROTOCOL_VERSION; static const std::string KEY_PROCEDURE_NAME; diff --git a/src/test/test_client.cpp b/src/test/test_client.cpp index 46eb60f0..0676825a 100644 --- a/src/test/test_client.cpp +++ b/src/test/test_client.cpp @@ -55,7 +55,17 @@ namespace testclient { } using namespace testclient; +TEST_CASE_METHOD(F, "test_client_id", TEST_MODULE) +{ + params.append(33); + c.SetResponse("{\"jsonrpc\":\"2.0\", \"id\": \"1\", \"result\": 23}"); + Json::Value response = client.CallMethod("abcd", params); + CHECK(response.asInt() == 23); + c.SetResponse("{\"jsonrpc\":\"2.0\", \"id\": 1, \"result\": 24}"); + response = client.CallMethod("abcd", params); + CHECK(response.asInt() == 24); +} TEST_CASE_METHOD(F, "test_client_v2_method_success", TEST_MODULE) { From 51255976014d12d5700427d2177ab076e340ecf4 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 10:31:41 +0200 Subject: [PATCH 054/114] Cleaned out a debug purpose cout. --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 3dee273a..4c87294e 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -140,7 +140,6 @@ void LinuxTcpSocketServer::ListenLoop() { while(this->running) { if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(connection_address)), &address_length)) > 0) { - cout << "Got a new client " << inet_ntoa(connection_address.sin_addr) << ":" << htons(connection_address.sin_port) << endl; pthread_t client_thread; struct GenerateResponseParameters *params = new struct GenerateResponseParameters(); params->instance = this; From f843db3df1460cd36d445e422511c8c01c370fdf Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 11:49:00 +0200 Subject: [PATCH 055/114] Matched client read/write functions with server ones on Linux implementation. --- src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index d8d44680..4ae545ec 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -60,7 +60,7 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin bool fullyWritten = false; string toSend = message; do { - ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); + ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); if(byteWritten < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); @@ -70,7 +70,7 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin } while(!fullyWritten); do { - nbytes = read(socket_fd, buffer, BUFFER_SIZE); + nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); string tmp; tmp.append(buffer, nbytes); result.append(buffer,nbytes); From e91d8603fd6b386f2f3934156ba5a267c3dd61ee Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 12:06:40 +0200 Subject: [PATCH 056/114] Improved errors handling on linux tcp socket client implementation. Now throw a ERROR_CLIENT_CONNECTOR which is more fit to errors involved by socket manipulation than ERROR_RPC_ERROR. --- .../connectors/linuxtcpsocketclient.cpp | 184 +++++++++++++++++- 1 file changed, 175 insertions(+), 9 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 4ae545ec..3b109996 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #define BUFFER_SIZE 64 #ifndef DELIMITER_CHAR @@ -42,8 +44,32 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin char buffer[BUFFER_SIZE]; socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { - cerr << "Socket failed" << endl; - throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + string message = "socket() failed"; + switch(errno) { + case EACCES: + message = strerror(EACCES); + break; + case EAFNOSUPPORT: + message = strerror(EAFNOSUPPORT); + break; + case EINVAL: + message = strerror(EINVAL); + break; + case EMFILE: + message = strerror(EMFILE); + break; + case ENOBUFS: + message = strerror(ENOBUFS); + break; + case ENOMEM: + message = strerror(ENOMEM); + break; + case EPROTONOSUPPORT: + message = strerror(EPROTONOSUPPORT); + break; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(sockaddr_in)); @@ -53,15 +79,119 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin address.sin_port = htons(this->port); if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) { - cerr << "connect failed" << endl; - throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + string message = "connect() failed"; + switch(errno) { + case EACCES: + message = strerror(EACCES); + break; + case EPERM: + message = strerror(EPERM); + break; + case EADDRINUSE: + message = strerror(EADDRINUSE); + break; + case EAFNOSUPPORT: + message = strerror(EAFNOSUPPORT); + break; + case EAGAIN: + message = strerror(EAGAIN); + break; + case EALREADY: + message = strerror(EALREADY); + break; + case EBADF: + message = strerror(EBADF); + break; + case ECONNREFUSED: + message = strerror(ECONNREFUSED); + break; + case EFAULT: + message = strerror(EFAULT); + break; + case EINPROGRESS: + message = strerror(EINPROGRESS); + break; + case EINTR: + message = strerror(EINTR); + break; + case EISCONN: + message = strerror(EISCONN); + break; + case ENETUNREACH: + message = strerror(ENETUNREACH); + break; + case ENOTSOCK: + message = strerror(ENOTSOCK); + break; + case ETIMEDOUT: + message = strerror(ETIMEDOUT); + break; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } bool fullyWritten = false; string toSend = message; do { ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < toSend.size()) { + if(byteWritten == -1) { + string message = "send() failed"; + switch(errno) { + case EACCES: + message = strerror(EACCES); + break; + case EWOULDBLOCK: + message = strerror(EWOULDBLOCK); + break; + case EBADF: + message = strerror(EBADF); + break; + case ECONNRESET: + message = strerror(ECONNRESET); + break; + case EDESTADDRREQ: + message = strerror(EDESTADDRREQ); + break; + case EFAULT: + message = strerror(EFAULT); + break; + case EINTR: + message = strerror(EINTR); + break; + case EINVAL: + message = strerror(EINVAL); + break; + case EISCONN: + message = strerror(EISCONN); + break; + case EMSGSIZE: + message = strerror(EMSGSIZE); + break; + case ENOBUFS: + message = strerror(ENOBUFS); + break; + case ENOMEM: + message = strerror(ENOMEM); + break; + case ENOTCONN: + message = strerror(ENOTCONN); + break; + case ENOTSOCK: + message = strerror(ENOTSOCK); + break; + case EOPNOTSUPP: + message = strerror(EOPNOTSUPP); + break; + case EPIPE: + message = strerror(EPIPE); + break; + } + close(socket_fd); + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(byteWritten < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -71,10 +201,46 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin do { nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); - + if(nbytes == -1) { + string message = "recv() failed"; + switch(errno) { + case EWOULDBLOCK: + message = strerror(EWOULDBLOCK); + break; + case EBADF: + message = strerror(EBADF); + break; + case ECONNRESET: + message = strerror(ECONNRESET); + break; + case EFAULT: + message = strerror(EFAULT); + break; + case EINTR: + message = strerror(EINTR); + break; + case EINVAL: + message = strerror(EINVAL); + break; + case ENOMEM: + message = strerror(ENOMEM); + break; + case ENOTCONN: + message = strerror(ENOTCONN); + break; + case ENOTSOCK: + message = strerror(ENOTSOCK); + break; + } + close(socket_fd); + cerr << message << endl; + 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); From c18e8444b6bc0d892ca8aa134ba9477d95995ef6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 14:31:48 +0200 Subject: [PATCH 057/114] Factorized client socket close code. --- .../connectors/linuxtcpsocketserver.cpp | 39 +++++++++++-------- .../server/connectors/linuxtcpsocketserver.h | 1 + 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 4c87294e..379c94c4 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -116,12 +116,7 @@ bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) else { result = this->WriteToSocket(connection_fd, temp); } - if(WaitClientClose(connection_fd)) { - close(connection_fd); - } - else { - CloseByReset(connection_fd); - } + CleanClose(connection_fd); return result; } @@ -149,12 +144,7 @@ void LinuxTcpSocketServer::ListenLoop() { pthread_detach(client_thread); delete params; params = NULL; - if(WaitClientClose(connection_fd)) { - close(connection_fd); - } - else { - CloseByReset(connection_fd); - } + CleanClose(connection_fd); } } else { @@ -175,7 +165,13 @@ void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { string request; do { //The client sends its json formatted request and a delimiter request. nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); - request.append(buffer,nbytes); + 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; @@ -188,8 +184,10 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { string toSend = toWrite; do { ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 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); @@ -202,12 +200,12 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { } bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) { - bool ret = false; + bool ret = false; int i = 0; while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { usleep(1); ++i; - ret = true; + ret = true; } return ret; @@ -224,3 +222,12 @@ int LinuxTcpSocketServer::CloseByReset(int fd) { return close(fd); } + +int LinuxTcpSocketServer::CleanClose(int 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 4fcc0fe6..2a9cb4d9 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -60,6 +60,7 @@ namespace jsonrpc bool WriteToSocket(int fd, const std::string& toSend); bool WaitClientClose(int fd, const int &timeout = 100000); int CloseByReset(int fd); + int CleanClose(int fd); }; } /* namespace jsonrpc */ From 8f38f8cd3de3bbce17b5b626447ff8d97de1b241 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 14:32:32 +0200 Subject: [PATCH 058/114] Added winsock2 library depency for tcp socket connectors. --- src/jsonrpccpp/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 199579a7..2a7451fe 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -65,13 +65,13 @@ if (TCP_SOCKET_SERVER) if (WIN32) list(APPEND server_connector_header "server/connectors/windowstcpsocketserver.h") list(APPEND server_connector_source "server/connectors/windowstcpsocketserver.cpp") + list(APPEND server_connector_libs ws2_32) endif() if(UNIX) list(APPEND server_connector_header "server/connectors/linuxtcpsocketserver.h") list(APPEND server_connector_source "server/connectors/linuxtcpsocketserver.cpp") endif() list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) - list(APPEND server_connector_libs ${CMAKE_THREAD_LIBS_INIT}) endif() if (TCP_SOCKET_CLIENT) @@ -81,13 +81,13 @@ if (TCP_SOCKET_CLIENT) if (WIN32) list(APPEND client_connector_header "client/connectors/windowstcpsocketclient.h") list(APPEND client_connector_source "client/connectors/windowstcpsocketclient.cpp") + list(APPEND client_connector_libs ws2_32) endif() if(UNIX) list(APPEND client_connector_header "client/connectors/linuxtcpsocketclient.h") list(APPEND client_connector_source "client/connectors/linuxtcpsocketclient.cpp") endif() list(APPEND client_connector_libs ${CMAKE_THREAD_LIBS_INIT}) - list(APPEND client_connector_libs ${CMAKE_THREAD_LIBS_INIT}) endif() # configure a header file to pass some of the CMake settings to the source code From 086e25018555c678a58ca2ef6aea54ff57bb1165 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 14:40:21 +0200 Subject: [PATCH 059/114] Added tcp simple server and client examples compilation to CMake files. --- CMakeLists.txt | 2 +- src/examples/CMakeLists.txt | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9dcc251c..4d59842f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ if (COMPILE_STUBGEN) endif () # setup examples -if ((HTTP_SERVER AND HTTP_CLIENT) OR (UNIX AND UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT)) +if ((HTTP_SERVER AND HTTP_CLIENT) OR (UNIX AND UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) OR (TCP_SOCKET_SERVER AND TCP_SOCKET_CLIENT)) add_subdirectory(src/examples) endif() diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index ce90ec47..c7dcfc4f 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -66,5 +66,11 @@ if (COMPILE_EXAMPLES) endif (UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) endif(UNIX) - + if (TCP_SOCKET_SERVER AND TCP_SOCKET_CLIENT) + add_executable(tcpsocketclient tcpsocketclient.cpp) + target_link_libraries(tcpsocketclient jsonrpcclient) + + add_executable(tcpsocketserver tcpsocketserver.cpp) + target_link_libraries(tcpsocketserver jsonrpcserver) + endif (TCP_SOCKET_SERVER AND TCP_SOCKET_CLIENT) endif() From f01fa71ba02a7a3d35177e211dc08dd9cdc28f19 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 15:01:06 +0200 Subject: [PATCH 060/114] Added clean client socket close procedure on windows tcp socket server implementation. --- .../connectors/windowstcpsocketserver.cpp | 23 +++++++++---------- .../connectors/windowstcpsocketserver.h | 1 + 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index a083fd24..36beac11 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -115,12 +115,7 @@ bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) else { result = this->WriteToSocket(connection_fd, temp); } - if(WaitClientClose(connection_fd)) { - closesocket(connection_fd); - } - else { - CloseByReset(connection_fd); - } + CleanClose(connection_fd); return result; } @@ -147,12 +142,7 @@ void WindowsTcpSocketServer::ListenLoop() { if(ret == NULL) { delete params; params = NULL; - if(WaitClientClose(connection_fd)) { - closesocket(connection_fd); - } - else { - CloseByReset(connection_fd); - } + CleanClose(connection_fd); } else { CloseHandle(ret); @@ -226,6 +216,15 @@ int WindowsTcpSocketServer::CloseByReset(SOCKET fd) { return closesocket(fd); } +int WindowsTcpSocketServer::CleanClose(SOCKET 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 { diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index d25820dc..debfd770 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -55,6 +55,7 @@ namespace jsonrpc bool WriteToSocket(SOCKET fd, const std::string& toSend); bool WaitClientClose(SOCKET fd, const int &timeout = 100); int CloseByReset(SOCKET fd); + int CleanClose(SOCKET fd); }; } /* namespace jsonrpc */ From 91adb9406f21d53d0eafcaf87a99c6f3c604850a Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 15:58:30 +0200 Subject: [PATCH 061/114] Set client socket in blocking mode. It seems that it was un non-blocking mode (probably inherited of listenning socket). --- src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 36beac11..fd99fb91 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -134,6 +134,8 @@ void WindowsTcpSocketServer::ListenLoop() { 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; From a0fdd28031a686bcf782707b3532b36745b7feb6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 16:07:25 +0200 Subject: [PATCH 062/114] Improved reading and writing operation in socket for Windows implementation (now close client socket on reading/writing issues). --- .../server/connectors/windowstcpsocketserver.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index fd99fb91..3879d17a 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -168,7 +168,12 @@ DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) { string request = ""; do { //The client sends its json formatted request and a delimiter request. nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); - request.append(buffer,nbytes); + 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()); @@ -181,8 +186,10 @@ bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) { string toSend = toWrite; do { ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 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); From 1baf2352b658977bfe9802da4e4e09d8cd0c1096 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 17:11:34 +0200 Subject: [PATCH 063/114] Handlded tcp error as ERROR_CLIENT_CONNECOTR on windows tpc socket client implementation. --- .../connectors/windowstcpsocketclient.cpp | 134 ++++++++++++++++-- .../connectors/windowstcpsocketclient.h | 1 + 2 files changed, 127 insertions(+), 8 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index faec6a2a..99de2524 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -39,8 +39,27 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str char buffer[BUFFER_SIZE]; socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { - cerr << "Socket failed" << endl; - throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + 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; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(SOCKADDR_IN)); @@ -50,15 +69,70 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str address.sin_port = htons(this->port); if(connect(socket_fd, reinterpret_cast(&address), sizeof(SOCKADDR_IN)) != 0) { - cerr << "connect failed" << endl; - throw JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR, result); + 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; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } bool fullyWritten = false; string toSend = message; do { ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < toSend.size()) { + 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); + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(byteWritten < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -68,15 +142,59 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str do { nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); + 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); + cerr << message << endl; + 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); 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; +} + //This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). struct ClientSocketInitializer { diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index 1bfc4297..18ea200c 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -26,6 +26,7 @@ namespace jsonrpc private: std::string ipToConnect; unsigned int port; + static std::string GetErrorMessage(const int &e); }; } /* namespace jsonrpc */ From 324617cddaa0541cc1c8c932d3d50341587175f4 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Mon, 27 Jul 2015 17:15:43 +0200 Subject: [PATCH 064/114] Factorized some errors message handling code in linux tcp socket client. --- .../connectors/linuxtcpsocketclient.cpp | 106 ++---------------- 1 file changed, 12 insertions(+), 94 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 3b109996..3b936ad2 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -45,27 +45,16 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { string message = "socket() failed"; - switch(errno) { + int err = errno; + switch(err) { case EACCES: - message = strerror(EACCES); - break; case EAFNOSUPPORT: - message = strerror(EAFNOSUPPORT); - break; case EINVAL: - message = strerror(EINVAL); - break; case EMFILE: - message = strerror(EMFILE); - break; case ENOBUFS: - message = strerror(ENOBUFS); - break; case ENOMEM: - message = strerror(ENOMEM); - break; case EPROTONOSUPPORT: - message = strerror(EPROTONOSUPPORT); + message = strerror(err); break; } cerr << message << endl; @@ -80,51 +69,24 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) { string message = "connect() failed"; - switch(errno) { + int err = errno; + switch(err) { case EACCES: - message = strerror(EACCES); - break; case EPERM: - message = strerror(EPERM); - break; case EADDRINUSE: - message = strerror(EADDRINUSE); - break; case EAFNOSUPPORT: - message = strerror(EAFNOSUPPORT); - break; case EAGAIN: - message = strerror(EAGAIN); - break; case EALREADY: - message = strerror(EALREADY); - break; case EBADF: - message = strerror(EBADF); - break; case ECONNREFUSED: - message = strerror(ECONNREFUSED); - break; case EFAULT: - message = strerror(EFAULT); - break; case EINPROGRESS: - message = strerror(EINPROGRESS); - break; case EINTR: - message = strerror(EINTR); - break; case EISCONN: - message = strerror(EISCONN); - break; case ENETUNREACH: - message = strerror(ENETUNREACH); - break; case ENOTSOCK: - message = strerror(ENOTSOCK); - break; case ETIMEDOUT: - message = strerror(ETIMEDOUT); + message = strerror(err); break; } cerr << message << endl; @@ -137,54 +99,25 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); if(byteWritten == -1) { string message = "send() failed"; - switch(errno) { + int err = errno; + switch(err) { case EACCES: - message = strerror(EACCES); - break; case EWOULDBLOCK: - message = strerror(EWOULDBLOCK); - break; case EBADF: - message = strerror(EBADF); - break; case ECONNRESET: - message = strerror(ECONNRESET); - break; case EDESTADDRREQ: - message = strerror(EDESTADDRREQ); - break; case EFAULT: - message = strerror(EFAULT); - break; case EINTR: - message = strerror(EINTR); - break; case EINVAL: - message = strerror(EINVAL); - break; case EISCONN: - message = strerror(EISCONN); - break; case EMSGSIZE: - message = strerror(EMSGSIZE); - break; case ENOBUFS: - message = strerror(ENOBUFS); - break; case ENOMEM: - message = strerror(ENOMEM); - break; case ENOTCONN: - message = strerror(ENOTCONN); - break; case ENOTSOCK: - message = strerror(ENOTSOCK); - break; case EOPNOTSUPP: - message = strerror(EOPNOTSUPP); - break; case EPIPE: - message = strerror(EPIPE); + message = strerror(err); break; } close(socket_fd); @@ -203,33 +136,18 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); if(nbytes == -1) { string message = "recv() failed"; - switch(errno) { + int err = errno; + switch(err) { case EWOULDBLOCK: - message = strerror(EWOULDBLOCK); - break; case EBADF: - message = strerror(EBADF); - break; case ECONNRESET: - message = strerror(ECONNRESET); - break; case EFAULT: - message = strerror(EFAULT); - break; case EINTR: - message = strerror(EINTR); - break; case EINVAL: - message = strerror(EINVAL); - break; case ENOMEM: - message = strerror(ENOMEM); - break; case ENOTCONN: - message = strerror(ENOTCONN); - break; case ENOTSOCK: - message = strerror(ENOTSOCK); + message = strerror(err); break; } close(socket_fd); From 63a925e8465935e29cae4a22b81949ea3b328ab2 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 11:44:59 +0200 Subject: [PATCH 065/114] Adding include to use cerr flow. --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 0a36e082..8101118d 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -10,6 +10,7 @@ #include "unixdomainsocketserver.h" #include #include +#include #include #include #include From abb6624173eb3ee6b7497ecc49e393a86a515f2c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 16:38:32 +0200 Subject: [PATCH 066/114] Corrected wrong behavior of StartListening and StopListening (for return value) on Unix Domain Socket Server. --- .../server/connectors/unixdomainsocketserver.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 8101118d..0cec7dfe 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -65,12 +65,13 @@ bool UnixDomainSocketServer::StartListening() cerr << "bind() failed" << endl; return false; } - + if(listen(this->socket_fd, 5) != 0) { cerr << "listen() failed" << endl; return false; } + //Launch listening loop there this->running = true; int ret = pthread_create(&(this->listenning_thread), NULL, UnixDomainSocketServer::LaunchLoop, this); @@ -78,8 +79,12 @@ bool UnixDomainSocketServer::StartListening() pthread_detach(this->listenning_thread); } this->running = static_cast(ret==0); + + return this->running; } - return this->running; + else { + return false; + } } bool UnixDomainSocketServer::StopListening() @@ -90,8 +95,11 @@ bool UnixDomainSocketServer::StopListening() pthread_join(this->listenning_thread, NULL); close(this->socket_fd); unlink(this->socket_path.c_str()); + return !(this->running); } - return !(this->running); + else { + return false; + } } bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) @@ -160,6 +168,7 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { 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; } From 40022717534c49fff96cb78504dca8501e96095b Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 16:43:18 +0200 Subject: [PATCH 067/114] Improved Unix Domain Sockets Connectors Test (needed greater timeout and right delimiter character). --- src/test/test_connector_unixdomainsocket.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/test/test_connector_unixdomainsocket.cpp b/src/test/test_connector_unixdomainsocket.cpp index 561fec39..bcd27108 100644 --- a/src/test/test_connector_unixdomainsocket.cpp +++ b/src/test/test_connector_unixdomainsocket.cpp @@ -18,6 +18,10 @@ using namespace jsonrpc; using namespace std; +#ifndef DELIMITER_CHAR + #define DELIMITER_CHAR char(0x0A) +#endif + #define TEST_MODULE "[connector_unixdomainsocket]" #define SOCKET_PATH "/tmp/jsonrpccpp-socket" @@ -50,15 +54,20 @@ namespace testunixdomainsocketserver } using namespace testunixdomainsocketserver; - TEST_CASE_METHOD(F, "test_unixdomainsocket_success", TEST_MODULE) { handler.response = "exampleresponse"; + handler.timeout = 100; string result; - client.SendRPCMessage("examplerequest", result); + string request = "examplerequest"; + request.push_back(DELIMITER_CHAR); + string expectedResult = "exampleresponse"; + expectedResult.push_back(DELIMITER_CHAR); + + client.SendRPCMessage(request, result); - CHECK(handler.request == "examplerequest"); - CHECK(result == "exampleresponse"); + CHECK(handler.request == request); + CHECK(result == expectedResult); } From bac4763ff90ddac2c5c6570ce249aa4922e479ee Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 16:45:59 +0200 Subject: [PATCH 068/114] Corrected same behavioral issue for LinuxTcpSocketServer that was spotted on UnixDomainSocketServer on StartListening and StopListening methods. --- .../server/connectors/linuxtcpsocketserver.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 379c94c4..9d09d897 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -82,8 +82,11 @@ bool LinuxTcpSocketServer::StartListening() close(this->socket_fd); } this->running = static_cast(ret==0); + return this->running; } - return this->running; + else { + return false; + } } bool LinuxTcpSocketServer::StopListening() @@ -94,8 +97,11 @@ bool LinuxTcpSocketServer::StopListening() pthread_join(this->listenning_thread, NULL); shutdown(this->socket_fd, 2); close(this->socket_fd); + return !(this->running); } - return !(this->running); + else { + return false; + } } bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) From c65fe7b6998deb3e91dcb903088de6b53d126ccc Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 16:46:24 +0200 Subject: [PATCH 069/114] Corrected same behavioral issue for WindowsTcpSocketServer that was spotted on UnixDomainSocketServer on StartListening and StopListening methods. --- .../server/connectors/windowstcpsocketserver.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 3879d17a..0d1f16e6 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -82,8 +82,12 @@ bool WindowsTcpSocketServer::StartListening() CloseHandle(ret); } this->running = static_cast(ret!=NULL); + return this->running; } - return this->running; + else { + return false; + } + } bool WindowsTcpSocketServer::StopListening() @@ -93,8 +97,11 @@ bool WindowsTcpSocketServer::StopListening() this->running = false; WaitForSingleObject(OpenThread(THREAD_ALL_ACCESS, FALSE,this->listenning_thread), INFINITE); closesocket(this->socket_fd); + return !(this->running); } - return !(this->running); + else { + return false; + } } bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) From f10e4a3c88f52350e40eebc87515790855204ff4 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 17:09:11 +0200 Subject: [PATCH 070/114] Added TcpSocket Connectors unit tests. --- src/test/test_connector_tcpsocket.cpp | 94 +++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/test/test_connector_tcpsocket.cpp diff --git a/src/test/test_connector_tcpsocket.cpp b/src/test/test_connector_tcpsocket.cpp new file mode 100644 index 00000000..e71730d7 --- /dev/null +++ b/src/test/test_connector_tcpsocket.cpp @@ -0,0 +1,94 @@ +/************************************************************************* + * libjson-rpc-cpp + ************************************************************************* + * @file test_connector_tcpsocket.cpp + * @date 27/07/2015 + * @author Alexandre Poirot + * @license See attached LICENSE.txt + ************************************************************************/ + +#ifdef TCPSOCKET_TESTING +#include +#include +#include +#include "mockclientconnectionhandler.h" + +#include "checkexception.h" + +using namespace jsonrpc; +using namespace std; + +#ifndef DELIMITER_CHAR + #define DELIMITER_CHAR char(0x0A) +#endif + +#define TEST_MODULE "[connector_tcpsocket]" + +#define IP "127.0.0.1" +#define PORT 50000 + +namespace testtcpsocketserver +{ + struct F { + TcpSocketServer server; + TcpSocketClient client; + MockClientConnectionHandler handler; + + F() : + server(IP, PORT), + client(IP, PORT) + { + server.SetHandler(&handler); + REQUIRE(server.StartListening()); + } + ~F() + { + server.StopListening(); + } + }; + + bool check_exception1(JsonRpcException const&ex) + { + return ex.GetCode() == Errors::ERROR_CLIENT_CONNECTOR; + } +} +using namespace testtcpsocketserver; + +TEST_CASE_METHOD(F, "test_tcpsocket_success", TEST_MODULE) +{ + handler.response = "exampleresponse"; + handler.timeout = 100; + string result; + string request = "examplerequest"; + request.push_back(DELIMITER_CHAR); + string expectedResult = "exampleresponse"; + expectedResult.push_back(DELIMITER_CHAR); + + client.SendRPCMessage(request, result); + + CHECK(handler.request == request); + CHECK(result == expectedResult); +} + + +TEST_CASE("test_tcpsocket_server_multiplestart", TEST_MODULE) +{ + TcpSocketServer server(IP, PORT); + CHECK(server.StartListening() == true); + CHECK(server.StartListening() == false); + + TcpSocketServer server2(IP, PORT); + CHECK(server2.StartListening() == false); + CHECK(server2.StopListening() == false); + + CHECK(server.StopListening() == true); +} + +TEST_CASE("test_tcpsocket_client_invalid", TEST_MODULE) +{ + TcpSocketClient client("127.10.10.10", 55555); + string result; + CHECK_EXCEPTION_TYPE(client.SendRPCMessage("foobar", result), JsonRpcException, check_exception1); +} + +#endif From d4af4dffe10956fc6376cb66bc923fe1da503234 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 28 Jul 2015 17:09:40 +0200 Subject: [PATCH 071/114] Modified CMake files to compile TcpSocket Connectors unit tests. --- src/test/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 088f5950..9a327766 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -23,6 +23,10 @@ if(UNIX_DOMAIN_SOCKET_SERVER AND UNIX_DOMAIN_SOCKET_CLIENT) add_definitions(-DUNIXDOMAINSOCKET_TESTING) endif() +if(TCP_SOCKET_SERVER AND TCP_SOCKET_CLIENT) + add_definitions(-DTCPSOCKET_TESTING) +endif() + if(COMPILE_STUBGEN) add_definitions(-DSTUBGEN_TESTING) endif() @@ -51,6 +55,10 @@ if (UNIX_DOMAIN_SOCKET_CLIENT AND UNIX_DOMAIN_SOCKET_SERVER) add_test(NAME connector_unixdomainsocket WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unit_testsuite "[connector_unixdomainsocket]") endif() +if (TCP_SOCKET_CLIENT AND TCP_SOCKET_SERVER) + add_test(NAME connector_tcpsocket WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unit_testsuite "[connector_tcpsocket]") +endif() + if(COMPILE_STUBGEN) add_test(NAME stubgen WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unit_testsuite "[stubgenerator]") endif() From 1a6e10c5817d126808e532468d543efc17feb675 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Wed, 29 Jul 2015 15:43:34 +0200 Subject: [PATCH 072/114] Changed port for unused port test. Added comment if port is not unused. --- src/test/test_connector_tcpsocket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/test_connector_tcpsocket.cpp b/src/test/test_connector_tcpsocket.cpp index e71730d7..920077bf 100644 --- a/src/test/test_connector_tcpsocket.cpp +++ b/src/test/test_connector_tcpsocket.cpp @@ -70,7 +70,6 @@ TEST_CASE_METHOD(F, "test_tcpsocket_success", TEST_MODULE) CHECK(result == expectedResult); } - TEST_CASE("test_tcpsocket_server_multiplestart", TEST_MODULE) { TcpSocketServer server(IP, PORT); @@ -84,9 +83,10 @@ TEST_CASE("test_tcpsocket_server_multiplestart", TEST_MODULE) CHECK(server.StopListening() == true); } + TEST_CASE("test_tcpsocket_client_invalid", TEST_MODULE) { - TcpSocketClient client("127.10.10.10", 55555); + TcpSocketClient client("127.0.0.1", 40000); //If this test fails, check that port 40000 is really unused. If it is used, change this port value to an unused port, recompile tests and run tests again. string result; CHECK_EXCEPTION_TYPE(client.SendRPCMessage("foobar", result), JsonRpcException, check_exception1); } From ad056d2e810471104b800ac518e7645b1870ece3 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Wed, 29 Jul 2015 16:33:31 +0200 Subject: [PATCH 073/114] Reindented code (with vim "gg=G" sequence) and adjusted openning brack policy (openning bracket to new line). --- .../connectors/linuxtcpsocketclient.cpp | 198 ++++++------ .../client/connectors/tcpsocketclient.cpp | 3 +- .../connectors/unixdomainsocketclient.cpp | 17 +- .../connectors/unixdomainsocketclient.h | 18 +- .../connectors/windowstcpsocketclient.cpp | 299 +++++++++--------- .../connectors/windowstcpsocketclient.h | 2 +- .../connectors/linuxtcpsocketserver.cpp | 87 +++-- .../server/connectors/linuxtcpsocketserver.h | 3 +- .../server/connectors/tcpsocketserver.cpp | 6 +- .../connectors/unixdomainsocketserver.cpp | 82 +++-- .../connectors/unixdomainsocketserver.h | 3 +- .../connectors/windowstcpsocketserver.cpp | 120 ++++--- .../connectors/windowstcpsocketserver.h | 5 +- 13 files changed, 477 insertions(+), 366 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 3b936ad2..c74a9ea5 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -43,22 +43,24 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin int socket_fd, nbytes; char buffer[BUFFER_SIZE]; socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + int err = errno; + switch(err) + { + case EACCES: + case EAFNOSUPPORT: + case EINVAL: + case EMFILE: + case ENOBUFS: + case ENOMEM: + case EPROTONOSUPPORT: + message = strerror(err); + break; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(sockaddr_in)); @@ -67,64 +69,70 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin inet_aton(this->ipToConnect.c_str(), &(address.sin_addr)); address.sin_port = htons(this->port); - if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_in)) != 0) { + 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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + 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; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } bool fullyWritten = false; string toSend = message; - do { + 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); - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else if(byteWritten < toSend.size()) { + 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); + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(byteWritten < toSend.size()) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -132,33 +140,37 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin fullyWritten = true; } while(!fullyWritten); - do { + do + { 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); - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else { - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); - } + 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); + cerr << message << endl; + 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); diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp index 24688d33..f8fec595 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp @@ -35,7 +35,8 @@ TcpSocketClient::~TcpSocketClient() void TcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - if(this->realSocket != NULL) { + if(this->realSocket != NULL) + { this->realSocket->SendRPCMessage(message, result); } } diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index 778f7fff..6192ccac 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -28,7 +28,7 @@ using namespace jsonrpc; using namespace std; UnixDomainSocketClient::UnixDomainSocketClient(const std::string& path) - : path(path) +: path(path) { } @@ -42,7 +42,8 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str int socket_fd, nbytes; char buffer[BUFFER_SIZE]; socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (socket_fd < 0) { + if (socket_fd < 0) + { cerr << "Socket failed" << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not created unix domain socket"); } @@ -52,16 +53,19 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str address.sun_family = AF_UNIX; snprintf(address.sun_path, PATH_MAX, this->path.c_str()); - if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) { + if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) + { cerr << "connect failed" << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not connect to: " + this->path); } bool fullyWritten = false; string toSend = message; - do { + do + { ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); - if(byteWritten < toSend.size()) { + if(byteWritten < toSend.size()) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -69,7 +73,8 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str fullyWritten = true; } while(!fullyWritten); - do { + do + { nbytes = read(socket_fd, buffer, BUFFER_SIZE); string tmp; tmp.append(buffer, nbytes); diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.h index cec64f87..78bfbe28 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 99de2524..beb57bd4 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -38,28 +38,30 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str int socket_fd, nbytes; char buffer[BUFFER_SIZE]; socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 0) { + if (socket_fd < 0) + { 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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + 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; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(SOCKADDR_IN)); @@ -68,71 +70,77 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str address.sin_addr.s_addr = inet_addr(this->ipToConnect.c_str()); address.sin_port = htons(this->port); - if(connect(socket_fd, reinterpret_cast(&address), sizeof(SOCKADDR_IN)) != 0) { + 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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + 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; + } + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } bool fullyWritten = false; string toSend = message; - do { + do + { ssize_t 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); - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else if(byteWritten < toSend.size()) { + 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); + cerr << message << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); + } + else if(byteWritten < toSend.size()) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -140,78 +148,87 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str fullyWritten = true; } while(!fullyWritten); - do { + do + { 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); - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - else { - string tmp; - tmp.append(buffer, nbytes); - result.append(buffer,nbytes); - } + 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); + cerr << message << endl; + 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); 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; +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; } //This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). struct ClientSocketInitializer { - ClientSocketInitializer() - { - WSADATA init; - if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { - cerr << "An issue occured while WSAStartup executed." << endl; - } - } - - ~ClientSocketInitializer() - { - if(WSACleanup() != 0) { - cerr << "An issue occured while WSAClean executed." << endl; - } - } + ClientSocketInitializer() + + { + WSADATA init; + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) + { + cerr << "An issue occured while WSAStartup executed." << endl; + } + } + + ~ClientSocketInitializer() + + { + if(WSACleanup() != 0) + { + cerr << "An issue occured while WSAClean executed." << endl; + } + } }; -struct ClientSocketInitializer clientGlobalInitializer; \ No newline at end of file +struct ClientSocketInitializer clientGlobalInitializer; diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index 18ea200c..d43eac01 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -26,7 +26,7 @@ namespace jsonrpc private: std::string ipToConnect; unsigned int port; - static std::string GetErrorMessage(const int &e); + static std::string GetErrorMessage(const int &e); }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 9d09d897..0c75468a 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -76,17 +76,19 @@ bool LinuxTcpSocketServer::StartListening() //Launch listening loop there this->running = true; int ret = pthread_create(&(this->listenning_thread), NULL, LinuxTcpSocketServer::LaunchLoop, this); - if(ret != 0) { + 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; + return this->running; + } + else + { + return false; } - else { - return false; - } } bool LinuxTcpSocketServer::StopListening() @@ -97,11 +99,12 @@ bool LinuxTcpSocketServer::StopListening() pthread_join(this->listenning_thread, NULL); shutdown(this->socket_fd, 2); close(this->socket_fd); - return !(this->running); + return !(this->running); + } + else + { + return false; } - else { - return false; - } } bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) @@ -110,35 +113,41 @@ bool LinuxTcpSocketServer::SendResponse(const string& response, void* addInfo) int connection_fd = reinterpret_cast(addInfo); string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) { + if(temp.find(DELIMITER_CHAR) == string::npos) + { temp.append(1, DELIMITER_CHAR); } - if(DELIMITER_CHAR != '\n') { + 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 { + else + { result = this->WriteToSocket(connection_fd, temp); } CleanClose(connection_fd); return result; } -void* LinuxTcpSocketServer::LaunchLoop(void *p_data) { +void* LinuxTcpSocketServer::LaunchLoop(void *p_data) +{ pthread_detach(pthread_self()); LinuxTcpSocketServer *instance = reinterpret_cast(p_data);; instance->ListenLoop(); return NULL; } -void LinuxTcpSocketServer::ListenLoop() { +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) { + while(this->running) + { if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(connection_address)), &address_length)) > 0) { pthread_t client_thread; @@ -146,20 +155,23 @@ void LinuxTcpSocketServer::ListenLoop() { params->instance = this; params->connection_fd = connection_fd; int ret = pthread_create(&client_thread, NULL, LinuxTcpSocketServer::GenerateResponse, params); - if(ret != 0) { + if(ret != 0) + { pthread_detach(client_thread); delete params; params = NULL; CleanClose(connection_fd); } } - else { + else + { usleep(2500); } } } -void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { +void* LinuxTcpSocketServer::GenerateResponse(void *p_data) +{ pthread_detach(pthread_self()); struct GenerateResponseParameters* params = reinterpret_cast(p_data); LinuxTcpSocketServer *instance = params->instance; @@ -169,13 +181,16 @@ void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { int nbytes; char buffer[BUFFER_SIZE]; string request; - do { //The client sends its json formatted request and a delimiter request. + do + { //The client sends its json formatted request and a delimiter request. nbytes = recv(connection_fd, buffer, BUFFER_SIZE, 0); - if(nbytes == -1) { + if(nbytes == -1) + { instance->CleanClose(connection_fd); return NULL; } - else { + else + { request.append(buffer,nbytes); } } while(request.find(DELIMITER_CHAR) == string::npos); @@ -184,17 +199,21 @@ void* LinuxTcpSocketServer::GenerateResponse(void *p_data) { } -bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { +bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) +{ bool fullyWritten = false; bool errorOccured = false; string toSend = toWrite; - do { + do + { ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 0) { + if(byteWritten < 0) + { errorOccured = true; CleanClose(fd); } - else if(byteWritten < toSend.size()) { + else if(byteWritten < toSend.size()) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -205,10 +224,12 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) { return fullyWritten && !errorOccured; } -bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) { +bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) +{ bool ret = false; int i = 0; - while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { + while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) + { usleep(1); ++i; ret = true; @@ -217,7 +238,8 @@ bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) { return ret; } -int LinuxTcpSocketServer::CloseByReset(int fd) { +int LinuxTcpSocketServer::CloseByReset(int fd) +{ struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; @@ -229,11 +251,14 @@ int LinuxTcpSocketServer::CloseByReset(int fd) { return close(fd); } -int LinuxTcpSocketServer::CleanClose(int fd) { - if(WaitClientClose(fd)) { +int LinuxTcpSocketServer::CleanClose(int fd) +{ + if(WaitClientClose(fd)) + { return close(fd); } - else { + else + { return CloseByReset(fd); } } diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index 2a9cb4d9..427da388 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -52,7 +52,8 @@ namespace jsonrpc static void* LaunchLoop(void *p_data); void ListenLoop(); - struct GenerateResponseParameters { + struct GenerateResponseParameters + { LinuxTcpSocketServer *instance; int connection_fd; }; diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp index a80505a3..e6c23c79 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.cpp @@ -32,7 +32,8 @@ TcpSocketServer::TcpSocketServer(const std::string& ipToBind, const unsigned int TcpSocketServer::~TcpSocketServer() { - if(this->realSocket != NULL) { + if(this->realSocket != NULL) + { delete this->realSocket; this->realSocket = NULL; } @@ -40,7 +41,8 @@ TcpSocketServer::~TcpSocketServer() bool TcpSocketServer::StartListening() { - if(this->realSocket != NULL) { + if(this->realSocket != NULL) + { this->realSocket->SetHandler(this->GetHandler()); return this->realSocket->StartListening(); } diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 0cec7dfe..72193f3a 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -24,12 +24,12 @@ using namespace std; #define BUFFER_SIZE 1024 #define PATH_MAX 108 #ifndef DELIMITER_CHAR - #define DELIMITER_CHAR char(0x0A) +#define DELIMITER_CHAR char(0x0A) #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)) { } @@ -40,7 +40,7 @@ bool UnixDomainSocketServer::StartListening() //Create and bind socket here. //Then launch the listenning loop. if (access(this->socket_path.c_str(), F_OK) != -1) - return false; + return false; this->socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -51,9 +51,9 @@ bool UnixDomainSocketServer::StartListening() } unlink(this->socket_path.c_str()); - + fcntl(this->socket_fd, F_SETFL, FNDELAY); - + /* start with a clean address structure */ memset(&(this->address), 0, sizeof(struct sockaddr_un)); @@ -65,26 +65,28 @@ bool UnixDomainSocketServer::StartListening() cerr << "bind() failed" << endl; return false; } - + if(listen(this->socket_fd, 5) != 0) { cerr << "listen() failed" << endl; return false; } - + //Launch listening loop there this->running = true; int ret = pthread_create(&(this->listenning_thread), NULL, UnixDomainSocketServer::LaunchLoop, this); - if(ret != 0) { + if(ret != 0) + { pthread_detach(this->listenning_thread); } this->running = static_cast(ret==0); - return this->running; + return this->running; + } + else + { + return false; } - else { - return false; - } } bool UnixDomainSocketServer::StopListening() @@ -95,11 +97,12 @@ bool UnixDomainSocketServer::StopListening() pthread_join(this->listenning_thread, NULL); close(this->socket_fd); unlink(this->socket_path.c_str()); - return !(this->running); + return !(this->running); + } + else + { + return false; } - else { - return false; - } } bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) @@ -108,33 +111,39 @@ bool UnixDomainSocketServer::SendResponse(const string& response, void* addInfo) int connection_fd = reinterpret_cast(addInfo); string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) { + if(temp.find(DELIMITER_CHAR) == string::npos) + { temp.append(1, DELIMITER_CHAR); } - if(DELIMITER_CHAR != '\n') { + 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 { + else + { result = this->WriteToSocket(connection_fd, temp); } close(connection_fd); return result; } -void* UnixDomainSocketServer::LaunchLoop(void *p_data) { +void* UnixDomainSocketServer::LaunchLoop(void *p_data) +{ pthread_detach(pthread_self()); UnixDomainSocketServer *instance = reinterpret_cast(p_data);; instance->ListenLoop(); return NULL; } -void UnixDomainSocketServer::ListenLoop() { +void UnixDomainSocketServer::ListenLoop() +{ int connection_fd; socklen_t address_length = sizeof(this->address); - while(this->running) { + while(this->running) + { if((connection_fd = accept(this->socket_fd, reinterpret_cast(&(this->address)), &address_length)) > 0) { pthread_t client_thread; @@ -142,21 +151,24 @@ void UnixDomainSocketServer::ListenLoop() { params->instance = this; params->connection_fd = connection_fd; int ret = pthread_create(&client_thread, NULL, UnixDomainSocketServer::GenerateResponse, params); - if(ret != 0) { + if(ret != 0) + { pthread_detach(client_thread); delete params; params = NULL; } } - else { + else + { usleep(25000); } } } -void* UnixDomainSocketServer::GenerateResponse(void *p_data) { - pthread_detach(pthread_self()); - struct ClientConnection* params = reinterpret_cast(p_data); +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; @@ -164,25 +176,29 @@ void* UnixDomainSocketServer::GenerateResponse(void *p_data) { int nbytes; char buffer[BUFFER_SIZE]; string request; - do { //The client sends its json formatted request and a delimiter 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 UnixDomainSocketServer::WriteToSocket(int fd, const string& toWrite) +{ bool fullyWritten = false; bool errorOccured = false; string toSend = toWrite; - do { + do + { ssize_t byteWritten = write(fd, toSend.c_str(), toSend.size()); if(byteWritten < 0) errorOccured = true; - else if(byteWritten < static_cast(toSend.size())) { + else if(byteWritten < static_cast(toSend.size())) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h index 97c66db3..2d2072b0 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.h @@ -50,7 +50,8 @@ namespace jsonrpc static void* LaunchLoop(void *p_data); void ListenLoop(); - struct ClientConnection { + struct ClientConnection + { UnixDomainSocketServer *instance; int connection_fd; }; diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 0d1f16e6..22270b0f 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -36,7 +36,8 @@ WindowsTcpSocketServer::WindowsTcpSocketServer(const std::string& ipToBind, cons { } -WindowsTcpSocketServer::~WindowsTcpSocketServer() { +WindowsTcpSocketServer::~WindowsTcpSocketServer() +{ } bool WindowsTcpSocketServer::StartListening() @@ -75,19 +76,22 @@ bool WindowsTcpSocketServer::StartListening() //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) { + if(ret == NULL) + { ExitProcess(3); } - else { + else + { CloseHandle(ret); } this->running = static_cast(ret!=NULL); - return this->running; + return this->running; } - else { - return false; - } - + else + { + return false; + } + } bool WindowsTcpSocketServer::StopListening() @@ -97,11 +101,12 @@ bool WindowsTcpSocketServer::StopListening() this->running = false; WaitForSingleObject(OpenThread(THREAD_ALL_ACCESS, FALSE,this->listenning_thread), INFINITE); closesocket(this->socket_fd); - return !(this->running); + return !(this->running); + } + else + { + return false; } - else { - return false; - } } bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) @@ -110,60 +115,70 @@ bool WindowsTcpSocketServer::SendResponse(const string& response, void* addInfo) int connection_fd = reinterpret_cast(addInfo); string temp = response; - if(temp.find(DELIMITER_CHAR) == string::npos) { + if(temp.find(DELIMITER_CHAR) == string::npos) + { temp.append(1, DELIMITER_CHAR); } - if(DELIMITER_CHAR != '\n') { + 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 { + else + { result = this->WriteToSocket(connection_fd, temp); } CleanClose(connection_fd); return result; } -DWORD WINAPI WindowsTcpSocketServer::LaunchLoop(LPVOID lp_data) { +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. } -void WindowsTcpSocketServer::ListenLoop() { - while(this->running) { +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 + 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) { + if(ret == NULL) + { delete params; params = NULL; CleanClose(connection_fd); } - else { + else + { CloseHandle(ret); } } - else { + else + { Sleep(2.5); } } } -DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) { +DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) +{ struct GenerateResponseParameters* params = reinterpret_cast(lp_data); WindowsTcpSocketServer *instance = params->instance; int connection_fd = params->connection_fd; @@ -173,31 +188,38 @@ DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) { char buffer[BUFFER_SIZE]; memset(&buffer, 0, BUFFER_SIZE); string request = ""; - do { //The client sends its json formatted request and a delimiter 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); - } + 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(SOCKET fd, const string& toWrite) { +bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) +{ bool fullyWritten = false; bool errorOccured = false; string toSend = toWrite; - do { + do + { ssize_t byteWritten = send(fd, toSend.c_str(), toSend.size(), 0); - if(byteWritten < 0) { + if(byteWritten < 0) + { errorOccured = true; - CleanClose(fd); - } - else if(byteWritten < toSend.size()) { + CleanClose(fd); + } + else if(byteWritten < toSend.size()) + { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); } @@ -208,10 +230,12 @@ bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) { return fullyWritten && !errorOccured; } -bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) { +bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) +{ bool ret = false; int i = 0; - while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) { + while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) + { Sleep(1); ++i; ret = true; @@ -220,7 +244,8 @@ bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) { return ret; } -int WindowsTcpSocketServer::CloseByReset(SOCKET fd) { +int WindowsTcpSocketServer::CloseByReset(SOCKET fd) +{ struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; @@ -232,11 +257,14 @@ int WindowsTcpSocketServer::CloseByReset(SOCKET fd) { return closesocket(fd); } -int WindowsTcpSocketServer::CleanClose(SOCKET fd) { - if(WaitClientClose(fd)) { +int WindowsTcpSocketServer::CleanClose(SOCKET fd) +{ + if(WaitClientClose(fd)) + { return closesocket(fd); } - else { + else + { return CloseByReset(fd); } } @@ -247,14 +275,16 @@ struct ServerSocketInitializer ServerSocketInitializer() { WSADATA init; - if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { + if(WSAStartup(MAKEWORD(2, 2), &init) != 0) + { cerr << "An issue occured while WSAStartup executed." << endl; } } ~ServerSocketInitializer() { - if(WSACleanup() != 0) { + if(WSACleanup() != 0) + { cerr << "An issue occured while WSAClean executed." << endl; } } diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index debfd770..77e0f177 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -47,7 +47,8 @@ namespace jsonrpc static DWORD WINAPI LaunchLoop(LPVOID lp_data); void ListenLoop(); - struct GenerateResponseParameters { + struct GenerateResponseParameters + { WindowsTcpSocketServer *instance; SOCKET connection_fd; }; @@ -55,7 +56,7 @@ namespace jsonrpc bool WriteToSocket(SOCKET fd, const std::string& toSend); bool WaitClientClose(SOCKET fd, const int &timeout = 100); int CloseByReset(SOCKET fd); - int CleanClose(SOCKET fd); + int CleanClose(SOCKET fd); }; } /* namespace jsonrpc */ From 7c50f8c2eecddce3400893024f6ec23127a47155 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 09:56:17 +0200 Subject: [PATCH 074/114] Added doxygen documentation for tcp socket connectors. --- .../client/connectors/linuxtcpsocketclient.h | 22 +++- .../client/connectors/tcpsocketclient.h | 28 ++++- .../connectors/tcpsocketclientprivate.h | 3 + .../connectors/windowstcpsocketclient.h | 27 ++++- .../server/connectors/linuxtcpsocketserver.h | 103 ++++++++++++++--- .../server/connectors/tcpsocketserver.h | 56 +++++++-- .../connectors/tcpsocketserverprivate.h | 4 +- .../connectors/windowstcpsocketserver.h | 106 +++++++++++++++--- 8 files changed, 303 insertions(+), 46 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h index 9b8a7c16..e689d5a8 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -16,16 +16,34 @@ 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 { public: + /** + * @brief LinuxTcpSocketClient, constructor of the Linux/UNIX implementation of class TcpSocketClient + * @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 + */ LinuxTcpSocketClient(const std::string& ipToConnect, 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 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 ipToConnect; - unsigned int port; + std::string ipToConnect; /*!< The ipv4 address on which the client should try to connect*/ + unsigned int port; /*!< The port on which the client should try to connect*/ }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.h b/src/jsonrpccpp/client/connectors/tcpsocketclient.h index 26fff40b..66e80054 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.h @@ -17,15 +17,39 @@ namespace jsonrpc { + /** + * This class provides an embedded TCP Socket Client that sends Requests over a tcp socket and read result from 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 client. Currently it has implementation for + * both Linux and Windows. + */ class TcpSocketClient : public IClientConnector { 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 + */ TcpSocketClient(const std::string& ipToConnect, const unsigned int &port); - virtual ~TcpSocketClient(); + /** + * @brief ~TcpSocketClient, the destructor of TcpSocketClient + */ + virtual ~TcpSocketClient(); + /** + * @brief The IClientConnector::SendRPCMessage method overload. + * @param message The message to send + * @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); private: - TcpSocketClientPrivate *realSocket; + TcpSocketClientPrivate *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 index e97f679d..767eecfe 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h +++ b/src/jsonrpccpp/client/connectors/tcpsocketclientprivate.h @@ -15,6 +15,9 @@ namespace jsonrpc { + /** + * This class is an interface to the real implementation of TcpSocketClient. Kind of a strategy design pattern. + */ class TcpSocketClientPrivate : public IClientConnector { }; diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index d43eac01..92058748 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -16,16 +16,39 @@ namespace jsonrpc { + /** + * This class is the windows implementation of TCPSocketClient. + * It uses the Winsock2 API to performs its job. + */ class WindowsTcpSocketClient : public TcpSocketClientPrivate { public: + /** + * @brief WindowsTcpSocketClient, constructor of the Windows implementation of class TcpSocketClient + * @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 + */ WindowsTcpSocketClient(const std::string& ipToConnect, 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 ipToConnect; - unsigned int port; + std::string ipToConnect; /*!< 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); }; diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index 427da388..19ace6a2 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -25,42 +25,117 @@ namespace jsonrpc { /** - * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. - */ + * 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 TcpSocketServerPrivate { public: /** - * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer - * @param socket_path, a string containing the path to the unix socket - */ + * @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); - + /** + * @brief The real implementation TcpSocketServer::StartListening method. + * + * 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(); + /** + * @brief The real implementation TcpSocketServer::StopListening method. + * + * 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(); + /** + * @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); private: - bool running; - std::string ipToBind; - unsigned int port; - int socket_fd; - struct sockaddr_in address; + 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; + 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); - void ListenLoop(); + /** + * @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*/ + /** + * @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); + /** + * @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(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 + * 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(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(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(int fd); }; diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.h b/src/jsonrpccpp/server/connectors/tcpsocketserver.h index 54870aee..accaa232 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.h @@ -17,28 +17,64 @@ namespace jsonrpc { /** - * This class provides an embedded Tcp Socket Server,to handle incoming Requests. - */ + * 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: /** - * @brief TcpSocketServer, constructor for the included TcpSocketServer - * @param ipToBind, a string containing the ip of the interface to bind to. - * @param port, the port that the server will listen to. - */ + * @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); /** - * @brief ~TcpSocketServer, destructor for the included TcpSocketServer - */ + * @brief ~TcpSocketServer, the destructor of TcpSocketServer + */ ~TcpSocketServer(); + /** + * @brief The AbstractServerConnector::StartListening method overload. + * + * 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(); + /** + * @brief The AbstractServerConnector::StopListening method overload. + * + * 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(); - + + /** + * @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); private: - TcpSocketServerPrivate *realSocket; + TcpSocketServerPrivate *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h b/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h index 53150a06..8082a70f 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h +++ b/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h @@ -17,8 +17,8 @@ namespace jsonrpc { /** - * This interface allows to abstract the real TcpSocketServer, either it be Windows, Linux or else. - */ + * This class is an interface to the real implementation of TcpSocketServer. Kind of a strategy design pattern. + */ class TcpSocketServerPrivate : public AbstractServerConnector { }; diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index 77e0f177..7942c505 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -19,43 +19,121 @@ namespace jsonrpc { /** - * This class provides an embedded Unix Domain Socket Server,to handle incoming Requests. - */ + * 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 TcpSocketServerPrivate { public: /** - * @brief UnixDomainSocketServer, constructor for the included UnixDomainSocketServer - * @param socket_path, a string containing the path to the unix socket - */ + * @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); + /** + * @brief ~WindowsTcpSocketServer, the destructor of WindowsTcpSocketServer + */ ~WindowsTcpSocketServer(); - + /** + * @brief The real implementation TcpSocketServer::StartListening method. + * + * 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(); + /** + * @brief The real implementation TcpSocketServer::StopListening method. + * + * 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(); + /** + * @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); private: - bool running; - std::string ipToBind; - unsigned int port; - SOCKET socket_fd; - SOCKADDR_IN address; + 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; + 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); + /** + * @brief The method that launches the listenning loop + */ void ListenLoop(); struct GenerateResponseParameters { WindowsTcpSocketServer *instance; SOCKET connection_fd; - }; - static DWORD WINAPI GenerateResponse(LPVOID lp_data); + }; /*!< 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(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 + * 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(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(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(SOCKET fd); }; From 1d0185832b45e8c0b0199173f4f651e11f6acdf6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 15:52:46 +0200 Subject: [PATCH 075/114] Improved Windows Tcp Socket Client implementation to resolve hostname. --- .../connectors/windowstcpsocketclient.cpp | 204 +++++++++++------- .../connectors/windowstcpsocketclient.h | 10 +- 2 files changed, 138 insertions(+), 76 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index beb57bd4..51dff053 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -11,8 +11,9 @@ #include #include #include -#include -#include +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x501 +#include #define BUFFER_SIZE 64 #ifndef DELIMITER_CHAR @@ -22,8 +23,8 @@ using namespace jsonrpc; using namespace std; -WindowsTcpSocketClient::WindowsTcpSocketClient(const std::string& ipToConnect, const unsigned int &port) : - ipToConnect(ipToConnect), +WindowsTcpSocketClient::WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port) : + hostToConnect(hostToConnect), port(port) { } @@ -34,79 +35,13 @@ WindowsTcpSocketClient::~WindowsTcpSocketClient() void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - SOCKADDR_IN address; - int socket_fd, nbytes; + SOCKET socket_fd = this->Connect(); char buffer[BUFFER_SIZE]; - socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd < 0) - { - 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; - } - cerr << message << endl; - 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(this->ipToConnect.c_str()); - address.sin_port = htons(this->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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - bool fullyWritten = false; string toSend = message; do { - ssize_t byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); + int byteWritten = send(socket_fd, toSend.c_str(), toSend.size(), 0); if(byteWritten == -1) { string message = "send() failed"; @@ -150,7 +85,7 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str do { - nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); if(nbytes == -1) { string message = "recv() failed"; @@ -208,6 +143,129 @@ string WindowsTcpSocketClient::GetErrorMessage(const int& e) 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; + char *port = new char[6]; + port = itoa(this->port, port, 10); + DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + delete port; + 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; + } + } + } + + if(!foundValidIp) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); + + 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; + } + cerr << message << endl; + 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; + } + cerr << message << endl; + 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); +} + //This is inspired from SFML to manage Winsock initialization. Thanks to them! ( http://www.sfml-dev.org/ ). struct ClientSocketInitializer { diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index 92058748..aaa18918 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -13,6 +13,7 @@ #include #include #include "tcpsocketclientprivate.h" +#include namespace jsonrpc { @@ -25,10 +26,10 @@ namespace jsonrpc public: /** * @brief WindowsTcpSocketClient, constructor of the Windows implementation of class TcpSocketClient - * @param ipToConnect The ipv4 address on which the client should try to connect + * @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& ipToConnect, const unsigned int &port); + WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); /** * @brief ~WindowsTcpSocketClient, the destructor of WindowsTcpSocketClient */ @@ -42,7 +43,7 @@ namespace jsonrpc virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); private: - std::string ipToConnect; /*!< The ipv4 address on which the client should try to connect*/ + 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. @@ -50,6 +51,9 @@ namespace jsonrpc * @return The message matching the error value */ static std::string GetErrorMessage(const int &e); + SOCKET Connect() throw (JsonRpcException); + SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); + bool IsIpv4Address(const std::string& ip); }; } /* namespace jsonrpc */ From 086d90f78970d365366af98451df9c84bc8f14eb Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 15:53:44 +0200 Subject: [PATCH 076/114] Improved tcp socketconnectors example --- src/examples/tcpsocketclient.cpp | 20 +++++++++++--------- src/examples/tcpsocketserver.cpp | 13 ++++++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/examples/tcpsocketclient.cpp b/src/examples/tcpsocketclient.cpp index cdaea952..98a4a3e0 100644 --- a/src/examples/tcpsocketclient.cpp +++ b/src/examples/tcpsocketclient.cpp @@ -15,22 +15,24 @@ using namespace std; int main(int argc, char** argv) { - string ip; + string host; unsigned int port; if(argc == 3) { - ip = string(argv[1]); - port = atoi(argv[2]); - cout << "Params are :" << endl; - cout << "\t ip: " << ip << endl; - cout << "\t port: " << port << endl; + host = string(argv[1]); + port = atoi(argv[2]); } else { - ip = "127.0.0.1"; - port = 6543; + host = "127.0.0.1"; + port = 6543; } - TcpSocketClient client(ip, port); + + cout << "Params are :" << endl; + cout << "\t host: " << host << endl; + cout << "\t port: " << port << endl; + + TcpSocketClient client(host, port); Client c(client); Json::Value params; diff --git a/src/examples/tcpsocketserver.cpp b/src/examples/tcpsocketserver.cpp index 6cf238d9..25d1d54c 100644 --- a/src/examples/tcpsocketserver.cpp +++ b/src/examples/tcpsocketserver.cpp @@ -47,18 +47,21 @@ int main(int argc, char** argv) string ip; unsigned int port; - if(argc == 3) { + if(argc == 3) + { ip = string(argv[1]); port = atoi(argv[2]); - cout << "Params are :" << endl; - cout << "\t ip: " << ip << endl; - cout << "\t port: " << port << endl; } - else { + else + { ip = "127.0.0.1"; port = 6543; } + cout << "Params are :" << endl; + cout << "\t ip: " << ip << endl; + cout << "\t port: " << port << endl; + TcpSocketServer server(ip, port); SampleServer serv(server); if (serv.StartListening()) From 702a368ba2e0a63aebd9dd7743ced86c37b2b2a7 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 16:33:31 +0200 Subject: [PATCH 077/114] Added hostname resolving to Linux Tcp Socket Client implementation. --- .../connectors/linuxtcpsocketclient.cpp | 182 ++++++++++++------ .../client/connectors/linuxtcpsocketclient.h | 9 +- 2 files changed, 128 insertions(+), 63 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index c74a9ea5..92437ab4 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -9,11 +9,13 @@ #include "linuxtcpsocketclient.h" #include +#include #include #include #include #include #include +#include #include #include #include @@ -26,9 +28,9 @@ using namespace jsonrpc; using namespace std; -LinuxTcpSocketClient::LinuxTcpSocketClient(const std::string& ipToConnect, const unsigned int &port) : +LinuxTcpSocketClient::LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port) : TcpSocketClientPrivate(), - ipToConnect(ipToConnect), + hostToConnect(hostToConnect), port(port) { } @@ -39,63 +41,8 @@ LinuxTcpSocketClient::~LinuxTcpSocketClient() void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - sockaddr_in address; - int socket_fd, nbytes; - char buffer[BUFFER_SIZE]; - 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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } - - memset(&address, 0, sizeof(sockaddr_in)); - - address.sin_family = AF_INET; - inet_aton(this->ipToConnect.c_str(), &(address.sin_addr)); - address.sin_port = htons(this->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; - } - cerr << message << endl; - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); - } + int socket_fd = this->Connect(); + char buffer[BUFFER_SIZE]; bool fullyWritten = false; string toSend = message; @@ -142,7 +89,7 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin do { - nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); if(nbytes == -1) { string message = "recv() failed"; @@ -175,3 +122,118 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin 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; + char *port = new char[6]; + snprintf(port, 6, "%d", this->port); + int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + delete port; + 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; + } + cerr << message << endl; + 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; + } + cerr << message << endl; + 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); +} \ No newline at end of file diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h index e689d5a8..f506fb4c 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -25,10 +25,10 @@ namespace jsonrpc public: /** * @brief LinuxTcpSocketClient, constructor of the Linux/UNIX implementation of class TcpSocketClient - * @param ipToConnect The ipv4 address on which the client should try to connect + * @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& ipToConnect, const unsigned int &port); + LinuxTcpSocketClient(const std::string& hostToConnect, const unsigned int &port); /** * @brief ~LinuxTcpSocketClient, the destructor of LinuxTcpSocketClient */ @@ -42,8 +42,11 @@ namespace jsonrpc virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException); private: - std::string ipToConnect; /*!< The ipv4 address on which the client should try to connect*/ + 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*/ + int Connect() throw (JsonRpcException); + int Connect(const std::string& ip, const int& port) throw (JsonRpcException); + bool IsIpv4Address(const std::string& ip); }; } /* namespace jsonrpc */ From ef4c97602d0d7cb17ab61dc0999c4630fca26df6 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 16:38:03 +0200 Subject: [PATCH 078/114] Autoindent with vim. --- .../connectors/linuxtcpsocketclient.cpp | 107 +++++++++--------- .../client/connectors/linuxtcpsocketclient.h | 42 +++---- .../connectors/windowstcpsocketclient.cpp | 105 ++++++++--------- .../connectors/windowstcpsocketclient.h | 52 ++++----- 4 files changed, 156 insertions(+), 150 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 92437ab4..e9257f6e 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -41,8 +41,8 @@ LinuxTcpSocketClient::~LinuxTcpSocketClient() void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - int socket_fd = this->Connect(); - char buffer[BUFFER_SIZE]; + int socket_fd = this->Connect(); + char buffer[BUFFER_SIZE]; bool fullyWritten = false; string toSend = message; @@ -125,56 +125,59 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin 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; - char *port = new char[6]; - snprintf(port, 6, "%d", this->port); - int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - delete port; - 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; - } + 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 = new char[6]; + snprintf(port, 6, "%d", this->port); + int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + delete port; + 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; + sockaddr_in address; int socket_fd; socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 0) @@ -229,11 +232,11 @@ int LinuxTcpSocketClient::Connect(const string& ip, const int& port) throw (Json cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } - return socket_fd; + return socket_fd; } bool LinuxTcpSocketClient::IsIpv4Address(const std::string& ip) { - struct in_addr addr; - return (inet_aton(ip.c_str(), &addr) != 0); -} \ No newline at end of file + 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 f506fb4c..8a3b9ad9 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -16,37 +16,37 @@ namespace jsonrpc { - /** - * This class is the Linux/UNIX implementation of TCPSocketClient. - * It uses the POSIX socket API to performs its job. - */ + /** + * This class is the Linux/UNIX implementation of TCPSocketClient. + * It uses the POSIX socket API to performs its job. + */ class LinuxTcpSocketClient : public TcpSocketClientPrivate { 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 - */ + /** + * @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 - */ + /** + * @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 encounter with socket manipulation (see message of exception for more information about what happened). - */ + /** + * @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*/ - int Connect() throw (JsonRpcException); - int Connect(const std::string& ip, const int& port) throw (JsonRpcException); - bool IsIpv4Address(const std::string& ip); + int Connect() throw (JsonRpcException); + int Connect(const std::string& ip, const int& port) throw (JsonRpcException); + bool IsIpv4Address(const std::string& ip); }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index 51dff053..87698017 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -35,7 +35,7 @@ WindowsTcpSocketClient::~WindowsTcpSocketClient() void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) { - SOCKET socket_fd = this->Connect(); + SOCKET socket_fd = this->Connect(); char buffer[BUFFER_SIZE]; bool fullyWritten = false; string toSend = message; @@ -85,7 +85,7 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str do { - int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); + int nbytes = recv(socket_fd, buffer, BUFFER_SIZE, 0); if(nbytes == -1) { string message = "recv() failed"; @@ -145,57 +145,60 @@ string WindowsTcpSocketClient::GetErrorMessage(const int& e) 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; - char *port = new char[6]; - port = itoa(this->port, port, 10); - DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - delete port; - 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; - } - } - } - - if(!foundValidIp) - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); - - return socket_fd; - } + 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 = new char[6]; + port = itoa(this->port, port, 10); + DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); + delete port; + 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; + } + } + } + + if(!foundValidIp) + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Hostname resolved but connection was refused on the given port."); + + return socket_fd; + } } SOCKET WindowsTcpSocketClient::Connect(const string& ip, const int& port) throw (JsonRpcException) { - SOCKADDR_IN address; + SOCKADDR_IN address; SOCKET socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd == INVALID_SOCKET) { @@ -258,12 +261,12 @@ SOCKET WindowsTcpSocketClient::Connect(const string& ip, const int& port) throw cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } - return socket_fd; + 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/ ). diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index aaa18918..91897634 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -17,43 +17,43 @@ namespace jsonrpc { - /** - * This class is the windows implementation of TCPSocketClient. - * It uses the Winsock2 API to performs its job. - */ + /** + * This class is the windows implementation of TCPSocketClient. + * It uses the Winsock2 API to performs its job. + */ class WindowsTcpSocketClient : public TcpSocketClientPrivate { 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 - */ + /** + * @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 - */ + /** + * @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). - */ + /** + * @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 - */ + /** + * @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); - SOCKET Connect() throw (JsonRpcException); - SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); - bool IsIpv4Address(const std::string& ip); + SOCKET Connect() throw (JsonRpcException); + SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException); + bool IsIpv4Address(const std::string& ip); }; } /* namespace jsonrpc */ From a0e47998cbedc84bb06133241dfa7bef86566d96 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 16:50:28 +0200 Subject: [PATCH 079/114] Added option REUSEADDR to listenning socket (helps to fast reuse of binded socket) on Linux Tcp Socket Server implemeantetion. --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 0c75468a..a5c1ea1d 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -54,6 +54,8 @@ bool LinuxTcpSocketServer::StartListening() } 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)); From aa8784d7dac4ac007e8caf0fb37519a45281ea27 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 16:50:48 +0200 Subject: [PATCH 080/114] Added option REUSEADDR to listening socket (helps to fast reuse of binded socket) on Windows Tcp Socket Server implemeantetion. --- src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 22270b0f..6b626f3e 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -54,6 +54,8 @@ bool WindowsTcpSocketServer::StartListening() } unsigned long nonBlocking = 1; ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking + 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(SOCKADDR_IN)); From 7733a3086d975eb51bc1ee52c7bbae252170b7af Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:02:34 +0200 Subject: [PATCH 081/114] Made some method parameter passed as const references (avoid copy passing for performance on calls) on Linux Tcp Socket Server implementation. --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 8 ++++---- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index a5c1ea1d..f968a869 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -201,7 +201,7 @@ void* LinuxTcpSocketServer::GenerateResponse(void *p_data) } -bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) +bool LinuxTcpSocketServer::WriteToSocket(const int& fd, const string& toWrite) { bool fullyWritten = false; bool errorOccured = false; @@ -226,7 +226,7 @@ bool LinuxTcpSocketServer::WriteToSocket(int fd, const string& toWrite) return fullyWritten && !errorOccured; } -bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) +bool LinuxTcpSocketServer::WaitClientClose(const int& fd, const int &timeout) { bool ret = false; int i = 0; @@ -240,7 +240,7 @@ bool LinuxTcpSocketServer::WaitClientClose(int fd, const int &timeout) return ret; } -int LinuxTcpSocketServer::CloseByReset(int fd) +int LinuxTcpSocketServer::CloseByReset(const int& fd) { struct linger so_linger; so_linger.l_onoff = 1; @@ -253,7 +253,7 @@ int LinuxTcpSocketServer::CloseByReset(int fd) return close(fd); } -int LinuxTcpSocketServer::CleanClose(int fd) +int LinuxTcpSocketServer::CleanClose(const int& fd) { if(WaitClientClose(fd)) { diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index 19ace6a2..264070f3 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -108,7 +108,7 @@ namespace jsonrpc * @param toSend The message to send over socket * @returns A boolean indicating the success or the failure of the operation */ - bool WriteToSocket(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 * @@ -119,7 +119,7 @@ namespace jsonrpc * @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(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 * @@ -127,7 +127,7 @@ namespace jsonrpc * @param fd The file descriptor of the socket that should be reset * @returns The return value of POSIX close() method */ - int CloseByReset(int fd); + int CloseByReset(const int& fd); /** * @brief A method that cleanly close a socket by avoid TIME_WAIT state * @@ -136,7 +136,7 @@ namespace jsonrpc * @param fd The file descriptor of the socket that should be cleanly closed * @returns The return value of POSIX close() method */ - int CleanClose(int fd); + int CleanClose(const int& fd); }; } /* namespace jsonrpc */ From 6052fa1acadd73a87456463d54dc82aa4e99298d Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:04:18 +0200 Subject: [PATCH 082/114] Made some method parameter passed as const references (avoid copy passing for performance on calls) on Windows Tcp Socket Server implementation. --- .../server/connectors/windowstcpsocketserver.cpp | 8 ++++---- src/jsonrpccpp/server/connectors/windowstcpsocketserver.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 6b626f3e..2580f62f 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -207,7 +207,7 @@ DWORD WINAPI WindowsTcpSocketServer::GenerateResponse(LPVOID lp_data) 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(SOCKET fd, const string& toWrite) +bool WindowsTcpSocketServer::WriteToSocket(const SOCKET& fd, const string& toWrite) { bool fullyWritten = false; bool errorOccured = false; @@ -232,7 +232,7 @@ bool WindowsTcpSocketServer::WriteToSocket(SOCKET fd, const string& toWrite) return fullyWritten && !errorOccured; } -bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) +bool WindowsTcpSocketServer::WaitClientClose(const SOCKET& fd, const int &timeout) { bool ret = false; int i = 0; @@ -246,7 +246,7 @@ bool WindowsTcpSocketServer::WaitClientClose(SOCKET fd, const int &timeout) return ret; } -int WindowsTcpSocketServer::CloseByReset(SOCKET fd) +int WindowsTcpSocketServer::CloseByReset(const SOCKET& fd) { struct linger so_linger; so_linger.l_onoff = 1; @@ -259,7 +259,7 @@ int WindowsTcpSocketServer::CloseByReset(SOCKET fd) return closesocket(fd); } -int WindowsTcpSocketServer::CleanClose(SOCKET fd) +int WindowsTcpSocketServer::CleanClose(const SOCKET& fd) { if(WaitClientClose(fd)) { diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index 7942c505..3f379e89 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -106,7 +106,7 @@ namespace jsonrpc * @param toSend The message to send over socket * @returns A boolean indicating the success or the failure of the operation */ - bool WriteToSocket(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 * @@ -117,7 +117,7 @@ namespace jsonrpc * @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(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 * @@ -125,7 +125,7 @@ namespace jsonrpc * @param fd The file descriptor of the socket that should be reset * @returns The return value of POSIX close() method */ - int CloseByReset(SOCKET fd); + int CloseByReset(const SOCKET& fd); /** * @brief A method that cleanly close a socket by avoid TIME_WAIT state * @@ -134,7 +134,7 @@ namespace jsonrpc * @param fd The file descriptor of the socket that should be cleanly closed * @returns The return value of POSIX close() method */ - int CleanClose(SOCKET fd); + int CleanClose(const SOCKET& fd); }; } /* namespace jsonrpc */ From a7d7eee6e5a1fb4db687cd4467e6e66363e74c97 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:11:41 +0200 Subject: [PATCH 083/114] Added documentation for new private methods of Linux Tcp Socket Client implementation. --- .../client/connectors/linuxtcpsocketclient.h | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h index 8a3b9ad9..5d05315f 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.h @@ -37,15 +37,41 @@ namespace jsonrpc * @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). + * @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); }; From 23a1dc5b0a7eedf987bcd38e7540f04bf72173ae Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:12:00 +0200 Subject: [PATCH 084/114] Added documentation for new private methods of Windows Tcp Socket Client implementation. --- .../connectors/windowstcpsocketclient.h | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h index 91897634..a1da2e96 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.h @@ -51,8 +51,34 @@ namespace jsonrpc * @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); }; From c21741cd9b1739bd1110bf87d5298872285f4d4c Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:38:25 +0200 Subject: [PATCH 085/114] Modified code to remove a warning message on compilation. --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index f968a869..80f7dc2c 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -230,7 +230,7 @@ bool LinuxTcpSocketServer::WaitClientClose(const int& fd, const int &timeout) { bool ret = false; int i = 0; - while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) + while((recv(fd, NULL, 0, 0) != 0) && i < timeout) { usleep(1); ++i; From 258c65ec410546d2e697df4247ba6f3829ac1357 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:40:21 +0200 Subject: [PATCH 086/114] Corrected an error in code (type conversion) and a warning message. --- src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 2580f62f..69e3a605 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -55,7 +55,7 @@ bool WindowsTcpSocketServer::StartListening() unsigned long nonBlocking = 1; ioctlsocket(this->socket_fd, FIONBIO, &nonBlocking); //Set non blocking int reuseaddr = 1; - setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); + 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)); @@ -236,7 +236,7 @@ bool WindowsTcpSocketServer::WaitClientClose(const SOCKET& fd, const int &timeou { bool ret = false; int i = 0; - while((recv(fd, NULL, NULL, 0) != 0) && i < timeout) + while((recv(fd, NULL, 0, 0) != 0) && i < timeout) { Sleep(1); ++i; From 84ae900826a32c02242dfc4e3cff95e755a90b5d Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 17:59:12 +0200 Subject: [PATCH 087/114] Added contribution specific information. --- AUTHORS.md | 1 + README.md | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 0d95cd08..081b7f70 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -31,6 +31,7 @@ Marek Kotewicz Alexandre Poirot + added client and server connectors that use Unix Domain Sockets + adapted build file to generate pkg-config file for this lib. ++ added client and server connectors that use Tcp Sockets on Linux and Windows (uses native socket and thread API on each OS) Bugfixes (chronological order) ============================== diff --git a/README.md b/README.md index 458937ac..e017642b 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,11 @@ It is fully JSON-RPC [2.0 & 1.0 compatible](http://www.jsonrpc.org/specification ![libjson-rpc-cpp logo](https://github.com/cinemast/libjson-rpc-cpp/blob/master/dev/artwork/logo.png?raw=true) -**5 good reasons for using libjson-rpc-cpp in your next RPC project** +**6 good reasons for using libjson-rpc-cpp in your next RPC project** - Full JSON-RPC 2.0 & 1.0 Client and Server Support. - jsonrpcstub - a tool that generates stub-classes for your JSON-RPC client AND server applications. - Ready to use HTTP server and client to provide simple interfaces for your JSON-RPC application. +- Ready to use TCP server and client to provide simple interfaces for your JSON-RPC application. See TCP Connectors below for more information. - Cross platform build support and [precompiled binaries for WIN32](http://spiessknafl.at/libjson-rpc-cpp). - Super liberal [MIT-License](http://en.wikipedia.org/wiki/MIT_License). @@ -27,6 +28,11 @@ Overview ========= ![libjson-rpc-cpp logo](https://github.com/cinemast/libjson-rpc-cpp/blob/develop/dev/artwork/overview.png?raw=true) +**TCP Connectors** +The provided TCP Connectors have os-dependent implementation but it is transparent on use. Just use TCPSocketClient and TCPSocketServer classes without bothering about whether you're running on Linux or Windows! +The TCP Server Connector can bind to a specific address and port. It processes each client requests in a new thread. +The TCP Client Connector can connect directly to an address on a specific port but it also works with host names : it automatically performs the name resolving. + Install the framework ===================== @@ -111,6 +117,8 @@ Default configuration should be fine for most systems, but here are available co - `-DHTTP_CLIENT=NO` disable the curl client. - `-DUNIX_DOMAIN_SOCKET_SERVER=NO` disable the unix domain socket server connector. - `-DUNIX_DOMAIN_SOCKET_CLIENT=NO` disable the unix domain socket client connector. +- `-DTCP_SOCKET_SERVER=NO` disable the tcp socket server connector. +- `-DTCP_SOCKET_CLIENT=NO` disable the tcp socket client connector. Using the framework =================== From c41a98e24ab4ae6dfe4586e3835d3bc9f70efc19 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Thu, 30 Jul 2015 18:03:52 +0200 Subject: [PATCH 088/114] Corrected wrong new line after title. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e017642b..6c7f0509 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Overview ![libjson-rpc-cpp logo](https://github.com/cinemast/libjson-rpc-cpp/blob/develop/dev/artwork/overview.png?raw=true) **TCP Connectors** + The provided TCP Connectors have os-dependent implementation but it is transparent on use. Just use TCPSocketClient and TCPSocketServer classes without bothering about whether you're running on Linux or Windows! The TCP Server Connector can bind to a specific address and port. It processes each client requests in a new thread. The TCP Client Connector can connect directly to an address on a specific port but it also works with host names : it automatically performs the name resolving. From b7332e1ab35bb62292dd04aec07deb66030d3dd4 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 31 Jul 2015 10:01:42 +0200 Subject: [PATCH 089/114] Removing some -Wsign-comparison warning on compilation --- src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp | 2 +- src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp | 2 +- src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp | 2 +- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index e9257f6e..167d34b8 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -78,7 +78,7 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } - else if(byteWritten < toSend.size()) + else if(static_cast(byteWritten) < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index ea2cf821..8b63274a 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -64,7 +64,7 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str do { ssize_t byteWritten = write(socket_fd, toSend.c_str(), toSend.size()); - if(byteWritten < toSend.size()) + if(static_cast(byteWritten) < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index 87698017..c3a557f9 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -74,7 +74,7 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } - else if(byteWritten < toSend.size()) + else if(static_cast(byteWritten) < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 80f7dc2c..ab159eff 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -214,7 +214,7 @@ bool LinuxTcpSocketServer::WriteToSocket(const int& fd, const string& toWrite) errorOccured = true; CleanClose(fd); } - else if(byteWritten < toSend.size()) + else if(static_cast(byteWritten) < toSend.size()) { int len = toSend.size() - byteWritten; toSend = toSend.substr(byteWritten + sizeof(char), len); From 543fbbd4f344346e29f41fd642a89ec215d697b5 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Fri, 31 Jul 2015 10:52:11 +0200 Subject: [PATCH 090/114] Fixing memleak in client (was not spotted before) --- src/jsonrpccpp/client/connectors/tcpsocketclient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp index f8fec595..874e0faa 100644 --- a/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/tcpsocketclient.cpp @@ -31,6 +31,11 @@ TcpSocketClient::TcpSocketClient(const std::string& ipToConnect, const unsigned TcpSocketClient::~TcpSocketClient() { + if(this->realSocket != NULL) + { + delete this->realSocket; + this->realSocket = NULL; + } } void TcpSocketClient::SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException) From c0544232cb306474e70c5036fd7cf33b9e574d82 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Tue, 4 Aug 2015 22:49:38 +0200 Subject: [PATCH 091/114] switch to c++11 --- cmake/CMakeCompilerSettings.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/CMakeCompilerSettings.cmake b/cmake/CMakeCompilerSettings.cmake index ef17165e..f8046529 100644 --- a/cmake/CMakeCompilerSettings.cmake +++ b/cmake/CMakeCompilerSettings.cmake @@ -1,7 +1,8 @@ # Set necessary compile and link flags if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wnon-virtual-dtor -fprofile-arcs -ftest-coverage -fPIC -O0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall -Wextra -Wnon-virtual-dtor -fprofile-arcs -ftest-coverage -fPIC -O0") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # TODO figure clang stuff to enable test-coverage # Instrument Program flow should be set to Yes From ce04bd489beb8b073f1ed48c0e22f4eca2b00ff9 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Tue, 4 Aug 2015 22:49:49 +0200 Subject: [PATCH 092/114] fix usage of hidden symbol --- src/jsonrpccpp/server/abstractprotocolhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsonrpccpp/server/abstractprotocolhandler.cpp b/src/jsonrpccpp/server/abstractprotocolhandler.cpp index 617403cd..23df5a7e 100644 --- a/src/jsonrpccpp/server/abstractprotocolhandler.cpp +++ b/src/jsonrpccpp/server/abstractprotocolhandler.cpp @@ -63,7 +63,7 @@ void AbstractProtocolHandler::ProcessRequest(const Json::Value &request, Json::V else { handler.HandleNotificationCall(method, request[KEY_REQUEST_PARAMETERS]); - response = Json::Value::null; + response = Json::nullValue; } } From 536774f1afc059c83c983326405486faae949bda Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 09:48:34 +0200 Subject: [PATCH 093/114] Fix reorder warning --- src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index ab159eff..93ecaf72 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -34,9 +34,9 @@ using namespace std; LinuxTcpSocketServer::LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : TcpSocketServerPrivate(), + running(false), ipToBind(ipToBind), - port(port), - running(false) + port(port) { } From ac70dd1d388cfa55d1511679caa752696d555e80 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 09:48:47 +0200 Subject: [PATCH 094/114] Fix README to keep it to 5 good reasons --- README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6c7f0509..5771c733 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,10 @@ It is fully JSON-RPC [2.0 & 1.0 compatible](http://www.jsonrpc.org/specification ![libjson-rpc-cpp logo](https://github.com/cinemast/libjson-rpc-cpp/blob/master/dev/artwork/logo.png?raw=true) -**6 good reasons for using libjson-rpc-cpp in your next RPC project** +**5 good reasons for using libjson-rpc-cpp in your next RPC project** - Full JSON-RPC 2.0 & 1.0 Client and Server Support. - jsonrpcstub - a tool that generates stub-classes for your JSON-RPC client AND server applications. -- Ready to use HTTP server and client to provide simple interfaces for your JSON-RPC application. -- Ready to use TCP server and client to provide simple interfaces for your JSON-RPC application. See TCP Connectors below for more information. +- Ready to use HTTP + TCP server and client to provide simple interfaces for your JSON-RPC application. - Cross platform build support and [precompiled binaries for WIN32](http://spiessknafl.at/libjson-rpc-cpp). - Super liberal [MIT-License](http://en.wikipedia.org/wiki/MIT_License). @@ -28,12 +27,6 @@ Overview ========= ![libjson-rpc-cpp logo](https://github.com/cinemast/libjson-rpc-cpp/blob/develop/dev/artwork/overview.png?raw=true) -**TCP Connectors** - -The provided TCP Connectors have os-dependent implementation but it is transparent on use. Just use TCPSocketClient and TCPSocketServer classes without bothering about whether you're running on Linux or Windows! -The TCP Server Connector can bind to a specific address and port. It processes each client requests in a new thread. -The TCP Client Connector can connect directly to an address on a specific port but it also works with host names : it automatically performs the name resolving. - Install the framework ===================== From 2d2bf052dda3291d5ed87a1c88f01132bc81c0d0 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 09:57:36 +0200 Subject: [PATCH 095/114] Removed cerrs from library parts. A library should never log something to the console --- .../client/connectors/linuxtcpsocketclient.cpp | 4 ---- .../client/connectors/unixdomainsocketclient.cpp | 2 -- .../client/connectors/windowstcpsocketclient.cpp | 8 ++------ src/jsonrpccpp/client/rpcprotocolclient.cpp | 14 ++++++++++++-- .../server/connectors/linuxtcpsocketserver.cpp | 3 --- .../server/connectors/unixdomainsocketserver.cpp | 7 ++----- .../server/connectors/windowstcpsocketserver.cpp | 7 ++----- 7 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 167d34b8..1f302fb4 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -75,7 +75,6 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin break; } close(socket_fd); - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } else if(static_cast(byteWritten) < toSend.size()) @@ -109,7 +108,6 @@ void LinuxTcpSocketClient::SendRPCMessage(const std::string& message, std::strin break; } close(socket_fd); - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } else @@ -196,7 +194,6 @@ int LinuxTcpSocketClient::Connect(const string& ip, const int& port) throw (Json message = strerror(err); break; } - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(sockaddr_in)); @@ -229,7 +226,6 @@ int LinuxTcpSocketClient::Connect(const string& ip, const int& port) throw (Json message = strerror(err); break; } - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } return socket_fd; diff --git a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp index 8b63274a..2e70a35d 100644 --- a/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/unixdomainsocketclient.cpp @@ -44,7 +44,6 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (socket_fd < 0) { - cerr << "Socket failed" << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not created unix domain socket"); } @@ -55,7 +54,6 @@ void UnixDomainSocketClient::SendRPCMessage(const std::string& message, std::str if(connect(socket_fd, (struct sockaddr *) &address, sizeof(sockaddr_un)) != 0) { - cerr << "connect failed" << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not connect to: " + this->path); } diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index c3a557f9..a11b7540 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -71,7 +71,6 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str break; } closesocket(socket_fd); - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } else if(static_cast(byteWritten) < toSend.size()) @@ -112,7 +111,6 @@ void WindowsTcpSocketClient::SendRPCMessage(const std::string& message, std::str break; } closesocket(socket_fd); - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } else @@ -222,7 +220,6 @@ SOCKET WindowsTcpSocketClient::Connect(const string& ip, const int& port) throw message = GetErrorMessage(err); break; } - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } memset(&address, 0, sizeof(SOCKADDR_IN)); @@ -258,7 +255,6 @@ SOCKET WindowsTcpSocketClient::Connect(const string& ip, const int& port) throw message = GetErrorMessage(err); break; } - cerr << message << endl; throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, message); } return socket_fd; @@ -278,7 +274,7 @@ struct ClientSocketInitializer WSADATA init; if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { - cerr << "An issue occured while WSAStartup executed." << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); } } @@ -287,7 +283,7 @@ struct ClientSocketInitializer { if(WSACleanup() != 0) { - cerr << "An issue occured while WSAClean executed." << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAClean executed."); } } }; diff --git a/src/jsonrpccpp/client/rpcprotocolclient.cpp b/src/jsonrpccpp/client/rpcprotocolclient.cpp index 83564422..d1eb67ab 100644 --- a/src/jsonrpccpp/client/rpcprotocolclient.cpp +++ b/src/jsonrpccpp/client/rpcprotocolclient.cpp @@ -86,10 +86,20 @@ void RpcProtocolClient::BuildRequest(int id, const std::string &method, const Js void RpcProtocolClient::throwErrorException(const Json::Value &response) { if (response[KEY_ERROR].isMember(KEY_ERROR_MESSAGE) && response[KEY_ERROR][KEY_ERROR_MESSAGE].isString()) + { if (response[KEY_ERROR].isMember(KEY_ERROR_DATA)) + { throw JsonRpcException(response[KEY_ERROR][KEY_ERROR_CODE].asInt(), response[KEY_ERROR][KEY_ERROR_MESSAGE].asString(), response[KEY_ERROR][KEY_ERROR_DATA]); - throw JsonRpcException(response[KEY_ERROR][KEY_ERROR_CODE].asInt(), response[KEY_ERROR][KEY_ERROR_MESSAGE].asString()); - throw JsonRpcException(response[KEY_ERROR][KEY_ERROR_CODE].asInt()); + } + else + { + throw JsonRpcException(response[KEY_ERROR][KEY_ERROR_CODE].asInt(), response[KEY_ERROR][KEY_ERROR_MESSAGE].asString()); + } + } + else + { + throw JsonRpcException(response[KEY_ERROR][KEY_ERROR_CODE].asInt()); + } } bool RpcProtocolClient::ValidateResponse(const Json::Value& response) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 93ecaf72..64e49271 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -49,7 +49,6 @@ bool LinuxTcpSocketServer::StartListening() this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); if(this->socket_fd < 0) { - cerr << "socket() failed" << endl; return false; } @@ -66,13 +65,11 @@ bool LinuxTcpSocketServer::StartListening() if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_in)) != 0) { - cerr << "bind() failed" << endl; return false; } if(listen(this->socket_fd, 5) != 0) { - cerr << "listen() failed" << endl; return false; } //Launch listening loop there diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index c9a284c8..5c0652d5 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -46,7 +46,6 @@ bool UnixDomainSocketServer::StartListening() if(this->socket_fd < 0) { - cerr << "socket() failed" << endl; return false; } @@ -62,14 +61,12 @@ bool UnixDomainSocketServer::StartListening() if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(struct sockaddr_un)) != 0) { - cerr << "bind() failed" << endl; return false; } if(listen(this->socket_fd, 5) != 0) - { - cerr << "listen() failed" << endl; - return false; + { + return false; } //Launch listening loop there diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 69e3a605..574d4691 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -49,7 +49,6 @@ bool WindowsTcpSocketServer::StartListening() this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); if(this->socket_fd < 0) { - cerr << "socket() failed" << endl; return false; } unsigned long nonBlocking = 1; @@ -66,13 +65,11 @@ bool WindowsTcpSocketServer::StartListening() if(bind(this->socket_fd, reinterpret_cast(&(this->address)), sizeof(SOCKADDR_IN)) != 0) { - cerr << "bind() failed" << endl; return false; } if(listen(this->socket_fd, 5) != 0) { - cerr << "listen() failed" << endl; return false; } //Launch listening loop there @@ -279,7 +276,7 @@ struct ServerSocketInitializer WSADATA init; if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { - cerr << "An issue occured while WSAStartup executed." << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); } } @@ -287,7 +284,7 @@ struct ServerSocketInitializer { if(WSACleanup() != 0) { - cerr << "An issue occured while WSAClean executed." << endl; + throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAClean executed."); } } }; From 13e8955acaedfbac4fbba00b0a7b1564d0d863d1 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 09:59:44 +0200 Subject: [PATCH 096/114] do not use heap allocation, where stack is possible. --- src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp | 3 +-- src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp index 1f302fb4..631998dd 100644 --- a/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/linuxtcpsocketclient.cpp @@ -135,10 +135,9 @@ int LinuxTcpSocketClient::Connect() throw (JsonRpcException) hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - char *port = new char[6]; + char port[6]; snprintf(port, 6, "%d", this->port); int retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - delete port; if(retval != 0) throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); bool foundValidIp = false; diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index a11b7540..7d33fd24 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -155,10 +155,9 @@ SOCKET WindowsTcpSocketClient::Connect() throw (JsonRpcException) hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - char *port = new char[6]; + char port[6]; port = itoa(this->port, port, 10); DWORD retval = getaddrinfo(this->hostToConnect.c_str(), port, &hints, &result); - delete port; if(retval != 0) throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "Could not resolve hostname."); From a44a6aa2710ff2ac5372d853476685f35227ef0c Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:03:01 +0200 Subject: [PATCH 097/114] use cerr again, where exceptions are unsafe (destructors) --- src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp | 2 +- src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp index 7d33fd24..4ebdf6f3 100644 --- a/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp +++ b/src/jsonrpccpp/client/connectors/windowstcpsocketclient.cpp @@ -282,7 +282,7 @@ struct ClientSocketInitializer { if(WSACleanup() != 0) { - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAClean executed."); + cerr << "An issue occured while WSAClean executed." << endl; } } }; diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index 574d4691..e31d63ea 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -276,7 +276,7 @@ struct ServerSocketInitializer WSADATA init; if(WSAStartup(MAKEWORD(2, 2), &init) != 0) { - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); + JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAStartup executed."); } } @@ -284,7 +284,7 @@ struct ServerSocketInitializer { if(WSACleanup() != 0) { - throw JsonRpcException(Errors::ERROR_CLIENT_CONNECTOR, "An issue occured while WSAClean executed."); + cerr << "An issue occured while WSAClean executed." << endl; } } }; From 66d48925c23450f6032d30de4740378fb980964e Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:06:33 +0200 Subject: [PATCH 098/114] removed duplicate pkg-config file --- CMakeLists.txt | 16 ---------------- libjson-rpc-cpp.pc.cmake | 11 ----------- 2 files changed, 27 deletions(-) delete mode 100644 libjson-rpc-cpp.pc.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a9985e1e..e735cedd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,22 +73,6 @@ endif() include_directories("${CMAKE_BINARY_DIR}/gen/") include_directories("${CMAKE_BINARY_DIR}/gen/jsonrpccpp/common") -#set pkg-config -find_package(PkgConfig) -get_filename_component(FULL_PATH_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} ABSOLUTE) -set(PROJECT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") -set(PKG_CONFIG_REQUIRES jsoncpp) -set(FULL_PATH_EXEC_PREFIX "${FULL_PATH_INSTALL_PREFIX}") -set(FULL_PATH_INCLUDEDIR "${FULL_PATH_INSTALL_PREFIX}/include") -set(FULL_PATH_LIBDIR "${FULL_PATH_INSTALL_PREFIX}/lib") - -CONFIGURE_FILE( - "${CMAKE_CURRENT_SOURCE_DIR}/libjson-rpc-cpp.pc.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/libjson-rpc-cpp.pc" -) - -INSTALL(FILES "${CMAKE_BINARY_DIR}/libjson-rpc-cpp.pc" - DESTINATION lib/pkgconfig) # the core framework add_subdirectory(src/jsonrpccpp) diff --git a/libjson-rpc-cpp.pc.cmake b/libjson-rpc-cpp.pc.cmake deleted file mode 100644 index 3008b3a0..00000000 --- a/libjson-rpc-cpp.pc.cmake +++ /dev/null @@ -1,11 +0,0 @@ -prefix=${FULL_PATH_INSTALL_PREFIX} -exec_prefix=${FULL_PATH_EXEC_PREFIX} -includedir=${FULL_PATH_INCLUDEDIR} -libdir=${FULL_PATH_LIBDIR} - -Name: libjson-rpc-cpp -Description: A C++ implementation of json-rpc. -Version: ${PROJECT_VERSION} -Requires: ${PKG_CONFIG_REQUIRES} -Libs: -L${FULL_PATH_LIBDIR} -ljsonrpccpp-common -ljsonrpccpp-server -ljsonrpccpp-client -Cflags: -I${FULL_PATH_INCLUDEDIR} From 97ecb4966b1925554a58e9b276c08e1d8660c0ad Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:10:05 +0200 Subject: [PATCH 099/114] possibly fixing valgrind error --- src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 5c0652d5..85456d43 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -131,6 +131,7 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { pthread_detach(pthread_self()); UnixDomainSocketServer *instance = reinterpret_cast(p_data);; + instance->running = true; instance->ListenLoop(); return NULL; } From f5b55f8f45ad744dcd764cbc19f2a2f144ed6851 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:16:57 +0200 Subject: [PATCH 100/114] add include path to ci.sh --- dev/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/ci.sh b/dev/ci.sh index aa967a6e..b2d39c1c 100755 --- a/dev/ci.sh +++ b/dev/ci.sh @@ -41,7 +41,7 @@ gcovr -x -r .. > ../reports/coverage.xml gcovr -r .. --html --html-details -o ../reports/coverage.html echo "Generating cppcheck report" -cppcheck --enable=all --xml ../src --xml-version=2 2> ../reports/cppcheck.xml +cppcheck -I ../src --enable=all --xml ../src --xml-version=2 2> ../reports/cppcheck.xml cd .. echo "Cleanup that mess" From 7509fbab589de3cd12c17cb0322cba5b8f073d03 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:19:20 +0200 Subject: [PATCH 101/114] trying to fix travis build --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 40702e8f..2d133ebd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,10 @@ before_install: - sudo make install && sudo ldconfig - cd .. && sudo rm -rf libmicrohttpd-0.9.38 - sudo pip install cpp-coveralls + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + - sudo apt-get update -qq + - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi + - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi env: - HTTP_SERVER=YES HTTP_CLIENT=YES COMPILE_STUBGEN=YES From ecde2ddff857fd1a0a5f21e705dd5fedadd952bd Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:21:05 +0200 Subject: [PATCH 102/114] excluding build and test from coverage --- dev/ci.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/ci.sh b/dev/ci.sh index b2d39c1c..dc59e981 100755 --- a/dev/ci.sh +++ b/dev/ci.sh @@ -37,8 +37,8 @@ valgrind --leak-check=full --xml=yes --xml-file=../reports/valgrind.xml ./bin/un echo "Generating coverage report" -gcovr -x -r .. > ../reports/coverage.xml -gcovr -r .. --html --html-details -o ../reports/coverage.html +gcovr -e "build" -e "src/test" -x -r .. > ../reports/coverage.xml +gcovr -e "build" -e "src/test" -r .. --html --html-details -o ../reports/coverage.html echo "Generating cppcheck report" cppcheck -I ../src --enable=all --xml ../src --xml-version=2 2> ../reports/cppcheck.xml From 8a93960b86ea0c73c38c2064c46b95940de38384 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:25:15 +0200 Subject: [PATCH 103/114] described planned features in changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6358a9a8..bbce7f06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in v1.0.0 +----------------- +- Change: Requiring C++11 support (gcc >= 4.8) +- NEW: TCP Server + Client connectors +- TODO: use PIMPL to keep the ABI/API more stable + Changes in v0.6.0 ----------------- - NEW: pkg-config files for all shared libraries From 58d0b7b4cc35d02c2cd73a511e083f1cf5b83d3d Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 10:55:32 +0200 Subject: [PATCH 104/114] fix testcase for now --- cmake/CMakeCompilerSettings.cmake | 2 +- src/examples/stubclient.cpp | 1 + src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CMakeCompilerSettings.cmake b/cmake/CMakeCompilerSettings.cmake index f8046529..d60915b8 100644 --- a/cmake/CMakeCompilerSettings.cmake +++ b/cmake/CMakeCompilerSettings.cmake @@ -2,7 +2,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall -Wextra -Wnon-virtual-dtor -fprofile-arcs -ftest-coverage -fPIC -O0") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -Wall -Wformat -Wno-format-extra-args -Wformat-security -Wformat-nonliteral -Wformat=2 -Wextra -Wnon-virtual-dtor -fprofile-arcs -ftest-coverage -fPIC -O0") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # TODO figure clang stuff to enable test-coverage # Instrument Program flow should be set to Yes diff --git a/src/examples/stubclient.cpp b/src/examples/stubclient.cpp index 014ab434..3b3d8151 100644 --- a/src/examples/stubclient.cpp +++ b/src/examples/stubclient.cpp @@ -17,6 +17,7 @@ using namespace std; int main() { + Json::Value a = 3; Json::Value b = "3"; diff --git a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp index 85456d43..5c0652d5 100644 --- a/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/unixdomainsocketserver.cpp @@ -131,7 +131,6 @@ void* UnixDomainSocketServer::LaunchLoop(void *p_data) { pthread_detach(pthread_self()); UnixDomainSocketServer *instance = reinterpret_cast(p_data);; - instance->running = true; instance->ListenLoop(); return NULL; } From f7322968d953d9effa86987833957b1b63fe9ab3 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 11:19:04 +0200 Subject: [PATCH 105/114] removing tcpsocketserverprivate.h --- src/jsonrpccpp/CMakeLists.txt | 1 - .../connectors/linuxtcpsocketserver.cpp | 2 +- .../server/connectors/linuxtcpsocketserver.h | 4 +-- .../server/connectors/tcpsocketserver.h | 4 +-- .../connectors/tcpsocketserverprivate.h | 27 ------------------- 5 files changed, 4 insertions(+), 34 deletions(-) delete mode 100644 src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 97a6e7b7..9952bf54 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -78,7 +78,6 @@ endif() if (TCP_SOCKET_CLIENT) list(APPEND client_connector_header "client/connectors/tcpsocketclient.h") list(APPEND client_connector_source "client/connectors/tcpsocketclient.cpp") - list(APPEND client_connector_header "client/connectors/tcpsocketclientprivate.h") if (WIN32) list(APPEND client_connector_header "client/connectors/windowstcpsocketclient.h") list(APPEND client_connector_source "client/connectors/windowstcpsocketclient.cpp") diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp index 64e49271..d25edc04 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.cpp @@ -33,7 +33,7 @@ using namespace std; #endif //DELIMITER_CHAR LinuxTcpSocketServer::LinuxTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : - TcpSocketServerPrivate(), + AbstractServerConnector(), running(false), ipToBind(ipToBind), port(port) diff --git a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h index 264070f3..d9461d0b 100644 --- a/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/linuxtcpsocketserver.h @@ -20,7 +20,7 @@ #include #include -#include "tcpsocketserverprivate.h" +#include "../abstractserverconnector.h" namespace jsonrpc { @@ -29,7 +29,7 @@ namespace jsonrpc * 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 TcpSocketServerPrivate + class LinuxTcpSocketServer: public AbstractServerConnector { public: /** diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserver.h b/src/jsonrpccpp/server/connectors/tcpsocketserver.h index accaa232..2c9c69f7 100644 --- a/src/jsonrpccpp/server/connectors/tcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/tcpsocketserver.h @@ -10,8 +10,6 @@ #ifndef JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ #define JSONRPC_CPP_TCPSOCKETSERVERCONNECTOR_H_ -#include "tcpsocketserverprivate.h" - #include "../abstractserverconnector.h" namespace jsonrpc @@ -74,7 +72,7 @@ namespace jsonrpc bool SendResponse(const std::string& response, void* addInfo = NULL); private: - TcpSocketServerPrivate *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ + AbstractServerConnector *realSocket; /*!< A pointer to the real implementation of this class depending of running OS*/ }; } /* namespace jsonrpc */ diff --git a/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h b/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h deleted file mode 100644 index 8082a70f..00000000 --- a/src/jsonrpccpp/server/connectors/tcpsocketserverprivate.h +++ /dev/null @@ -1,27 +0,0 @@ -/************************************************************************* - * libjson-rpc-cpp - ************************************************************************* - * @file tcpsocketserverprivate.h - * @date 17.07.2015 - * @author Alexandre Poirot - * @license See attached LICENSE.txt - ************************************************************************/ - -#ifndef JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ -#define JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ - -#include "tcpsocketserverprivate.h" - -#include "../abstractserverconnector.h" - -namespace jsonrpc -{ - /** - * This class is an interface to the real implementation of TcpSocketServer. Kind of a strategy design pattern. - */ - class TcpSocketServerPrivate : public AbstractServerConnector - { - }; - -} /* namespace jsonrpc */ -#endif /* JSONRPC_CPP_TCPSOCKETSERVERPRIVATECONNECTOR_H_ */ From 2a09ea6d002316784a870751c73848dec47d10b3 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 11:19:52 +0200 Subject: [PATCH 106/114] fixing ci build --- dev/ci.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/ci.sh b/dev/ci.sh index dc59e981..5b6b1f44 100755 --- a/dev/ci.sh +++ b/dev/ci.sh @@ -7,7 +7,6 @@ build_configuration() { cd build cmake $1 .. make - make test mkdir -p root make DESTDIR=root install cd .. From b5e190b931bd9068c35425b415cb1647ae43ffc6 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Thu, 6 Aug 2015 11:35:02 +0200 Subject: [PATCH 107/114] removing left ofer private classes of tcpserver --- src/jsonrpccpp/CMakeLists.txt | 1 - src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp | 2 +- src/jsonrpccpp/server/connectors/windowstcpsocketserver.h | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index 9952bf54..b8f68d41 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -62,7 +62,6 @@ endif() if (TCP_SOCKET_SERVER) list(APPEND server_connector_header "server/connectors/tcpsocketserver.h") list(APPEND server_connector_source "server/connectors/tcpsocketserver.cpp") - list(APPEND server_connector_header "server/connectors/tcpsocketserverprivate.h") if (WIN32) list(APPEND server_connector_header "server/connectors/windowstcpsocketserver.h") list(APPEND server_connector_source "server/connectors/windowstcpsocketserver.cpp") diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp index e31d63ea..95dcbc2d 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.cpp @@ -29,7 +29,7 @@ using namespace std; #endif //DELIMITER_CHAR WindowsTcpSocketServer::WindowsTcpSocketServer(const std::string& ipToBind, const unsigned int &port) : - TcpSocketServerPrivate(), + AbstractServerConnector(), ipToBind(ipToBind), port(port), running(false) diff --git a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h index 3f379e89..88f0e80e 100644 --- a/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h +++ b/src/jsonrpccpp/server/connectors/windowstcpsocketserver.h @@ -14,7 +14,7 @@ #include #include -#include "tcpsocketserverprivate.h" +#include "../abstractserverconnector.h" namespace jsonrpc { @@ -23,7 +23,7 @@ namespace jsonrpc * 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 TcpSocketServerPrivate + class WindowsTcpSocketServer: public AbstractServerConnector { public: /** From b5480485a68a5aa4a04e23b03e6c58967946ed16 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 24 Feb 2016 16:28:28 +0100 Subject: [PATCH 108/114] fix build --- .travis.yml | 2 +- CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index cbeb11c0..6d85a0f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_install: - sudo apt-get install -qq libcurl4-openssl-dev libjsoncpp-dev libargtable2-dev libgnutls-dev libgcrypt11-dev valgrind wget - wget http://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.44.tar.gz - tar -xvf libmicrohttpd-0.9.44.tar.gz - - cd libmicrohttpd-0.9.38 + - cd libmicrohttpd-0.9.44 - ./configure && make - sudo make install && sudo ldconfig - cd .. && sudo rm -rf libmicrohttpd-0.9.44 diff --git a/CMakeLists.txt b/CMakeLists.txt index e735cedd..b05d856d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,8 +28,8 @@ if(UNIX) set(UNIX_DOMAIN_SOCKET_SERVER YES CACHE BOOL "Include Unix Domain Socket server") set(UNIX_DOMAIN_SOCKET_CLIENT YES CACHE BOOL "Include Unix Domain Socket client") endif(UNIX) -set(TCP_SOCKET_SERVER YES CACHE BOOL "Include Tcp Socket server") -set(TCP_SOCKET_CLIENT YES CACHE BOOL "Include Tcp Socket client") +set(TCP_SOCKET_SERVER NO CACHE BOOL "Include Tcp Socket server") +set(TCP_SOCKET_CLIENT NO CACHE BOOL "Include Tcp Socket client") set(HTTP_SERVER YES CACHE BOOL "Include HTTP server using libmicrohttpd") set(HTTP_CLIENT YES CACHE BOOL "Include HTTP client support using curl") set(COMPILE_TESTS YES CACHE BOOL "Compile test framework") From ce30f9287cd41b5a9ca80ea95cba034e4984790a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Tue, 24 May 2016 13:00:23 +0200 Subject: [PATCH 109/114] cmake: Fix respecting LIBDIR_SUFFIX for non-Debian multilib support Fixes: cafb6c1286cad024f3e77275914d595ca658162d Fixes: 77ecb82e491535968c41d9b305afdf009b04f35c --- src/jsonrpccpp/CMakeLists.txt | 6 +++--- src/stubgenerator/CMakeLists.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/jsonrpccpp/CMakeLists.txt b/src/jsonrpccpp/CMakeLists.txt index b8f68d41..a3ec6e1e 100644 --- a/src/jsonrpccpp/CMakeLists.txt +++ b/src/jsonrpccpp/CMakeLists.txt @@ -193,8 +193,8 @@ if (WIN32) endif() install(TARGETS ${ALL_LIBS} - LIBRARY DESTINATION lib/${CMAKE_LIBRARY_PATH} - ARCHIVE DESTINATION lib/${CMAKE_LIBRARY_PATH} + LIBRARY DESTINATION lib${LIB_SUFFIX}/${CMAKE_LIBRARY_PATH} + ARCHIVE DESTINATION lib${LIB_SUFFIX}/${CMAKE_LIBRARY_PATH} RUNTIME DESTINATION bin ) @@ -211,6 +211,6 @@ INSTALL(FILES "${CMAKE_BINARY_DIR}/libjsonrpccpp-server.pc" "${CMAKE_BINARY_DIR}/libjsonrpccpp-client.pc" "${CMAKE_BINARY_DIR}/libjsonrpccpp-common.pc" - DESTINATION "lib/${CMAKE_LIBRARY_PATH}/pkgconfig") + DESTINATION "lib${LIB_SUFFIX}/${CMAKE_LIBRARY_PATH}/pkgconfig") diff --git a/src/stubgenerator/CMakeLists.txt b/src/stubgenerator/CMakeLists.txt index 2dbf7450..df5f2016 100644 --- a/src/stubgenerator/CMakeLists.txt +++ b/src/stubgenerator/CMakeLists.txt @@ -65,8 +65,8 @@ install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/stubgenerator/ FILES_MATCHING PATTERN "*.h") install(TARGETS ${ALL_LIBS} jsonrpcstub - LIBRARY DESTINATION lib/${CMAKE_LIBRARY_PATH} - ARCHIVE DESTINATION lib/${CMAKE_LIBRARY_PATH} + LIBRARY DESTINATION lib${LIB_SUFFIX}/${CMAKE_LIBRARY_PATH} + ARCHIVE DESTINATION lib${LIB_SUFFIX}/${CMAKE_LIBRARY_PATH} RUNTIME DESTINATION bin ) From e0c93d3be8ce4504f1672f596817bc54027c2f0b Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 10 Aug 2016 09:56:42 +0200 Subject: [PATCH 110/114] fix build error --- src/jsonrpccpp/client/client.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jsonrpccpp/client/client.cpp b/src/jsonrpccpp/client/client.cpp index a13c43ac..7ce96587 100644 --- a/src/jsonrpccpp/client/client.cpp +++ b/src/jsonrpccpp/client/client.cpp @@ -53,9 +53,9 @@ void Client::CallProcedures(const BatchCall &calls, BatchResponse &result) throw result.addResponse(id, singleResult, false); } catch (JsonRpcException& ex) { - int id = -1; - if(tmpresult[i].isMember("id") && tmpresult[i]["id"].isIntegral()) - id = tmpresult[i]["id"].asInt(); + Json::Value id = -1; + if(tmpresult[i].isMember("id")) + id = tmpresult[i]["id"]; result.addResponse(id, tmpresult[i]["error"], true); } } From ccd57228afe38c1986eaf1ba3f2052dbbe5d4bc4 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 10 Aug 2016 10:01:55 +0200 Subject: [PATCH 111/114] disable broken valgrind analysis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e4f30445..67ca6ea8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,6 @@ script: - mkdir -p build && cd build - cmake -DCMAKE_BUILD_TYPE=Debug -DHTTP_CLIENT=${HTTP_CLIENT} -DHTTP_SERVER=${HTTP_SERVER} -DCOMPILE_STUBGEN=${COMPILE_STUBGEN} .. - make - - valgrind --leak-check=full --error-exitcode=1 ./bin/unit_testsuite - make test - sudo make install && sudo ldconfig - g++ ../src/examples/simpleclient.cpp -ljsonrpccpp-client -ljsoncpp -ljsonrpccpp-common -lcurl -o sampleclient From 7375daea40bb6bad868fa627f9375c4c483e6df9 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 10 Aug 2016 10:18:19 +0200 Subject: [PATCH 112/114] Apply debian patch to always build manpage on unix systems --- src/stubgenerator/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stubgenerator/CMakeLists.txt b/src/stubgenerator/CMakeLists.txt index df5f2016..f9dbe4c4 100644 --- a/src/stubgenerator/CMakeLists.txt +++ b/src/stubgenerator/CMakeLists.txt @@ -40,7 +40,7 @@ add_executable(jsonrpcstub main.cpp) target_link_libraries(jsonrpcstub jsonrpccommon libjsonrpcstub ) #Generate manpage -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") +if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows") configure_file("${CMAKE_SOURCE_DIR}/doc/manpage.in" "${CMAKE_BINARY_DIR}/manpage" @ONLY) add_custom_command(OUTPUT jsonrpcstub.1.gz COMMAND gzip -c "${CMAKE_BINARY_DIR}/manpage" > ${CMAKE_BINARY_DIR}/jsonrpcstub.1.gz @@ -52,7 +52,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") install(FILES ${CMAKE_BINARY_DIR}/jsonrpcstub.1.gz DESTINATION share/man/man1/) add_dependencies(jsonrpcstub manpage) -endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") +endif() CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/libjsonrpccpp-stub.pc.cmake ${CMAKE_BINARY_DIR}/libjsonrpccpp-stub.pc) From 78a608dfed903e340d3139d9fa7dea04d6824b67 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 10 Aug 2016 10:34:40 +0200 Subject: [PATCH 113/114] prepared changelog --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbce7f06..d3204857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ -Changes in v1.0.0 +Changes in v0.7.0 ----------------- - Change: Requiring C++11 support (gcc >= 4.8) +- Fix: armhf compatibility +- Fix: Invalid client id field handling (removed int only check) +- Fix: Security issues in unixdomainsocket connectors +- Fix: Missing CURL include directive +- Fix: Parallel build which failed due to failing CATCH dependency +- Fix: Handling 64-bit ids +- Fix: Invalid parameter check +- Fix: Invalid pointer handling in HTTP-Server +- NEW: HttpServer can now be configured to listen localhost only - NEW: TCP Server + Client connectors -- TODO: use PIMPL to keep the ABI/API more stable Changes in v0.6.0 ----------------- From bfd0f8d1b021cac019a3f3aad5725b151e8a2648 Mon Sep 17 00:00:00 2001 From: Peter Spiess-Knafl Date: Wed, 10 Aug 2016 10:35:38 +0200 Subject: [PATCH 114/114] Version bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 85e0e54c..a3cf5e0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ if (${CMAKE_MAJOR_VERSION} GREATER 2) endif() set(MAJOR_VERSION 0) -set(MINOR_VERSION 6) +set(MINOR_VERSION 7) set(PATCH_VERSION 0) set(SO_VERSION 0)