]> gitweb.hamatoma.de Git - crepublib/commitdiff
dirtool tcp up- and download
authorHamatoma <git.tortouse@hm.f-r-e-i.de>
Wed, 18 Mar 2015 21:43:53 +0000 (22:43 +0100)
committerHamatoma <git.tortouse@hm.f-r-e-i.de>
Wed, 18 Mar 2015 21:43:53 +0000 (22:43 +0100)
base/ReByteBuffer.cpp
base/ReByteBuffer.hpp
cunit/cuReByteBuffer.cpp
cunit/cuReTCP.cpp
cunit/testall.cpp
net/ReTCP.cpp
os/ReDirTools.cpp
os/ReDirTools.hpp

index 9d19ff3997d76559e46534b07b796a0125c73753..045d37eaabbeae408931097ce192fba0180f6cda 100644 (file)
@@ -235,7 +235,7 @@ ReByteBuffer& ReByteBuffer::appendDump(const char* data, size_t length, int maxL
        if (! isBinary)
                append(data, length);
        else
-               appendHexDump(data, length / 5);
+               appendHexDump(data, min(length, maxLength / 5)).reduceLength();
        return *this;
 }
 /**
@@ -675,6 +675,28 @@ int ReByteBuffer::indexOf(const Byte* toFind, size_t toFindLength, int start,
        }
        return rc;
 }
+/**
+ * Tests whether the instance is a prefix of a given string.
+ *
+ * @param source               the string to inspect
+ * @param length               the length of the string<br>
+ *                                             -1: <code>strlen(source)</code>
+ * @param ignoreCase   <code>true</code>: the test is case insensitive
+ * @param minLength            the substring (instance) must have at least this length
+ *                                             for a positive test
+ * @return                             <code>true</code>the instance is a prefix of the <code>source</code>
+ *                                             and the length is at least <code>minLength</code> bytes
+ */
+bool ReByteBuffer::isPrefixOf(const char* source, size_t length,
+       bool ignoreCase, int minLength){
+       if (length == (size_t) -1)
+               length = strlen(source);
+       bool rc = length >= m_length && m_length <= length;
+       if (rc)
+               rc = equals(source, m_length, ignoreCase);
+       return rc;
+}
+
 /** @brief Searches revers for a byte sequence in the internal buffer.
  *
  * Finds the last occurrence of a byte sequence in a given range.
index 3a4012f9b188bc2b88a61efb8fba16cfc316884b..461ec694b4417b5f1dec639186f38e908cd3f353 100644 (file)
@@ -177,6 +177,7 @@ public:
        bool insert(size_t ix, const Byte* source, size_t length) {
                return splice(ix, 0, source, length);
        }
+       bool isPrefixOf(const char* source, size_t length = -1, bool ignoreCase = false, int minLength = 0);
        /** Returns the last character.
         * @return      '\0': empty buffer<br>
         *                      otherwise: the last character
index aa10b298bfc5aca44aa5b6b0e4c8d9f1abec347a..cbb0697a27314eb9c59d5204f9fabea9a366da57 100644 (file)
@@ -16,6 +16,7 @@ public:
        }
 private:
        void run() {
+               testAppendDump();
                testAppendFix();
                testEnsureLastChar();
                testLastChar();
@@ -47,6 +48,53 @@ private:
                testSplice();
                testReplace();
        }
+       void testIsPrefixOf(){
+               ReByteBuffer buffer;
+               // predefined length (of source):
+               // case sensitive, same size
+               checkT(buffer.set("aBc").isPrefixOf("aBc"));
+               // case sensitive, shorter
+               checkT(buffer.set("aB").isPrefixOf("aBc"));
+               checkF(buffer.set("ab").isPrefixOf("aBc"));
+               // case sensitive, longer
+               checkF(buffer.set("aBcd").isPrefixOf("aBc"));
+
+               // given length (of source):
+               // case sensitive, same size
+               checkT(buffer.set("aBc").isPrefixOf("aBcd", 3));
+               // case sensitive, shorter
+               checkT(buffer.set("aB").isPrefixOf("aBcd", 3));
+               checkF(buffer.set("ab").isPrefixOf("aBcd", 3));
+               // case sensitive, longer
+               checkF(buffer.set("aBcd").isPrefixOf("aBcd", 3));
+
+
+               // case insensitive, same size
+               checkT(buffer.set("aBc").isPrefixOf("abc", -1, true));
+               // case sensitive, shorter
+               checkT(buffer.set("aB").isPrefixOf("abc", -1, true));
+               // case sensitive, longer
+               checkF(buffer.set("aBcd").isPrefixOf("abc", -1, true));
+
+               // minSize:
+               checkT(buffer.set("aBc").isPrefixOf("abcd", -1, true, 2));
+               checkF(buffer.set("aB").isPrefixOf("abc", -1, true, 3));
+       }
+       void testAppendDump(){
+               ReByteBuffer buffer;
+               // true ASCII:
+               buffer.appendDump("abc");
+               checkEqu("abc", buffer.str());
+               buffer.setLength(0).appendDump("abcdefg", -1, 4);
+               checkEqu("abcd", buffer.str());
+               buffer.setLength(0).appendDump("a\tb\nc\rd");
+               checkEqu("a\tb\nc\rd", buffer.str());
+               // binary:
+               int64_t ii = 0x12345678abcdefll;
+               buffer.setLength(0).appendDump(reinterpret_cast<const char*>(&ii), sizeof ii, 40);
+               checkEqu("0000: ef cd ab 78 56 34 12 00                          | ...xV4..         ",
+                       buffer.str());
+       }
        void testAppendFix() {
                ReByteBuffer buffer;
                // maxLength exceeded
index e3960d454cfa712aeb015960fa7fdc7bf8495702..dc9aa22ed9090fb7665165adccf16137abd252ed 100644 (file)
@@ -111,7 +111,7 @@ private:
                pool.startThread(new TCPThread("echo"));
                pool.startThread(new TCPThread("upload"));
                pool.startThread(new TCPThread("download"));
-               pool.waitForAlmostAll(1, 20000);
+               pool.waitForAlmostAll(1, 20);
                ReTCPStopClient stopper(&logger);
                stopper.stopServer(s_port);
        }
index f23ee46811c4dc1b9367d72c9686956ec605b92f..d4c8cd10990473c43d739f9b80ed88379e3c871f 100644 (file)
@@ -85,6 +85,7 @@ void testMath() {
 }
 void testAll() {
        try {
+               testBase();
                testNet();
                if (s_testAll) {
                        testString();
index a1a2cf0fd458c3193018b3d3112fafdd498b6d32..acd5871ab8bcd67f50ecd3815da81888bead8476 100644 (file)
-/*
- * ReTCP.cpp
- *
- *  Created on: 04.03.2015
- *      Author: hm
- */
-
-#include "base/rebase.hpp"
-#include "net/renet.hpp"
-
-enum LOCATION_DIRTOOL {
-       LC_LISTEN_FOR_ALL_1 = LC_TCP + 1, // 50501
-       LC_LISTEN_FOR_ALL_2,    // 50502
-       LC_LISTEN_FOR_ALL_3,    // 50503
-       LC_LISTEN_FOR_ALL_4,    // 50504
-       LC_LISTEN_FOR_ALL_5,    // 50505
-       LC_LISTEN_FOR_ALL_6,    // 50506
-       LC_WRITE_1,                     // 50507
-       LC_CONNECT_1,                   // 50508
-       LC_SOCKET_ADDR_SET_1,   // 50509
-       LC_LISTEN_FOR_ALL_7,    // 50510
-       LC_HANDLE_CONNECTION_1, // 50511
-       LC_RECEIVE_1,                   // 50512
-       LC_RECEIVE_2,                   // 50513
-       LC_RECEIVE_3,                   // 50514
-       LC_RECEIVE_4,                   // 50515
-       LC_CONNECT_2,                   // 50516
-       LC_CONNECT_3,                   // 50517
-       LC_TCP_CONNECTION_1,    // 50518
-       LC_WRITE_2,                             // 50519
-       LC_RECEIVE_5,                   // 50520
-};
-
-#if defined __WIN32__
-bool ReTCPConnection::isGlobalInitialized = false;
-#endif
-
-/**
- * Constructor.
- *
- * @param logger       the logger for error handling
- */
-ReSocketAddress::ReSocketAddress(ReLoggerOwner* loggerOwner) :
-           m_preferredFamily(AF_INET),
-           m_family(-1),
-           m_port(0),
-           m_loggerOwner(loggerOwner),
-           // m_ip
-           m_name() {
-       memset(&m_ip, 0, sizeof m_ip);
-}
-/**
- * Destructor.
- */
-ReSocketAddress::~ReSocketAddress() {
-}
-void addressToString(struct addrinfo& addr, char* ip, size_t ipSize) {
-       if (addr.ai_family == AF_INET) {
-               inet_ntop(addr.ai_family, (struct sockaddr_in *) addr.ai_addr, ip,
-                   ipSize);
-       } else if (addr.ai_family == AF_INET6) {
-               inet_ntop(addr.ai_family, (struct sockaddr_in6 *) addr.ai_addr, ip,
-                   ipSize);
-       }
-}
-/**
- * Sets the data from symbolic values.
- */
-void ReSocketAddress::setAddress(const char* ip, int port) {
-       struct addrinfo hints;
-       struct addrinfo* infoList;
-       int status;
-       m_port = port;
-       memset(&hints, 0, sizeof hints);
-       hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
-       hints.ai_socktype = SOCK_STREAM;
-
-       if ((status = getaddrinfo(ip, NULL, &hints, &infoList)) != 0) {
-               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,
-                   LC_SOCKET_ADDR_SET_1, i18n("getaddrinfo($1) failed: $2")).arg(ip)
-                   .arg(errno).end();
-       }
-
-       struct addrinfo* ptr;
-       bool hasIP4 = false;
-       bool hasIP6 = false;
-
-       // Search for a available ip address
-       // if more than one are available, prefer m_preferredFamily:
-       m_ip[0] = '\0';
-       for (ptr = infoList; ptr != NULL; ptr = ptr->ai_next) {
-               // different fields in IPv4 and IPv6:
-               if (!hasIP4 && ptr->ai_family == AF_INET) {
-                       m_family = AF_INET;
-                       hasIP4 = true;
-               } else if (!hasIP6 && ptr->ai_family == AF_INET6) {
-                       m_family = AF_INET6;
-                       hasIP6 = true;
-               }
-               addressToString(*ptr, m_ip, sizeof m_ip);
-               if (ptr->ai_family == m_preferredFamily)
-                       break;
-       }
-       // free the linked list
-       freeaddrinfo(infoList);
-       if (m_ip[0] == '\0')
-               m_name.setLength(0);
-       else
-               m_name.set(m_ip).appendChar(':').appendInt(port);
-}
-
-/**
- * Constructor.
- *
- * @param logger       logger for the error handling
- */
+/*\r
+ * ReTCP.cpp\r
+ *\r
+ *  Created on: 04.03.2015\r
+ *      Author: hm\r
+ */\r
+\r
+#include "base/rebase.hpp"\r
+#include "net/renet.hpp"\r
+\r
+enum LOCATION_DIRTOOL {\r
+       LC_LISTEN_FOR_ALL_1 = LC_TCP + 1, // 50501\r
+       LC_LISTEN_FOR_ALL_2,    // 50502\r
+       LC_LISTEN_FOR_ALL_3,    // 50503\r
+       LC_LISTEN_FOR_ALL_4,    // 50504\r
+       LC_LISTEN_FOR_ALL_5,    // 50505\r
+       LC_LISTEN_FOR_ALL_6,    // 50506\r
+       LC_WRITE_1,                     // 50507\r
+       LC_CONNECT_1,                   // 50508\r
+       LC_SOCKET_ADDR_SET_1,   // 50509\r
+       LC_LISTEN_FOR_ALL_7,    // 50510\r
+       LC_HANDLE_CONNECTION_1, // 50511\r
+       LC_RECEIVE_1,                   // 50512\r
+       LC_RECEIVE_2,                   // 50513\r
+       LC_RECEIVE_3,                   // 50514\r
+       LC_RECEIVE_4,                   // 50515\r
+       LC_CONNECT_2,                   // 50516\r
+       LC_CONNECT_3,                   // 50517\r
+       LC_TCP_CONNECTION_1,    // 50518\r
+       LC_WRITE_2,                             // 50519\r
+       LC_RECEIVE_5,                   // 50520\r
+};\r
+\r
+#if defined __WIN32__\r
+bool ReTCPConnection::isGlobalInitialized = false;\r
+#endif\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param logger       the logger for error handling\r
+ */\r
+ReSocketAddress::ReSocketAddress(ReLoggerOwner* loggerOwner) :\r
+           m_preferredFamily(AF_INET),\r
+           m_family(-1),\r
+           m_port(0),\r
+           m_loggerOwner(loggerOwner),\r
+           // m_ip\r
+           m_name() {\r
+       memset(&m_ip, 0, sizeof m_ip);\r
+}\r
+/**\r
+ * Destructor.\r
+ */\r
+ReSocketAddress::~ReSocketAddress() {\r
+}\r
+void addressToString(struct addrinfo& addr, char* ip, size_t ipSize) {\r
+       if (addr.ai_family == AF_INET) {\r
+               inet_ntop(addr.ai_family, (struct sockaddr_in *) addr.ai_addr, ip,\r
+                   ipSize);\r
+       } else if (addr.ai_family == AF_INET6) {\r
+               inet_ntop(addr.ai_family, (struct sockaddr_in6 *) addr.ai_addr, ip,\r
+                   ipSize);\r
+       }\r
+}\r
+/**\r
+ * Sets the data from symbolic values.\r
+ */\r
+void ReSocketAddress::setAddress(const char* ip, int port) {\r
+       struct addrinfo hints;\r
+       struct addrinfo* infoList;\r
+       int status;\r
+       m_port = port;\r
+       memset(&hints, 0, sizeof hints);\r
+       hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version\r
+       hints.ai_socktype = SOCK_STREAM;\r
+\r
+       if ((status = getaddrinfo(ip, NULL, &hints, &infoList)) != 0) {\r
+               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,\r
+                   LC_SOCKET_ADDR_SET_1, i18n("getaddrinfo($1) failed: $2")).arg(ip)\r
+                   .arg(errno).end();\r
+       }\r
+\r
+       struct addrinfo* ptr;\r
+       bool hasIP4 = false;\r
+       bool hasIP6 = false;\r
+\r
+       // Search for a available ip address\r
+       // if more than one are available, prefer m_preferredFamily:\r
+       m_ip[0] = '\0';\r
+       for (ptr = infoList; ptr != NULL; ptr = ptr->ai_next) {\r
+               // different fields in IPv4 and IPv6:\r
+               if (!hasIP4 && ptr->ai_family == AF_INET) {\r
+                       m_family = AF_INET;\r
+                       hasIP4 = true;\r
+               } else if (!hasIP6 && ptr->ai_family == AF_INET6) {\r
+                       m_family = AF_INET6;\r
+                       hasIP6 = true;\r
+               }\r
+               addressToString(*ptr, m_ip, sizeof m_ip);\r
+               if (ptr->ai_family == m_preferredFamily)\r
+                       break;\r
+       }\r
+       // free the linked list\r
+       freeaddrinfo(infoList);\r
+       if (m_ip[0] == '\0')\r
+               m_name.setLength(0);\r
+       else\r
+               m_name.set(m_ip).appendChar(':').appendInt(port);\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param logger       logger for the error handling\r
+ */\r
 #pragma warning( push )\r
 #pragma warning( disable : 4355 )\r
-ReTCPClient::ReTCPClient(ReLogger* logger) :
-           ReTCPConnection(-1, this),
-           m_logger(logger) {
-#pragma warning( pop )
-}
-/**
- * Destructor.
- */
-ReTCPClient::~ReTCPClient() {
-}
-/**
- * Connects a client with the server.
- *
- * @param ip   domain address ("denic.de") or ip address ("192.168.2.1")
- * @param port port number: 1..65535
- */
-bool ReTCPClient::connect(const char* ip, int port) {
-       bool rc = false;
-       struct addrinfo hints;
-       struct addrinfo* addr = NULL;
-
-       memset(&hints, 0, sizeof hints);
-       hints.ai_family = AF_UNSPEC;
-       hints.ai_socktype = SOCK_STREAM;
-
-       getaddrinfo(ip, ReByteBuffer("").appendInt(port).str(), &hints, &addr);
-       if (addr == NULL) {
-               m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_1,
-                   i18n("ip not reachable: $1")).arg(ip).end();
-       } else {
-               addressToString(*addr, m_ip, sizeof m_ip);
-               m_peerName.set(m_ip).appendChar(':').appendInt(port);
-               m_port = port;
-               if ((m_handleSocket = socket(addr->ai_family, addr->ai_socktype,
-                   addr->ai_protocol)) < 0)
-                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_2,
-                           i18n("socket() failed ($1): $2")).arg(errno).arg(m_peerName).end();
-               else if (::connect(m_handleSocket, addr->ai_addr, addr->ai_addrlen)
-                   != 0)
-                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_3,
-                           i18n("connect() failed ($1): $2")).arg(errno).arg(m_peerName)
-                           .end();
-               else
-                       rc = true;
-       }
-       return rc;
-}
-
-/**
- * Returns the logger.
- *
- * @param the logger for error handling
- */
-ReLogger* ReTCPClient::logger() {
-       return m_logger;
-}
-
-/**
- * Constructor.
- *
- * @param id           an identifier for logging
- * @param logger       the logger for error handling
- */
-ReTCPConnection::ReTCPConnection(int id, ReLoggerOwner* loggerOwner) :
-           ReSocketAddress(loggerOwner),
-           m_peerName(),
-           m_received(),
-           m_handleSocket(-1),
-           m_id(id),
-           m_noSent(0),
-           m_noReceived(0) {
-#if defined __WIN32__
-       WSADATA wsaData;
-       if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
-               loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_TCP_CONNECTION_1,
-                       i18n("WSAStartup() failed: $1")).arg(errno).arg(getLastOSError()).end();
-               throw ReException("WSAStartup() failed");
-       }
-#endif
-}
-
-/**
- * Destructor.
- */
-ReTCPConnection::~ReTCPConnection() {
-}
-/**
- * Finishes the connection (in both directions) and frees the resouces.
- */
-void ReTCPConnection::close() {
-       if (m_handleSocket >= 0) {
-               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".
- *
- * @param family       AF_INET or AF_INET6
- * @param ip           the string describing the address, e.g. "192.168.0.1"
- * @param port         the port of the peer
- */
-void ReTCPConnection::setConnectedAddress(int family, const char* ip,
-    int port) {
-       m_family = family;
-       m_name = ip;
-       m_port = port;
-       int length = strlen(ip);
-       memcpy(m_ip, ip, length);
-       m_ip[length] = '\0';
-       m_name.appendChar(':').appendInt(port);
-}
-
-/**
- * Receives a message.
- *
- * @param command      OUT: the received command
- * @param data         OUT: the received data
- */
-void ReTCPConnection::receive(ReByteBuffer& command, ReByteBuffer& data) {
-       command.setLength(8);
-       int received = recv(m_handleSocket, command.buffer(), 8, 0);
-       if (received != 8) {
-               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_RECEIVE_1,
-                   i18n("cannot receive ($1): $2 [$3]")).arg(errno).arg(received).arg(
-                   m_peerName).end();
-       } else {
-               int flags = 0;
-               int length = 0;
-               int found;
-               if ((found = sscanf(command.str(), "%8x", &length)) != 1
-                   || (flags = (length >> 24)) > 256 || (length &= 0xffffff) < 8) {
-                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_RECEIVE_2,
-                           i18n("wrong format: $1 [$2]")).arg(command).arg(m_peerName).end();
-               } else {
-                       data.setLength(length);
-                       int readBytes = 0;
-                       int rest = length;
-                       char* buf = data.buffer();
-                       int rounds = 0;
-                       while (readBytes < length) {
-                               rounds++;
-                               received = recv(m_handleSocket, buf, rest, 0);
-                               if (received > 0) {
-                                       buf += received;
-                                       rest -= received;
-                                       readBytes += received;
-                               } else if (received == 0) {
-                                       data.setLength(readBytes);
-                                       break;
-                               } else {
-                                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,
-                                           LC_RECEIVE_3, i18n("cannot receive ($1): $2 [$3]")).arg(
-                                       errno).arg(received).arg(m_peerName).end();
-                                       break;
-                               }
-                       }
-                       if (rounds)
-                               rounds += 0;
-                       if (readBytes < length) {
-                               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,
-                                   LC_RECEIVE_4, i18n("too few bytes read: $1/$2 [$3]")).arg(
-                                   readBytes).arg(received).arg(m_peerName).end();
-                       } else {
-                               m_loggerOwner->logger()->sayF(LOG_DEBUG | CAT_NETWORK, LC_RECEIVE_5,
-                                       i18n("received: $1 bytes in $2 round(s) [$3]: $4")).arg(length).arg(rounds).arg(
-                                       m_peerName).arg(ReByteBuffer().appendDump(data.str(), data.length(), 80).str()).end();
-                       }
-                       command.setLength(0);
-                       if (readBytes >= 8) {
-                               command.append(data.str(), 8);
-                               data.remove(0, 8);
-                       }
-               }
-       }
-}
-/**
- * Sends a command with (or without) data to the peer.
- *
- * @param command      the command to send
- * @param data         the data to send
- */
-void ReTCPConnection::send(const char* command, const char* data, int length) {
-       if (data == NULL)
-               length = 0;
-       else if (length < 0)
-               length = strlen(data);
-       m_toSend.ensureSize(length + 16);
-       ++m_noSent;
-       m_toSend.setLength(0);
-       int flags = 0x7b;
-       length += 8;
-       m_toSend.appendInt(length | (flags << 24), "%08x");
-       m_toSend.appendFix(command, -1, 8, 8, NULL);
-       m_toSend.append(data, length);
-       length += 8;
-       int sent = 0;
-       int rest = length;
-       const char* buf = m_toSend.str();
-       int rounds = 0;
-       while (rest > 0) {
-               rounds++;
-               if ((sent = ::send(m_handleSocket, buf, rest, 0)) > 0) {
-                       buf += sent;
-                       rest -= sent;
-               } else {
-                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_WRITE_1,
-                           i18n("cannot send ($1): $2")).arg(errno).arg(m_peerName).end();
-                       break;
-               }
-       }
-       if (rest == 0)
-               m_loggerOwner->logger()->sayF(LOG_DEBUG | CAT_NETWORK, LC_WRITE_2,
-                           i18n("sent: $1 bytes in $2 round(s): $3")).arg(length).arg(rounds)
-                               .arg(ReByteBuffer().appendDump(data, length, 80).str()).end();
-}
-
-/**
- * Constructor.
- *
- * @param id           an identifier for logging
- * @param logger       the logger for error handling
- */
+ReTCPClient::ReTCPClient(ReLogger* logger) :\r
+           ReTCPConnection(-1, this),\r
+           m_logger(logger) {\r
+#pragma warning( pop )\r
+}\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPClient::~ReTCPClient() {\r
+}\r
+/**\r
+ * Connects a client with the server.\r
+ *\r
+ * @param ip   domain address ("denic.de") or ip address ("192.168.2.1")\r
+ * @param port port number: 1..65535\r
+ */\r
+bool ReTCPClient::connect(const char* ip, int port) {\r
+       bool rc = false;\r
+       struct addrinfo hints;\r
+       struct addrinfo* addr = NULL;\r
+\r
+       memset(&hints, 0, sizeof hints);\r
+       hints.ai_family = AF_UNSPEC;\r
+       hints.ai_socktype = SOCK_STREAM;\r
+\r
+       getaddrinfo(ip, ReByteBuffer("").appendInt(port).str(), &hints, &addr);\r
+       if (addr == NULL) {\r
+               m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_1,\r
+                   i18n("ip not reachable: $1")).arg(ip).end();\r
+       } else {\r
+               addressToString(*addr, m_ip, sizeof m_ip);\r
+               m_peerName.set(m_ip).appendChar(':').appendInt(port);\r
+               m_port = port;\r
+               if ((m_handleSocket = socket(addr->ai_family, addr->ai_socktype,\r
+                   addr->ai_protocol)) < 0)\r
+                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_2,\r
+                           i18n("socket() failed ($1): $2")).arg(errno).arg(m_peerName).end();\r
+               else if (::connect(m_handleSocket, addr->ai_addr, addr->ai_addrlen)\r
+                   != 0)\r
+                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_3,\r
+                           i18n("connect() failed ($1): $2")).arg(errno).arg(m_peerName)\r
+                           .end();\r
+               else\r
+                       rc = true;\r
+       }\r
+       return rc;\r
+}\r
+\r
+/**\r
+ * Returns the logger.\r
+ *\r
+ * @param the logger for error handling\r
+ */\r
+ReLogger* ReTCPClient::logger() {\r
+       return m_logger;\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param id           an identifier for logging\r
+ * @param logger       the logger for error handling\r
+ */\r
+ReTCPConnection::ReTCPConnection(int id, ReLoggerOwner* loggerOwner) :\r
+           ReSocketAddress(loggerOwner),\r
+           m_peerName(),\r
+           m_received(),\r
+           m_handleSocket(-1),\r
+           m_id(id),\r
+           m_noSent(0),\r
+           m_noReceived(0) {\r
+#if defined __WIN32__\r
+       WSADATA wsaData;\r
+       if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {\r
+               loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_TCP_CONNECTION_1,\r
+                       i18n("WSAStartup() failed: $1")).arg(errno).arg(getLastOSError()).end();\r
+               throw ReException("WSAStartup() failed");\r
+       }\r
+#endif\r
+}\r
+\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPConnection::~ReTCPConnection() {\r
+}\r
+/**\r
+ * Finishes the connection (in both directions) and frees the resouces.\r
+ */\r
+void ReTCPConnection::close() {\r
+       if (m_handleSocket >= 0) {\r
+               reCloseSocket(m_handleSocket);\r
+               m_handleSocket = -1;\r
+       }\r
+}\r
+\r
+/**\r
+ * Frees the global resources.\r
+ */\r
+void ReTCPConnection::globalClose() {\r
+#if defined __WIN32__\r
+       WSACleanup();\r
+#endif\r
+}\r
+\r
+/**\r
+ * Sets the address given by a family and a string like "192.168.0.1:22".\r
+ *\r
+ * @param family       AF_INET or AF_INET6\r
+ * @param ip           the string describing the address, e.g. "192.168.0.1"\r
+ * @param port         the port of the peer\r
+ */\r
+void ReTCPConnection::setConnectedAddress(int family, const char* ip,\r
+    int port) {\r
+       m_family = family;\r
+       m_name = ip;\r
+       m_port = port;\r
+       int length = strlen(ip);\r
+       memcpy(m_ip, ip, length);\r
+       m_ip[length] = '\0';\r
+       m_name.appendChar(':').appendInt(port);\r
+}\r
+\r
+/**\r
+ * Receives a message.\r
+ *\r
+ * @param command      OUT: the received command\r
+ * @param data         OUT: the received data\r
+ */\r
+void ReTCPConnection::receive(ReByteBuffer& command, ReByteBuffer& data) {\r
+       command.setLength(8);\r
+       int received = recv(m_handleSocket, command.buffer(), 8, 0);\r
+       if (received != 8) {\r
+               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_RECEIVE_1,\r
+                   i18n("cannot receive ($1): $2 [$3]")).arg(errno).arg(received).arg(\r
+                   m_peerName).end();\r
+       } else {\r
+               int flags = 0;\r
+               int length = 0;\r
+               int found;\r
+               if ((found = sscanf(command.str(), "%8x", &length)) != 1\r
+                   || (flags = (length >> 24)) > 256 || (length &= 0xffffff) < 8) {\r
+                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_RECEIVE_2,\r
+                           i18n("wrong format: $1 [$2]")).arg(command).arg(m_peerName).end();\r
+               } else {\r
+                       data.setLength(length);\r
+                       int readBytes = 0;\r
+                       int rest = length;\r
+                       char* buf = data.buffer();\r
+                       int rounds = 0;\r
+                       while (readBytes < length) {\r
+                               rounds++;\r
+                               received = recv(m_handleSocket, buf, rest, 0);\r
+                               if (received > 0) {\r
+                                       buf += received;\r
+                                       rest -= received;\r
+                                       readBytes += received;\r
+                               } else if (received == 0) {\r
+                                       data.setLength(readBytes);\r
+                                       break;\r
+                               } else {\r
+                                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,\r
+                                           LC_RECEIVE_3, i18n("cannot receive ($1): $2 [$3]")).arg(\r
+                                       errno).arg(received).arg(m_peerName).end();\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if (rounds)\r
+                               rounds += 0;\r
+                       if (readBytes < length) {\r
+                               m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK,\r
+                                   LC_RECEIVE_4, i18n("too few bytes read: $1/$2 [$3]")).arg(\r
+                                   readBytes).arg(received).arg(m_peerName).end();\r
+                       } else {\r
+                               m_loggerOwner->logger()->sayF(LOG_DEBUG | CAT_NETWORK, LC_RECEIVE_5,\r
+                                       i18n("received: $1 bytes in $2 round(s) [$3]: $4")).arg(length).arg(rounds).arg(\r
+                                       m_peerName).arg(ReByteBuffer().appendDump(data.str(), data.length(), 80).str()).end();\r
+                       }\r
+                       command.setLength(0);\r
+                       if (readBytes >= 8) {\r
+                               command.append(data.str(), 8);\r
+                               data.remove(0, 8);\r
+                       }\r
+               }\r
+       }\r
+}\r
+/**\r
+ * Sends a command with (or without) data to the peer.\r
+ *\r
+ * @param command      the command to send\r
+ * @param data         the data to send\r
+ */\r
+void ReTCPConnection::send(const char* command, const char* data, int length) {\r
+       if (data == NULL)\r
+               length = 0;\r
+       else if (length < 0)\r
+               length = strlen(data);\r
+       m_toSend.ensureSize(length + 16);\r
+       ++m_noSent;\r
+       m_toSend.setLength(0);\r
+       int flags = 0x7b;\r
+       length += 8;\r
+       m_toSend.appendInt(length | (flags << 24), "%08x");\r
+       m_toSend.appendFix(command, -1, 8, 8, NULL);\r
+       m_toSend.append(data, length);\r
+       length += 8;\r
+       int sent = 0;\r
+       int rest = length;\r
+       const char* buf = m_toSend.str();\r
+       int rounds = 0;\r
+       while (rest > 0) {\r
+               rounds++;\r
+               if ((sent = ::send(m_handleSocket, buf, rest, 0)) > 0) {\r
+                       buf += sent;\r
+                       rest -= sent;\r
+               } else {\r
+                       m_loggerOwner->logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_WRITE_1,\r
+                           i18n("cannot send ($1): $2")).arg(errno).arg(m_peerName).end();\r
+                       break;\r
+               }\r
+       }\r
+       if (rest == 0)\r
+               m_loggerOwner->logger()->sayF(LOG_DEBUG | CAT_NETWORK, LC_WRITE_2,\r
+                           i18n("sent: $1 bytes in $2 round(s): $3")).arg(length).arg(rounds)\r
+                               .arg(ReByteBuffer().appendDump(data, length, 80).str()).end();\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param id           an identifier for logging\r
+ * @param logger       the logger for error handling\r
+ */\r
 #pragma warning( push )\r
 #pragma warning( disable : 4355 )\r
-ReTCPServerConnection::ReTCPServerConnection(int id, ReTCPServer* server) :
-           ReTCPConnection(id, this),
-           ReThread(true),
-           m_server(server) {
+ReTCPServerConnection::ReTCPServerConnection(int id, ReTCPServer* server) :\r
+           ReTCPConnection(id, this),\r
+           ReThread(true),\r
+           m_server(server) {\r
 #pragma warning( pop )\r
-}
-
-/**
- * Destructor.
- */
-ReTCPServerConnection::~ReTCPServerConnection() {
-}
-
-/**
- * Serves the commands of a single connection (in a single thread).
- */
-void ReTCPServerConnection::run() {
-       ReByteBuffer command;
-       ReNetCommandHandler::ProcessingState rc = ReNetCommandHandler::PS_UNDEF;
-       do {
-               receive(command, m_received);
-               rc = m_server->handler().handleNetCommand(command, m_received, this);
-               if (rc == ReNetCommandHandler::PS_UNKNOWN) {
-                       logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_HANDLE_CONNECTION_1,
-                           i18n("unknown command: $1 length: $2")).arg(command).arg(
-                           m_received.length()).end();
-               }
-       } while (rc != ReNetCommandHandler::PS_STOP && ! m_shouldStop);
-       if (rc != ReNetCommandHandler::PS_STOP)
-               m_pool->setShouldStop();
-       close();
-       m_id = -1;
-}
-
-/**
- * Constructor.
- *
- * @param port                         the port for listening
- * @param commandHandler       a handler which can process the incoming commands.
- *                                                     May be NULL
- * @param logger                       the logger for error handling
- * @param maxConnections       maximal count of threads handling a connection
- */
+}\r
+\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPServerConnection::~ReTCPServerConnection() {\r
+}\r
+\r
+/**\r
+ * Serves the commands of a single connection (in a single thread).\r
+ */\r
+void ReTCPServerConnection::run() {\r
+       ReByteBuffer command;\r
+       ReNetCommandHandler::ProcessingState rc = ReNetCommandHandler::PS_UNDEF;\r
+       do {\r
+               receive(command, m_received);\r
+               rc = m_server->handler().handleNetCommand(command, m_received, this);\r
+               if (rc == ReNetCommandHandler::PS_UNKNOWN) {\r
+                       logger()->sayF(LOG_ERROR | CAT_NETWORK, LC_HANDLE_CONNECTION_1,\r
+                           i18n("unknown command: $1 length: $2")).arg(command).arg(\r
+                           m_received.length()).end();\r
+               }\r
+       } while (rc != ReNetCommandHandler::PS_STOP && ! m_shouldStop);\r
+       if (rc != ReNetCommandHandler::PS_STOP)\r
+               m_pool->setShouldStop();\r
+       close();\r
+       m_id = -1;\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param port                         the port for listening\r
+ * @param commandHandler       a handler which can process the incoming commands.\r
+ *                                                     May be NULL\r
+ * @param logger                       the logger for error handling\r
+ * @param maxConnections       maximal count of threads handling a connection\r
+ */\r
 #pragma warning( push )\r
 #pragma warning( disable : 4355 )\r
-ReTCPServer::ReTCPServer(int port, class ReNetCommandHandler& commandHandler,
-    ReLogger* logger, int maxConnections) :
-           ReTCPConnection(0, this),
-           m_maxConnections(maxConnections),
-           m_countConnections(0),
-           m_connections(new ReTCPServerConnection*[maxConnections]),
-           m_handler(commandHandler),
-           m_logger(logger) {
-#pragma warning( pop )
-       m_port = port;
-       memset(m_connections, 0, maxConnections * sizeof *m_connections);
-}
-
-/**
- * Destructor.
- */
-ReTCPServer::~ReTCPServer() {
-       for (int ii = 0; ii < m_countConnections; ii++) {
-               delete m_connections[ii];
-               m_connections[ii] = NULL;
-       }
-       delete[] m_connections;
-       m_connections = NULL;
-}
-/**
- * Creates a server connection.
- *
- * @param id                   the connection identifier
- * @param handleSocket the handle of the read/write channel
- * @address                            the data about the client connection (ip, port)
- */
-ReTCPServerConnection* ReTCPServer::createConnection(int id, int handleSocket,
-    const struct sockaddr& address) {
-       ReTCPServerConnection* rc = NULL;
-       for (int ii = 0; rc == NULL && ii < m_maxConnections; ii++) {
-               if (m_connections[ii] == NULL)
-                       m_connections[ii] = rc = new ReTCPServerConnection(id, this);
-               else if (m_connections[ii]->id() < 0) {
-                       rc = m_connections[ii];
-                       rc->setId(id);
-               }
-       }
-       if (rc != NULL) {
-               rc->setHandleSocket(handleSocket);
-               char ip[INET6_ADDRSTRLEN];
-               inet_ntop(address.sa_family,
-                   address.sa_family == AF_INET ?
-                       (void *) &(((struct sockaddr_in*) &address)->sin_addr) :
-                       (void *) &(((struct sockaddr_in6*) &address)->sin6_addr), ip,
-                   sizeof ip);
-               int port =
-                   address.sa_family == AF_INET ?
-                       (int) ntohs(((struct sockaddr_in*) &address)->sin_port) :
-                       (int) ntohl(((struct sockaddr_in6*) &address)->sin6_port);
-               rc->setConnectedAddress(address.sa_family, ip, port);
-       }
-       return rc;
-}
-
-/**
- * Accepts connections and create a thread which will handle this connection.
- */
-bool ReTCPServer::listenForAll() {
-       bool rc = false;
-       struct addrinfo hints;
-       struct addrinfo* addrInfo;
-       ReThreadPool pool(m_maxConnections + 1, m_logger);
-
-// first, load up address structs with getaddrinfo():
-       memset(&hints, 0, sizeof hints);
-       hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
-       hints.ai_socktype = SOCK_STREAM;
-       hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
-
-       memcpy(m_ip, "0.0.0.0", 8);
-       m_name.set(m_ip).appendChar(':').appendInt(m_port);
-       getaddrinfo(NULL, ReByteBuffer().appendInt(m_port).str(), &hints,
-           &addrInfo);
-       m_family = addrInfo->ai_family;
-// make a socket:
-       m_handleSocket = socket(addrInfo->ai_family, addrInfo->ai_socktype,
-           addrInfo->ai_protocol);
-       if (m_handleSocket == -1) {
-               m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_LISTEN_FOR_ALL_1,
-                   i18n("cannot create a socket: $1")).arg(errno).end();
-       } else {
-               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,
-                   reinterpret_cast<const char*>(&yes), sizeof(int)) == -1) {
-                       m_logger->sayF(LOG_WARNING | CAT_NETWORK, LC_LISTEN_FOR_ALL_7,
-                           i18n("setsockopt() failed: $1")).arg(errno).end();
-                       // this error is not fatal, continue!
-               }
-               // bind it to the port we passed in to getaddrinfo():
-               if (bind(m_handleSocket, addrInfo->ai_addr, addrInfo->ai_addrlen) != 0)
-                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_LISTEN_FOR_ALL_2,
-                           i18n("cannot bind: $1")).arg(errno).end();
-               else {
-                       //Listen
-                       listen(m_handleSocket,
-                           m_maxConnections < 16 ? m_maxConnections : 16);
-
-                       //Accept and incoming connection
-                       m_logger->sayF(LOG_INFO | CAT_NETWORK, LC_LISTEN_FOR_ALL_3,
-                           i18n("listening on $1...")).arg(m_port).end();
-                       int nextId = 1;
-                       //Accept and incoming connection
-                       int clientSocket;
-                       struct sockaddr addrClient;
-                       socklen_t lengthAddr = sizeof(struct sockaddr_in);
-                       while ((clientSocket = accept(m_handleSocket,
-                           (struct sockaddr *) &addrClient, &lengthAddr)) != 0) {
-                               if (! pool.shouldStop()) {
-                                       m_logger->sayF(LOG_INFO | CAT_NETWORK, LC_LISTEN_FOR_ALL_4,
-                                           i18n("accepted: $1")).arg(m_port).end();
-                                       if (m_countConnections >= m_maxConnections) {
-                                               // close the connection at once:
-                                               m_logger->sayF(LOG_WARNING | CAT_NETWORK,
-                                                   LC_LISTEN_FOR_ALL_5,
-                                                   i18n(
-                                                       "connection refused (too many connections): $1"))
-                                                   .arg(m_port).end();
-                                               reCloseSocket(clientSocket);
-                                       } else {
-                                               ReTCPServerConnection* connection = createConnection(
-                                                   nextId++, clientSocket, addrClient);
-
-                                               if (!pool.startThread(connection)) {
-                                                       m_logger->sayF(LOG_ERROR | CAT_PROCESS,
-                                                           LC_LISTEN_FOR_ALL_6,
-                                                           i18n("cannot create a thread: $1")).arg(
-                                                           getLastOSError()).end();
-                                                       reCloseSocket(clientSocket);
-                                                       clientSocket = -1;
-                                               }
-                                       }
-                               }
-                       }
-                       if (pool.shouldStop()) {
-                               m_logger->say(LOG_INFO | CAT_PROCESS, LC_LISTEN_FOR_ALL_7,
-                                   i18n("stop request received"));
-                       }
-               }
-       }
-       return rc;
-}
-
-/**
- * Returns the logger.
- *
- * @param the logger for error handling
- */
-ReLogger* ReTCPServer::logger() {
-       return m_logger;
-}
-
-/**
- * Constructor.
- */
-ReNetCommandHandler::ReNetCommandHandler() :
-           m_nextHandler(NULL) {
-}
-
-/**
- * Adds a handler at the end of the handler chain.
- */
-void ReNetCommandHandler::addHandler(ReNetCommandHandler* handler) {
-       if (m_nextHandler == NULL)
-               m_nextHandler = handler;
-       else
-               m_nextHandler->addHandler(handler);
-}
-
-/**
- * Constructor.
- *
- * @param port         port for listening
- * @param logger       logger for error handling
- */
+ReTCPServer::ReTCPServer(int port, class ReNetCommandHandler& commandHandler,\r
+    ReLogger* logger, int maxConnections) :\r
+           ReTCPConnection(0, this),\r
+           m_maxConnections(maxConnections),\r
+           m_countConnections(0),\r
+           m_connections(new ReTCPServerConnection*[maxConnections]),\r
+           m_handler(commandHandler),\r
+           m_logger(logger) {\r
+#pragma warning( pop )\r
+       m_port = port;\r
+       memset(m_connections, 0, maxConnections * sizeof *m_connections);\r
+}\r
+\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPServer::~ReTCPServer() {\r
+       for (int ii = 0; ii < m_countConnections; ii++) {\r
+               delete m_connections[ii];\r
+               m_connections[ii] = NULL;\r
+       }\r
+       delete[] m_connections;\r
+       m_connections = NULL;\r
+}\r
+/**\r
+ * Creates a server connection.\r
+ *\r
+ * @param id                   the connection identifier\r
+ * @param handleSocket the handle of the read/write channel\r
+ * @address                            the data about the client connection (ip, port)\r
+ */\r
+ReTCPServerConnection* ReTCPServer::createConnection(int id, int handleSocket,\r
+    const struct sockaddr& address) {\r
+       ReTCPServerConnection* rc = NULL;\r
+       for (int ii = 0; rc == NULL && ii < m_maxConnections; ii++) {\r
+               if (m_connections[ii] == NULL)\r
+                       m_connections[ii] = rc = new ReTCPServerConnection(id, this);\r
+               else if (m_connections[ii]->id() < 0) {\r
+                       rc = m_connections[ii];\r
+                       rc->setId(id);\r
+               }\r
+       }\r
+       if (rc != NULL) {\r
+               rc->setHandleSocket(handleSocket);\r
+               char ip[INET6_ADDRSTRLEN];\r
+               inet_ntop(address.sa_family,\r
+                   address.sa_family == AF_INET ?\r
+                       (void *) &(((struct sockaddr_in*) &address)->sin_addr) :\r
+                       (void *) &(((struct sockaddr_in6*) &address)->sin6_addr), ip,\r
+                   sizeof ip);\r
+               int port =\r
+                   address.sa_family == AF_INET ?\r
+                       (int) ntohs(((struct sockaddr_in*) &address)->sin_port) :\r
+                       (int) ntohl(((struct sockaddr_in6*) &address)->sin6_port);\r
+               rc->setConnectedAddress(address.sa_family, ip, port);\r
+       }\r
+       return rc;\r
+}\r
+\r
+/**\r
+ * Accepts connections and create a thread which will handle this connection.\r
+ */\r
+bool ReTCPServer::listenForAll() {\r
+       bool rc = false;\r
+       struct addrinfo hints;\r
+       struct addrinfo* addrInfo;\r
+       ReThreadPool pool(m_maxConnections + 1, m_logger);\r
+\r
+// first, load up address structs with getaddrinfo():\r
+       memset(&hints, 0, sizeof hints);\r
+       hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever\r
+       hints.ai_socktype = SOCK_STREAM;\r
+       hints.ai_flags = AI_PASSIVE;     // fill in my IP for me\r
+\r
+       memcpy(m_ip, "0.0.0.0", 8);\r
+       m_name.set(m_ip).appendChar(':').appendInt(m_port);\r
+       getaddrinfo(NULL, ReByteBuffer().appendInt(m_port).str(), &hints,\r
+           &addrInfo);\r
+       m_family = addrInfo->ai_family;\r
+// make a socket:\r
+       m_handleSocket = socket(addrInfo->ai_family, addrInfo->ai_socktype,\r
+           addrInfo->ai_protocol);\r
+       if (m_handleSocket == -1) {\r
+               m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_LISTEN_FOR_ALL_1,\r
+                   i18n("cannot create a socket: $1")).arg(errno).end();\r
+       } else {\r
+               int yes = 1;\r
+               // Avoid the "Address already in use" error message of finished processes\r
+               // that are still waiting for the release by the kernel:\r
+               if (setsockopt(m_handleSocket, SOL_SOCKET, SO_REUSEADDR,\r
+                   reinterpret_cast<const char*>(&yes), sizeof(int)) == -1) {\r
+                       m_logger->sayF(LOG_WARNING | CAT_NETWORK, LC_LISTEN_FOR_ALL_7,\r
+                           i18n("setsockopt() failed: $1")).arg(errno).end();\r
+                       // this error is not fatal, continue!\r
+               }\r
+               // bind it to the port we passed in to getaddrinfo():\r
+               if (bind(m_handleSocket, addrInfo->ai_addr, addrInfo->ai_addrlen) != 0)\r
+                       m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_LISTEN_FOR_ALL_2,\r
+                           i18n("cannot bind: $1")).arg(errno).end();\r
+               else {\r
+                       //Listen\r
+                       listen(m_handleSocket,\r
+                           m_maxConnections < 16 ? m_maxConnections : 16);\r
+\r
+                       //Accept and incoming connection\r
+                       m_logger->sayF(LOG_INFO | CAT_NETWORK, LC_LISTEN_FOR_ALL_3,\r
+                           i18n("listening on $1...")).arg(m_port).end();\r
+                       int nextId = 1;\r
+                       //Accept and incoming connection\r
+                       int clientSocket;\r
+                       struct sockaddr addrClient;\r
+                       socklen_t lengthAddr = sizeof(struct sockaddr_in);\r
+                       while ((clientSocket = accept(m_handleSocket,\r
+                           (struct sockaddr *) &addrClient, &lengthAddr)) != 0) {\r
+                               if (! pool.shouldStop()) {\r
+                                       m_logger->sayF(LOG_INFO | CAT_NETWORK, LC_LISTEN_FOR_ALL_4,\r
+                                           i18n("accepted: $1")).arg(m_port).end();\r
+                                       if (m_countConnections >= m_maxConnections) {\r
+                                               // close the connection at once:\r
+                                               m_logger->sayF(LOG_WARNING | CAT_NETWORK,\r
+                                                   LC_LISTEN_FOR_ALL_5,\r
+                                                   i18n(\r
+                                                       "connection refused (too many connections): $1"))\r
+                                                   .arg(m_port).end();\r
+                                               reCloseSocket(clientSocket);\r
+                                       } else {\r
+                                               ReTCPServerConnection* connection = createConnection(\r
+                                                   nextId++, clientSocket, addrClient);\r
+\r
+                                               if (!pool.startThread(connection)) {\r
+                                                       m_logger->sayF(LOG_ERROR | CAT_PROCESS,\r
+                                                           LC_LISTEN_FOR_ALL_6,\r
+                                                           i18n("cannot create a thread: $1")).arg(\r
+                                                           getLastOSError()).end();\r
+                                                       reCloseSocket(clientSocket);\r
+                                                       clientSocket = -1;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       if (pool.shouldStop()) {\r
+                               m_logger->say(LOG_INFO | CAT_PROCESS, LC_LISTEN_FOR_ALL_7,\r
+                                   i18n("stop request received"));\r
+                       }\r
+               }\r
+       }\r
+       return rc;\r
+}\r
+\r
+/**\r
+ * Returns the logger.\r
+ *\r
+ * @param the logger for error handling\r
+ */\r
+ReLogger* ReTCPServer::logger() {\r
+       return m_logger;\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ */\r
+ReNetCommandHandler::ReNetCommandHandler() :\r
+           m_nextHandler(NULL) {\r
+}\r
+\r
+/**\r
+ * Adds a handler at the end of the handler chain.\r
+ */\r
+void ReNetCommandHandler::addHandler(ReNetCommandHandler* handler) {\r
+       if (m_nextHandler == NULL)\r
+               m_nextHandler = handler;\r
+       else\r
+               m_nextHandler->addHandler(handler);\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ *\r
+ * @param port         port for listening\r
+ * @param logger       logger for error handling\r
+ */\r
 #pragma warning( push )\r
 #pragma warning( disable : 4355 )\r
-ReTCPEchoServer::ReTCPEchoServer(int port, ReLogger* logger) :
-           ReTCPServer(port, *this, logger),
-           ReNetCommandHandler() {
-#pragma warning( pop )
-}
-/**
- * Destructor.
- */
-ReTCPEchoServer::~ReTCPEchoServer() {
-}
-
-/**
- * Handler for the commands "echo", "localtim" and "stop".
- *
- * @param command              a string describing what do to
- * @param data                 data of the command, may be empty
- * @param connection   the connection which can be used for answers
- * @result                             PS_UNKNOWN: command is not known<br>
- *                                             PS_PROCESSED: command successfully processed<br>
- *                                             PS_FAILED: command processed, error occurred<br>
- *                                             PS_ABORT: connection should be finished
- */
-ReNetCommandHandler::ProcessingState ReTCPEchoServer::handleNetCommand(
-    ReByteBuffer& command, ReByteBuffer& data, ReTCPConnection* connection) {
-       ProcessingState rc = PS_UNDEF;
-       if (command.equals("echo    ")) {
-               connection->send("Echo", data.str(), data.length());
-               rc = PS_PROCESSED;
-       } else if (command.equals("strlen  ")) {
-               m_toSend.setLength(0).appendInt(data.length());
-               connection->send("Strlen  ", m_toSend.str(), m_toSend.length());
-               rc = PS_PROCESSED;
-       } else if (command.equals("filldata")) {
-               int length = atol(data.str());
-               if (m_toSend.length() != length || !m_toSend.startsWith("xxxxx"))
-                       m_toSend.setLength(0).appendChar('x', length);
-               connection->send("Filldata", m_toSend.str(), m_toSend.length());
-               rc = PS_PROCESSED;
-       } else if (command.equals("localtim")) {
-               time_t now2 = time(NULL);
-               struct tm* now = localtime(&now2);
-               char buffer[128];
-               strftime(buffer, sizeof buffer, "%y.%m.%d %H:%M:%S", now);
-               connection->send("Localtim", buffer, strlen(buffer));
-               rc = PS_PROCESSED;
-       } else if (command.equals("stop    ")) {
-               rc = PS_STOP;
-       } else {
-               rc = PS_UNKNOWN;
-               if (m_nextHandler != NULL)
-                       rc = m_nextHandler->handleNetCommand(command, data, connection);
-       }
-       return rc;
-}
-
-/**
- * Constructor.
- */
-ReTCPStopClient::ReTCPStopClient(ReLogger* logger) :
-           ReTCPClient(logger) {
-}
-/**
- * Destructor.
- */
-ReTCPStopClient::~ReTCPStopClient() {
-}
-
-void ReTCPStopClient::stopServer(int port, const char* ip) {
-       connect(ip, port);
-       send("stop", NULL);
-}
+ReTCPEchoServer::ReTCPEchoServer(int port, ReLogger* logger) :\r
+           ReTCPServer(port, *this, logger),\r
+           ReNetCommandHandler() {\r
+#pragma warning( pop )\r
+}\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPEchoServer::~ReTCPEchoServer() {\r
+}\r
+\r
+/**\r
+ * Handler for the commands "echo", "localtim" and "stop".\r
+ *\r
+ * @param command              a string describing what do to\r
+ * @param data                 data of the command, may be empty\r
+ * @param connection   the connection which can be used for answers\r
+ * @result                             PS_UNKNOWN: command is not known<br>\r
+ *                                             PS_PROCESSED: command successfully processed<br>\r
+ *                                             PS_FAILED: command processed, error occurred<br>\r
+ *                                             PS_ABORT: connection should be finished\r
+ */\r
+ReNetCommandHandler::ProcessingState ReTCPEchoServer::handleNetCommand(\r
+    ReByteBuffer& command, ReByteBuffer& data, ReTCPConnection* connection) {\r
+       ProcessingState rc = PS_UNDEF;\r
+       if (command.equals("echo    ")) {\r
+               connection->send("Echo", data.str(), data.length());\r
+               rc = PS_PROCESSED;\r
+       } else if (command.equals("strlen  ")) {\r
+               m_toSend.setLength(0).appendInt(data.length());\r
+               connection->send("Strlen  ", m_toSend.str(), m_toSend.length());\r
+               rc = PS_PROCESSED;\r
+       } else if (command.equals("filldata")) {\r
+               int length = atol(data.str());\r
+               if (m_toSend.length() != length || !m_toSend.startsWith("xxxxx"))\r
+                       m_toSend.setLength(0).appendChar('x', length);\r
+               connection->send("Filldata", m_toSend.str(), m_toSend.length());\r
+               rc = PS_PROCESSED;\r
+       } else if (command.equals("localtim")) {\r
+               time_t now2 = time(NULL);\r
+               struct tm* now = localtime(&now2);\r
+               char buffer[128];\r
+               strftime(buffer, sizeof buffer, "%y.%m.%d %H:%M:%S", now);\r
+               connection->send("Localtim", buffer, strlen(buffer));\r
+               rc = PS_PROCESSED;\r
+       } else if (command.equals("stop    ")) {\r
+               rc = PS_STOP;\r
+       } else {\r
+               rc = PS_UNKNOWN;\r
+               if (m_nextHandler != NULL)\r
+                       rc = m_nextHandler->handleNetCommand(command, data, connection);\r
+       }\r
+       return rc;\r
+}\r
+\r
+/**\r
+ * Constructor.\r
+ */\r
+ReTCPStopClient::ReTCPStopClient(ReLogger* logger) :\r
+           ReTCPClient(logger) {\r
+}\r
+/**\r
+ * Destructor.\r
+ */\r
+ReTCPStopClient::~ReTCPStopClient() {\r
+}\r
+\r
+void ReTCPStopClient::stopServer(int port, const char* ip) {\r
+       connect(ip, port);\r
+       send("stop", NULL);\r
+}\r
index eb5b261c3cd37fb34e31c92c75cb04f89f5fc2e3..553c9b4f2a62d9adc2a0247e0663e7edd682ba28 100644 (file)
@@ -139,8 +139,9 @@ const char* s_syncExamples[] = {
 const char* s_tcpUsage[] = {\r
     "<command>: tcp [<opts>] <subcommand> [<param> ...]",\r
     "   test tool for network test", "<subcommand>:", "   server",\r
-    "   client <ip> [<rounds> [<print_interval>]]",\r
+    "   client <ip> [<direction> [<rounds> [<print_interval>]]]",\r
     "   <ip>: URL of the server", "   <rounds>: number of messages to send",\r
+    "   <direction>: 'upload', 'download' or 'mixed'",\r
     NULL };\r
 const char* s_tcpExamples[] = { "dirtool tcp -p 5555 server",\r
     "dirtool tcp -p 5555 client localhost 10000 10",\r
@@ -983,25 +984,25 @@ ReDirBatch::ReDirBatch(ReLogger* logger) :
            m_isExe(false) {\r
        // standard short options: D d O o P p T t v y Z z\r
        m_programArgs.addString("first",\r
-           i18n("defines the first line of the output"), '1', "first-line", true,\r
+               i18n("defines the first line of the output"), '1', "first-line", true,\r
 #if defined __linux__\r
-           "#! /bin/sh"\r
+               "#! /bin/sh"\r
 #elif defined __WIN32__\r
-           "rem this batch is created by dirtool"\r
+               "rem this batch is created by dirtool"\r
 #endif\r
-)      ;\r
+       );\r
        m_programArgs.addString("arguments", i18n("template for the output line.\n"\r
-                       "Possible placeholders: (e.g. e:\\data\\sample.txt)\n"\r
-                       "   !full!: e:\\data\\sample.txt\n"\r
-                       "   !path!: e:\\data\\\n"\r
-                       "   !basename!: sample.txt\n"\r
-                       "   !name!: sample\n"\r
-                       "   !ext!: .txt\n"\r
-                       "example: --arguments='echo !basename! in !path! found'"), 'a',\r
-               "arguments", false, NULL);\r
+               "Possible placeholders: (e.g. e:\\data\\sample.txt)\n"\r
+               "   !full!: e:\\data\\sample.txt\n"\r
+               "   !path!: e:\\data\\\n"\r
+               "   !basename!: sample.txt\n"\r
+               "   !name!: sample\n"\r
+               "   !ext!: .txt\n"\r
+               "example: --arguments='echo !basename! in !path! found'"), 'a',\r
+           "arguments", false, NULL);\r
        m_programArgs.addString("script",\r
-               i18n("name of the script (starts each output line)"), 'c', "script",\r
-               false, NULL);\r
+           i18n("name of the script (starts each output line)"), 'c', "script",\r
+           false, NULL);\r
 #if defined __WIN32__\r
        m_programArgs.addBool("isexe",\r
                i18n("supresses the starting 'call' of each output line"\r
@@ -1079,7 +1080,7 @@ void ReDirBatch::doIt() {
 #elif defined __WIN32__\r
        static const char* prefix = "rem ";\r
 #endif\r
-       printSummary(prefix);\r
+       printSummary (prefix);\r
 }\r
 \r
 /**\r
@@ -1833,7 +1834,7 @@ void ReDirTouch::processDir(ReDirStatus_t* entry) {
 \r
 static bool isAbsoluteTime(ReFileTime_t& time) {\r
 #if defined __linux__\r
-       static struct tm year1980 = { 0, 0, 0, 1, 1 - 1, 1980 - 1900 };\r
+       static struct tm year1980 = {0, 0, 0, 1, 1 - 1, 1980 - 1900};\r
        static time_t time1980 = mktime(&year1980);\r
        return time.tv_sec >= time1980;\r
 #elif defined __WIN32__\r
@@ -2077,47 +2078,47 @@ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties,
        struct stat info;\r
        if (properties == NULL) {\r
                if (stat(source, &info) == 0)\r
-                       properties = &info;\r
+               properties = &info;\r
                else {\r
                        if (logger != NULL)\r
-                               logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_1,\r
-                                   i18n("could not find: $1 (errno: $2)")).arg(source).arg(\r
-                                   errno).end();\r
+                       logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_1,\r
+                               i18n("could not find: $1 (errno: $2)")).arg(source).arg(\r
+                               errno).end();\r
                }\r
        }\r
        FILE* fpSource = fopen(source, "rb");\r
        if (fpSource == NULL) {\r
                if (logger != NULL)\r
-                       logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_2,\r
-                           i18n("cannot open $1 (errno: $2)")).arg(source).arg(errno).end();\r
+               logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_2,\r
+                       i18n("cannot open $1 (errno: $2)")).arg(source).arg(errno).end();\r
        } else {\r
                ReFileSize_t size =\r
-                   properties == NULL ? 0x7fffffff : properties->st_size;\r
+               properties == NULL ? 0x7fffffff : properties->st_size;\r
                FILE* fpTarget = fopen(target, "w");\r
                if (fpTarget == NULL) {\r
                        if (logger != NULL)\r
-                               logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_3,\r
-                                   i18n("cannot open $1 (errno: $2)")).arg(target).arg(errno)\r
-                                   .end();\r
+                       logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_3,\r
+                               i18n("cannot open $1 (errno: $2)")).arg(target).arg(errno)\r
+                       .end();\r
                } else {\r
                        while (size > 0) {\r
                                size_t blockSize = buffer.capacity();\r
                                if ((int) blockSize > size)\r
-                                       blockSize = size;\r
+                               blockSize = size;\r
                                if (fread(buffer.buffer(), blockSize, 1, fpSource) != 1) {\r
                                        if (logger != NULL)\r
-                                               logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_5,\r
-                                                   i18n("cannot read $1 (errno: $2)")).arg(source).arg(\r
-                                                   errno).end();\r
+                                       logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_5,\r
+                                               i18n("cannot read $1 (errno: $2)")).arg(source).arg(\r
+                                               errno).end();\r
                                        break;\r
                                }\r
                                size_t written;\r
                                if ((written = fwrite(buffer.buffer(), 1, blockSize, fpTarget))\r
-                                   != blockSize) {\r
+                                       != blockSize) {\r
                                        if (logger != NULL)\r
-                                               logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_6,\r
-                                                   i18n("cannot write $1 [$2] (errno: $3)")).arg(\r
-                                                   target).arg(written).arg(errno).end();\r
+                                       logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_6,\r
+                                               i18n("cannot write $1 [$2] (errno: $3)")).arg(\r
+                                               target).arg(written).arg(errno).end();\r
                                        break;\r
                                }\r
                                size -= blockSize;\r
@@ -2125,7 +2126,7 @@ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties,
                        rc = size == 0ll;\r
                        fclose(fpTarget);\r
                        if (properties != NULL)\r
-                               setProperties(target, properties, logger);\r
+                       setProperties(target, properties, logger);\r
                }\r
                fclose(fpSource);\r
        }\r
@@ -2158,24 +2159,24 @@ bool ReDirSync::setProperties(const char* fullName,
        times[1].tv_usec = properties->st_mtim.tv_nsec / 1000;\r
        if (utimes(fullName, times) != 0) {\r
                if (logger != NULL)\r
-                       logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_1,\r
-                           i18n("cannot change file times: $1 (errno: $2)")).arg(fullName)\r
-                           .arg(errno).end();\r
+               logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_1,\r
+                       i18n("cannot change file times: $1 (errno: $2)")).arg(fullName)\r
+               .arg(errno).end();\r
                rc = false;\r
        }\r
        int rights = properties->st_mode & (S_IRWXO | S_IRWXG | S_IRWXU);\r
        if (chmod(fullName, rights) != 0) {\r
                if (logger != NULL)\r
-                       logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_2,\r
-                           i18n("cannot change file modes: $1 (errno: $2)")).arg(fullName)\r
-                           .arg(errno).end();\r
+               logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_2,\r
+                       i18n("cannot change file modes: $1 (errno: $2)")).arg(fullName)\r
+               .arg(errno).end();\r
                rc = false;\r
        }\r
        if (chown(fullName, properties->st_uid, properties->st_gid) != 0) {\r
                if (logger != NULL)\r
-                       logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_3,\r
-                           i18n("cannot change file owner: $1 (errno: $2)")).arg(fullName)\r
-                           .arg(errno).end();\r
+               logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_PROPERTIES_3,\r
+                       i18n("cannot change file owner: $1 (errno: $2)")).arg(fullName)\r
+               .arg(errno).end();\r
                rc = false;\r
        }\r
 #endif\r
@@ -2375,49 +2376,77 @@ void ReDirTCP::doIt() {
        int port = m_programArgs.getInt("port");\r
        int bufferSize = m_programArgs.getInt("size") * 1024;\r
 \r
-       const char* command = m_programArgs.arg(0);\r
-       if (_stricmp(command, "server") == 0) {\r
+       ReByteBuffer command = m_programArgs.arg(0);\r
+       if (command.isPrefixOf("server", -1, true)) {\r
                ReTCPEchoServer server(port, m_logger);\r
                server.listenForAll();\r
-       } else if (_stricmp(command, "client") == 0) {\r
+       } else if (command.isPrefixOf("client", -1, true)) {\r
                const char* ip = m_programArgs.arg(1);\r
+               ReByteBuffer direction("download");\r
                int rounds = 10;\r
                int interval = 5;\r
-               if (m_programArgs.argCount() > 2)\r
-                       rounds = atoi(m_programArgs.arg(2));\r
+               if (m_programArgs.argCount() > 2) {\r
+                       direction = m_programArgs.arg(2);\r
+                       if (!direction.isPrefixOf("download", -1, true)\r
+                           && !direction.isPrefixOf("upload", -1, true)\r
+                           && !direction.isPrefixOf("mixed", -1, true))\r
+                               help(\r
+                                   "unknown direction: $1 (use 'download', 'upload' or 'mixed')",\r
+                                   direction.str());\r
+               }\r
                if (m_programArgs.argCount() > 3)\r
-                       interval = atoi(m_programArgs.arg(3));\r
-               ReTCPClient client(m_logger);\r
-               if (client.connect(ip, port)) {\r
-                       time_t start = time(NULL);\r
-                       ReByteBuffer message;\r
+                       rounds = atoi(m_programArgs.arg(3));\r
+               if (m_programArgs.argCount() > 4)\r
+                       interval = atoi(m_programArgs.arg(4));\r
+               if (tolower(direction.at(0)) == 'm')\r
+                       runMixedClient(ip, port, rounds, interval, bufferSize);\r
+               else\r
+                       runOneThreadClient(ip, port, rounds, interval, bufferSize,\r
+                           tolower(direction.at(0)) == 'u');\r
+       } else\r
+               help("unknown subcommand: $1", command.str());\r
+\r
+}\r
+void ReDirTCP::runMixedClient(const char* ip, int port, int rounds,\r
+    int interval, int bufferSize) {\r
+       help("not implemented: mixed");\r
+}\r
+void ReDirTCP::runOneThreadClient(const char* ip, int port, int rounds,\r
+    int interval, int bufferSize, bool upload) {\r
+       ReTCPClient client(m_logger);\r
+       if (client.connect(ip, port)) {\r
+               time_t start = time(NULL);\r
+               const char* command = upload ? "strlen" : "filldata";\r
+               ReByteBuffer message;\r
+               if (upload)\r
+                       message.appendInt(bufferSize);\r
+               else\r
                        message.appendChar('x', bufferSize);\r
-                       time_t lastPrint = start;\r
-                       int64_t size = 0;\r
-                       int duration = 0;\r
-                       for (int ii = 0; ii < rounds; ii++) {\r
-                               client.send("strlen", message.str(), message.length());\r
-                               size += message.length();\r
-                               time_t now = time(NULL);\r
-                               if (now >= lastPrint + interval) {\r
-                                       duration = int(now - start);\r
-                                       printf("%2d: %9.3f MiByte %8.3f kiByte/sec\n", ii,\r
-                                           size / 1024.0 / 1024, (double) size / duration / 1024);\r
-                                       lastPrint = now;\r
-                               }\r
+               time_t lastPrint = start;\r
+               int64_t size = 0;\r
+               int duration = 0;\r
+               ReByteBuffer answer, data;\r
+               for (int ii = 0; ii < rounds; ii++) {\r
+                       client.send(command, message.str(), message.length());\r
+                       client.receive(answer, data);\r
+                       size += message.length() + data.length();\r
+                       time_t now = time(NULL);\r
+                       if (now >= lastPrint + interval) {\r
+                               duration = int(now - start);\r
+                               printf("%2d: %9.3f MiByte %8.3f kiByte/sec %s\n", ii,\r
+                                   size / 1024.0 / 1024, (double) size / duration / 1024,\r
+                                   upload ? "up" : "down");\r
+                               lastPrint = now;\r
                        }\r
-                       duration = int(time(NULL) - start);\r
-                       if (duration == 0)\r
-                               duration = 1;\r
-                       printf("%2d: %9.3f MiByte %8.3f kiByte/sec\n", rounds,\r
-                           size / 1024.0 / 1024, (double) size / duration / 1024);\r
-\r
                }\r
-       } else\r
-               help("unknown subcommand: $1", command);\r
+               duration = int(time(NULL) - start);\r
+               if (duration == 0)\r
+                       duration = 1;\r
+               printf("%2d: %9.3f MiByte %8.3f kiByte %s/sec %s\n", rounds,\r
+                   size / 1024.0 / 1024, (double) size / duration / 1024, upload ? "up" : "down");\r
 \r
+       }\r
 }\r
-\r
 /**\r
  * Constructor.\r
  *\r
@@ -2425,20 +2454,21 @@ void ReDirTCP::doIt() {
  */\r
 ReDirWhich::ReDirWhich(ReLogger* logger) :\r
            ReTool(s_batchUsage, s_batchExamples, 0, 0, 0, true, logger) {\r
-       // no standard options:\r
+// no standard options:\r
        m_programArgs.addBool("all",\r
            i18n("all files will be found, not only the first"), 'a', "all", false);\r
        m_programArgs.addString("list",\r
            i18n("a path list (separator see option 'separator'"), 'l', "list",\r
-           false, NULL);\r
+           false,\r
+           NULL);\r
        m_programArgs.addString("separator",\r
-           i18n("separator between the path elements"), 's', "separator", false,\r
+               i18n("separator between the path elements"), 's', "separator", false,\r
 #if defined __linux__\r
-           ":"\r
+               ":"\r
 #elif defined __WIN32__\r
-           ";"\r
+               ";"\r
 #endif\r
-)      ;\r
+       );\r
        m_programArgs.addString("variable", i18n("variable with the path list"),\r
            'v', "variable", false, "PATH");\r
        m_hasStandardArgs = false;\r
index 0b52e5c01058fb370201751c992c1d3980fed238..3623a0a07821f23d4c1f08befe0b955d317ba646 100644 (file)
@@ -290,6 +290,10 @@ public:
        ReDirTCP(ReLogger* logger);
 protected:
        virtual void doIt();
+private:
+       void runMixedClient(const char* ip, int port, int rounds, int interval, int bufferSize);
+       void runOneThreadClient(const char* ip, int port, int rounds,
+           int interval, int bufferSize, bool upload);
 };
 
 /**