• Main Page
  • Classes
  • Files
  • File List

CClientListener.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2004 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CClientListener.h"
00020 #include "CClientProxy.h"
00021 #include "CClientProxyUnknown.h"
00022 #include "CPacketStreamFilter.h"
00023 #include "IStreamFilterFactory.h"
00024 #include "IDataSocket.h"
00025 #include "IListenSocket.h"
00026 #include "ISocketFactory.h"
00027 #include "XSocket.h"
00028 #include "CLog.h"
00029 #include "IEventQueue.h"
00030 #include "TMethodEventJob.h"
00031 #include "CCryptoStream.h"
00032 #include "CCryptoOptions.h"
00033 
00034 // TODO: these are just for testing -- make sure they're gone by release!
00035 const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
00036 const byte g_iv[] = "aaaaaaaaaaaaaaa";
00037 
00038 //
00039 // CClientListener
00040 //
00041 
00042 CEvent::Type            CClientListener::s_connectedEvent = CEvent::kUnknown;
00043 
00044 CClientListener::CClientListener(const CNetworkAddress& address,
00045                 ISocketFactory* socketFactory,
00046                 IStreamFilterFactory* streamFilterFactory,
00047                 const CCryptoOptions& crypto) :
00048     m_socketFactory(socketFactory),
00049     m_streamFilterFactory(streamFilterFactory),
00050     m_server(NULL),
00051     m_crypto(crypto)
00052 {
00053     assert(m_socketFactory != NULL);
00054 
00055     try {
00056         // create listen socket
00057         m_listen = m_socketFactory->createListen();
00058 
00059         // bind listen address
00060         LOG((CLOG_DEBUG1 "binding listen socket"));
00061         m_listen->bind(address);
00062     }
00063     catch (XSocketAddressInUse&) {
00064         delete m_listen;
00065         delete m_socketFactory;
00066         delete m_streamFilterFactory;
00067         throw;
00068     }
00069     catch (XBase&) {
00070         delete m_listen;
00071         delete m_socketFactory;
00072         delete m_streamFilterFactory;
00073         throw;
00074     }
00075     LOG((CLOG_DEBUG1 "listening for clients"));
00076 
00077     // setup event handler
00078     EVENTQUEUE->adoptHandler(m_listen->getConnectingEvent(), m_listen,
00079                             new TMethodEventJob<CClientListener>(this,
00080                                 &CClientListener::handleClientConnecting));
00081 }
00082 
00083 CClientListener::~CClientListener()
00084 {
00085     LOG((CLOG_DEBUG1 "stop listening for clients"));
00086 
00087     // discard already connected clients
00088     for (CNewClients::iterator index = m_newClients.begin();
00089                                 index != m_newClients.end(); ++index) {
00090         CClientProxyUnknown* client = *index;
00091         EVENTQUEUE->removeHandler(
00092                             CClientProxyUnknown::getSuccessEvent(), client);
00093         EVENTQUEUE->removeHandler(
00094                             CClientProxyUnknown::getFailureEvent(), client);
00095         EVENTQUEUE->removeHandler(
00096                             CClientProxy::getDisconnectedEvent(), client);
00097         delete client;
00098     }
00099 
00100     // discard waiting clients
00101     CClientProxy* client = getNextClient();
00102     while (client != NULL) {
00103         delete client;
00104         client = getNextClient();
00105     }
00106 
00107     EVENTQUEUE->removeHandler(m_listen->getConnectingEvent(), m_listen);
00108     delete m_listen;
00109     delete m_socketFactory;
00110     delete m_streamFilterFactory;
00111 }
00112 
00113 void
00114 CClientListener::setServer(CServer* server)
00115 {
00116     assert(server != NULL);
00117     m_server = server;
00118 }
00119 
00120 CClientProxy*
00121 CClientListener::getNextClient()
00122 {
00123     CClientProxy* client = NULL;
00124     if (!m_waitingClients.empty()) {
00125         client = m_waitingClients.front();
00126         m_waitingClients.pop_front();
00127         EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client);
00128     }
00129     return client;
00130 }
00131 
00132 CEvent::Type
00133 CClientListener::getConnectedEvent()
00134 {
00135     return EVENTQUEUE->registerTypeOnce(s_connectedEvent,
00136                             "CClientListener::connected");
00137 }
00138 
00139 void
00140 CClientListener::handleClientConnecting(const CEvent&, void*)
00141 {
00142     // accept client connection
00143     synergy::IStream* stream = m_listen->accept();
00144     if (stream == NULL) {
00145         return;
00146     }
00147     LOG((CLOG_NOTE "accepted client connection"));
00148 
00149     // filter socket messages, including a packetizing filter
00150     if (m_streamFilterFactory != NULL) {
00151         stream = m_streamFilterFactory->create(stream, true);
00152     }
00153     stream = new CPacketStreamFilter(stream, true);
00154     
00155     if (m_crypto.m_mode != kDisabled) {
00156         CCryptoStream* cryptoStream = new CCryptoStream(
00157             EVENTQUEUE, stream, m_crypto, true);
00158         stream = cryptoStream;
00159     }
00160 
00161     assert(m_server != NULL);
00162 
00163     // create proxy for unknown client
00164     CClientProxyUnknown* client = new CClientProxyUnknown(stream, 30.0, m_server);
00165     m_newClients.insert(client);
00166 
00167     // watch for events from unknown client
00168     EVENTQUEUE->adoptHandler(CClientProxyUnknown::getSuccessEvent(), client,
00169                             new TMethodEventJob<CClientListener>(this,
00170                                 &CClientListener::handleUnknownClient, client));
00171     EVENTQUEUE->adoptHandler(CClientProxyUnknown::getFailureEvent(), client,
00172                             new TMethodEventJob<CClientListener>(this,
00173                                 &CClientListener::handleUnknownClient, client));
00174 }
00175 
00176 void
00177 CClientListener::handleUnknownClient(const CEvent&, void* vclient)
00178 {
00179     CClientProxyUnknown* unknownClient =
00180         reinterpret_cast<CClientProxyUnknown*>(vclient);
00181 
00182     // we should have the client in our new client list
00183     assert(m_newClients.count(unknownClient) == 1);
00184 
00185     // get the real client proxy and install it
00186     CClientProxy* client = unknownClient->orphanClientProxy();
00187     if (client != NULL) {
00188         // handshake was successful
00189         m_waitingClients.push_back(client);
00190         EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this));
00191 
00192         // watch for client to disconnect while it's in our queue
00193         EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client,
00194                             new TMethodEventJob<CClientListener>(this,
00195                                 &CClientListener::handleClientDisconnected,
00196                                 client));
00197     }
00198 
00199     // now finished with unknown client
00200     EVENTQUEUE->removeHandler(CClientProxyUnknown::getSuccessEvent(), client);
00201     EVENTQUEUE->removeHandler(CClientProxyUnknown::getFailureEvent(), client);
00202     m_newClients.erase(unknownClient);
00203     delete unknownClient;
00204 }
00205 
00206 void
00207 CClientListener::handleClientDisconnected(const CEvent&, void* vclient)
00208 {
00209     CClientProxy* client = reinterpret_cast<CClientProxy*>(vclient);
00210 
00211     // find client in waiting clients queue
00212     for (CWaitingClients::iterator i = m_waitingClients.begin(),
00213                             n = m_waitingClients.end(); i != n; ++i) {
00214         if (*i == client) {
00215             m_waitingClients.erase(i);
00216             EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(),
00217                             client);
00218             delete client;
00219             break;
00220         }
00221     }
00222 }

Generated on Sat May 18 2013 00:00:03 for Synergy by  doxygen 1.7.1