00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
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
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
00131 return NULL;
00132 }
00133 return job;
00134 }