source: vendor/synergy/current/lib/server/CClientProxyUnknown.cpp

Last change on this file was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 7.1 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2004 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "CClientProxyUnknown.h"
16#include "CClientProxy1_0.h"
17#include "CClientProxy1_1.h"
18#include "CClientProxy1_2.h"
19#include "CClientProxy1_3.h"
20#include "ProtocolTypes.h"
21#include "CProtocolUtil.h"
22#include "XSynergy.h"
23#include "IStream.h"
24#include "XIO.h"
25#include "CLog.h"
26#include "CString.h"
27#include "IEventQueue.h"
28#include "TMethodEventJob.h"
29
30//
31// CClientProxyUnknown
32//
33
34CEvent::Type CClientProxyUnknown::s_successEvent = CEvent::kUnknown;
35CEvent::Type CClientProxyUnknown::s_failureEvent = CEvent::kUnknown;
36
37CClientProxyUnknown::CClientProxyUnknown(IStream* stream, double timeout) :
38 m_stream(stream),
39 m_proxy(NULL),
40 m_ready(false)
41{
42 EVENTQUEUE->adoptHandler(CEvent::kTimer, this,
43 new TMethodEventJob<CClientProxyUnknown>(this,
44 &CClientProxyUnknown::handleTimeout, NULL));
45 m_timer = EVENTQUEUE->newOneShotTimer(timeout, this);
46 addStreamHandlers();
47
48 LOG((CLOG_DEBUG1 "saying hello"));
49 CProtocolUtil::writef(m_stream, kMsgHello,
50 kProtocolMajorVersion,
51 kProtocolMinorVersion);
52}
53
54CClientProxyUnknown::~CClientProxyUnknown()
55{
56 removeHandlers();
57 removeTimer();
58 delete m_stream;
59 delete m_proxy;
60}
61
62CClientProxy*
63CClientProxyUnknown::orphanClientProxy()
64{
65 if (m_ready) {
66 removeHandlers();
67 CClientProxy* proxy = m_proxy;
68 m_proxy = NULL;
69 return proxy;
70 }
71 else {
72 return NULL;
73 }
74}
75
76CEvent::Type
77CClientProxyUnknown::getSuccessEvent()
78{
79 return CEvent::registerTypeOnce(s_successEvent,
80 "CClientProxy::success");
81}
82
83CEvent::Type
84CClientProxyUnknown::getFailureEvent()
85{
86 return CEvent::registerTypeOnce(s_failureEvent,
87 "CClientProxy::failure");
88}
89
90void
91CClientProxyUnknown::sendSuccess()
92{
93 m_ready = true;
94 removeTimer();
95 EVENTQUEUE->addEvent(CEvent(getSuccessEvent(), this));
96}
97
98void
99CClientProxyUnknown::sendFailure()
100{
101 delete m_proxy;
102 m_proxy = NULL;
103 m_ready = false;
104 removeHandlers();
105 removeTimer();
106 EVENTQUEUE->addEvent(CEvent(getFailureEvent(), this));
107}
108
109void
110CClientProxyUnknown::addStreamHandlers()
111{
112 assert(m_stream != NULL);
113
114 EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(),
115 m_stream->getEventTarget(),
116 new TMethodEventJob<CClientProxyUnknown>(this,
117 &CClientProxyUnknown::handleData));
118 EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(),
119 m_stream->getEventTarget(),
120 new TMethodEventJob<CClientProxyUnknown>(this,
121 &CClientProxyUnknown::handleWriteError));
122 EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(),
123 m_stream->getEventTarget(),
124 new TMethodEventJob<CClientProxyUnknown>(this,
125 &CClientProxyUnknown::handleDisconnect));
126 EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(),
127 m_stream->getEventTarget(),
128 new TMethodEventJob<CClientProxyUnknown>(this,
129 &CClientProxyUnknown::handleWriteError));
130}
131
132void
133CClientProxyUnknown::addProxyHandlers()
134{
135 assert(m_proxy != NULL);
136
137 EVENTQUEUE->adoptHandler(CClientProxy::getReadyEvent(),
138 m_proxy,
139 new TMethodEventJob<CClientProxyUnknown>(this,
140 &CClientProxyUnknown::handleReady));
141 EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(),
142 m_proxy,
143 new TMethodEventJob<CClientProxyUnknown>(this,
144 &CClientProxyUnknown::handleDisconnect));
145}
146
147void
148CClientProxyUnknown::removeHandlers()
149{
150 if (m_stream != NULL) {
151 EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(),
152 m_stream->getEventTarget());
153 EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(),
154 m_stream->getEventTarget());
155 EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(),
156 m_stream->getEventTarget());
157 EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(),
158 m_stream->getEventTarget());
159 }
160 if (m_proxy != NULL) {
161 EVENTQUEUE->removeHandler(CClientProxy::getReadyEvent(),
162 m_proxy);
163 EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
164 m_proxy);
165 }
166}
167
168void
169CClientProxyUnknown::removeTimer()
170{
171 if (m_timer != NULL) {
172 EVENTQUEUE->deleteTimer(m_timer);
173 EVENTQUEUE->removeHandler(CEvent::kTimer, this);
174 m_timer = NULL;
175 }
176}
177
178void
179CClientProxyUnknown::handleData(const CEvent&, void*)
180{
181 LOG((CLOG_DEBUG1 "parsing hello reply"));
182
183 CString name("<unknown>");
184 try {
185 // limit the maximum length of the hello
186 UInt32 n = m_stream->getSize();
187 if (n > kMaxHelloLength) {
188 LOG((CLOG_DEBUG1 "hello reply too long"));
189 throw XBadClient();
190 }
191
192 // parse the reply to hello
193 SInt16 major, minor;
194 if (!CProtocolUtil::readf(m_stream, kMsgHelloBack,
195 &major, &minor, &name)) {
196 throw XBadClient();
197 }
198
199 // disallow invalid version numbers
200 if (major <= 0 || minor < 0) {
201 throw XIncompatibleClient(major, minor);
202 }
203
204 // remove stream event handlers. the proxy we're about to create
205 // may install its own handlers and we don't want to accidentally
206 // remove those later.
207 removeHandlers();
208
209 // create client proxy for highest version supported by the client
210 if (major == 1) {
211 switch (minor) {
212 case 0:
213 m_proxy = new CClientProxy1_0(name, m_stream);
214 break;
215
216 case 1:
217 m_proxy = new CClientProxy1_1(name, m_stream);
218 break;
219
220 case 2:
221 m_proxy = new CClientProxy1_2(name, m_stream);
222 break;
223
224 case 3:
225 m_proxy = new CClientProxy1_3(name, m_stream);
226 break;
227 }
228 }
229
230 // hangup (with error) if version isn't supported
231 if (m_proxy == NULL) {
232 throw XIncompatibleClient(major, minor);
233 }
234
235 // the proxy is created and now proxy now owns the stream
236 LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor));
237 m_stream = NULL;
238
239 // wait until the proxy signals that it's ready or has disconnected
240 addProxyHandlers();
241 return;
242 }
243 catch (XIncompatibleClient& e) {
244 // client is incompatible
245 LOG((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
246 CProtocolUtil::writef(m_stream,
247 kMsgEIncompatible,
248 kProtocolMajorVersion, kProtocolMinorVersion);
249 }
250 catch (XBadClient&) {
251 // client not behaving
252 LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
253 CProtocolUtil::writef(m_stream, kMsgEBad);
254 }
255 catch (XBase& e) {
256 // misc error
257 LOG((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
258 }
259 sendFailure();
260}
261
262void
263CClientProxyUnknown::handleWriteError(const CEvent&, void*)
264{
265 LOG((CLOG_NOTE "error communicating with new client"));
266 sendFailure();
267}
268
269void
270CClientProxyUnknown::handleTimeout(const CEvent&, void*)
271{
272 LOG((CLOG_NOTE "new client is unresponsive"));
273 sendFailure();
274}
275
276void
277CClientProxyUnknown::handleDisconnect(const CEvent&, void*)
278{
279 LOG((CLOG_NOTE "new client disconnected"));
280 sendFailure();
281}
282
283void
284CClientProxyUnknown::handleReady(const CEvent&, void*)
285{
286 sendSuccess();
287}
Note: See TracBrowser for help on using the repository browser.