From 0f3e128e179400a5810ff757a214e46158ce2b71 Mon Sep 17 00:00:00 2001 From: Serhii Hadzhilov <71632867+SerhiiGadzhilov@users.noreply.github.com> Date: Mon, 3 Oct 2022 17:08:24 +0300 Subject: [PATCH] Add ability to reconnect from server side (#7226) * Add ability to reconnect from server side * Fix code smell Co-authored-by: Serhii Hadzhilov --- .../InverseSockets/InverseServerSocket.cpp | 7 +- .../net/InverseSockets/InverseServerSocket.h | 3 + src/lib/net/SecureSocket.cpp | 21 +++-- src/lib/server/ClientListener.cpp | 91 +++++++++++-------- src/lib/server/ClientListener.h | 8 +- src/lib/server/Config.cpp | 5 + src/lib/server/Config.h | 7 ++ src/lib/server/Server.cpp | 4 + src/lib/synergy/ServerApp.cpp | 17 ++-- 9 files changed, 104 insertions(+), 59 deletions(-) diff --git a/src/lib/net/InverseSockets/InverseServerSocket.cpp b/src/lib/net/InverseSockets/InverseServerSocket.cpp index ba07e27a6..d31eddf35 100644 --- a/src/lib/net/InverseSockets/InverseServerSocket.cpp +++ b/src/lib/net/InverseSockets/InverseServerSocket.cpp @@ -51,7 +51,8 @@ void InverseServerSocket::bind(const NetworkAddress& addr) { Lock lock(&m_mutex); - m_socket.connectSocket(addr); + m_address = addr; + m_socket.connectSocket(m_address); setListeningJob(true); } @@ -110,8 +111,8 @@ InverseServerSocket::serviceListening(ISocketMultiplexerJob* job, bool, bool write, bool error) { if (error) { - close(); - return nullptr; + m_socket.connectSocket(m_address); + return job; } if (write) { m_events->addEvent(Event(m_events->forIListenSocket().connecting(), this)); diff --git a/src/lib/net/InverseSockets/InverseServerSocket.h b/src/lib/net/InverseSockets/InverseServerSocket.h index 6a8febfaf..7e0d09cc8 100644 --- a/src/lib/net/InverseSockets/InverseServerSocket.h +++ b/src/lib/net/InverseSockets/InverseServerSocket.h @@ -58,4 +58,7 @@ protected: Mutex m_mutex; IEventQueue* m_events; SocketMultiplexer* m_socketMultiplexer; + +private: + NetworkAddress m_address; }; diff --git a/src/lib/net/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp index f194be300..7add6994a 100644 --- a/src/lib/net/SecureSocket.cpp +++ b/src/lib/net/SecureSocket.cpp @@ -403,17 +403,20 @@ SecureSocket::freeSSL() // could cause events to get called on a dead object. TCPSocket // will do this, too, but the double-call is harmless setJob(NULL); - if (m_ssl->m_ssl != NULL) { - SSL_shutdown(m_ssl->m_ssl); + if (m_ssl) { + if (m_ssl->m_ssl != NULL) { + SSL_shutdown(m_ssl->m_ssl); - SSL_free(m_ssl->m_ssl); - m_ssl->m_ssl = NULL; + SSL_free(m_ssl->m_ssl); + m_ssl->m_ssl = NULL; + } + if (m_ssl->m_context != NULL) { + SSL_CTX_free(m_ssl->m_context); + m_ssl->m_context = NULL; + } + delete m_ssl; + m_ssl = nullptr; } - if (m_ssl->m_context != NULL) { - SSL_CTX_free(m_ssl->m_context); - m_ssl->m_context = NULL; - } - delete m_ssl; } int diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index 2aeca1f3f..e07778525 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -40,22 +40,13 @@ ClientListener::ClientListener(const NetworkAddress& address, m_socketFactory(socketFactory), m_server(NULL), m_events(events), - m_useSecureNetwork(enableCrypto) + m_useSecureNetwork(enableCrypto), + m_address(address) { assert(m_socketFactory != NULL); try { - m_listen = m_socketFactory->createListen(m_useSecureNetwork, ARCH->getAddrFamily(address.getAddress())); - - // setup event handler - m_events->adoptHandler(m_events->forIListenSocket().connecting(), - m_listen, - new TMethodEventJob(this, - &ClientListener::handleClientConnecting)); - - // bind listen address - LOG((CLOG_DEBUG1 "binding listen socket")); - m_listen->bind(address); + start(); } catch (XSocketAddressInUse&) { cleanupListenSocket(); @@ -72,31 +63,7 @@ ClientListener::ClientListener(const NetworkAddress& address, ClientListener::~ClientListener() { - LOG((CLOG_DEBUG1 "stop listening for clients")); - - // discard already connected clients - for (NewClients::iterator index = m_newClients.begin(); - index != m_newClients.end(); ++index) { - ClientProxyUnknown* client = *index; - m_events->removeHandler( - m_events->forClientProxyUnknown().success(), client); - m_events->removeHandler( - m_events->forClientProxyUnknown().failure(), client); - m_events->removeHandler( - m_events->forClientProxy().disconnected(), client); - delete client; - } - - // discard waiting clients - ClientProxy* client = getNextClient(); - while (client != NULL) { - delete client; - client = getNextClient(); - } - - m_events->removeHandler(m_events->forIListenSocket().connecting(), m_listen); - cleanupListenSocket(); - cleanupClientSockets(); + stop(); delete m_socketFactory; } @@ -119,6 +86,56 @@ ClientListener::getNextClient() return client; } +void ClientListener::start() +{ + m_listen = m_socketFactory->createListen(m_useSecureNetwork, ARCH->getAddrFamily(m_address.getAddress())); + + // setup event handler + m_events->adoptHandler(m_events->forIListenSocket().connecting(), + m_listen, + new TMethodEventJob(this, + &ClientListener::handleClientConnecting)); + + // bind listen address + LOG((CLOG_DEBUG1 "binding listen socket")); + m_listen->bind(m_address); +} + +void ClientListener::stop() +{ + LOG((CLOG_DEBUG1 "stop listening for clients")); + + // discard already connected clients + for (NewClients::iterator index = m_newClients.begin(); + index != m_newClients.end(); ++index) { + ClientProxyUnknown* client = *index; + m_events->removeHandler( + m_events->forClientProxyUnknown().success(), client); + m_events->removeHandler( + m_events->forClientProxyUnknown().failure(), client); + m_events->removeHandler( + m_events->forClientProxy().disconnected(), client); + delete client; + } + + // discard waiting clients + ClientProxy* client = getNextClient(); + while (client != nullptr) { + delete client; + client = getNextClient(); + } + + m_events->removeHandler(m_events->forIListenSocket().connecting(), m_listen); + cleanupListenSocket(); + cleanupClientSockets(); +} + +void ClientListener::restart() +{ + stop(); + start(); +} + void ClientListener::handleClientConnecting(const Event&, void*) { diff --git a/src/lib/server/ClientListener.h b/src/lib/server/ClientListener.h index 81ffaddd3..2fe2b4e65 100644 --- a/src/lib/server/ClientListener.h +++ b/src/lib/server/ClientListener.h @@ -66,7 +66,10 @@ public: ClientProxy* getNextClient(); //! Get server which owns this listener - Server* getServer() { return m_server; } + Server* getServer() { return m_server; } + + //! This method restarts the listener + void restart(); //@} @@ -79,6 +82,8 @@ private: void cleanupListenSocket(); void cleanupClientSockets(); + void start(); + void stop(); private: typedef std::set NewClients; @@ -93,4 +98,5 @@ private: IEventQueue* m_events; bool m_useSecureNetwork; ClientSockets m_clientSockets; + NetworkAddress m_address; }; diff --git a/src/lib/server/Config.cpp b/src/lib/server/Config.cpp index 0856018a3..be36199e0 100644 --- a/src/lib/server/Config.cpp +++ b/src/lib/server/Config.cpp @@ -658,6 +658,11 @@ String Config::getClientAddress() const return m_clientAddress; } +bool Config::isClientMode() const +{ + return (!m_clientAddress.empty()); +} + void Config::readSection(ConfigReadContext& s) { diff --git a/src/lib/server/Config.h b/src/lib/server/Config.h index 92ee0ee4f..aeb7bb46c 100644 --- a/src/lib/server/Config.h +++ b/src/lib/server/Config.h @@ -455,6 +455,13 @@ public: * Return client address a string. */ String getClientAddress() const; + + //! Return true if server started in client mode + /*! + * In client mode the server initiates connection to client + */ + bool isClientMode() const; + //@} private: diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index 437e1769e..79a575ae2 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -1432,6 +1432,10 @@ Server::handleClientDisconnected(const Event&, void* vclient) removeOldClient(client); delete client; + + if (m_args.m_config->isClientMode()) { + m_clientListener->restart(); + } } void diff --git a/src/lib/synergy/ServerApp.cpp b/src/lib/synergy/ServerApp.cpp index ffa1771e4..51a37adcb 100644 --- a/src/lib/synergy/ServerApp.cpp +++ b/src/lib/synergy/ServerApp.cpp @@ -682,13 +682,12 @@ ServerApp::handleScreenSwitched(const Event& e, void*) ISocketFactory* ServerApp::getSocketFactory() const { ISocketFactory* socketFactory = nullptr; - const auto clientAddress = args().m_config->getClientAddress(); - if (clientAddress.empty()) { - socketFactory = new TCPSocketFactory(m_events, getSocketMultiplexer()); + if (args().m_config->isClientMode()) { + socketFactory = new InverseSocketFactory(m_events, getSocketMultiplexer()); } else { - socketFactory = new InverseSocketFactory(m_events, getSocketMultiplexer()); + socketFactory = new TCPSocketFactory(m_events, getSocketMultiplexer()); } return socketFactory; @@ -696,15 +695,15 @@ ISocketFactory* ServerApp::getSocketFactory() const NetworkAddress ServerApp::getAddress(const NetworkAddress& address) const { - const auto clientAddress = args().m_config->getClientAddress(); - if (clientAddress.empty()) { - return address; - } - else { + if (args().m_config->isClientMode()) { + const auto clientAddress = args().m_config->getClientAddress(); NetworkAddress addr(clientAddress.c_str(), kDefaultPort); addr.resolve(); return addr; } + else { + return address; + } } int