--- /dev/null
+/*
+ * 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
+};
+
+/**
+ * Base class for TCP servers and clients.
+ */
+class ReTCPConnection {
+public:
+ ReTCPConnection(int id, ReLogger* logger);
+ virtual ~ReTCPConnection();
+public:
+ /**
+ * Returns the connection id.
+ * @return the id
+ */
+ inline int id() const {
+ return m_id;
+ }
+ /**
+ * Returns the connection port.
+ * @return the port
+ */
+ inline int port() const {
+ return m_port;
+ }
+ /**
+ * Returns the socket (ip:port).
+ * @return a string describing the socket
+ */
+ const char* socketName() const{
+ return m_socketName.str();
+ }
+ void receive(ReByteBuffer& command, ReByteBuffer& message);
+ void send(const char* command, const char* message, int length = -1);
+ /** Sets the socket handle.
+ * @param handle the socket handle to set
+ */
+ inline void setHandleSocket(int handle){
+ m_handleSocket = handle;
+ }
+ /** Sets the id
+ * @param id the id to set
+ */
+ inline void setId(int id){
+ m_id = id;
+ }
+protected:
+ int m_port;
+ ReByteBuffer m_socketName;
+ ReByteBuffer m_received;
+ ReLogger* m_logger;
+ int m_handleSocket;
+ struct sockaddr_in m_address;
+ int m_id;
+ uint32_t m_noSent;
+ uint32_t m_noReceived;
+};
+
+class ReTCPServerConnection: public ReTCPConnection {
+public:
+ ReTCPServerConnection(int id, ReLogger* logger);
+ virtual ~ReTCPServerConnection();
+public:
+ void handleConnection();
+
+};
+/**
+ * Implements a multithreaded TCP server.
+ */
+class ReTCPServer: public ReTCPConnection {
+public:
+ ReTCPServer(ReLogger* logger, int maxConnections = 16);
+ virtual ~ReTCPServer();
+public:
+ bool listenForAll();
+private:
+ ReTCPServerConnection* createConnection(int id, int socket,
+ struct sockaddr& address);
+protected:
+ int m_maxConnections;
+ int m_countConnections;
+ ReTCPServerConnection** m_connections;
+};
+
+/**
+ * Implements a TCP client.
+ */
+class ReTCPClient: public ReTCPConnection {
+public:
+ ReTCPClient(ReLogger* logger);
+ virtual ~ReTCPClient();
+};
+
+/**
+ * Constructor.
+ *
+ * @param id an identifier for logging
+ * @param logger the logger for error handling
+ */
+ReTCPConnection::ReTCPConnection(int id, ReLogger* logger) :
+ m_port(0),
+ m_socketName(),
+ m_received(),
+ m_logger(logger),
+ m_handleSocket(-1),
+ // m_address
+ m_id(id),
+ m_noSent(0),
+ m_noReceived(0){
+ memset(&m_address, 0, sizeof m_address);
+}
+
+/**
+ * Destructor.
+ */
+ReTCPConnection::~ReTCPConnection() {
+}
+
+void ReTCPConnection::receive(ReByteBuffer& command, ReByteBuffer& message){
+
+}
+void ReTCPConnection::send(const char* command, const char* message,
+ int length){
+ if (length < 0)
+ length = strlen(message);
+ ReByteBuffer header;
+ ++m_noSent;
+ header.appendFix(command, -1, 8, 8, NULL).appendInt(length, "%08x");
+ header.append(reinterpret_cast<char*>(&m_noSent), sizeof m_noSent);
+ int error = 0;
+#if defined __linux__
+ if (write(m_handleSocket, header.str(), header.length()) != header.length())
+ error = getLastOSError();
+ if (write(m_handleSocket, message, length) != length)
+ error = getLastOSError();
+ error = error + 0;
+#elif defined __WIN32__
+#endif
+ if (error != 0){
+ error += 0;
+ m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_WRITE_1,
+ i18n("Id=$1: cannot write ($1): $2"));
+ //.arg.(m_id)
+ // .arg(error).arg(m_socketName).end();
+ }
+}
+
+/**
+ * Constructor.
+ *
+ * @param id an identifier for logging
+ * @param logger the logger for error handling
+ */
+ReTCPServerConnection::ReTCPServerConnection(int id, ReLogger* logger) :
+ ReTCPConnection(id, logger) {
+}
+
+/**
+ * Destructor.
+ */
+ReTCPServerConnection::~ReTCPServerConnection(){
+}
+
+/**
+ * Constructor.
+ *
+ * @param logger the logger for error handling
+ * @param maxConnections maximal count of threads handling a connection
+ */
+ReTCPServer::ReTCPServer(ReLogger* logger, int maxConnections) :
+ ReTCPConnection(0, logger),
+ m_maxConnections(maxConnections),
+ m_countConnections(0),
+ m_connections(new ReTCPServerConnection*[maxConnections]) {
+}
+
+/**
+ * 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;
+}
+
+ReTCPServerConnection* ReTCPServer::createConnection(int id, int socket,
+ struct sockaddr& address) {
+ ReTCPServerConnection* rc = NULL;
+
+ for (int ii = 0; ii < m_maxConnections; ii++) {
+ if (m_connections[ii] == NULL)
+ m_connections[ii] = rc = new ReTCPServerConnection(id, m_logger);
+ else if (m_connections[ii]->id() < 0) {
+ rc = m_connections[ii];
+ rc->setId(id);
+ }
+ }
+ if (rc != NULL) {
+ rc->setHandleSocket(socket);
+ rc->setAddress(address);
+ }
+ return rc;
+}
+
+
+/**
+ * The start routine of pthread_start
+ *
+ * This will handle the connection for each client (in an own thread).
+ *
+ * @param pConnection a void* pointer to the ReTCPServerConnection instance
+ * */
+void* connection_handler(void *pConnection) {
+ ReTCPServerConnection* connection =
+ reinterpret_cast<ReTCPServerConnection*>(pConnection);
+ connection->handleConnection();
+}
+
+
+/**
+ * Accepts connections and create a thread which will handle this connection.
+ */
+bool ReTCPServer::listenForAll() {
+ bool rc = false;
+ //Create socket
+ m_handleSocket = socket(AF_INET, SOCK_STREAM, 0);
+ 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 {
+ //Prepare the sockaddr_in structure
+ m_address.sin_family = AF_INET;
+ m_address.sin_addr.s_addr = INADDR_ANY;
+ m_address.sin_port = htons(m_port);
+
+ //Bind
+ if (bind(m_handleSocket, (struct sockaddr *) &m_address, sizeof(m_address))
+ < 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, 3);
+
+ //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) {
+ 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 atonce:
+ m_logger->sayF(LOG_WARNING | CAT_NETWORK,
+ LC_LISTEN_FOR_ALL_5,
+ i18n("connection refused (too many connections): $1"))
+ .arg(m_port).end();
+ close(clientSocket);
+ } else {
+ pthread_t sniffer_thread;
+ ReTCPConnection* connection = createConnection(nextId++,
+ clientSocket, addrClient);
+
+ if (pthread_create(&sniffer_thread, NULL,
+ connection_handler, (void*) connection) < 0) {
+ m_logger->sayF(LOG_ERROR | CAT_PROCESS,
+ LC_LISTEN_FOR_ALL_6,
+ i18n("cannot create a thread: $1")).arg(
+ getLastOSError()).end();
+ close(clientSocket);
+ }
+
+ //Now join the thread , so that we dont terminate before the thread
+ //pthread_join( sniffer_thread , NULL);
+ puts("Handler assigned");
+ }
+ }
+
+ if (clientSocket < 0) {
+ perror("accept failed");
+ return 1;
+ }
+ }
+ }
+ return rc;
+}
+
+void ReTCPServerConnection::handleConnection() {
+ //Get the socket descriptor
+ int read_size;
+ char *message, client_message[2000];
+#if 0
+ receive(m_received, command);
+ if (! m_received.startsWith("login"))
+//Send some messages to the m_addrClient
+ message = "Greetings! I am your connection handler\n";
+ write(m_handleSocket, message, strlen(message));
+
+ message = "Now type something and i shall repeat what you type \n";
+ write(m_handleSocket, message, strlen(message));
+
+//Receive a message from m_addrClient
+ while ((read_size = recv(sock, client_message, 2000, 0)) > 0) {
+ //Send the message back to m_addrClient
+ write(m_handleSocket, client_message, strlen(client_message));
+ }
+
+ if (read_size == 0) {
+ puts("Client disconnected");
+ fflush(stdout);
+ } else if (read_size == -1) {
+ perror("recv failed");
+ }
+#endif
+//Free the socket pointer
+ close(m_handleSocket);
+ m_id = -1;
+}
+