summaryrefslogtreecommitdiffstats
path: root/source/ListenThread.cpp
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-03-04 22:13:08 +0100
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-03-04 22:13:08 +0100
commit28d8d8419a5b900e9d20ce91dc63e28349b6470a (patch)
treebf5b7bafa902a138339c78877ecec376c055b727 /source/ListenThread.cpp
parentRemoved the unused cHeartbeat object (diff)
downloadcuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar.gz
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar.bz2
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar.lz
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar.xz
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.tar.zst
cuberite-28d8d8419a5b900e9d20ce91dc63e28349b6470a.zip
Diffstat (limited to '')
-rw-r--r--source/ListenThread.cpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/source/ListenThread.cpp b/source/ListenThread.cpp
new file mode 100644
index 000000000..52a4df9e4
--- /dev/null
+++ b/source/ListenThread.cpp
@@ -0,0 +1,172 @@
+
+// ListenThread.cpp
+
+// Implements the cListenThread class representing the thread that listens for client connections
+
+#include "Globals.h"
+#include "ListenThread.h"
+
+
+
+
+
+cListenThread::cListenThread(cCallback & a_Callback) :
+ super("ListenThread"),
+ m_Callback(a_Callback)
+{
+}
+
+
+
+
+
+cListenThread::~cListenThread()
+{
+ // TODO
+}
+
+
+
+
+
+bool cListenThread::Initialize(const AString & a_PortsString)
+{
+ ASSERT(m_Sockets.empty()); // Not yet started
+
+ if (!CreateSockets(a_PortsString))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+
+bool cListenThread::Start(void)
+{
+ ASSERT(!m_Sockets.empty()); // Has Initialize() been called?
+
+ return super::Start();
+}
+
+
+
+
+
+void cListenThread::Stop(void)
+{
+ m_ShouldTerminate = true;
+
+ // Close one socket to wake the thread up from the select() call
+ m_Sockets[0].CloseSocket();
+
+ // Wait for the thread to finish
+ super::Wait();
+
+ // Clean up all sockets
+ m_Sockets.clear();
+}
+
+
+
+
+
+void cListenThread::SetReuseAddr(bool a_Reuse)
+{
+ ASSERT(m_Sockets.empty()); // Must not be started
+
+ m_ShouldReuseAddr = a_Reuse;
+}
+
+
+
+
+
+bool cListenThread::CreateSockets(const AString & a_PortsString)
+{
+ AStringVector Ports = StringSplit(a_PortsString, ",");
+
+ if (Ports.empty())
+ {
+ return false;
+ }
+
+ for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
+ {
+ int Port = atoi(Trim(*itr).c_str());
+ if ((Port <= 0) || (Port > 65535))
+ {
+ LOGWARNING("Invalid port specified: \"%s\".", Trim(*itr).c_str());
+ continue;
+ }
+ m_Sockets.push_back(cSocket::CreateSocket());
+ if (!m_Sockets.back().IsValid())
+ {
+ LOGERROR("Cannot create listening socket for port %d: \"%s\"", Port, cSocket::GetLastErrorString().c_str());
+ m_Sockets.pop_back();
+ continue;
+ }
+
+ if (m_ShouldReuseAddr)
+ {
+ if (m_Sockets.back().SetReuseAddress() == -1)
+ {
+ LOG("Port %d cannot reuse addr, syscall failed: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
+ }
+ }
+ m_Sockets.back().BindToAny(Port);
+ m_Sockets.back().Listen();
+ LOGD("Port %d is open for connections", Port);
+ } // for itr - Ports[]
+
+ return !(m_Sockets.empty());
+}
+
+
+
+
+
+void cListenThread::Execute(void)
+{
+ // Find the highest socket number:
+ cSocket::xSocket Highest = m_Sockets[0].GetSocket();
+ for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
+ {
+ if (itr->GetSocket() > Highest)
+ {
+ Highest = itr->GetSocket();
+ }
+ } // for itr - m_Sockets[]
+
+ while (!m_ShouldTerminate)
+ {
+ // Put all sockets into a FD set:
+ fd_set fdRead;
+ FD_ZERO(&fdRead);
+ for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
+ {
+ FD_SET(itr->GetSocket(), &fdRead);
+ } // for itr - m_Sockets[]
+
+ if (select(Highest + 1, &fdRead, NULL, NULL, NULL) == -1)
+ {
+ LOG("select(R) call failed in cListenThread: \"%s\"", cSocket::GetLastErrorString().c_str());
+ continue;
+ }
+ for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
+ {
+ if (FD_ISSET(itr->GetSocket(), &fdRead))
+ {
+ cSocket Client = itr->Accept();
+ m_Callback.OnConnectionAccepted(Client);
+ }
+ } // for itr - m_Sockets[]
+ } // while (!m_ShouldTerminate)
+}
+
+
+
+