00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
00186 UInt32 n = m_stream->getSize();
00187 if (n > kMaxHelloLength) {
00188 LOG((CLOG_DEBUG1 "hello reply too long"));
00189 throw XBadClient();
00190 }
00191
00192
00193 SInt16 major, minor;
00194 if (!CProtocolUtil::readf(m_stream, kMsgHelloBack,
00195 &major, &minor, &name)) {
00196 throw XBadClient();
00197 }
00198
00199
00200 if (major <= 0 || minor < 0) {
00201 throw XIncompatibleClient(major, minor);
00202 }
00203
00204
00205
00206
00207 removeHandlers();
00208
00209
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
00231 if (m_proxy == NULL) {
00232 throw XIncompatibleClient(major, minor);
00233 }
00234
00235
00236 LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
00237 m_stream = NULL;
00238
00239
00240 addProxyHandlers();
00241 return;
00242 }
00243 catch (XIncompatibleClient& e) {
00244
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
00252 LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
00253 CProtocolUtil::writef(m_stream, kMsgEBad);
00254 }
00255 catch (XBase& e) {
00256
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 }