CClientProxyUnknown.cpp

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

Generated on Fri Nov 6 00:18:44 2009 for synergy-plus by  doxygen 1.4.7