-/*
- * 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
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
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
#elif defined __WIN32__\r
static const char* prefix = "rem ";\r
#endif\r
- printSummary(prefix);\r
+ printSummary (prefix);\r
}\r
\r
/**\r
\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
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
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
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
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
*/\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