CTCPListenSocket.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 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 "CTCPListenSocket.h"
00016 #include "CNetworkAddress.h"
00017 #include "CSocketMultiplexer.h"
00018 #include "CTCPSocket.h"
00019 #include "TSocketMultiplexerMethodJob.h"
00020 #include "XSocket.h"
00021 #include "XIO.h"
00022 #include "CLock.h"
00023 #include "CMutex.h"
00024 #include "IEventQueue.h"
00025 #include "CArch.h"
00026 #include "XArch.h"
00027 
00028 //
00029 // CTCPListenSocket
00030 //
00031 
00032 CTCPListenSocket::CTCPListenSocket()
00033 {
00034     m_mutex = new CMutex;
00035     try {
00036         m_socket = ARCH->newSocket(IArchNetwork::kINET, IArchNetwork::kSTREAM);
00037     }
00038     catch (XArchNetwork& e) {
00039         throw XSocketCreate(e.what());
00040     }
00041 }
00042 
00043 CTCPListenSocket::~CTCPListenSocket()
00044 {
00045     try {
00046         if (m_socket != NULL) {
00047             CSocketMultiplexer::getInstance()->removeSocket(this);
00048             ARCH->closeSocket(m_socket);
00049         }
00050     }
00051     catch (...) {
00052         // ignore
00053     }
00054     delete m_mutex;
00055 }
00056 
00057 void
00058 CTCPListenSocket::bind(const CNetworkAddress& addr)
00059 {
00060     try {
00061         CLock lock(m_mutex);
00062         ARCH->setReuseAddrOnSocket(m_socket, true);
00063         ARCH->bindSocket(m_socket, addr.getAddress());
00064         ARCH->listenOnSocket(m_socket);
00065         CSocketMultiplexer::getInstance()->addSocket(this,
00066                             new TSocketMultiplexerMethodJob<CTCPListenSocket>(
00067                                 this, &CTCPListenSocket::serviceListening,
00068                                 m_socket, true, false));
00069     }
00070     catch (XArchNetworkAddressInUse& e) {
00071         throw XSocketAddressInUse(e.what());
00072     }
00073     catch (XArchNetwork& e) {
00074         throw XSocketBind(e.what());
00075     }
00076 }
00077 
00078 void
00079 CTCPListenSocket::close()
00080 {
00081     CLock lock(m_mutex);
00082     if (m_socket == NULL) {
00083         throw XIOClosed();
00084     }
00085     try {
00086         CSocketMultiplexer::getInstance()->removeSocket(this);
00087         ARCH->closeSocket(m_socket);
00088         m_socket = NULL;
00089     }
00090     catch (XArchNetwork& e) {
00091         throw XSocketIOClose(e.what());
00092     }
00093 }
00094 
00095 void*
00096 CTCPListenSocket::getEventTarget() const
00097 {
00098     return const_cast<void*>(reinterpret_cast<const void*>(this));
00099 }
00100 
00101 IDataSocket*
00102 CTCPListenSocket::accept()
00103 {
00104     try {
00105         IDataSocket* socket =
00106             new CTCPSocket(ARCH->acceptSocket(m_socket, NULL));
00107         if (socket != NULL) {
00108             CSocketMultiplexer::getInstance()->addSocket(this,
00109                             new TSocketMultiplexerMethodJob<CTCPListenSocket>(
00110                                 this, &CTCPListenSocket::serviceListening,
00111                                 m_socket, true, false));
00112         }
00113         return socket;
00114     }
00115     catch (XArchNetwork&) {
00116         return NULL;
00117     }
00118 }
00119 
00120 ISocketMultiplexerJob*
00121 CTCPListenSocket::serviceListening(ISocketMultiplexerJob* job,
00122                             bool read, bool, bool error)
00123 {
00124     if (error) {
00125         close();
00126         return NULL;
00127     }
00128     if (read) {
00129         EVENTQUEUE->addEvent(CEvent(getConnectingEvent(), this, NULL));
00130         // stop polling on this socket until the client accepts
00131         return NULL;
00132     }
00133     return job;
00134 }

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