diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index a1b7e186e..2e9d4b4b7 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -1230,14 +1230,6 @@
RelativePath="..\source\OSSupport\SocketThreads.h"
>
-
-
-
-
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index 18fb72fde..7a7c54412 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -43,7 +43,6 @@ $cfile "WebAdmin.h"
$cfile "WebPlugin.h"
$cfile "Pickup.h"
$cfile "Root.h"
-$cfile "OSSupport/TCPLink.h"
$cfile "Vector3f.h"
$cfile "Vector3d.h"
$cfile "Vector3i.h"
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index ad8c397c6..a1d79ff04 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 03/03/13 20:02:17.
+** Generated automatically by tolua++-1.0.92 on 03/04/13 22:33:20.
*/
#ifndef __cplusplus
@@ -42,7 +42,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "WebPlugin.h"
#include "Pickup.h"
#include "Root.h"
-#include "OSSupport/TCPLink.h"
#include "Vector3f.h"
#include "Vector3d.h"
#include "Vector3i.h"
@@ -120,13 +119,6 @@ static int tolua_collect_cBlockArea (lua_State* tolua_S)
return 0;
}
-static int tolua_collect_cTCPLink (lua_State* tolua_S)
-{
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
- Mtolua_delete(self);
- return 0;
-}
-
static int tolua_collect_Vector3d (lua_State* tolua_S)
{
Vector3d* self = (Vector3d*) tolua_tousertype(tolua_S,1,0);
@@ -146,26 +138,24 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cBlockArea");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
- tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"cItems");
- tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cClientHandle");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
- tolua_usertype(tolua_S,"cTracer");
+ tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cChatColor");
- tolua_usertype(tolua_S,"cCuboid");
- tolua_usertype(tolua_S,"Vector3i");
+ tolua_usertype(tolua_S,"cGroup");
+ tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"Lua__cWebPlugin");
tolua_usertype(tolua_S,"Lua__cPawn");
- tolua_usertype(tolua_S,"cPawn");
+ tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
- tolua_usertype(tolua_S,"Lua__cTCPLink");
+ tolua_usertype(tolua_S,"Vector3i");
tolua_usertype(tolua_S,"cCraftingRecipes");
tolua_usertype(tolua_S,"Lua__cPlayer");
- tolua_usertype(tolua_S,"cTCPLink");
+ tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cGroupManager");
@@ -14439,329 +14429,6 @@ static int tolua_AllToLua_cRoot_GetProtocolVersionTextFromInt00(lua_State* tolua
}
#endif //#ifndef TOLUA_DISABLE
-/* method: delete of class cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cTCPLink_delete00
-static int tolua_AllToLua_cTCPLink_delete00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'delete'", NULL);
-#endif
- Mtolua_delete(self);
- }
- return 0;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'delete'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: Connect of class cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cTCPLink_Connect00
-static int tolua_AllToLua_cTCPLink_Connect00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cTCPLink",0,&tolua_err) ||
- !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,4,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
- const AString a_Address = ((const AString) tolua_tocppstring(tolua_S,2,0));
- unsigned int a_Port = ((unsigned int) tolua_tonumber(tolua_S,3,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Connect'", NULL);
-#endif
- {
- bool tolua_ret = (bool) self->Connect(a_Address,a_Port);
- tolua_pushboolean(tolua_S,(bool)tolua_ret);
- tolua_pushcppstring(tolua_S,(const char*)a_Address);
- }
- }
- return 2;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'Connect'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: Send of class cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cTCPLink_Send00
-static int tolua_AllToLua_cTCPLink_Send00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cTCPLink",0,&tolua_err) ||
- !tolua_isstring(tolua_S,2,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,4,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,5,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
- const char* a_Data = ((const char*) tolua_tostring(tolua_S,2,0));
- unsigned int a_Size = ((unsigned int) tolua_tonumber(tolua_S,3,0));
- int a_Flags = ((int) tolua_tonumber(tolua_S,4,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Send'", NULL);
-#endif
- {
- int tolua_ret = (int) self->Send(a_Data,a_Size,a_Flags);
- tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'Send'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: SendMessage of class cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cTCPLink_SendMessage00
-static int tolua_AllToLua_cTCPLink_SendMessage00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cTCPLink",0,&tolua_err) ||
- !tolua_isstring(tolua_S,2,0,&tolua_err) ||
- !tolua_isnumber(tolua_S,3,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,4,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
- const char* a_Message = ((const char*) tolua_tostring(tolua_S,2,0));
- int a_Flags = ((int) tolua_tonumber(tolua_S,3,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SendMessage'", NULL);
-#endif
- {
- int tolua_ret = (int) self->SendMessage(a_Message,a_Flags);
- tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'SendMessage'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: CloseSocket of class cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cTCPLink_CloseSocket00
-static int tolua_AllToLua_cTCPLink_CloseSocket00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- cTCPLink* self = (cTCPLink*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CloseSocket'", NULL);
-#endif
- {
- self->CloseSocket();
- }
- }
- return 0;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'CloseSocket'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
- class Lua__cTCPLink : public cTCPLink, public ToluaBase {
-public:
- void ReceivedData( char* a_Data, int a_Size) {
- if (push_method("ReceivedData", NULL)) {
- tolua_pushstring(lua_state, (const char*)a_Data);
- tolua_pushnumber(lua_state, (lua_Number)a_Size);
- ToluaBase::dbcall(lua_state, 3, 0);
- } else {
- if (lua_state)
- LOG("pure-virtual method cTCPLink::ReceivedData not implemented.");
- else {
- LOG("pure-virtual method cTCPLink::ReceivedData called with no lua_state. Aborting");
- ::abort();
- };
- return ( void )0;
- };
- };
-
- Lua__cTCPLink( void ): cTCPLink(){};
-};
-
-/* method: tolua__set_instance of class Lua__cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_Lua__cTCPLink_tolua__set_instance00
-static int tolua_AllToLua_Lua__cTCPLink_tolua__set_instance00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"Lua__cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,3,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- Lua__cTCPLink* self = (Lua__cTCPLink*) tolua_tousertype(tolua_S,1,0);
- lua_State* L = tolua_S;
- lua_Object lo = ((lua_Object) tolua_tovalue(tolua_S,2,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'tolua__set_instance'", NULL);
-#endif
- {
- self->tolua__set_instance(L,lo);
- }
- }
- return 0;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'tolua__set_instance'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: new of class Lua__cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_Lua__cTCPLink_new00
-static int tolua_AllToLua_Lua__cTCPLink_new00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertable(tolua_S,1,"Lua__cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- {
- Lua__cTCPLink* tolua_ret = (Lua__cTCPLink*) Mtolua_new((Lua__cTCPLink)());
- tolua_pushusertype(tolua_S,(void*)tolua_ret,"Lua__cTCPLink");
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: new_local of class Lua__cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_Lua__cTCPLink_new00_local
-static int tolua_AllToLua_Lua__cTCPLink_new00_local(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertable(tolua_S,1,"Lua__cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- {
- Lua__cTCPLink* tolua_ret = (Lua__cTCPLink*) Mtolua_new((Lua__cTCPLink)());
- tolua_pushusertype(tolua_S,(void*)tolua_ret,"Lua__cTCPLink");
- tolua_register_gc(tolua_S,lua_gettop(tolua_S));
- }
- }
- return 1;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-/* method: delete of class Lua__cTCPLink */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_Lua__cTCPLink_delete00
-static int tolua_AllToLua_Lua__cTCPLink_delete00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (
- !tolua_isusertype(tolua_S,1,"Lua__cTCPLink",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
- )
- goto tolua_lerror;
- else
-#endif
- {
- Lua__cTCPLink* self = (Lua__cTCPLink*) tolua_tousertype(tolua_S,1,0);
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'delete'", NULL);
-#endif
- Mtolua_delete(self);
- }
- return 0;
-#ifndef TOLUA_RELEASE
- tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'delete'.",&tolua_err);
- return 0;
-#endif
-}
-#endif //#ifndef TOLUA_DISABLE
-
-
-/* function to release collected object via destructor */
-#ifdef __cplusplus
-
-static int tolua_collect_Lua__cTCPLink (lua_State* tolua_S)
-{
- Lua__cTCPLink* self = (Lua__cTCPLink*) tolua_tousertype(tolua_S,1,0);
- delete self;
- return 0;
-}
-#endif
-
/* method: new of class Vector3f */
#ifndef TOLUA_DISABLE_tolua_AllToLua_Vector3f_new00
static int tolua_AllToLua_Vector3f_new00(lua_State* tolua_S)
@@ -22513,30 +22180,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetProtocolVersionTextFromInt",tolua_AllToLua_cRoot_GetProtocolVersionTextFromInt00);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
- tolua_cclass(tolua_S,"cTCPLink","cTCPLink","",tolua_collect_cTCPLink);
- #else
- tolua_cclass(tolua_S,"cTCPLink","cTCPLink","",NULL);
- #endif
- tolua_beginmodule(tolua_S,"cTCPLink");
- tolua_function(tolua_S,"delete",tolua_AllToLua_cTCPLink_delete00);
- tolua_function(tolua_S,"Connect",tolua_AllToLua_cTCPLink_Connect00);
- tolua_function(tolua_S,"Send",tolua_AllToLua_cTCPLink_Send00);
- tolua_function(tolua_S,"SendMessage",tolua_AllToLua_cTCPLink_SendMessage00);
- tolua_function(tolua_S,"CloseSocket",tolua_AllToLua_cTCPLink_CloseSocket00);
- tolua_endmodule(tolua_S);
- #ifdef __cplusplus
- tolua_cclass(tolua_S,"Lua__cTCPLink","Lua__cTCPLink","cTCPLink",tolua_collect_Lua__cTCPLink);
- #else
- tolua_cclass(tolua_S,"Lua__cTCPLink","Lua__cTCPLink","cTCPLink",NULL);
- #endif
- tolua_beginmodule(tolua_S,"Lua__cTCPLink");
- tolua_function(tolua_S,"tolua__set_instance",tolua_AllToLua_Lua__cTCPLink_tolua__set_instance00);
- tolua_function(tolua_S,"new",tolua_AllToLua_Lua__cTCPLink_new00);
- tolua_function(tolua_S,"new_local",tolua_AllToLua_Lua__cTCPLink_new00_local);
- tolua_function(tolua_S,".call",tolua_AllToLua_Lua__cTCPLink_new00_local);
- tolua_function(tolua_S,"delete",tolua_AllToLua_Lua__cTCPLink_delete00);
- tolua_endmodule(tolua_S);
- #ifdef __cplusplus
tolua_cclass(tolua_S,"Vector3f","Vector3f","",tolua_collect_Vector3f);
#else
tolua_cclass(tolua_S,"Vector3f","Vector3f","",NULL);
diff --git a/source/Bindings.h b/source/Bindings.h
index 6a9515913..1a56d4e60 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 03/03/13 20:02:18.
+** Generated automatically by tolua++-1.0.92 on 03/04/13 22:33:20.
*/
/* Exported function */
diff --git a/source/Globals.h b/source/Globals.h
index 958c6d6ae..038b173cf 100644
--- a/source/Globals.h
+++ b/source/Globals.h
@@ -94,6 +94,7 @@ typedef unsigned short UInt16;
#define WIN32_LEAN_AND_MEAN
#include
#include
+ #include // IPv6 stuff
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
#undef min
diff --git a/source/ListenThread.cpp b/source/ListenThread.cpp
index 52a4df9e4..e1031a3cd 100644
--- a/source/ListenThread.cpp
+++ b/source/ListenThread.cpp
@@ -10,9 +10,10 @@
-cListenThread::cListenThread(cCallback & a_Callback) :
+cListenThread::cListenThread(cCallback & a_Callback, cSocket::eFamily a_Family) :
super("ListenThread"),
- m_Callback(a_Callback)
+ m_Callback(a_Callback),
+ m_Family(a_Family)
{
}
@@ -47,8 +48,12 @@ bool cListenThread::Initialize(const AString & a_PortsString)
bool cListenThread::Start(void)
{
- ASSERT(!m_Sockets.empty()); // Has Initialize() been called?
-
+ if (m_Sockets.empty())
+ {
+ // There are no sockets listening, either forgotten to initialize or the user specified no listening ports
+ // Report as successful, though
+ return true;
+ }
return super::Start();
}
@@ -58,6 +63,12 @@ bool cListenThread::Start(void)
void cListenThread::Stop(void)
{
+ if (m_Sockets.empty())
+ {
+ // No sockets means no thread was running in the first place
+ return;
+ }
+
m_ShouldTerminate = true;
// Close one socket to wake the thread up from the select() call
@@ -76,7 +87,7 @@ void cListenThread::Stop(void)
void cListenThread::SetReuseAddr(bool a_Reuse)
{
- ASSERT(m_Sockets.empty()); // Must not be started
+ ASSERT(m_Sockets.empty()); // Must not have been Initialize()d yet
m_ShouldReuseAddr = a_Reuse;
}
@@ -94,6 +105,18 @@ bool cListenThread::CreateSockets(const AString & a_PortsString)
return false;
}
+ const char * FamilyStr = "";
+ switch (m_Family)
+ {
+ case cSocket::IPv4: FamilyStr = "IPv4: "; break;
+ case cSocket::IPv6: FamilyStr = "IPv6: "; break;
+ default:
+ {
+ ASSERT(!"Unknown address family");
+ break;
+ }
+ }
+
for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
{
int Port = atoi(Trim(*itr).c_str());
@@ -102,7 +125,7 @@ bool cListenThread::CreateSockets(const AString & a_PortsString)
LOGWARNING("Invalid port specified: \"%s\".", Trim(*itr).c_str());
continue;
}
- m_Sockets.push_back(cSocket::CreateSocket());
+ m_Sockets.push_back(cSocket::CreateSocket(m_Family));
if (!m_Sockets.back().IsValid())
{
LOGERROR("Cannot create listening socket for port %d: \"%s\"", Port, cSocket::GetLastErrorString().c_str());
@@ -112,14 +135,39 @@ bool cListenThread::CreateSockets(const AString & a_PortsString)
if (m_ShouldReuseAddr)
{
- if (m_Sockets.back().SetReuseAddress() == -1)
+ if (!m_Sockets.back().SetReuseAddress())
{
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);
+
+ // Bind to port:
+ bool res = false;
+ switch (m_Family)
+ {
+ case cSocket::IPv4: res = m_Sockets.back().BindToAnyIPv4(Port); break;
+ case cSocket::IPv6: res = m_Sockets.back().BindToAnyIPv6(Port); break;
+ default:
+ {
+ ASSERT(!"Unknown address family");
+ res = false;
+ }
+ }
+ if (!res)
+ {
+ LOGWARNING("Cannot bind port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
+ m_Sockets.pop_back();
+ continue;
+ }
+
+ if (!m_Sockets.back().Listen())
+ {
+ LOGWARNING("Cannot listen on port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
+ m_Sockets.pop_back();
+ continue;
+ }
+
+ LOGD("%sPort %d is open for connections", FamilyStr, Port);
} // for itr - Ports[]
return !(m_Sockets.empty());
@@ -131,6 +179,12 @@ bool cListenThread::CreateSockets(const AString & a_PortsString)
void cListenThread::Execute(void)
{
+ if (m_Sockets.empty())
+ {
+ LOGD("Empty cListenThread, ending thread now.");
+ return;
+ }
+
// 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)
diff --git a/source/ListenThread.h b/source/ListenThread.h
index 90523ea4f..ab2c97b9d 100644
--- a/source/ListenThread.h
+++ b/source/ListenThread.h
@@ -37,7 +37,7 @@ public:
virtual void OnConnectionAccepted(cSocket & a_Socket) = 0;
} ;
- cListenThread(cCallback & a_Callback);
+ cListenThread(cCallback & a_Callback, cSocket::eFamily a_Family);
~cListenThread();
/// Creates all the sockets, returns trus if successful, false if not.
@@ -56,6 +56,9 @@ protected:
/// The callback which to notify of incoming connections
cCallback & m_Callback;
+ /// Socket address family to use
+ cSocket::eFamily m_Family;
+
/// Sockets that are being monitored
cSockets m_Sockets;
diff --git a/source/OSSupport/Socket.cpp b/source/OSSupport/Socket.cpp
index e0cecc0e3..2412852d5 100644
--- a/source/OSSupport/Socket.cpp
+++ b/source/OSSupport/Socket.cpp
@@ -155,14 +155,14 @@ int cSocket::GetLastError()
-int cSocket::SetReuseAddress()
+bool cSocket::SetReuseAddress(void)
{
-#if defined(_WIN32) || defined(ANDROID_NDK)
- char yes = 1;
-#else
- int yes = 1;
-#endif
- return setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
+ #if defined(_WIN32) || defined(ANDROID_NDK)
+ char yes = 1;
+ #else
+ int yes = 1;
+ #endif
+ return (setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == 0);
}
@@ -184,9 +184,9 @@ int cSocket::WSAStartup()
-cSocket cSocket::CreateSocket()
+cSocket cSocket::CreateSocket(eFamily a_Family)
{
- return socket(AF_INET,SOCK_STREAM,0);
+ return socket((int)a_Family, SOCK_STREAM, 0);
}
@@ -207,23 +207,40 @@ unsigned long cSocket::INTERNET_ADDRESS_LOCALHOST(void)
-int cSocket::BindToAny(unsigned short a_Port)
+bool cSocket::BindToAnyIPv4(unsigned short a_Port)
{
sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
- local.sin_addr.s_addr = 0;
local.sin_port = htons((u_short)a_Port);
- return bind(m_Socket, (sockaddr*)&local, sizeof(local));
+ return (bind(m_Socket, (sockaddr *)&local, sizeof(local)) == 0);
}
-int cSocket::BindToLocalhost(unsigned short a_Port)
+bool cSocket::BindToAnyIPv6(unsigned short a_Port)
+{
+ // Cannot use socckaddr_in6, because it is not defined in the default VS2008 SDK
+ // Must jump through hoops here
+
+ sockaddr_in6 local;
+ memset(&local, 0, sizeof(local));
+
+ local.sin6_family = AF_INET6;
+ local.sin6_port = htons((u_short)a_Port);
+
+ return (bind(m_Socket, (sockaddr *)&local, sizeof(local)) == 0);
+}
+
+
+
+
+
+bool cSocket::BindToLocalhostIPv4(unsigned short a_Port)
{
sockaddr_in local;
memset(&local, 0, sizeof(local));
@@ -232,16 +249,16 @@ int cSocket::BindToLocalhost(unsigned short a_Port)
local.sin_addr.s_addr = INTERNET_ADDRESS_LOCALHOST();
local.sin_port = htons((u_short)a_Port);
- return bind(m_Socket, (sockaddr*)&local, sizeof(local));
+ return (bind(m_Socket, (sockaddr*)&local, sizeof(local)) == 0);
}
-int cSocket::Listen(int a_Backlog)
+bool cSocket::Listen(int a_Backlog)
{
- return listen(m_Socket, a_Backlog);
+ return (listen(m_Socket, a_Backlog) == 0);
}
@@ -267,6 +284,7 @@ cSocket cSocket::Accept()
+/*
int cSocket::Connect(SockAddr_In & a_Address)
{
sockaddr_in local;
@@ -277,12 +295,26 @@ int cSocket::Connect(SockAddr_In & a_Address)
return connect(m_Socket, (sockaddr *)&local, sizeof(local));
}
+*/
-int cSocket::Connect(const AString & a_HostNameOrAddr, unsigned short a_Port)
+bool cSocket::ConnectToLocalhostIPv4(unsigned short a_Port)
+{
+ sockaddr_in server;
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INTERNET_ADDRESS_LOCALHOST();
+ server.sin_port = htons(a_Port);
+ return (connect(m_Socket, (sockaddr *)&server, sizeof(server)) == 0);
+}
+
+
+
+
+
+bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Port)
{
// First try IP Address string to hostent conversion, because it's faster
unsigned long addr = inet_addr(a_HostNameOrAddr.c_str());
@@ -303,7 +335,7 @@ int cSocket::Connect(const AString & a_HostNameOrAddr, unsigned short a_Port)
server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);
server.sin_family = AF_INET;
server.sin_port = htons( (unsigned short)a_Port );
- return connect(m_Socket, (sockaddr *)&server, sizeof(server));
+ return (connect(m_Socket, (sockaddr *)&server, sizeof(server)) == 0);
}
diff --git a/source/OSSupport/Socket.h b/source/OSSupport/Socket.h
index c1e510387..7c051d229 100644
--- a/source/OSSupport/Socket.h
+++ b/source/OSSupport/Socket.h
@@ -8,6 +8,12 @@
class cSocket
{
public:
+ enum eFamily
+ {
+ IPv4 = AF_INET,
+ IPv6 = AF_INET6,
+ } ;
+
#ifdef _WIN32
typedef SOCKET xSocket;
#else
@@ -20,28 +26,31 @@ public:
~cSocket();
bool IsValid(void) const { return IsValidSocket(m_Socket); }
- void CloseSocket();
+ void CloseSocket(void);
- operator xSocket() const;
- xSocket GetSocket() const;
+ operator xSocket(void) const;
+ xSocket GetSocket(void) const;
bool operator == (const cSocket & a_Other) {return m_Socket == a_Other.m_Socket; }
- void SetSocket( xSocket a_Socket );
+ void SetSocket(xSocket a_Socket);
- int SetReuseAddress();
- static int WSAStartup();
+ /// Sets the address-reuse socket flag; returns true on success
+ bool SetReuseAddress(void);
+
+ static int WSAStartup(void);
- static AString GetErrorString( int a_ErrNo );
+ static AString GetErrorString(int a_ErrNo);
static int GetLastError();
static AString GetLastErrorString(void)
{
return GetErrorString(GetLastError());
}
- static cSocket CreateSocket();
+ /// Creates a new socket of the specified address family
+ static cSocket CreateSocket(eFamily a_Family);
- inline static bool IsSocketError( int a_ReturnedValue )
+ inline static bool IsSocketError(int a_ReturnedValue)
{
#ifdef _WIN32
return (a_ReturnedValue == SOCKET_ERROR || a_ReturnedValue == 0);
@@ -52,37 +61,31 @@ public:
static bool IsValidSocket(xSocket a_Socket);
- struct SockAddr_In
- {
- short Family;
- unsigned short Port;
- unsigned long Address;
- };
-
- static const short ADDRESS_FAMILY_INTERNET = 2;
- static const unsigned long INTERNET_ADDRESS_ANY = 0;
static unsigned long INTERNET_ADDRESS_LOCALHOST(void); // 127.0.0.1 represented in network byteorder; must be a function due to GCC :(
static const unsigned short ANY_PORT = 0; // When given to Bind() functions, they will find a free port
static const int DEFAULT_BACKLOG = 10;
- /// Binds to the specified port on "any" interface (0.0.0.0)
- int BindToAny(unsigned short a_Port);
+ /// Binds to the specified port on "any" interface (0.0.0.0). Returns true if successful.
+ bool BindToAnyIPv4(unsigned short a_Port);
- /*
- // TODO:
- /// Binds to the specified port
- int BindToAny6(unsigned short a_Port);
- */
+ /// Binds to the specified port on "any" interface (::/128). Returns true if successful.
+ bool BindToAnyIPv6(unsigned short a_Port);
- /// Binds to the specified port on localhost interface (127.0.0.1) through IPv4
- int BindToLocalhost(unsigned short a_Port);
+ /// Binds to the specified port on localhost interface (127.0.0.1) through IPv4. Returns true if successful.
+ bool BindToLocalhostIPv4(unsigned short a_Port);
- int Listen(int a_Backlog = DEFAULT_BACKLOG);
+ /// Sets the socket to listen for incoming connections. Returns true if successful.
+ bool Listen(int a_Backlog = DEFAULT_BACKLOG);
+
+ /// Accepts an incoming connection. Blocks if none available.
cSocket Accept();
- int Connect(SockAddr_In & a_Address); // Returns 0 on success, !0 on failure
+ /// Connects to a localhost socket on the specified port using IPv4; returns true if successful.
+ bool ConnectToLocalhostIPv4(unsigned short a_Port);
+
+ /// Connects to the specified host or string IP address and port, using IPv4. Returns true if successful.
+ bool ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Port);
- int Connect(const AString & a_HostNameOrAddr, unsigned short a_Port); // Returns 0 on success, !0 on failure
int Receive(char * a_Buffer, unsigned int a_Length, unsigned int a_Flags);
int Send (const char * a_Buffer, unsigned int a_Length);
diff --git a/source/OSSupport/SocketThreads.cpp b/source/OSSupport/SocketThreads.cpp
index 943293f5c..e7061ed31 100644
--- a/source/OSSupport/SocketThreads.cpp
+++ b/source/OSSupport/SocketThreads.cpp
@@ -427,13 +427,13 @@ bool cSocketThreads::cSocketThread::QueueClose(const cCallback * a_Client)
bool cSocketThreads::cSocketThread::Start(void)
{
// Create the control socket listener
- m_ControlSocket2 = cSocket::CreateSocket();
+ m_ControlSocket2 = cSocket::CreateSocket(cSocket::IPv4);
if (!m_ControlSocket2.IsValid())
{
LOGERROR("Cannot create a Control socket for a cSocketThread (\"%s\"); continuing, but server may be unreachable from now on.", cSocket::GetLastErrorString().c_str());
return false;
}
- if (m_ControlSocket2.BindToLocalhost(cSocket::ANY_PORT) != 0)
+ if (m_ControlSocket2.BindToLocalhostIPv4(cSocket::ANY_PORT) != 0)
{
LOGERROR("Cannot bind a Control socket for a cSocketThread (\"%s\"); continuing, but server may be unreachable from now on.", cSocket::GetLastErrorString().c_str());
m_ControlSocket2.CloseSocket();
@@ -481,13 +481,9 @@ bool cSocketThreads::cSocketThread::Start(void)
void cSocketThreads::cSocketThread::Execute(void)
{
// Connect the "client" part of the Control socket:
- m_ControlSocket1 = cSocket::CreateSocket();
- cSocket::SockAddr_In Addr;
- Addr.Family = cSocket::ADDRESS_FAMILY_INTERNET;
- Addr.Address = cSocket::INTERNET_ADDRESS_LOCALHOST();
- Addr.Port = m_ControlSocket2.GetPort();
- ASSERT(Addr.Port != 0); // We checked in the Start() method, but let's be sure
- if (m_ControlSocket1.Connect(Addr) != 0)
+ m_ControlSocket1 = cSocket::CreateSocket(cSocket::IPv4);
+ ASSERT(m_ControlSocket2.GetPort() != 0); // We checked in the Start() method, but let's be sure
+ if (!m_ControlSocket1.ConnectToLocalhostIPv4(m_ControlSocket2.GetPort()))
{
LOGERROR("Cannot connect Control sockets for a cSocketThread (\"%s\"); continuing, but the server may be unreachable from now on.", cSocket::GetLastErrorString().c_str());
m_ControlSocket2.CloseSocket();
diff --git a/source/OSSupport/TCPLink.cpp b/source/OSSupport/TCPLink.cpp
deleted file mode 100644
index d4c423b94..000000000
--- a/source/OSSupport/TCPLink.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "TCPLink.h"
-
-
-
-
-
-#ifdef _WIN32
- #define MSG_NOSIGNAL (0)
-#endif
-#ifdef __MACH__
- #define MSG_NOSIGNAL (0)
-#endif
-
-
-
-
-
-cTCPLink::cTCPLink()
- : m_Socket( 0 )
- , m_StopEvent( new cEvent() )
-{
-}
-
-cTCPLink::~cTCPLink()
-{
- if( m_Socket )
- {
- CloseSocket();
- m_StopEvent->Wait();
- }
- delete m_StopEvent;
-}
-
-void cTCPLink::CloseSocket()
-{
- if( m_Socket )
- {
- m_Socket.CloseSocket();
- m_Socket = 0;
- }
-}
-
-bool cTCPLink::Connect( const AString & a_Address, unsigned int a_Port )
-{
- if( m_Socket )
- {
- LOGWARN("WARNING: cTCPLink Connect() called while still connected. ALWAYS disconnect before re-connecting!");
- }
-
- m_Socket = cSocket::CreateSocket();
- if( !m_Socket.IsValid() )
- {
- LOGERROR("cTCPLink: Failed to create socket");
- return false;
- }
-
- if (m_Socket.Connect(a_Address, a_Port) != 0)
- {
- LOGWARN("cTCPLink: Cannot connect to server \"%s\" (%s)", m_Socket.GetLastErrorString().c_str());
- m_Socket.CloseSocket();
- return false;
- }
-
- cThread( ReceiveThread, this );
-
- return true;
-}
-
-
-
-
-
-int cTCPLink::Send(const char * a_Data, unsigned int a_Size, int a_Flags /* = 0 */ )
-{
- (void)a_Flags;
- if (!m_Socket.IsValid())
- {
- LOGWARN("cTCPLink: Trying to send data without a valid connection!");
- return -1;
- }
- return m_Socket.Send(a_Data, a_Size);
-}
-
-
-
-
-
-int cTCPLink::SendMessage(const char * a_Message, int a_Flags /* = 0 */ )
-{
- (void)a_Flags;
- if (!m_Socket.IsValid())
- {
- LOGWARN("cTCPLink: Trying to send message without a valid connection!");
- return -1;
- }
- return m_Socket.Send(a_Message, strlen(a_Message));
-}
-
-
-
-
-
-void cTCPLink::ReceiveThread( void* a_Param)
-{
- cTCPLink* self = (cTCPLink*)a_Param;
- cSocket Socket = self->m_Socket;
- int Received = 0;
- do
- {
- char Data[256];
- Received = Socket.Receive(Data, sizeof(Data), 0);
- self->ReceivedData( Data, ((Received > 0) ? Received : -1) );
- } while ( Received > 0 );
-
- LOGINFO("cTCPLink Disconnected (%i)", Received );
-
- if (Socket == self->m_Socket)
- {
- self->m_StopEvent->Set();
- }
-}
-
-
-
-
diff --git a/source/OSSupport/TCPLink.h b/source/OSSupport/TCPLink.h
deleted file mode 100644
index ce7abcef0..000000000
--- a/source/OSSupport/TCPLink.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include "Socket.h"
-
-class cTCPLink // tolua_export
-{ // tolua_export
-public: // tolua_export
- cTCPLink(); // tolua_export
- ~cTCPLink(); // tolua_export
-
- bool Connect (const AString & a_Address, unsigned int a_Port ); // tolua_export
- int Send (const char * a_Data, unsigned int a_Size, int a_Flags = 0 ); // tolua_export
- int SendMessage(const char * a_Message, int a_Flags = 0 ); // tolua_export
- void CloseSocket(); // tolua_export
-protected: // tolua_export
- virtual void ReceivedData( char a_Data[256], int a_Size ) = 0; // tolua_export
-
- static void ReceiveThread( void* a_Param );
-
- cSocket m_Socket;
- cEvent* m_StopEvent;
-}; // tolua_export
diff --git a/source/Server.cpp b/source/Server.cpp
index 3fcaa6e8e..24d999b31 100644
--- a/source/Server.cpp
+++ b/source/Server.cpp
@@ -153,10 +153,24 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
return false;
}
+ bool HasAnyPorts = false;
AString Ports = a_SettingsIni.GetValueSet("Server", "Port", "25565");
- m_ListenThread.SetReuseAddr(true);
- if (!m_ListenThread.Initialize(Ports))
+ m_ListenThreadIPv4.SetReuseAddr(true);
+ if (m_ListenThreadIPv4.Initialize(Ports))
{
+ HasAnyPorts = true;
+ }
+
+ Ports = a_SettingsIni.GetValueSet("Server", "PortsIPv6", "25565");
+ m_ListenThreadIPv6.SetReuseAddr(true);
+ if (m_ListenThreadIPv6.Initialize(Ports))
+ {
+ HasAnyPorts = true;
+ }
+
+ if (!HasAnyPorts)
+ {
+ LOGERROR("Couldn't open any ports. Aborting the server");
return false;
}
@@ -201,7 +215,8 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
cServer::cServer(void)
: m_pState(new sServerState)
- , m_ListenThread(*this)
+ , m_ListenThreadIPv4(*this, cSocket::IPv4)
+ , m_ListenThreadIPv6(*this, cSocket::IPv6)
, m_Millisecondsf(0)
, m_Milliseconds(0)
, m_bIsConnected(false)
@@ -385,7 +400,11 @@ void ServerTickThread( void * a_Param )
bool cServer::Start(void)
{
m_pState->pTickThread = new cThread( ServerTickThread, this, "cServer::ServerTickThread" );
- if (!m_ListenThread.Start())
+ if (!m_ListenThreadIPv4.Start())
+ {
+ return false;
+ }
+ if (!m_ListenThreadIPv6.Start())
{
return false;
}
@@ -483,7 +502,8 @@ void cServer::SendMessage(const AString & a_Message, cPlayer * a_Player /* = NUL
void cServer::Shutdown()
{
- m_ListenThread.Stop();
+ m_ListenThreadIPv4.Stop();
+ m_ListenThreadIPv6.Stop();
m_bRestarting = true;
m_pState->RestartEvent.Wait();
diff --git a/source/Server.h b/source/Server.h
index ec91bb6c0..b12453aec 100644
--- a/source/Server.h
+++ b/source/Server.h
@@ -101,10 +101,12 @@ private:
} ;
struct sServerState;
- sServerState* m_pState;
+ sServerState * m_pState;
cNotifyWriteThread m_NotifyWriteThread;
- cListenThread m_ListenThread;
+
+ cListenThread m_ListenThreadIPv4; // IPv4
+ cListenThread m_ListenThreadIPv6; // IPv6
cCriticalSection m_CSClients; // Locks client list
cClientHandleList m_Clients; // Clients that are connected to the server