From 28afcddf62ae01cc69cdc84888712d5ea724ee1c Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 9 Jun 2002 22:20:28 +0000 Subject: [PATCH] added support for camping, i.e. repeatly trying to connect to the server until we succeed. --- client/CClient.cpp | 57 ++++++++++++++++++++++++++++++++++++---------- client/CClient.h | 12 +++++++++- client/client.cpp | 25 ++++++++++++++++++-- 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/client/CClient.cpp b/client/CClient.cpp index 61ed3f54..af8855f9 100644 --- a/client/CClient.cpp +++ b/client/CClient.cpp @@ -33,6 +33,7 @@ CClient::CClient(const CString& clientName) : m_input(NULL), m_output(NULL), m_screen(NULL), + m_camp(false), m_active(false), m_seqNum(0), m_ignoreMove(false) @@ -45,7 +46,12 @@ CClient::~CClient() // do nothing } -void CClient::run(const CNetworkAddress& serverAddress) +void CClient::camp(bool on) +{ + m_camp = on; +} + +bool CClient::run(const CNetworkAddress& serverAddress) { CThread* thread = NULL; try { @@ -74,9 +80,10 @@ void CClient::run(const CNetworkAddress& serverAddress) // clean up log((CLOG_NOTE "stopping client")); thread->cancel(); - thread->wait(); + void* result = thread->getResult(); delete thread; closeSecondaryScreen(); + return (result != NULL); } catch (XBase& e) { log((CLOG_ERR "client error: %s", e.what())); @@ -89,6 +96,7 @@ void CClient::run(const CNetworkAddress& serverAddress) delete thread; } closeSecondaryScreen(); + return true; } catch (XThread&) { // clean up @@ -183,14 +191,29 @@ void CClient::runSession(void*) std::auto_ptr input; std::auto_ptr output; try { - // allow connect this much time to succeed - CTimerThread timer(30.0); // FIXME -- timeout in member + for (;;) { + try { + // allow connect this much time to succeed + // FIXME -- timeout in member + CTimerThread timer(m_camp ? -1.0 : 30.0); - // create socket and attempt to connect to server - log((CLOG_DEBUG1 "connecting to server")); - assign(socket, new CTCPSocket(), ISocket); // FIXME -- use factory - socket->connect(*m_serverAddress); - log((CLOG_INFO "connected to server")); + // create socket and attempt to connect to server + log((CLOG_DEBUG1 "connecting to server")); + assign(socket, new CTCPSocket(), ISocket); // FIXME -- use factory + socket->connect(*m_serverAddress); + log((CLOG_INFO "connected to server")); + break; + } + catch (XSocketConnect&) { + // failed to connect. if not camping then rethrow. + if (!m_camp) { + throw; + } + + // we're camping. wait a bit before retrying + CThread::sleep(5.0); + } + } // get the input and output streams IInputStream* srcInput = socket->getInputStream(); @@ -208,6 +231,9 @@ void CClient::runSession(void*) } */ + // give handshake some time + CTimerThread timer(30.0); + // attach the packetizing filters assign(input, new CInputPacketStream(srcInput, own), IInputStream); assign(output, new COutputPacketStream(srcOutput, own), IOutputStream); @@ -238,7 +264,7 @@ void CClient::runSession(void*) catch (XIncompatibleClient& e) { log((CLOG_ERR "server has incompatible version %d.%d", e.getMajor(), e.getMinor())); m_screen->stop(); - return; + CThread::exit(NULL); } catch (XThread&) { log((CLOG_ERR "connection timed out")); @@ -248,7 +274,12 @@ void CClient::runSession(void*) catch (XBase& e) { log((CLOG_ERR "connection failed: %s", e.what())); m_screen->stop(); - return; + CThread::exit(NULL); + } + catch (...) { + log((CLOG_ERR "connection failed: ")); + m_screen->stop(); + CThread::exit(NULL); } try { @@ -346,7 +377,7 @@ void CClient::runSession(void*) catch (XBase& e) { log((CLOG_ERR "error: %s", e.what())); m_screen->stop(); - return; + CThread::exit(reinterpret_cast(1)); } // done with socket @@ -355,6 +386,8 @@ void CClient::runSession(void*) // exit event loop m_screen->stop(); + + CThread::exit(reinterpret_cast(1)); } // FIXME -- use factory to create screen diff --git a/client/CClient.h b/client/CClient.h index 30bcee50..992d51c9 100644 --- a/client/CClient.h +++ b/client/CClient.h @@ -19,8 +19,17 @@ public: // manipulators + // turn camping on or off. when camping the client will keep + // trying to connect to the server until it succeeds. this + // is useful if the client may start before the server. do + // not call this while in run(). + void camp(bool on); + // start the client. does not return until quit() is called. - void run(const CNetworkAddress& serverAddress); + // returns true if the client ever connected to the server + // successfully. may also throw exceptions after successfully + // connecting. + bool run(const CNetworkAddress& serverAddress); // tell client to exit gracefully void quit(); @@ -67,6 +76,7 @@ private: IOutputStream* m_output; ISecondaryScreen* m_screen; const CNetworkAddress* m_serverAddress; + bool m_camp; bool m_active; UInt32 m_seqNum; bool m_ignoreMove; diff --git a/client/client.cpp b/client/client.cpp index f7a12d5a..6f9ed543 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -29,6 +29,7 @@ static const char* pname = NULL; static bool s_restartable = true; static bool s_daemon = true; +static bool s_camp = true; static bool s_install = false; static bool s_uninstall = false; static const char* s_logFilter = NULL; @@ -76,13 +77,14 @@ static int realMain(CMutex* mutex) try { // create client s_client = new CClient(s_name); + s_client->camp(s_camp); // run client if (mutex != NULL) { mutex->unlock(); } locked = false; - s_client->run(s_serverAddress); + bool success = s_client->run(s_serverAddress); locked = true; if (mutex != NULL) { mutex->lock(); @@ -94,6 +96,8 @@ static int realMain(CMutex* mutex) CNetwork::cleanup(); CLog::setLock(NULL); s_logMutex = NULL; + + return success ? 16 : 0; } catch (...) { // clean up @@ -166,6 +170,7 @@ static void help() log((CLOG_PRINT "Usage: %s" " [--"DAEMON"|--no-"DAEMON"]" +" [--camp|--no-camp]" " [--debug ]" " [--name ]" " [--restart|--no-restart]" @@ -175,6 +180,9 @@ static void help() " --uninstall\n" "Start the synergy mouse/keyboard sharing server.\n" "\n" +"* --camp keep attempting to connect to the server until\n" +" successful.\n" +" --no-camp do not camp.\n" " -d, --debug filter out log messages with priorty below level.\n" " level may be: FATAL, ERROR, WARNING, NOTE, INFO,\n" " DEBUG, DEBUG1, DEBUG2.\n" @@ -184,7 +192,10 @@ static void help() " ourself to the server.\n" " -1, --no-restart do not try to restart the client if it fails for\n" " some reason.\n" -"* --restart restart the client automatically if it fails.\n" +"* --restart restart the client automatically if it fails for\n" +" some unexpected reason, including the server\n" +" disconnecting but not including failing to\n" +" connect to the server." " --install install server as a "DAEMON".\n" " --uninstall uninstall server "DAEMON".\n" " -h, --help display this help and exit.\n" @@ -248,6 +259,16 @@ static void parse(int argc, const char** argv) s_name = argv[++i]; } + else if (isArg(i, argc, argv, NULL, "--camp")) { + // enable camping + s_camp = true; + } + + else if (isArg(i, argc, argv, NULL, "--no-camp")) { + // disable camping + s_camp = false; + } + else if (isArg(i, argc, argv, "-f", "--no-"DAEMON)) { // not a daemon s_daemon = false;