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