CClientListener.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 "CClientListener.h"
00016 #include "CClientProxy.h"
00017 #include "CClientProxyUnknown.h"
00018 #include "CPacketStreamFilter.h"
00019 #include "IStreamFilterFactory.h"
00020 #include "IDataSocket.h"
00021 #include "IListenSocket.h"
00022 #include "ISocketFactory.h"
00023 #include "XSocket.h"
00024 #include "CLog.h"
00025 #include "IEventQueue.h"
00026 #include "TMethodEventJob.h"
00027 
00028 //
00029 // CClientListener
00030 //
00031 
00032 CEvent::Type            CClientListener::s_connectedEvent = CEvent::kUnknown;
00033 
00034 CClientListener::CClientListener(const CNetworkAddress& address,
00035                 ISocketFactory* socketFactory,
00036                 IStreamFilterFactory* streamFilterFactory) :
00037     m_socketFactory(socketFactory),
00038     m_streamFilterFactory(streamFilterFactory)
00039 {
00040     assert(m_socketFactory != NULL);
00041 
00042     try {
00043         // create listen socket
00044         m_listen = m_socketFactory->createListen();
00045 
00046         // bind listen address
00047         LOG((CLOG_DEBUG1 "binding listen socket"));
00048         m_listen->bind(address);
00049     }
00050     catch (XSocketAddressInUse&) {
00051         delete m_listen;
00052         delete m_socketFactory;
00053         delete m_streamFilterFactory;
00054         throw;
00055     }
00056     catch (XBase&) {
00057         delete m_listen;
00058         delete m_socketFactory;
00059         delete m_streamFilterFactory;
00060         throw;
00061     }
00062     LOG((CLOG_DEBUG1 "listening for clients"));
00063 
00064     // setup event handler
00065     EVENTQUEUE->adoptHandler(IListenSocket::getConnectingEvent(), m_listen,
00066                             new TMethodEventJob<CClientListener>(this,
00067                                 &CClientListener::handleClientConnecting));
00068 }
00069 
00070 CClientListener::~CClientListener()
00071 {
00072     LOG((CLOG_DEBUG1 "stop listening for clients"));
00073 
00074     // discard already connected clients
00075     for (CNewClients::iterator index = m_newClients.begin();
00076                                 index != m_newClients.end(); ++index) {
00077         CClientProxyUnknown* client = *index;
00078         EVENTQUEUE->removeHandler(
00079                             CClientProxyUnknown::getSuccessEvent(), client);
00080         EVENTQUEUE->removeHandler(
00081                             CClientProxyUnknown::getFailureEvent(), client);
00082         EVENTQUEUE->removeHandler(
00083                             CClientProxy::getDisconnectedEvent(), client);
00084         delete client;
00085     }
00086 
00087     // discard waiting clients
00088     CClientProxy* client = getNextClient();
00089     while (client != NULL) {
00090         delete client;
00091         client = getNextClient();
00092     }
00093 
00094     EVENTQUEUE->removeHandler(IListenSocket::getConnectingEvent(), m_listen);
00095     delete m_listen;
00096     delete m_socketFactory;
00097     delete m_streamFilterFactory;
00098 }
00099 
00100 CClientProxy*
00101 CClientListener::getNextClient()
00102 {
00103     CClientProxy* client = NULL;
00104     if (!m_waitingClients.empty()) {
00105         client = m_waitingClients.front();
00106         m_waitingClients.pop_front();
00107         EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client);
00108     }
00109     return client;
00110 }
00111 
00112 CEvent::Type
00113 CClientListener::getConnectedEvent()
00114 {
00115     return CEvent::registerTypeOnce(s_connectedEvent,
00116                             "CClientListener::connected");
00117 }
00118 
00119 void
00120 CClientListener::handleClientConnecting(const CEvent&, void*)
00121 {
00122     // accept client connection
00123     IStream* stream = m_listen->accept();
00124     if (stream == NULL) {
00125         return;
00126     }
00127     LOG((CLOG_NOTE "accepted client connection"));
00128 
00129     // filter socket messages, including a packetizing filter
00130     if (m_streamFilterFactory != NULL) {
00131         stream = m_streamFilterFactory->create(stream, true);
00132     }
00133     stream = new CPacketStreamFilter(stream, true);
00134 
00135     // create proxy for unknown client
00136     CClientProxyUnknown* client = new CClientProxyUnknown(stream, 30.0);
00137     m_newClients.insert(client);
00138 
00139     // watch for events from unknown client
00140     EVENTQUEUE->adoptHandler(CClientProxyUnknown::getSuccessEvent(), client,
00141                             new TMethodEventJob<CClientListener>(this,
00142                                 &CClientListener::handleUnknownClient, client));
00143     EVENTQUEUE->adoptHandler(CClientProxyUnknown::getFailureEvent(), client,
00144                             new TMethodEventJob<CClientListener>(this,
00145                                 &CClientListener::handleUnknownClient, client));
00146 }
00147 
00148 void
00149 CClientListener::handleUnknownClient(const CEvent&, void* vclient)
00150 {
00151     CClientProxyUnknown* unknownClient =
00152         reinterpret_cast<CClientProxyUnknown*>(vclient);
00153 
00154     // we should have the client in our new client list
00155     assert(m_newClients.count(unknownClient) == 1);
00156 
00157     // get the real client proxy and install it
00158     CClientProxy* client = unknownClient->orphanClientProxy();
00159     if (client != NULL) {
00160         // handshake was successful
00161         m_waitingClients.push_back(client);
00162         EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this));
00163 
00164         // watch for client to disconnect while it's in our queue
00165         EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client,
00166                             new TMethodEventJob<CClientListener>(this,
00167                                 &CClientListener::handleClientDisconnected,
00168                                 client));
00169     }
00170 
00171     // now finished with unknown client
00172     EVENTQUEUE->removeHandler(CClientProxyUnknown::getSuccessEvent(), client);
00173     EVENTQUEUE->removeHandler(CClientProxyUnknown::getFailureEvent(), client);
00174     m_newClients.erase(unknownClient);
00175     delete unknownClient;
00176 }
00177 
00178 void
00179 CClientListener::handleClientDisconnected(const CEvent&, void* vclient)
00180 {
00181     CClientProxy* client = reinterpret_cast<CClientProxy*>(vclient);
00182 
00183     // find client in waiting clients queue
00184     for (CWaitingClients::iterator i = m_waitingClients.begin(),
00185                             n = m_waitingClients.end(); i != n; ++i) {
00186         if (*i == client) {
00187             m_waitingClients.erase(i);
00188             EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
00189                             client);
00190             delete client;
00191             break;
00192         }
00193     }
00194 }

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