00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CServerApp.h"
00020 #include "CLog.h"
00021 #include "CArch.h"
00022 #include "XSocket.h"
00023 #include "Version.h"
00024 #include "IEventQueue.h"
00025 #include "CServer.h"
00026 #include "CClientListener.h"
00027 #include "CClientProxy.h"
00028 #include "TMethodEventJob.h"
00029 #include "CServerTaskBarReceiver.h"
00030 #include "CPrimaryClient.h"
00031 #include "CScreen.h"
00032 #include "CSocketMultiplexer.h"
00033 #include "CEventQueue.h"
00034 #include "LogOutputters.h"
00035 #include "CFunctionEventJob.h"
00036 #include "TMethodJob.h"
00037 #include "CVncClient.h"
00038
00039 #if SYSAPI_WIN32
00040 #include "CArchMiscWindows.h"
00041 #endif
00042
00043 #if WINAPI_MSWINDOWS
00044 #include "CMSWindowsScreen.h"
00045 #elif WINAPI_XWINDOWS
00046 #include "CXWindowsScreen.h"
00047 #elif WINAPI_CARBON
00048 #include "COSXScreen.h"
00049 #endif
00050
00051 #include <iostream>
00052 #include <stdio.h>
00053 #include <fstream>
00054 #include "XScreen.h"
00055 #include "CTCPSocketFactory.h"
00056
00057 CEvent::Type CServerApp::s_reloadConfigEvent = CEvent::kUnknown;
00058
00059 CServerApp::CServerApp(CreateTaskBarReceiverFunc createTaskBarReceiver) :
00060 CApp(createTaskBarReceiver, new CArgs()),
00061 s_server(NULL),
00062 s_forceReconnectEvent(CEvent::kUnknown),
00063 s_resetServerEvent(CEvent::kUnknown),
00064 s_serverState(kUninitialized),
00065 s_serverScreen(NULL),
00066 s_primaryClient(NULL),
00067 s_listener(NULL),
00068 s_timer(NULL),
00069 m_vncClient(NULL)
00070 {
00071 }
00072
00073 CServerApp::~CServerApp()
00074 {
00075 }
00076
00077 CServerApp::CArgs::CArgs() :
00078 m_synergyAddress(NULL),
00079 m_config(NULL)
00080 {
00081 }
00082
00083 CServerApp::CArgs::~CArgs()
00084 {
00085 }
00086
00087 bool
00088 CServerApp::parseArg(const int& argc, const char* const* argv, int& i)
00089 {
00090 if (CApp::parseArg(argc, argv, i)) {
00091
00092 return true;
00093 }
00094
00095 else if (isArg(i, argc, argv, "-a", "--address", 1)) {
00096
00097 try {
00098 *args().m_synergyAddress = CNetworkAddress(argv[i + 1],
00099 kDefaultPort);
00100 args().m_synergyAddress->resolve();
00101 }
00102 catch (XSocketAddress& e) {
00103 LOG((CLOG_PRINT "%s: %s" BYE,
00104 args().m_pname, e.what(), args().m_pname));
00105 m_bye(kExitArgs);
00106 }
00107 ++i;
00108 }
00109
00110 else if (isArg(i, argc, argv, "-c", "--config", 1)) {
00111
00112 args().m_configFile = argv[++i];
00113 }
00114
00115 else {
00116
00117 return false;
00118 }
00119
00120
00121 return true;
00122 }
00123
00124 void
00125 CServerApp::parseArgs(int argc, const char* const* argv)
00126 {
00127
00128 int i;
00129 CApp::parseArgs(argc, argv, i);
00130
00131
00132 if (i != argc) {
00133 LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
00134 args().m_pname, argv[i], args().m_pname));
00135 m_bye(kExitArgs);
00136 }
00137
00138
00139 if (!CLOG->setFilter(args().m_logFilter)) {
00140 LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
00141 args().m_pname, args().m_logFilter, args().m_pname));
00142 m_bye(kExitArgs);
00143 }
00144
00145
00146 LOG((CLOG_INFO "%s Server on %s %s", kAppVersion, ARCH->getOSName().c_str(), ARCH->getPlatformName().c_str()));
00147
00148 loggingFilterWarning();
00149 }
00150
00151 void
00152 CServerApp::help()
00153 {
00154
00155 #if WINAPI_XWINDOWS
00156 # define WINAPI_ARGS \
00157 " [--display <display>] [--no-xinitthreads]"
00158 # define WINAPI_INFO \
00159 " --display <display> connect to the X server at <display>\n" \
00160 " --no-xinitthreads do not call XInitThreads()\n"
00161 #else
00162 # define WINAPI_ARGS
00163 # define WINAPI_INFO
00164 #endif
00165
00166 char buffer[2000];
00167 sprintf(
00168 buffer,
00169 "Usage: %s"
00170 " [--address <address>]"
00171 " [--config <pathname>]"
00172 WINAPI_ARGS
00173 HELP_SYS_ARGS
00174 HELP_COMMON_ARGS
00175 "\n\n"
00176 "Start the synergy mouse/keyboard sharing server.\n"
00177 "\n"
00178 " -a, --address <address> listen for clients on the given address.\n"
00179 " -c, --config <pathname> use the named configuration file instead.\n"
00180 HELP_COMMON_INFO_1
00181 WINAPI_INFO
00182 HELP_SYS_INFO
00183 HELP_COMMON_INFO_2
00184 "\n"
00185 "* marks defaults.\n"
00186 "\n"
00187 "The argument for --address is of the form: [<hostname>][:<port>]. The\n"
00188 "hostname must be the address or hostname of an interface on the system.\n"
00189 "The default is to listen on all interfaces. The port overrides the\n"
00190 "default port, %d.\n"
00191 "\n"
00192 "If no configuration file pathname is provided then the first of the\n"
00193 "following to load successfully sets the configuration:\n"
00194 " %s\n"
00195 " %s\n",
00196 args().m_pname, kDefaultPort,
00197 ARCH->concatPath(ARCH->getUserDirectory(), USR_CONFIG_NAME).c_str(),
00198 ARCH->concatPath(ARCH->getSystemDirectory(), SYS_CONFIG_NAME).c_str()
00199 );
00200
00201 LOG((CLOG_PRINT "%s", buffer));
00202 }
00203
00204 void
00205 CServerApp::reloadSignalHandler(CArch::ESignal, void*)
00206 {
00207 EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(),
00208 IEventQueue::getSystemTarget()));
00209 }
00210
00211 void
00212 CServerApp::reloadConfig(const CEvent&, void*)
00213 {
00214 LOG((CLOG_DEBUG "reload configuration"));
00215 if (loadConfig(args().m_configFile)) {
00216 if (s_server != NULL) {
00217 s_server->setConfig(*args().m_config);
00218 }
00219 LOG((CLOG_NOTE "reloaded configuration"));
00220 }
00221 }
00222
00223 void
00224 CServerApp::loadConfig()
00225 {
00226 bool loaded = false;
00227
00228
00229 if (!args().m_configFile.empty()) {
00230 loaded = loadConfig(args().m_configFile);
00231 }
00232
00233
00234 else {
00235
00236 CString path = ARCH->getUserDirectory();
00237 if (!path.empty()) {
00238
00239 path = ARCH->concatPath(path, USR_CONFIG_NAME);
00240
00241
00242 if (loadConfig(path)) {
00243 loaded = true;
00244 args().m_configFile = path;
00245 }
00246 }
00247 if (!loaded) {
00248
00249 path = ARCH->getSystemDirectory();
00250 if (!path.empty()) {
00251 path = ARCH->concatPath(path, SYS_CONFIG_NAME);
00252 if (loadConfig(path)) {
00253 loaded = true;
00254 args().m_configFile = path;
00255 }
00256 }
00257 }
00258 }
00259
00260 if (!loaded) {
00261 LOG((CLOG_PRINT "%s: no configuration available", args().m_pname));
00262 m_bye(kExitConfig);
00263 }
00264 }
00265
00266 bool
00267 CServerApp::loadConfig(const CString& pathname)
00268 {
00269 try {
00270
00271 LOG((CLOG_DEBUG "opening configuration \"%s\"", pathname.c_str()));
00272 std::ifstream configStream(pathname.c_str());
00273 if (!configStream.is_open()) {
00274
00275
00276
00277 LOG((CLOG_DEBUG "cannot open configuration \"%s\"",
00278 pathname.c_str()));
00279 return false;
00280 }
00281 configStream >> *args().m_config;
00282 LOG((CLOG_DEBUG "configuration read successfully"));
00283 return true;
00284 }
00285 catch (XConfigRead& e) {
00286
00287 LOG((CLOG_ERR "cannot read configuration \"%s\": %s",
00288 pathname.c_str(), e.what()));
00289 }
00290 return false;
00291 }
00292
00293 CEvent::Type
00294 CServerApp::getReloadConfigEvent()
00295 {
00296 return EVENTQUEUE->registerTypeOnce(s_reloadConfigEvent, "reloadConfig");
00297 }
00298
00299 void
00300 CServerApp::forceReconnect(const CEvent&, void*)
00301 {
00302 if (s_server != NULL) {
00303 s_server->disconnect();
00304 }
00305 }
00306
00307 CEvent::Type
00308 CServerApp::getForceReconnectEvent()
00309 {
00310 return EVENTQUEUE->registerTypeOnce(s_forceReconnectEvent, "forceReconnect");
00311 }
00312
00313 CEvent::Type
00314 CServerApp::getResetServerEvent()
00315 {
00316 return EVENTQUEUE->registerTypeOnce(s_resetServerEvent, "resetServer");
00317 }
00318
00319 void
00320 CServerApp::handleClientConnected(const CEvent&, void* vlistener)
00321 {
00322 CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
00323 CClientProxy* client = listener->getNextClient();
00324 if (client != NULL) {
00325 s_server->adoptClient(client);
00326 updateStatus();
00327
00328 if (args().m_enableVnc) {
00329
00330 CVncClient* vncClient = new CVncClient("192.168.0.13", client->getName());
00331 vncClient->start();
00332 m_vncClients.insert(std::pair<CString, CVncClient*>(client->getName(), vncClient));
00333 }
00334 }
00335 }
00336
00337 void
00338 CServerApp::handleClientsDisconnected(const CEvent&, void*)
00339 {
00340 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00341 }
00342
00343 void
00344 CServerApp::closeServer(CServer* server)
00345 {
00346 if (server == NULL) {
00347 return;
00348 }
00349
00350
00351 server->disconnect();
00352
00353
00354 double timeout = 3.0;
00355 CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(timeout, NULL);
00356 EVENTQUEUE->adoptHandler(CEvent::kTimer, timer,
00357 new TMethodEventJob<CServerApp>(this, &CServerApp::handleClientsDisconnected));
00358 EVENTQUEUE->adoptHandler(CServer::getDisconnectedEvent(), server,
00359 new TMethodEventJob<CServerApp>(this, &CServerApp::handleClientsDisconnected));
00360
00361 EVENTQUEUE->loop();
00362
00363 EVENTQUEUE->removeHandler(CEvent::kTimer, timer);
00364 EVENTQUEUE->deleteTimer(timer);
00365 EVENTQUEUE->removeHandler(CServer::getDisconnectedEvent(), server);
00366
00367
00368 delete server;
00369 }
00370
00371 void
00372 CServerApp::stopRetryTimer()
00373 {
00374 if (s_timer != NULL) {
00375 EVENTQUEUE->deleteTimer(s_timer);
00376 EVENTQUEUE->removeHandler(CEvent::kTimer, NULL);
00377 s_timer = NULL;
00378 }
00379 }
00380
00381 void
00382 CServerApp::updateStatus()
00383 {
00384 updateStatus("");
00385 }
00386
00387 void CServerApp::updateStatus( const CString& msg )
00388 {
00389 if (m_taskBarReceiver)
00390 {
00391 m_taskBarReceiver->updateStatus(s_server, msg);
00392 }
00393 }
00394
00395 void
00396 CServerApp::closeClientListener(CClientListener* listen)
00397 {
00398 if (listen != NULL) {
00399 EVENTQUEUE->removeHandler(CClientListener::getConnectedEvent(), listen);
00400 delete listen;
00401 }
00402 }
00403
00404 void
00405 CServerApp::stopServer()
00406 {
00407 if (s_serverState == kStarted) {
00408 closeClientListener(s_listener);
00409 closeServer(s_server);
00410 s_server = NULL;
00411 s_listener = NULL;
00412 s_serverState = kInitialized;
00413 }
00414 else if (s_serverState == kStarting) {
00415 stopRetryTimer();
00416 s_serverState = kInitialized;
00417 }
00418 assert(s_server == NULL);
00419 assert(s_listener == NULL);
00420 }
00421
00422 void
00423 CServerApp::closePrimaryClient(CPrimaryClient* primaryClient)
00424 {
00425 delete primaryClient;
00426 }
00427
00428 void
00429 CServerApp::closeServerScreen(CScreen* screen)
00430 {
00431 if (screen != NULL) {
00432 EVENTQUEUE->removeHandler(IScreen::getErrorEvent(),
00433 screen->getEventTarget());
00434 EVENTQUEUE->removeHandler(IScreen::getSuspendEvent(),
00435 screen->getEventTarget());
00436 EVENTQUEUE->removeHandler(IScreen::getResumeEvent(),
00437 screen->getEventTarget());
00438 delete screen;
00439 }
00440 }
00441
00442 void CServerApp::cleanupServer()
00443 {
00444 stopServer();
00445 if (s_serverState == kInitialized) {
00446 closePrimaryClient(s_primaryClient);
00447 closeServerScreen(s_serverScreen);
00448 s_primaryClient = NULL;
00449 s_serverScreen = NULL;
00450 s_serverState = kUninitialized;
00451 }
00452 else if (s_serverState == kInitializing ||
00453 s_serverState == kInitializingToStart) {
00454 stopRetryTimer();
00455 s_serverState = kUninitialized;
00456 }
00457 assert(s_primaryClient == NULL);
00458 assert(s_serverScreen == NULL);
00459 assert(s_serverState == kUninitialized);
00460 }
00461
00462 void
00463 CServerApp::retryHandler(const CEvent&, void*)
00464 {
00465
00466 assert(s_timer != NULL);
00467 stopRetryTimer();
00468
00469
00470 switch (s_serverState) {
00471 case kUninitialized:
00472 case kInitialized:
00473 case kStarted:
00474 assert(0 && "bad internal server state");
00475 break;
00476
00477 case kInitializing:
00478 LOG((CLOG_DEBUG1 "retry server initialization"));
00479 s_serverState = kUninitialized;
00480 if (!initServer()) {
00481 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00482 }
00483 break;
00484
00485 case kInitializingToStart:
00486 LOG((CLOG_DEBUG1 "retry server initialization"));
00487 s_serverState = kUninitialized;
00488 if (!initServer()) {
00489 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00490 }
00491 else if (s_serverState == kInitialized) {
00492 LOG((CLOG_DEBUG1 "starting server"));
00493 if (!startServer()) {
00494 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00495 }
00496 }
00497 break;
00498
00499 case kStarting:
00500 LOG((CLOG_DEBUG1 "retry starting server"));
00501 s_serverState = kInitialized;
00502 if (!startServer()) {
00503 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00504 }
00505 break;
00506 }
00507 }
00508
00509 bool CServerApp::initServer()
00510 {
00511
00512 if (s_serverState != kUninitialized) {
00513 return true;
00514 }
00515
00516 double retryTime;
00517 CScreen* serverScreen = NULL;
00518 CPrimaryClient* primaryClient = NULL;
00519 try {
00520 CString name = args().m_config->getCanonicalName(args().m_name);
00521 serverScreen = openServerScreen();
00522 primaryClient = openPrimaryClient(name, serverScreen);
00523 s_serverScreen = serverScreen;
00524 s_primaryClient = primaryClient;
00525 s_serverState = kInitialized;
00526 updateStatus();
00527 return true;
00528 }
00529 catch (XScreenUnavailable& e) {
00530 LOG((CLOG_WARN "primary screen unavailable: %s", e.what()));
00531 closePrimaryClient(primaryClient);
00532 closeServerScreen(serverScreen);
00533 updateStatus(CString("primary screen unavailable: ") + e.what());
00534 retryTime = e.getRetryTime();
00535 }
00536 catch (XScreenOpenFailure& e) {
00537 LOG((CLOG_CRIT "failed to start server: %s", e.what()));
00538 closePrimaryClient(primaryClient);
00539 closeServerScreen(serverScreen);
00540 return false;
00541 }
00542 catch (XBase& e) {
00543 LOG((CLOG_CRIT "failed to start server: %s", e.what()));
00544 closePrimaryClient(primaryClient);
00545 closeServerScreen(serverScreen);
00546 return false;
00547 }
00548
00549 if (args().m_restartable) {
00550
00551 assert(s_timer == NULL);
00552 LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime));
00553 s_timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL);
00554 EVENTQUEUE->adoptHandler(CEvent::kTimer, s_timer,
00555 new TMethodEventJob<CServerApp>(this, &CServerApp::retryHandler));
00556 s_serverState = kInitializing;
00557 return true;
00558 }
00559 else {
00560
00561 return false;
00562 }
00563 }
00564
00565 CScreen* CServerApp::openServerScreen()
00566 {
00567 CScreen* screen = createScreen();
00568 EVENTQUEUE->adoptHandler(IScreen::getErrorEvent(),
00569 screen->getEventTarget(),
00570 new TMethodEventJob<CServerApp>(
00571 this, &CServerApp::handleScreenError));
00572 EVENTQUEUE->adoptHandler(IScreen::getSuspendEvent(),
00573 screen->getEventTarget(),
00574 new TMethodEventJob<CServerApp>(
00575 this, &CServerApp::handleSuspend));
00576 EVENTQUEUE->adoptHandler(IScreen::getResumeEvent(),
00577 screen->getEventTarget(),
00578 new TMethodEventJob<CServerApp>(
00579 this, &CServerApp::handleResume));
00580 return screen;
00581 }
00582
00583 bool
00584 CServerApp::startServer()
00585 {
00586
00587 if (s_serverState == kStarting || s_serverState == kStarted) {
00588 return true;
00589 }
00590
00591
00592 if (s_serverState != kInitialized) {
00593 if (!initServer()) {
00594
00595 return false;
00596 }
00597 if (s_serverState == kInitializing) {
00598
00599 s_serverState = kInitializingToStart;
00600 return true;
00601 }
00602 assert(s_serverState == kInitialized);
00603 }
00604
00605 double retryTime;
00606 CClientListener* listener = NULL;
00607 try {
00608 listener = openClientListener(args().m_config->getSynergyAddress());
00609 s_server = openServer(*args().m_config, s_primaryClient);
00610 listener->setServer(s_server);
00611 s_listener = listener;
00612 updateStatus();
00613 LOG((CLOG_NOTE "started server, waiting for clients"));
00614 s_serverState = kStarted;
00615 return true;
00616 }
00617 catch (XSocketAddressInUse& e) {
00618 LOG((CLOG_WARN "cannot listen for clients: %s", e.what()));
00619 closeClientListener(listener);
00620 updateStatus(CString("cannot listen for clients: ") + e.what());
00621 retryTime = 10.0;
00622 }
00623 catch (XBase& e) {
00624 LOG((CLOG_CRIT "failed to start server: %s", e.what()));
00625 closeClientListener(listener);
00626 return false;
00627 }
00628
00629 if (args().m_restartable) {
00630
00631 assert(s_timer == NULL);
00632 LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime));
00633 s_timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL);
00634 EVENTQUEUE->adoptHandler(CEvent::kTimer, s_timer,
00635 new TMethodEventJob<CServerApp>(this, &CServerApp::retryHandler));
00636 s_serverState = kStarting;
00637 return true;
00638 }
00639 else {
00640
00641 return false;
00642 }
00643 }
00644
00645 CScreen*
00646 CServerApp::createScreen()
00647 {
00648 #if WINAPI_MSWINDOWS
00649 return new CScreen(new CMSWindowsScreen(
00650 true, args().m_noHooks, args().m_gameDevice, args().m_stopOnDeskSwitch));
00651 #elif WINAPI_XWINDOWS
00652 return new CScreen(new CXWindowsScreen(
00653 args().m_display, true, args().m_disableXInitThreads, 0, *EVENTQUEUE));
00654 #elif WINAPI_CARBON
00655 return new CScreen(new COSXScreen(true));
00656 #endif
00657 }
00658
00659 CPrimaryClient*
00660 CServerApp::openPrimaryClient(const CString& name, CScreen* screen)
00661 {
00662 LOG((CLOG_DEBUG1 "creating primary screen"));
00663 return new CPrimaryClient(name, screen);
00664
00665 }
00666
00667 void
00668 CServerApp::handleScreenError(const CEvent&, void*)
00669 {
00670 LOG((CLOG_CRIT "error on screen"));
00671 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00672 }
00673
00674 void
00675 CServerApp::handleSuspend(const CEvent&, void*)
00676 {
00677 if (!m_suspended) {
00678 LOG((CLOG_INFO "suspend"));
00679 stopServer();
00680 m_suspended = true;
00681 }
00682 }
00683
00684 void
00685 CServerApp::handleResume(const CEvent&, void*)
00686 {
00687 if (m_suspended) {
00688 LOG((CLOG_INFO "resume"));
00689 startServer();
00690 m_suspended = false;
00691 }
00692 }
00693
00694 CClientListener*
00695 CServerApp::openClientListener(const CNetworkAddress& address)
00696 {
00697 CClientListener* listen =
00698 new CClientListener(address, new CTCPSocketFactory, NULL, args().m_crypto);
00699 EVENTQUEUE->adoptHandler(CClientListener::getConnectedEvent(), listen,
00700 new TMethodEventJob<CServerApp>(
00701 this, &CServerApp::handleClientConnected, listen));
00702 return listen;
00703 }
00704
00705 CServer*
00706 CServerApp::openServer(const CConfig& config, CPrimaryClient* primaryClient)
00707 {
00708 CServer* server = new CServer(config, primaryClient, s_serverScreen);
00709
00710 try {
00711 EVENTQUEUE->adoptHandler(
00712 CServer::getDisconnectedEvent(), server,
00713 new TMethodEventJob<CServerApp>(this, &CServerApp::handleNoClients));
00714
00715 EVENTQUEUE->adoptHandler(
00716 CServer::getScreenSwitchedEvent(), server,
00717 new TMethodEventJob<CServerApp>(this, &CServerApp::handleScreenSwitched));
00718
00719 } catch (std::bad_alloc &ba) {
00720 delete server;
00721 throw ba;
00722 }
00723
00724 return server;
00725 }
00726
00727 void
00728 CServerApp::handleNoClients(const CEvent&, void*)
00729 {
00730 updateStatus();
00731 }
00732
00733 void
00734 CServerApp::handleScreenSwitched(const CEvent& e, void*)
00735 {
00736 if (!args().m_enableVnc)
00737 return;
00738
00739 if (m_vncClient != NULL) {
00740 LOG((CLOG_DEBUG "hiding vnc viewer for: %s", m_vncClient->m_screen.c_str()));
00741 m_vncClient->hideViewer();
00742 }
00743
00744 CServer::CSwitchToScreenInfo* info = reinterpret_cast<CServer::CSwitchToScreenInfo*>(e.getData());
00745 std::map<CString, CVncClient*>::iterator it = m_vncClients.find(info->m_screen);
00746 if (it == m_vncClients.end()) {
00747 LOG((CLOG_DEBUG "could not find vnc client for: %s", info->m_screen));
00748 return;
00749 }
00750
00751 LOG((CLOG_DEBUG "showing vnc viewer for: %s", info->m_screen));
00752 m_vncClient = it->second;
00753 m_vncClient->showViewer();
00754 }
00755
00756 int
00757 CServerApp::mainLoop()
00758 {
00759
00760
00761 CSocketMultiplexer multiplexer;
00762
00763
00764
00765 if (args().m_config->begin() == args().m_config->end()) {
00766 args().m_config->addScreen(args().m_name);
00767 }
00768
00769
00770
00771
00772 if (args().m_synergyAddress->isValid()) {
00773 args().m_config->setSynergyAddress(*args().m_synergyAddress);
00774 }
00775 else if (!args().m_config->getSynergyAddress().isValid()) {
00776 args().m_config->setSynergyAddress(CNetworkAddress(kDefaultPort));
00777 }
00778
00779
00780 CString primaryName = args().m_config->getCanonicalName(args().m_name);
00781 if (primaryName.empty()) {
00782 LOG((CLOG_CRIT "unknown screen name `%s'", args().m_name.c_str()));
00783 return kExitFailed;
00784 }
00785
00786
00787 appUtil().startNode();
00788
00789
00790
00791 if (argsBase().m_enableIpc) {
00792 initIpcClient();
00793 }
00794
00795
00796 ARCH->plugin().init(s_serverScreen->getEventTarget());
00797
00798
00799 ARCH->setSignalHandler(CArch::kHANGUP, &reloadSignalHandler, NULL);
00800 EVENTQUEUE->adoptHandler(getReloadConfigEvent(),
00801 IEventQueue::getSystemTarget(),
00802 new TMethodEventJob<CServerApp>(this, &CServerApp::reloadConfig));
00803
00804
00805
00806 EVENTQUEUE->adoptHandler(getForceReconnectEvent(),
00807 IEventQueue::getSystemTarget(),
00808 new TMethodEventJob<CServerApp>(this, &CServerApp::forceReconnect));
00809
00810
00811
00812 EVENTQUEUE->adoptHandler(getResetServerEvent(),
00813 IEventQueue::getSystemTarget(),
00814 new TMethodEventJob<CServerApp>(this, &CServerApp::resetServer));
00815
00816
00817
00818
00819 DAEMON_RUNNING(true);
00820 EVENTQUEUE->loop();
00821 DAEMON_RUNNING(false);
00822
00823
00824 LOG((CLOG_DEBUG1 "stopping server"));
00825 EVENTQUEUE->removeHandler(getForceReconnectEvent(),
00826 IEventQueue::getSystemTarget());
00827 EVENTQUEUE->removeHandler(getReloadConfigEvent(),
00828 IEventQueue::getSystemTarget());
00829 cleanupServer();
00830 updateStatus();
00831 LOG((CLOG_NOTE "stopped server"));
00832
00833 if (argsBase().m_enableIpc) {
00834 cleanupIpcClient();
00835 }
00836
00837 return kExitSuccess;
00838 }
00839
00840 void CServerApp::resetServer(const CEvent&, void*)
00841 {
00842 LOG((CLOG_DEBUG1 "resetting server"));
00843 stopServer();
00844 cleanupServer();
00845 startServer();
00846 }
00847
00848 int
00849 CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
00850 {
00851
00852 args().m_synergyAddress = new CNetworkAddress;
00853 args().m_config = new CConfig;
00854 args().m_pname = ARCH->getBasename(argv[0]);
00855
00856
00857 if (outputter != NULL) {
00858 CLOG->insert(outputter);
00859 }
00860
00861
00862 int result = startup(argc, argv);
00863
00864 if (m_taskBarReceiver)
00865 {
00866
00867 delete m_taskBarReceiver;
00868 }
00869
00870 delete args().m_config;
00871 delete args().m_synergyAddress;
00872 return result;
00873 }
00874
00875 int daemonMainLoopStatic(int argc, const char** argv) {
00876 return CServerApp::instance().daemonMainLoop(argc, argv);
00877 }
00878
00879 int
00880 CServerApp::standardStartup(int argc, char** argv)
00881 {
00882 initApp(argc, argv);
00883
00884
00885 if (args().m_daemon) {
00886 return ARCH->daemonize(daemonName(), daemonMainLoopStatic);
00887 }
00888 else {
00889 return mainLoop();
00890 }
00891 }
00892
00893 int
00894 CServerApp::foregroundStartup(int argc, char** argv)
00895 {
00896 initApp(argc, argv);
00897
00898
00899 return mainLoop();
00900 }
00901
00902 static
00903 int
00904 mainLoopStatic()
00905 {
00906 return CServerApp::instance().mainLoop();
00907 }
00908
00909 const char*
00910 CServerApp::daemonName() const
00911 {
00912 #if SYSAPI_WIN32
00913 return "Synergy Server";
00914 #elif SYSAPI_UNIX
00915 return "synergys";
00916 #endif
00917 }
00918
00919 const char*
00920 CServerApp::daemonInfo() const
00921 {
00922 #if SYSAPI_WIN32
00923 return "Shares this computers mouse and keyboard with other computers.";
00924 #elif SYSAPI_UNIX
00925 return "";
00926 #endif
00927 }
00928
00929 void
00930 CServerApp::startNode()
00931 {
00932
00933
00934 LOG((CLOG_DEBUG1 "starting server"));
00935 if (!startServer()) {
00936 m_bye(kExitFailed);
00937 }
00938 }