From c7d0a656ba64a1b540c40fe7aa05d92e110b27e1 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Thu, 12 Mar 2015 23:35:50 +0100 Subject: [PATCH] ReThread, ReTCP for win32 --- base/ReLogger.hpp | 2 +- base/ReThread.cpp | 104 ++++++++++++++++++++ base/ReThread.hpp | 47 ++++++++++ base/baselocations.hpp | 1 + base/rebase.hpp | 203 ++++++++++++++++++++-------------------- net/ReTCP.cpp | 36 +++++-- net/ReTCP.hpp | 13 ++- net/ReUdpConnection.hpp | 6 -- net/renet.hpp | 44 +++++---- 9 files changed, 322 insertions(+), 134 deletions(-) create mode 100644 base/ReThread.cpp create mode 100644 base/ReThread.hpp diff --git a/base/ReLogger.hpp b/base/ReLogger.hpp index 6ec0321..f177aa4 100644 --- a/base/ReLogger.hpp +++ b/base/ReLogger.hpp @@ -180,7 +180,7 @@ protected: ReAppender* m_stdConsoleAppender; ReFileAppender* m_stdFileAppender; int m_locationOfOpenSayF; - sem_t m_mutex; + ReMutex_t m_mutex; char m_charPrefix; private: diff --git a/base/ReThread.cpp b/base/ReThread.cpp new file mode 100644 index 0000000..4c8959e --- /dev/null +++ b/base/ReThread.cpp @@ -0,0 +1,104 @@ +/* + * ReThreadStarter.cpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + */ + +#include "base/rebase.hpp" + +enum RELOC_HASHLIST { + LC_SET_MASTER_LOGGER_1 = LC_THREAD + 1, // 50601 + LC_START_THREAD_1, // 50602 +}; + +/** + * Constructor. + */ +ReThread::ReThread() : + m_logger(false), + m_appender(NULL){ +} +/** + * Destructor. + */ +ReThread::~ReThread(){ +} + +void ReThread::setMasterLogger(ReLogger* masterLogger){ + if (m_appender == NULL){ + m_appender = new ReSlaveAppender(masterLogger); + } else { + globalLogger()->say(LOG_ERROR | CAT_LIB, LC_NEXT_1, + i18n("setMasterLogger() is called multiple times")); + } +} + +/** + * Constructor. + */ +ReThreadStarter::ReThreadStarter(ReLogger* logger) : + m_id(0), + m_logger(logger){ +} +/** + * Destructor. + */ +ReThreadStarter::~ReThreadStarter(){ +} + +#if defined __linux__ +/** + * The start routine of pthread_start + * + * This will handle the connection for each client (in an own thread). + * + * @param pConnection a void* pointer to the ReThread instance + * */ +static void* starterFunction(void *pConnection) { + ReThread* thread = reinterpret_cast(pConnection); + thread->run(); +} +#elif defined __WIN32__ +DWORD WINAPI starterFunction(_In_ LPVOID pParameter){ + ReThread* thread = reinterpret_cast(pConnection); + thread->run(); + return 0; +} + +#endif +/** + * Starts a new thread. + * + * @param thread the + */ +void ReThreadStarter::startThread(ReThread& thread){ + thread.setId(++m_nextId); + thread.setMasterLogger(m_logger); + bool error; +#if defined __linux__ + pthread_t sniffer_thread; + error = (pthread_create(&sniffer_thread, NULL, starterFunction, + (void*) thread) < 0; + +#else defined __WIN32__ + HANDLE threadHandle; + error = (threadHandle = CreateThread(NULL, 0, starterFunction, + &thread, 0)) == NULL; + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ SIZE_T dwStackSize, + _In_ LPTHREAD_START_ROUTINE lpStartAddress, + _In_opt_ LPVOID lpParameter, + _In_ DWORD dwCreationFlags, + _Out_opt_ LPDWORD lpThreadId + ); +#endif + if (error) + m_logger->sayF(LOG_ERROR | CAT_PROCESS, + LC_START_THREAD_1, + i18n("cannot create a thread: $1")).arg( + getLastOSError()).end(); + +} diff --git a/base/ReThread.hpp b/base/ReThread.hpp new file mode 100644 index 0000000..f6b088d --- /dev/null +++ b/base/ReThread.hpp @@ -0,0 +1,47 @@ +/* + * ReThreadStarter.hpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + */ + +#ifndef BASE_RETHREAD_HPP_ +#define BASE_RETHREAD_HPP_ + +/** + * Abstract base class for threads + * + * Starting is done with a ReThreadStarter. + */ +class ReThread { +public: + ReThread(); + virtual ~ReThread(); +private: + friend class ReThreadStarter; + void setId(int id); + void setMasterLogger(ReLogger* masterLogger); +public: + virtual void run() = 0; +protected: + int m_id; + ReLogger m_logger; + ReSlaveAppender* m_appender; +}; + +/** + * Offers a portable way to start threads. + */ +class ReThreadStarter { +public: + ReThreadStarter(ReLogger* logger); + virtual ~ReThreadStarter(); +public: + void startThread(ReThread& thread); +private: + int m_nextId; + ReLogger* m_logger; +}; +#endif /* BASE_RETHREAD_HPP_ */ diff --git a/base/baselocations.hpp b/base/baselocations.hpp index be56134..7ef4b40 100644 --- a/base/baselocations.hpp +++ b/base/baselocations.hpp @@ -19,6 +19,7 @@ enum RELOC_LIB { LC_HASHLIST = 50300, LC_TRAVERSER = 50400, LC_TCP = 50500, + LC_THREAD = 50600, }; enum RELOC_UDPCONNECTION { LC_UDPCONNECTION_CONSTRUCT = 50101, diff --git a/base/rebase.hpp b/base/rebase.hpp index 9f0e26e..93b40f0 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -1,99 +1,104 @@ -/* - * rebase.hpp - * - * License: Public domain - * Do what you want. - * No warranties and disclaimer of any damages. - * The latest sources: https://github.com/republib - */ -#ifndef REBASE_HPP_ -#define REBASE_HPP_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define __LITTLE_ENDIAN__ -//#define __BIG_ENDIAN__ - -#if defined __linux__ - -# include -# include -# include -# include -# include -# include -# include -# include -typedef u_int64_t uint64_t; -typedef u_int8_t uint8_t; -typedef __off_t ReFileSize_t; -typedef timespec ReFileTime_t; -# define _strdup strdup -# define _unlink unlink -# define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n) -# define _stricmp(s1, s2) strcasecmp(s1, s2) -# define _snprintf snprintf -# define _memcmp(t,s,n) memcmp(t,s,n) -# define _mkdir(path, mode) mkdir(path, mode) -# define _rmdir(path) rmdir(path) -# define OS_SEPARATOR_CHAR '/' -# define OS_SEPARATOR "/" -inline int getLastOSError() { - return errno; -} -#elif defined __WIN32__ -# include -# include -# define _memcmp(t,s,n) memcmp(t,s,n) -# define lstat stat -# define OS_SEPARATOR_CHAR '\\' -# define OS_SEPARATOR "\\" -typedef _int64 int64_t; -typedef unsigned long long uint64_t; -typedef unsigned char uint8_t; -typedef unsigned long uint32_t; -typedef long int int32_t; -typedef int64_t ReFileSize_t; -typedef FILETIME ReFileTime_t; -# define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0) -# define ALLPERMS 0 -//# define _mkdir(name, mode) (!CreateDirectory(name, NULL)) -# define _mkdir(name, mode) _mkdir(name) -inline int getLastOSError() { - return GetLastError(); -} -#endif - -#define RE_TESTUNIT -#include "base/ReByteBuffer.hpp" -#include "base/ReVarArgs.hpp" -#include "base/ReLogger.hpp" -#include "base/ReTestUnit.hpp" -#include "base/ReCString.hpp" -#include "base/ReException.hpp" -#include "base/ReStringUtils.hpp" -#include "base/ReDirectory.hpp" -#include "base/ReSeqArray.hpp" -#include "base/ReStringList.hpp" -#include "base/ReHashList.hpp" -#include "base/ReConfigFile.hpp" -#include "base/ReI18N.hpp" -#include "base/ReProgramArgs.hpp" -#include "base/ReAppenders.hpp" - -typedef unsigned char byte_t; -typedef int ReErrNo_t; -#include "../base/baselocations.hpp" -#endif /* REBASE_HPP_ */ +/* + * rebase.hpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + */ +#ifndef REBASE_HPP_ +#define REBASE_HPP_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __LITTLE_ENDIAN__ +//#define __BIG_ENDIAN__ + +#if defined __linux__ + +# include +# include +# include +# include +# include +# include +# include +# include +#include +#include +typedef u_int64_t uint64_t; +typedef u_int8_t uint8_t; +typedef __off_t ReFileSize_t; +typedef timespec ReFileTime_t; +typedef sem_t ReMutex_t; +#define reInitMutex(mutex) +# define _strdup strdup +# define _unlink unlink +# define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +# define _stricmp(s1, s2) strcasecmp(s1, s2) +# define _snprintf snprintf +# define _memcmp(t,s,n) memcmp(t,s,n) +# define _mkdir(path, mode) mkdir(path, mode) +# define _rmdir(path) rmdir(path) +# define OS_SEPARATOR_CHAR '/' +# define OS_SEPARATOR "/" +inline int getLastOSError() { + return errno; +} +#elif defined __WIN32__ +# include +# include +# include +# define _memcmp(t,s,n) memcmp(t,s,n) +# define lstat stat +# define OS_SEPARATOR_CHAR '\\' +# define OS_SEPARATOR "\\" +typedef HANDLE ReMutex_t; +#define initMutex(mutex) mutex = CreateMutex(NULL, FALSE, NULL) +typedef _int64 int64_t; +typedef unsigned long long uint64_t; +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef long int int32_t; +typedef int64_t ReFileSize_t; +typedef FILETIME ReFileTime_t; +# define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0) +# define ALLPERMS 0 +//# define _mkdir(name, mode) (!CreateDirectory(name, NULL)) +# define _mkdir(name, mode) _mkdir(name) +inline int getLastOSError() { + return GetLastError(); +} +#endif + +#define RE_TESTUNIT +#include "base/ReByteBuffer.hpp" +#include "base/ReVarArgs.hpp" +#include "base/ReLogger.hpp" +#include "base/ReTestUnit.hpp" +#include "base/ReCString.hpp" +#include "base/ReException.hpp" +#include "base/ReStringUtils.hpp" +#include "base/ReDirectory.hpp" +#include "base/ReSeqArray.hpp" +#include "base/ReStringList.hpp" +#include "base/ReHashList.hpp" +#include "base/ReConfigFile.hpp" +#include "base/ReI18N.hpp" +#include "base/ReProgramArgs.hpp" +#include "base/ReAppenders.hpp" + +typedef unsigned char byte_t; +typedef int ReErrNo_t; +#include "../base/baselocations.hpp" +#endif /* REBASE_HPP_ */ diff --git a/net/ReTCP.cpp b/net/ReTCP.cpp index 8995ef9..7a77901 100644 --- a/net/ReTCP.cpp +++ b/net/ReTCP.cpp @@ -26,7 +26,13 @@ enum LOCATION_DIRTOOL { LC_RECEIVE_4, // 50515 LC_CONNECT_2, // 50516 LC_CONNECT_3, // 50517 + LC_TCP_CONNECTION_1, // 50518 }; + +#if defined __WIN32__ +bool ReTCPConnection::isGlobalInitialized = false; +#endif + /** * Constructor. * @@ -123,7 +129,6 @@ bool ReTCPClient::connect(const char* ip, int port) { bool rc = false; struct addrinfo hints; struct addrinfo* addr = NULL; - int sockfd; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; @@ -167,6 +172,15 @@ ReTCPConnection::ReTCPConnection(int id, ReLogger* logger) : m_id(id), m_noSent(0), m_noReceived(0) { +#if defined __WIN32__ + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){ + m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_TCP_CONNECTION_1, + i18n("WSAStartup() failed: $1")).arg(errno).arg(getLastOSError()).end(); + throw ReException("WSAStartup() failed"); + } + +#endif } /** @@ -179,11 +193,20 @@ ReTCPConnection::~ReTCPConnection() { */ void ReTCPConnection::close() { if (m_handleSocket >= 0) { - ::close(m_handleSocket); + reCloseSocket(m_handleSocket); m_handleSocket = -1; } } +/** + * Frees the global resources. + */ +void ReTCPConnection::globalClose(){ +#if defined __WIN32__ + WSACleanup(); +#endif +} + /** * Sets the address given by a family and a string like "192.168.0.1:22". * @@ -312,8 +335,6 @@ ReTCPServerConnection::~ReTCPServerConnection() { * Serves the commands of a single connection (in a single thread). */ void ReTCPServerConnection::handleConnection() { -//Get the socket descriptor - int read_size; ReByteBuffer command; ReNetCommandHandler::ProcessingState rc = ReNetCommandHandler::PS_UNDEF; do { @@ -438,7 +459,8 @@ bool ReTCPServer::listenForAll() { int yes = 1; // Avoid the "Address already in use" error message of finished processes // that are still waiting for the release by the kernel: - if (setsockopt(m_handleSocket, SOL_SOCKET, SO_REUSEADDR, &yes, + if (setsockopt(m_handleSocket, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&yes), sizeof(int)) == -1) { m_logger->sayF(LOG_WARNING | CAT_NETWORK, LC_LISTEN_FOR_ALL_7, i18n("setsockopt() failed: $1")).arg(errno).end(); @@ -471,7 +493,7 @@ bool ReTCPServer::listenForAll() { LC_LISTEN_FOR_ALL_5, i18n("connection refused (too many connections): $1")) .arg(m_port).end(); - ::close(clientSocket); + reCloseSocket(clientSocket); } else { pthread_t sniffer_thread; ReTCPConnection* connection = createConnection(nextId++, @@ -483,7 +505,7 @@ bool ReTCPServer::listenForAll() { LC_LISTEN_FOR_ALL_6, i18n("cannot create a thread: $1")).arg( getLastOSError()).end(); - ::close(clientSocket); + reCloseSocket(clientSocket); clientSocket = -1; } diff --git a/net/ReTCP.hpp b/net/ReTCP.hpp index a13fa6e..4364ed8 100644 --- a/net/ReTCP.hpp +++ b/net/ReTCP.hpp @@ -9,6 +9,12 @@ #ifndef NET_RETCP_HPP_ #define NET_RETCP_HPP_ + +#if defined __linux__ +# define reCloseSocket(handle) ::close(handle) +#elif defined __WIN32__ +# define reCloseSocket(handle) ::closesocket(handle) +#endif /** * Administrates the internal data of an ip address, usable for IP4 and IP6. */ @@ -97,8 +103,13 @@ protected: int m_id; uint32_t m_noSent; uint32_t m_noReceived; +#if defined __WIN32__ +private: + static bool isGlobalInitialized; +#endif +public: + static void globalClose(); }; - /** * Implements a TCP client. */ diff --git a/net/ReUdpConnection.hpp b/net/ReUdpConnection.hpp index 48ffd49..36ae8a2 100644 --- a/net/ReUdpConnection.hpp +++ b/net/ReUdpConnection.hpp @@ -8,12 +8,6 @@ #ifndef UDPSERVER_H_ #define UDPSERVER_H_ -#include -#include -#include -#include -#include - /** * Implements a base class for UDP server and client. */ diff --git a/net/renet.hpp b/net/renet.hpp index 840ff53..0ccc8c0 100644 --- a/net/renet.hpp +++ b/net/renet.hpp @@ -1,20 +1,24 @@ -/* - * renet.hpp - * - * License: Public domain - * Do what you want. - * No warranties and disclaimer of any damages. - * The latest sources: https://github.com/republib - * - */ - -#ifndef NET_RENET_HPP_ -#define NET_RENET_HPP_ - -#include -#include -#include -#include -#include "net/ReUdpConnection.hpp" -#include "net/ReTCP.hpp" -#endif /* NET_RENET_HPP_ */ +/* + * renet.hpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + * + */ + +#ifndef NET_RENET_HPP_ +#define NET_RENET_HPP_ + +#if defined __linux__ +#include +#include +#include +#include +#elif defined __WIN32__ +#include +#endif +#include "net/ReUdpConnection.hpp" +#include "net/ReTCP.hpp" +#endif /* NET_RENET_HPP_ */ -- 2.39.5