00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00195 UInt32 n = m_stream->getSize();
00196 if (n > kMaxHelloLength) {
00197 LOG((CLOG_DEBUG1 "hello reply too long"));
00198 throw XBadClient();
00199 }
00200
00201
00202 SInt16 major, minor;
00203 if (!CProtocolUtil::readf(m_stream, kMsgHelloBack,
00204 &major, &minor, &name)) {
00205 throw XBadClient();
00206 }
00207
00208
00209 if (major <= 0 || minor < 0) {
00210 throw XIncompatibleClient(major, minor);
00211 }
00212
00213
00214
00215
00216 removeHandlers();
00217
00218
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
00244 if (m_proxy == NULL) {
00245 throw XIncompatibleClient(major, minor);
00246 }
00247
00248
00249 LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
00250 m_stream = NULL;
00251
00252
00253 addProxyHandlers();
00254 return;
00255 }
00256 catch (XIncompatibleClient& e) {
00257
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
00265 LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
00266 CProtocolUtil::writef(m_stream, kMsgEBad);
00267 }
00268 catch (XBase& e) {
00269
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 }