• Main Page
  • Classes
  • Files
  • File List

CClientProxyUnknown.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2004 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CClientProxyUnknown.h"
00020 #include "CClientProxy1_0.h"
00021 #include "CClientProxy1_1.h"
00022 #include "CClientProxy1_2.h"
00023 #include "CClientProxy1_3.h"
00024 #include "CClientProxy1_4.h"
00025 #include "ProtocolTypes.h"
00026 #include "CProtocolUtil.h"
00027 #include "XSynergy.h"
00028 #include "IStream.h"
00029 #include "XIO.h"
00030 #include "CLog.h"
00031 #include "CString.h"
00032 #include "IEventQueue.h"
00033 #include "TMethodEventJob.h"
00034 #include "CServer.h"
00035 
00036 //
00037 // CClientProxyUnknown
00038 //
00039 
00040 CEvent::Type            CClientProxyUnknown::s_successEvent = CEvent::kUnknown;
00041 CEvent::Type            CClientProxyUnknown::s_failureEvent = CEvent::kUnknown;
00042 
00043 CClientProxyUnknown::CClientProxyUnknown(synergy::IStream* stream, double timeout, CServer* server) :
00044     m_stream(stream),
00045     m_proxy(NULL),
00046     m_ready(false),
00047     m_server(server)
00048 {
00049     assert(m_server != NULL);
00050 
00051     EVENTQUEUE->adoptHandler(CEvent::kTimer, this,
00052                             new TMethodEventJob<CClientProxyUnknown>(this,
00053                                 &CClientProxyUnknown::handleTimeout, NULL));
00054     m_timer = EVENTQUEUE->newOneShotTimer(timeout, this);
00055     addStreamHandlers();
00056 
00057     LOG((CLOG_DEBUG1 "saying hello"));
00058     CProtocolUtil::writef(m_stream, kMsgHello,
00059                             kProtocolMajorVersion,
00060                             kProtocolMinorVersion);
00061 }
00062 
00063 CClientProxyUnknown::~CClientProxyUnknown()
00064 {
00065     removeHandlers();
00066     removeTimer();
00067     delete m_stream;
00068     delete m_proxy;
00069 }
00070 
00071 CClientProxy*
00072 CClientProxyUnknown::orphanClientProxy()
00073 {
00074     if (m_ready) {
00075         removeHandlers();
00076         CClientProxy* proxy = m_proxy;
00077         m_proxy = NULL;
00078         return proxy;
00079     }
00080     else {
00081         return NULL;
00082     }
00083 }
00084 
00085 CEvent::Type
00086 CClientProxyUnknown::getSuccessEvent()
00087 {
00088     return EVENTQUEUE->registerTypeOnce(s_successEvent,
00089                             "CClientProxy::success");
00090 }
00091 
00092 CEvent::Type
00093 CClientProxyUnknown::getFailureEvent()
00094 {
00095     return EVENTQUEUE->registerTypeOnce(s_failureEvent,
00096                             "CClientProxy::failure");
00097 }
00098 
00099 void
00100 CClientProxyUnknown::sendSuccess()
00101 {
00102     m_ready = true;
00103     removeTimer();
00104     EVENTQUEUE->addEvent(CEvent(getSuccessEvent(), this));
00105 }
00106 
00107 void
00108 CClientProxyUnknown::sendFailure()
00109 {
00110     delete m_proxy;
00111     m_proxy = NULL;
00112     m_ready = false;
00113     removeHandlers();
00114     removeTimer();
00115     EVENTQUEUE->addEvent(CEvent(getFailureEvent(), this));
00116 }
00117 
00118 void
00119 CClientProxyUnknown::addStreamHandlers()
00120 {
00121     assert(m_stream != NULL);
00122 
00123     EVENTQUEUE->adoptHandler(m_stream->getInputReadyEvent(),
00124                             m_stream->getEventTarget(),
00125                             new TMethodEventJob<CClientProxyUnknown>(this,
00126                                 &CClientProxyUnknown::handleData));
00127     EVENTQUEUE->adoptHandler(m_stream->getOutputErrorEvent(),
00128                             m_stream->getEventTarget(),
00129                             new TMethodEventJob<CClientProxyUnknown>(this,
00130                                 &CClientProxyUnknown::handleWriteError));
00131     EVENTQUEUE->adoptHandler(m_stream->getInputShutdownEvent(),
00132                             m_stream->getEventTarget(),
00133                             new TMethodEventJob<CClientProxyUnknown>(this,
00134                                 &CClientProxyUnknown::handleDisconnect));
00135     EVENTQUEUE->adoptHandler(m_stream->getOutputShutdownEvent(),
00136                             m_stream->getEventTarget(),
00137                             new TMethodEventJob<CClientProxyUnknown>(this,
00138                                 &CClientProxyUnknown::handleWriteError));
00139 }
00140 
00141 void
00142 CClientProxyUnknown::addProxyHandlers()
00143 {
00144     assert(m_proxy != NULL);
00145 
00146     EVENTQUEUE->adoptHandler(CClientProxy::getReadyEvent(),
00147                             m_proxy,
00148                             new TMethodEventJob<CClientProxyUnknown>(this,
00149                                 &CClientProxyUnknown::handleReady));
00150     EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(),
00151                             m_proxy,
00152                             new TMethodEventJob<CClientProxyUnknown>(this,
00153                                 &CClientProxyUnknown::handleDisconnect));
00154 }
00155 
00156 void
00157 CClientProxyUnknown::removeHandlers()
00158 {
00159     if (m_stream != NULL) {
00160         EVENTQUEUE->removeHandler(m_stream->getInputReadyEvent(),
00161                             m_stream->getEventTarget());
00162         EVENTQUEUE->removeHandler(m_stream->getOutputErrorEvent(),
00163                             m_stream->getEventTarget());
00164         EVENTQUEUE->removeHandler(m_stream->getInputShutdownEvent(),
00165                             m_stream->getEventTarget());
00166         EVENTQUEUE->removeHandler(m_stream->getOutputShutdownEvent(),
00167                             m_stream->getEventTarget());
00168     }
00169     if (m_proxy != NULL) {
00170         EVENTQUEUE->removeHandler(CClientProxy::getReadyEvent(),
00171                             m_proxy);
00172         EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
00173                             m_proxy);
00174     }
00175 }
00176 
00177 void
00178 CClientProxyUnknown::removeTimer()
00179 {
00180     if (m_timer != NULL) {
00181         EVENTQUEUE->deleteTimer(m_timer);
00182         EVENTQUEUE->removeHandler(CEvent::kTimer, this);
00183         m_timer = NULL;
00184     }
00185 }
00186 
00187 void
00188 CClientProxyUnknown::handleData(const CEvent&, void*)
00189 {
00190     LOG((CLOG_DEBUG1 "parsing hello reply"));
00191 
00192     CString name("<unknown>");
00193     try {
00194         // limit the maximum length of the hello
00195         UInt32 n = m_stream->getSize();
00196         if (n > kMaxHelloLength) {
00197             LOG((CLOG_DEBUG1 "hello reply too long"));
00198             throw XBadClient();
00199         }
00200 
00201         // parse the reply to hello
00202         SInt16 major, minor;
00203         if (!CProtocolUtil::readf(m_stream, kMsgHelloBack,
00204                                     &major, &minor, &name)) {
00205             throw XBadClient();
00206         }
00207 
00208         // disallow invalid version numbers
00209         if (major <= 0 || minor < 0) {
00210             throw XIncompatibleClient(major, minor);
00211         }
00212 
00213         // remove stream event handlers.  the proxy we're about to create
00214         // may install its own handlers and we don't want to accidentally
00215         // remove those later.
00216         removeHandlers();
00217 
00218         // create client proxy for highest version supported by the client
00219         if (major == 1) {
00220             switch (minor) {
00221             case 0:
00222                 m_proxy = new CClientProxy1_0(name, m_stream, EVENTQUEUE);
00223                 break;
00224 
00225             case 1:
00226                 m_proxy = new CClientProxy1_1(name, m_stream, EVENTQUEUE);
00227                 break;
00228 
00229             case 2:
00230                 m_proxy = new CClientProxy1_2(name, m_stream, EVENTQUEUE);
00231                 break;
00232 
00233             case 3:
00234                 m_proxy = new CClientProxy1_3(name, m_stream, EVENTQUEUE);
00235                 break;
00236 
00237             case 4:
00238                 m_proxy = new CClientProxy1_4(name, m_stream, m_server, EVENTQUEUE);
00239                 break;
00240             }
00241         }
00242 
00243         // hangup (with error) if version isn't supported
00244         if (m_proxy == NULL) {
00245             throw XIncompatibleClient(major, minor);
00246         }
00247 
00248         // the proxy is created and now proxy now owns the stream
00249         LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
00250         m_stream = NULL;
00251 
00252         // wait until the proxy signals that it's ready or has disconnected
00253         addProxyHandlers();
00254         return;
00255     }
00256     catch (XIncompatibleClient& e) {
00257         // client is incompatible
00258         LOG((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
00259         CProtocolUtil::writef(m_stream,
00260                             kMsgEIncompatible,
00261                             kProtocolMajorVersion, kProtocolMinorVersion);
00262     }
00263     catch (XBadClient&) {
00264         // client not behaving
00265         LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
00266         CProtocolUtil::writef(m_stream, kMsgEBad);
00267     }
00268     catch (XBase& e) {
00269         // misc error
00270         LOG((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
00271     }
00272     sendFailure();
00273 }
00274 
00275 void
00276 CClientProxyUnknown::handleWriteError(const CEvent&, void*)
00277 {
00278     LOG((CLOG_NOTE "error communicating with new client"));
00279     sendFailure();
00280 }
00281 
00282 void
00283 CClientProxyUnknown::handleTimeout(const CEvent&, void*)
00284 {
00285     LOG((CLOG_NOTE "new client is unresponsive"));
00286     sendFailure();
00287 }
00288 
00289 void
00290 CClientProxyUnknown::handleDisconnect(const CEvent&, void*)
00291 {
00292     LOG((CLOG_NOTE "new client disconnected"));
00293     sendFailure();
00294 }
00295 
00296 void
00297 CClientProxyUnknown::handleReady(const CEvent&, void*)
00298 {
00299     sendSuccess();
00300 }

Generated on Wed Jun 19 2013 00:00:04 for Synergy by  doxygen 1.7.1