From 48d30d6ab4657e00c0c861d67285256daeff1142 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 1 Feb 2012 22:38:03 +0000 Subject: Rewritten cAuthenticator to make use of the new cIsThread architecture - now authentication runs in a single separate thread for all clients; Global player-kicking function (cServer, cRoot); More char * -> AString conversion git-svn-id: http://mc-server.googlecode.com/svn/trunk@221 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 49 +++---- source/Bindings.h | 2 +- source/Globals.h | 11 ++ source/StringUtils.cpp | 13 ++ source/StringUtils.h | 3 + source/cAuthenticator.cpp | 261 ++++++++++++++++++++++-------------- source/cAuthenticator.h | 81 ++++++++++- source/cBlockingTCPLink.cpp | 116 ++++++++-------- source/cBlockingTCPLink.h | 5 +- source/cChunk.cpp | 4 +- source/cClientHandle.cpp | 68 ++++------ source/cClientHandle.h | 8 +- source/cMonster.cpp | 2 +- source/cPlayer.cpp | 20 ++- source/cPlayer.h | 6 +- source/cRoot.cpp | 68 +++++++++- source/cRoot.h | 42 ++++-- source/cServer.cpp | 109 +++++++++++++-- source/cServer.h | 5 +- source/cSocket.cpp | 61 +++++++-- source/cSocket.h | 8 +- source/cWebAdmin.cpp | 6 - source/cWorld.cpp | 4 + source/packets/cPacket_Disconnect.h | 4 +- 24 files changed, 667 insertions(+), 289 deletions(-) (limited to 'source') diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 51bc36108..0021b1d3b 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/01/12 20:13:33. +** Generated automatically by tolua++-1.0.92 on 02/01/12 21:13:18. */ #ifndef __cplusplus @@ -164,55 +164,56 @@ static void tolua_reg_types (lua_State* tolua_S) tolua_usertype(tolua_S,"TakeDamageInfo"); tolua_usertype(tolua_S,"cPlugin"); tolua_usertype(tolua_S,"cStringMap"); - tolua_usertype(tolua_S,"Lua__cEntity"); + tolua_usertype(tolua_S,"cPluginManager"); + tolua_usertype(tolua_S,"Lua__cPacket_BlockDig"); tolua_usertype(tolua_S,"Json::Value"); tolua_usertype(tolua_S,"cInventory"); tolua_usertype(tolua_S,"cRoot"); - tolua_usertype(tolua_S,"Lua__cPacket_BlockDig"); + tolua_usertype(tolua_S,"cTCPLink"); tolua_usertype(tolua_S,"Lua__cTCPLink"); - tolua_usertype(tolua_S,"cWorld"); + tolua_usertype(tolua_S,"cTracer"); tolua_usertype(tolua_S,"cPlugin::CommandStruct"); tolua_usertype(tolua_S,"cPickup"); tolua_usertype(tolua_S,"cGroup"); tolua_usertype(tolua_S,"cPacket_Login"); tolua_usertype(tolua_S,"cClientHandle"); - tolua_usertype(tolua_S,"cTracer"); - tolua_usertype(tolua_S,"cFurnaceRecipe"); tolua_usertype(tolua_S,"cMCLogger"); - tolua_usertype(tolua_S,"cChatColor"); + tolua_usertype(tolua_S,"cFurnaceRecipe"); tolua_usertype(tolua_S,"cCuboid"); + tolua_usertype(tolua_S,"cChatColor"); + tolua_usertype(tolua_S,"Vector3i"); tolua_usertype(tolua_S,"cPacket_PickupSpawn"); tolua_usertype(tolua_S,"Lua__cWebPlugin"); tolua_usertype(tolua_S,"Lua__cPawn"); - tolua_usertype(tolua_S,"Vector3i"); + tolua_usertype(tolua_S,"cPlugin_NewLua"); tolua_usertype(tolua_S,"cItem"); tolua_usertype(tolua_S,"Vector3f"); tolua_usertype(tolua_S,"cPlugin_Lua"); tolua_usertype(tolua_S,"cWebPlugin_Lua"); - tolua_usertype(tolua_S,"Lua__cPlugin_NewLua"); + tolua_usertype(tolua_S,"Lua__cPlayer"); tolua_usertype(tolua_S,"cPacket"); tolua_usertype(tolua_S,"cPacket_BlockDig"); tolua_usertype(tolua_S,"cWebAdmin"); - tolua_usertype(tolua_S,"cTCPLink"); - tolua_usertype(tolua_S,"cBlockEntity"); tolua_usertype(tolua_S,"cRecipeChecker"); + tolua_usertype(tolua_S,"cBlockEntity"); tolua_usertype(tolua_S,"cGroupManager"); - tolua_usertype(tolua_S,"Lua__cPlugin"); tolua_usertype(tolua_S,"Lua__cPickup"); + tolua_usertype(tolua_S,"Lua__cPlugin"); + tolua_usertype(tolua_S,"Lua__cEntity"); tolua_usertype(tolua_S,"cPacket_BlockPlace"); tolua_usertype(tolua_S,"cLadder"); - tolua_usertype(tolua_S,"cPluginManager"); - tolua_usertype(tolua_S,"Lua__cPlayer"); - tolua_usertype(tolua_S,"cIniFile"); tolua_usertype(tolua_S,"cWebPlugin"); + tolua_usertype(tolua_S,"AString"); + tolua_usertype(tolua_S,"cIniFile"); + tolua_usertype(tolua_S,"cEntity"); tolua_usertype(tolua_S,"HTTPRequest"); tolua_usertype(tolua_S,"cPawn"); tolua_usertype(tolua_S,"cPlayer"); tolua_usertype(tolua_S,"cTorch"); - tolua_usertype(tolua_S,"cEntity"); - tolua_usertype(tolua_S,"cPlugin_NewLua"); tolua_usertype(tolua_S,"HTTPFormData"); tolua_usertype(tolua_S,"cServer"); + tolua_usertype(tolua_S,"cWorld"); + tolua_usertype(tolua_S,"Lua__cPlugin_NewLua"); tolua_usertype(tolua_S,"cStairs"); tolua_usertype(tolua_S,"Vector3d"); } @@ -2967,7 +2968,7 @@ static int tolua_AllToLua_cClientHandle_Kick00(lua_State* tolua_S) tolua_Error tolua_err; if ( !tolua_isusertype(tolua_S,1,"cClientHandle",0,&tolua_err) || - !tolua_isstring(tolua_S,2,0,&tolua_err) || + (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const AString",0,&tolua_err)) || !tolua_isnoobj(tolua_S,3,&tolua_err) ) goto tolua_lerror; @@ -2975,12 +2976,12 @@ static int tolua_AllToLua_cClientHandle_Kick00(lua_State* tolua_S) #endif { cClientHandle* self = (cClientHandle*) tolua_tousertype(tolua_S,1,0); - const char* a_Reason = ((const char*) tolua_tostring(tolua_S,2,0)); + const AString* a_Reason = ((const AString*) tolua_tousertype(tolua_S,2,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Kick'", NULL); #endif { - self->Kick(a_Reason); + self->Kick(*a_Reason); } } return 0; @@ -5444,20 +5445,20 @@ static int tolua_AllToLua_cPlayer_GetName00(lua_State* tolua_S) #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) || + !tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) || !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { - cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0); + const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetName'", NULL); #endif { - const char* tolua_ret = (const char*) self->GetName(); - tolua_pushstring(tolua_S,(const char*)tolua_ret); + const AString& tolua_ret = (const AString&) self->GetName(); + tolua_pushusertype(tolua_S,(void*)&tolua_ret,"const AString"); } } return 1; diff --git a/source/Bindings.h b/source/Bindings.h index 45e35709e..76a4e453d 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/01/12 20:13:33. +** Generated automatically by tolua++-1.0.92 on 02/01/12 21:13:19. */ /* Exported function */ diff --git a/source/Globals.h b/source/Globals.h index 8d42d6341..2b37c6df4 100644 --- a/source/Globals.h +++ b/source/Globals.h @@ -8,6 +8,16 @@ +// Compiler-dependent stuff: +#ifndef _MSC_VER + // Non-MS compilers don't know the override keyword + #define override +#endif // _MSC_VER + + + + + // OS-dependent stuff: #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -52,6 +62,7 @@ // STL stuff: #include #include +#include #include #include #include diff --git a/source/StringUtils.cpp b/source/StringUtils.cpp index 94b4d3c0f..c9dbb1113 100644 --- a/source/StringUtils.cpp +++ b/source/StringUtils.cpp @@ -146,3 +146,16 @@ int NoCaseCompare(const AString & s1, const AString & s2) +void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith) +{ + size_t pos1 = iHayStack.find(iNeedle); + while (pos1 != AString::npos) + { + iHayStack.replace( pos1, iNeedle.size(), iReplaceWith); + pos1 = iHayStack.find(iNeedle, pos1); + } +} + + + + diff --git a/source/StringUtils.h b/source/StringUtils.h index 97e42f5f5..8805c1d99 100644 --- a/source/StringUtils.h +++ b/source/StringUtils.h @@ -38,6 +38,9 @@ extern AString & StrToUpper(AString & s); /// Case-insensitive string comparison; returns 0 if the strings are the same extern int NoCaseCompare(const AString & s1, const AString & s2); +/// Replaces *each* occurence of iNeedle in iHayStack with iReplaceWith +extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith); + // If you have any other string helper functions, declare them here diff --git a/source/cAuthenticator.cpp b/source/cAuthenticator.cpp index 83b2695a4..1f7e5b35c 100644 --- a/source/cAuthenticator.cpp +++ b/source/cAuthenticator.cpp @@ -3,6 +3,8 @@ #include "cAuthenticator.h" #include "cBlockingTCPLink.h" +#include "cRoot.h" +#include "cServer.h" #include "../iniFile/iniFile.h" @@ -12,116 +14,174 @@ -extern void ReplaceString( std::string & a_HayStack, const std::string & a_Needle, const std::string & a_ReplaceWith ); +#define DEFAULT_AUTH_SERVER "session.minecraft.net" +#define DEFAULT_AUTH_ADDRESS "/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID%" +#define MAX_REDIRECTS 10 -cAuthenticator::cAuthenticator() +cAuthenticator::cAuthenticator(void) : + super("cAuthenticator"), + mServer(DEFAULT_AUTH_SERVER), + mAddress(DEFAULT_AUTH_ADDRESS), + mShouldAuthenticate(true) { + ReadINI(); } -cAuthenticator::~cAuthenticator() + + + + +/// Read custom values from INI +void cAuthenticator::ReadINI(void) { + cIniFile IniFile("settings.ini"); + if (!IniFile.ReadFile()) + { + return; + } + + mServer = IniFile.GetValue("Authentication", "Server"); + mAddress = IniFile.GetValue("Authentication", "Address"); + mShouldAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true); + bool bSave = false; + + if (mServer.length() == 0) + { + mServer = DEFAULT_AUTH_SERVER; + IniFile.SetValue("Authentication", "Server", mServer); + bSave = true; + } + if (mAddress.length() == 0) + { + mAddress = DEFAULT_AUTH_ADDRESS; + IniFile.SetValue("Authentication", "Address", mAddress); + bSave = true; + } + + if (bSave) + { + IniFile.SetValueB("Authentication", "Authenticate", mShouldAuthenticate); + IniFile.WriteFile(); + } } -bool cAuthenticator::Authenticate( const char* a_PlayerName, const char* a_ServerID ) + + + + +/// Queues a request for authenticating a user. If the auth fails, the user is kicked +void cAuthenticator::Authenticate(const AString & iUserName, const AString & iServerID) { - // Default values - std::string Server = "session.minecraft.net"; - std::string Address = "/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID%"; - bool bAuthenticate = true; + if (!mShouldAuthenticate) + { + cRoot::Get()->AuthenticateUser(iUserName); + return; + } - // Read custom values from INI - cIniFile IniFile("settings.ini"); - if( IniFile.ReadFile() ) + cCSLock Lock(mCS); + mQueue.push_back(cUser(iUserName, iServerID)); + mQueueNonempty.Set(); +} + + + + + +void cAuthenticator::Execute(void) +{ + while (true) { - std::string tServer = IniFile.GetValue("Authentication", "Server"); - std::string tAddress = IniFile.GetValue("Authentication", "Address"); - bAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true); - bool bSave = false; - if( tServer.length() == 0 ) + cCSLock Lock(mCS); + while (!mShouldTerminate && (mQueue.size() == 0)) { - IniFile.SetValue("Authentication", "Server", Server, true ); - bSave = true; + cCSUnlock Unlock(Lock); + mQueueNonempty.Wait(); } - else - Server = tServer; - if( tAddress.length() == 0 ) + if (mShouldTerminate) + { + return; + } + assert(mQueue.size() > 0); + + AString UserName = mQueue.front().mName; + AString ActualAddress = mAddress; + ReplaceString(ActualAddress, "%USERNAME%", UserName); + ReplaceString(ActualAddress, "%SERVERID%", cRoot::Get()->GetServer()->GetServerID()); + mQueue.pop_front(); + Lock.Unlock(); + + if (!AuthFromAddress(mServer, ActualAddress, UserName)) { - IniFile.SetValue("Authentication", "Address", Address, true ); - bSave = true; + cRoot::Get()->KickUser(UserName, "auth failed"); } else - Address = tAddress; - - if( bSave ) { - IniFile.SetValueB("Authentication", "Authenticate", bAuthenticate, true ); - IniFile.WriteFile(); + cRoot::Get()->AuthenticateUser(UserName); } } +} - if( !bAuthenticate ) // If we don't want to authenticate.. just return true - { - return true; - } - ReplaceString( Address, "%USERNAME%", a_PlayerName ); - ReplaceString( Address, "%SERVERID%", a_ServerID ); - cBlockingTCPLink TCPLink; - if( TCPLink.Connect( Server.c_str(), 80 ) ) - { - //TCPLink.SendMessage( std::string( "GET /game/checkserver.jsp?user=" + std::string(a_PlayerName) + "&serverId=" + std::string(a_ServerID) + " HTTP/1.0\r\n\r\n" ).c_str() ); - TCPLink.SendMessage( std::string( "GET " + Address + " HTTP/1.0\r\n\r\n" ).c_str() ); - //LOGINFO("Successfully connected to mc.net"); - std::string Received = TCPLink.ReceiveData(); - //LOGINFO("Received data: %s", Received.c_str() ); - return ParseReceived( Received.c_str(), &TCPLink ); - } - else + +bool cAuthenticator::AuthFromAddress(const AString & iServer, const AString & iAddress, const AString & iUserName, int iLevel) +{ + // Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep) + + cBlockingTCPLink Link; + if (!Link.Connect(iServer.c_str(), 80)) { - LOGERROR("Could not connect to %s to verify player name! (%s)", Server.c_str(), a_PlayerName ); + LOGERROR("cAuthenticator: cannot connect to auth server \"%s\", kicking user \"%s\"", iServer.c_str(), iUserName.c_str()); return false; } -} + + Link.SendMessage( AString( "GET " + iAddress + " HTTP/1.0\r\n\r\n" ).c_str()); + AString DataRecvd; + Link.ReceiveData(DataRecvd); + Link.CloseSocket(); -bool cAuthenticator::ParseReceived( const char* a_Data, cBlockingTCPLink* a_TCPLink ) -{ - std::stringstream ss(a_Data); + std::stringstream ss(DataRecvd); + // Parse the data received: std::string temp; ss >> temp; - //LOGINFO("tmp: %s", temp.c_str() ); - bool bRedirect = false; bool bOK = false; - - if( temp.compare("HTTP/1.1") == 0 || temp.compare("HTTP/1.0") == 0 ) + if ((temp.compare("HTTP/1.1") == 0) || (temp.compare("HTTP/1.0") == 0)) { int code; ss >> code; - if( code == 302 ) + if (code == 302) { // redirect blabla LOGINFO("Need to redirect!"); + if (iLevel > MAX_REDIRECTS) + { + LOGERROR("cAuthenticator: received too many levels of redirection from auth server \"%s\" for user \"%s\", bailing out and kicking the user", iServer.c_str(), iUserName.c_str()); + return false; + } bRedirect = true; } - else if( code == 200 ) + else if (code == 200) { LOGINFO("Got 200 OK :D"); bOK = true; } } else + { + LOGERROR("cAuthenticator: cannot parse auth reply from server \"%s\" for user \"%s\", kicking the user.", iServer.c_str(), iUserName.c_str()); return false; + } if( bRedirect ) { - std::string Location; + AString Location; // Search for "Location:" bool bFoundLocation = false; while( !bFoundLocation && ss.good() ) @@ -131,70 +191,63 @@ bool cAuthenticator::ParseReceived( const char* a_Data, cBlockingTCPLink* a_TCPL { ss.get( c ); } - std::string Name; + AString Name; ss >> Name; - if( Name.compare("Location:") == 0 ) + if (Name.compare("Location:") == 0) { bFoundLocation = true; ss >> Location; } } - if( !bFoundLocation ) + if (!bFoundLocation) { - LOGERROR("Could not find location"); + LOGERROR("cAuthenticator: received invalid redirection from auth server \"%s\" for user \"%s\", kicking user.", iServer.c_str(), iUserName.c_str()); return false; } - Location = Location.substr( strlen("http://"), std::string::npos ); // Strip http:// + Location = Location.substr(strlen("http://"), std::string::npos); // Strip http:// std::string Server = Location.substr( 0, Location.find( "/" ) ); // Only leave server address - Location = Location.substr( Server.length(), std::string::npos ); - //LOGINFO("Got location: (%s)", Location.c_str() ); - //LOGINFO("Got server addr: (%s)", Server.c_str() ); - a_TCPLink->CloseSocket(); - if( a_TCPLink->Connect( Server.c_str(), 80 ) ) - { - LOGINFO("Successfully connected to %s", Server.c_str() ); - a_TCPLink->SendMessage( ( std::string("GET ") + Location + " HTTP/1.0\r\n\r\n").c_str() ); - std::string Received = a_TCPLink->ReceiveData(); - //LOGINFO("Received data: %s", Received.c_str() ); - return ParseReceived( Received.c_str(), a_TCPLink ); - } - else - { - LOGERROR("Could not connect to %s to verify player name!", Server.c_str() ); - } + Location = Location.substr( Server.length(), std::string::npos); + return AuthFromAddress(Server, Location, iUserName, iLevel + 1); } - else if( bOK ) + + if (!bOK) { - // Header says OK, so receive the rest. + LOGERROR("cAuthenticator: received an error from auth server \"%s\" for user \"%s\", kicking user.", iServer.c_str(), iUserName.c_str()); + return false; + } - // Go past header, double \n means end of headers - char c = 0; - while( ss.good() ) + // Header says OK, so receive the rest. + // Go past header, double \n means end of headers + char c = 0; + while (ss.good()) + { + while (c != '\n') { - while( c != '\n' ) - { - ss.get( c ); - } - ss.get( c ); - if( c == '\n' || c == '\r' || ss.peek() == '\r' || ss.peek() == '\n' ) - break; + ss.get(c); } - if( !ss.good() ) return false; + ss.get(c); + if( c == '\n' || c == '\r' || ss.peek() == '\r' || ss.peek() == '\n' ) + break; + } + if (!ss.good()) + { + LOGERROR("cAuthenticator: error while parsing response body from auth server \"%s\" for user \"%s\", kicking user.", iServer.c_str(), iUserName.c_str()); + return false; + } - std::string Result; - ss >> Result; - LOGINFO("Got result: %s", Result.c_str() ); - if( Result.compare("YES") == 0 ) - { - LOGINFO("Result was \"YES\", so player is authenticated!"); - return true; - } - else - { - LOGINFO("Result was \"%s\", so player is NOT authenticated!", Result.c_str() ); - return false; - } + std::string Result; + ss >> Result; + LOGINFO("Got result: %s", Result.c_str()); + if (Result.compare("YES") == 0) + { + LOGINFO("Result was \"YES\", so player is authenticated!"); + return true; } + LOGINFO("Result was \"%s\", so player is NOT authenticated!", Result.c_str()); return false; } + + + + diff --git a/source/cAuthenticator.h b/source/cAuthenticator.h index dada1ce43..6b9e7142b 100644 --- a/source/cAuthenticator.h +++ b/source/cAuthenticator.h @@ -1,13 +1,80 @@ + +// cAuthenticator.h + +// Interfaces to the cAuthenticator class representing the thread that authenticates users against the official MC server +// Authentication prevents "hackers" from joining with an arbitrary username (possibly impersonating the server admins) +// For more info, see http://wiki.vg/Session#Server_operation +// In MCS, authentication is implemented as a single thread that receives queued auth requests and dispatches them one by one. + + + + + #pragma once +#ifndef CAUTHENTICATOR_H_INCLUDED +#define CAUTHENTICATOR_H_INCLUDED + +#include "cIsThread.h" + + + + + +// fwd: "cRoot.h" +class cRoot; + -class cBlockingTCPLink; -class cAuthenticator + + + +class cAuthenticator : + public cIsThread { + typedef cIsThread super; + public: - cAuthenticator(); - ~cAuthenticator(); + cAuthenticator(void); + + /// (Re-)read server and address from INI: + void ReadINI(void); - bool Authenticate( const char* a_PlayerName, const char* a_ServerID ); + /// Queues a request for authenticating a user. If the auth fails, the user is kicked + void Authenticate(const AString & iUserName, const AString & iServerHash); + private: - bool ParseReceived( const char* a_Data, cBlockingTCPLink* a_TCPLink ); -}; \ No newline at end of file + + class cUser + { + public: + AString mName; + AString mServerHash; + + cUser(const AString & iName, const AString & iServerHash) : mName(iName), mServerHash(iServerHash) {} + } ; + + typedef std::deque cUserList; + + cCriticalSection mCS; + cUserList mQueue; + cEvent mQueueNonempty; + + AString mServer; + AString mAddress; + bool mShouldAuthenticate; + + // cIsThread override: + virtual void Execute(void) override; + + // Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep) + bool AuthFromAddress(const AString & iServer, const AString & iAddress, const AString & iUserName, int iLevel = 1); +}; + + + + + +#endif // CAUTHENTICATOR_H_INCLUDED + + + + diff --git a/source/cBlockingTCPLink.cpp b/source/cBlockingTCPLink.cpp index d436a52cf..9705f3a84 100644 --- a/source/cBlockingTCPLink.cpp +++ b/source/cBlockingTCPLink.cpp @@ -16,80 +16,75 @@ -cBlockingTCPLink::cBlockingTCPLink() - : m_Socket( 0 ) +cBlockingTCPLink::cBlockingTCPLink(void) { } + + + + cBlockingTCPLink::~cBlockingTCPLink() { CloseSocket(); } + + + + void cBlockingTCPLink::CloseSocket() { - if( m_Socket ) + if (m_Socket.IsValid()) { m_Socket.CloseSocket(); - m_Socket = 0; } } -bool cBlockingTCPLink::Connect( const char* a_Address, unsigned int a_Port ) + + + + +bool cBlockingTCPLink::Connect(const char * iAddress, unsigned int iPort) { - if( m_Socket ) + assert(!m_Socket.IsValid()); + if (m_Socket.IsValid()) { - LOGWARN("WARNING: cTCPLink Connect() called while still connected. ALWAYS disconnect before re-connecting!"); + LOGWARN("WARNING: cTCPLink Connect() called while still connected."); + m_Socket.CloseSocket(); } struct hostent *hp; unsigned int addr; struct sockaddr_in server; -#ifdef _WIN32 - WSADATA wsaData; - int wsaret=WSAStartup(/*0x101*/ MAKEWORD(2, 2),&wsaData); - - if(wsaret!=0) - { - LOGERROR("cTCPLink: WSAStartup returned error"); - return false; - } -#endif - - m_Socket=socket(AF_INET,SOCK_STREAM,0); -#ifdef _WIN32 - if( m_Socket==INVALID_SOCKET ) -#else - if( m_Socket < 0 ) -#endif + m_Socket = socket(AF_INET, SOCK_STREAM, 0); + if (!m_Socket.IsValid()) { - LOGERROR("cTCPLink: Invalid socket"); - m_Socket = 0; + LOGERROR("cTCPLink: Cannot create a socket"); return false; } - - addr=inet_addr( a_Address ); - hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET); - if(hp==NULL) + addr = inet_addr(iAddress); + hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); + if (hp == NULL) { //LOGWARN("cTCPLink: gethostbyaddr returned NULL"); - hp = gethostbyname( a_Address ); - if( hp == NULL ) + hp = gethostbyname(iAddress); + if (hp == NULL) { - LOGWARN("cTCPLink: Could not resolve %s", a_Address); + LOGWARN("cTCPLink: Could not resolve %s", iAddress); CloseSocket(); return false; } } - server.sin_addr.s_addr=*((unsigned long*)hp->h_addr); - server.sin_family=AF_INET; - server.sin_port=htons( (unsigned short)a_Port ); - if( connect( m_Socket, (struct sockaddr*)&server, sizeof(server) ) ) + server.sin_addr.s_addr = *((unsigned long *)hp->h_addr); + server.sin_family = AF_INET; + server.sin_port = htons( (unsigned short)iPort); + if (connect(m_Socket, (struct sockaddr *)&server, sizeof(server))) { - LOGWARN("cTCPLink: No response from server (%i)", errno); + LOGWARN("cTCPLink: Connection to \"%s:%d\" failed (%s)", iAddress, iPort, m_Socket.GetLastErrorString()); CloseSocket(); return false; } @@ -97,19 +92,29 @@ bool cBlockingTCPLink::Connect( const char* a_Address, unsigned int a_Port ) return true; } -int cBlockingTCPLink::Send( char* a_Data, unsigned int a_Size, int a_Flags /* = 0 */ ) + + + + +int cBlockingTCPLink::Send(char * a_Data, unsigned int a_Size, int a_Flags /* = 0 */ ) { - if( !m_Socket ) + assert(m_Socket.IsValid()); + if (!m_Socket.IsValid()) { - LOGWARN("cBlockingTCPLink: Trying to send data without a valid connection!"); + LOGERROR("cBlockingTCPLink: Trying to send data without a valid connection!"); return -1; } return cPacket::SendData( m_Socket, a_Data, a_Size, a_Flags ); } + + + + int cBlockingTCPLink::SendMessage( const char* a_Message, int a_Flags /* = 0 */ ) { - if( !m_Socket ) + assert(m_Socket.IsValid()); + if (!m_Socket.IsValid()) { LOGWARN("cBlockingTCPLink: Trying to send message without a valid connection!"); return -1; @@ -117,21 +122,26 @@ int cBlockingTCPLink::SendMessage( const char* a_Message, int a_Flags /* = 0 */ return cPacket::SendData( m_Socket, a_Message, strlen(a_Message), a_Flags ); } -std::string cBlockingTCPLink::ReceiveData() + + + + +void cBlockingTCPLink::ReceiveData(AString & oData) { - if( !m_Socket ) return ""; + assert(m_Socket.IsValid()); + if (!m_Socket.IsValid()) + { + return; + } int Received = 0; char Buffer[256]; - std::string Data; - while( (Received = recv(m_Socket, Buffer, 256, 0) ) > 0 ) + while ((Received = recv(m_Socket, Buffer, sizeof(Buffer), 0)) > 0) { - //LOGINFO("Recv: %i", Received); - //LOG("%s", Buffer ); - Data.append( Buffer, Received ); - memset( Buffer, 0, 256 ); + oData.append(Buffer, Received); } - - //LOGINFO("Received returned: %i", Received ); - return Data; } + + + + diff --git a/source/cBlockingTCPLink.h b/source/cBlockingTCPLink.h index 11f3287e2..8257f25d7 100644 --- a/source/cBlockingTCPLink.h +++ b/source/cBlockingTCPLink.h @@ -6,18 +6,17 @@ -class cEvent; class cBlockingTCPLink //tolua_export { //tolua_export public: //tolua_export - cBlockingTCPLink(); //tolua_export + cBlockingTCPLink(void); //tolua_export ~cBlockingTCPLink(); //tolua_export bool Connect( const char* a_Address, unsigned int a_Port ); //tolua_export int Send( 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 - std::string ReceiveData(); //tolua_export + void ReceiveData(AString & oData); //tolua_export protected: cSocket m_Socket; diff --git a/source/cChunk.cpp b/source/cChunk.cpp index 3a143b5f3..edd39a378 100644 --- a/source/cChunk.cpp +++ b/source/cChunk.cpp @@ -800,7 +800,7 @@ void cChunk::AddClient( cClientHandle* a_Client ) LockEntities(); for( EntityList::iterator itr = m_pState->Entities.begin(); itr != m_pState->Entities.end(); ++itr ) { - LOG("%i %i %i Spawning on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername() ); + LOG("%i %i %i Spawning on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername().c_str() ); (*itr)->SpawnOn( a_Client ); } UnlockEntities(); @@ -815,7 +815,7 @@ void cChunk::RemoveClient( cClientHandle* a_Client ) LockEntities(); for( EntityList::iterator itr = m_pState->Entities.begin(); itr != m_pState->Entities.end(); ++itr ) { - LOG("%i %i %i Destroying on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername() ); + LOG("%i %i %i Destroying on %s", m_PosX, m_PosY, m_PosZ, a_Client->GetUsername().c_str() ); cPacket_DestroyEntity DestroyEntity( *itr ); a_Client->Send( DestroyEntity ); } diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 53d2a40cf..492c2b7ea 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -197,24 +197,22 @@ cClientHandle::cClientHandle(const cSocket & a_Socket) cClientHandle::~cClientHandle() { - LOG("Deleting client %s", GetUsername() ); + LOG("Deleting client %s", GetUsername().c_str() ); for(unsigned int i = 0; i < VIEWDISTANCE*VIEWDISTANCE; i++) { if( m_LoadedChunks[i] ) m_LoadedChunks[i]->RemoveClient( this ); } - cWorld::PlayerList PlayerList = cRoot::Get()->GetWorld()->GetAllPlayers(); for( cWorld::PlayerList::iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr ) { - if ((*itr) && (*itr)->GetClientHandle() && strlen(GetUsername()) > 0) + if ((*itr) && (*itr)->GetClientHandle() && !GetUsername().empty()) { std::string NameColor = ( m_Player ? m_Player->GetColor() : "" ); cPacket_PlayerListItem PlayerList(NameColor + GetUsername(), false, (short)9999); - (*itr)->GetClientHandle()->Send( PlayerList ); + (*itr)->GetClientHandle()->Send(PlayerList); } - } if (m_pState && m_pState->Username.size() > 0) @@ -239,7 +237,6 @@ cClientHandle::~cClientHandle() m_pState->SocketCriticalSection.Unlock(); m_pState->pSemaphore->Signal(); - delete m_pState->pAuthenticateThread; delete m_pState->pReceiveThread; delete m_pState->pSendThread; delete m_pState->pSemaphore; @@ -294,9 +291,9 @@ void cClientHandle::Destroy() -void cClientHandle::Kick( const char* a_Reason ) +void cClientHandle::Kick(const AString & a_Reason) { - Send( cPacket_Disconnect( a_Reason ) ); + Send(cPacket_Disconnect(a_Reason)); m_bKicking = true; } @@ -304,7 +301,16 @@ void cClientHandle::Kick( const char* a_Reason ) -void cClientHandle::StreamChunks() +void cClientHandle::Authenticate(void) +{ + m_bSendLoginResponse = true; +} + + + + + +void cClientHandle::StreamChunks(void) { if( !m_bLoggedIn ) return; @@ -522,7 +528,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) { cPacket_Handshake* PacketData = reinterpret_cast(a_Packet); m_pState->Username = PacketData->m_Username; - LOG("HANDSHAKE %s", GetUsername() ); + LOG("HANDSHAKE %s", GetUsername().c_str()); cPacket_Chat Connecting(m_pState->Username + " is connecting."); if (cRoot::Get()->GetWorld()->GetNumPlayers() >= cRoot::Get()->GetWorld()->GetMaxPlayers()) { @@ -539,7 +545,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) break; case E_LOGIN: { - LOG("LOGIN %s", GetUsername() ); + LOG("LOGIN %s", GetUsername().c_str()); cPacket_Login* PacketData = reinterpret_cast(a_Packet); if (PacketData->m_ProtocolVersion < m_pState->ProtocolVersion) { Kick("Your client is outdated!"); @@ -561,9 +567,8 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) return; } - if( m_pState->pAuthenticateThread ) delete m_pState->pAuthenticateThread; - m_pState->pAuthenticateThread = new cThread( AuthenticateThread, this, "cClientHandle::AuthenticateThread" ); - m_pState->pAuthenticateThread->Start( true ); + // Schedule for authentication; until then, let them wait (but do not block) + cRoot::Get()->GetAuthenticator().Authenticate(m_pState->Username, cRoot::Get()->GetServer()->GetServerID()); } break; case E_PLAYERMOVELOOK: // After this is received we're safe to send anything @@ -587,7 +592,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) // Then we can start doing more stuffs! :D m_bLoggedIn = true; - LOG("%s completely logged in", GetUsername() ); + LOG("%s completely logged in", GetUsername().c_str()); StreamChunks(); // Send position @@ -660,7 +665,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. m_Player->SetLastBlockActionCnt(LastActionCnt+1); if (m_Player->GetLastBlockActionCnt() > MAXBLOCKCHANGEINTERACTIONS) { //kick if more than MAXBLOCKCHANGEINTERACTIONS per .1 seconds - LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot) Was Kicked.", GetUsername() ); + LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot) Was Kicked.", GetUsername().c_str()); //TODO Too many false-positives :s for example on a minimal server lagg :s should be re checked Kick("You're a baaaaaad boy!"); break; @@ -783,7 +788,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. m_Player->SetLastBlockActionCnt(LastActionCnt+1); if (m_Player->GetLastBlockActionCnt() > MAXBLOCKCHANGEINTERACTIONS) { //kick if more than MAXBLOCKCHANGEINTERACTIONS per .1 seconds - LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot) Was Kicked.", GetUsername() ); + LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot) Was Kicked.", GetUsername().c_str()); Kick("You're a baaaaaad boy!"); break; } @@ -797,7 +802,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) if( (Equipped.m_ItemID != PacketData->m_ItemType)) // Not valid { - LOGWARN("Player %s tried to place a block that was not selected! (could indicate bot)", GetUsername() ); + LOGWARN("Player %s tried to place a block that was not selected! (could indicate bot)", GetUsername().c_str()); break; } @@ -1361,7 +1366,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) break; case E_DISCONNECT: { - LOG("Received d/c packet from %s", GetUsername() ); + LOG("Received d/c packet from %s", GetUsername().c_str()); cPacket_Disconnect* PacketData = reinterpret_cast(a_Packet); if( !cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_DISCONNECT, 2, PacketData->m_Reason.c_str(), m_Player ) ) { @@ -1392,23 +1397,6 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) -void cClientHandle::AuthenticateThread( void* a_Param ) -{ - cClientHandle* self = (cClientHandle*)a_Param; - - cAuthenticator Authenticator; - if( !Authenticator.Authenticate( self->GetUsername(), cRoot::Get()->GetServer()->GetServerID() ) ) - { - self->Kick("Failed to verify username!"); - return; - } - self->m_bSendLoginResponse = true; -} - - - - - void cClientHandle::Tick(float a_Dt) { (void)a_Dt; @@ -1553,7 +1541,7 @@ void cClientHandle::SendThread( void *lpParam ) //LOG("Pending packets: %i", m_PendingPackets.size() ); if( NrmSendPackets.size() + LowSendPackets.size() > MAX_SEMAPHORES ) { - LOGERROR("ERROR: Too many packets in queue for player %s !!", self->GetUsername() ); + LOGERROR("ERROR: Too many packets in queue for player %s !!", self->GetUsername().c_str()); cPacket_Disconnect DC("Too many packets in queue."); DC.Send( m_pState->Socket ); @@ -1654,7 +1642,7 @@ void cClientHandle::ReceiveThread( void *lpParam ) else { LOGERROR("Something went wrong during PacketID 0x%02x (%s)", temp, cSocket::GetLastErrorString() ); - LOG("CLIENT %s DISCONNECTED", self->GetUsername() ); + LOG("CLIENT %s DISCONNECTED", self->GetUsername().c_str()); break; } } @@ -1684,9 +1672,9 @@ void cClientHandle::ReceiveThread( void *lpParam ) -const char* cClientHandle::GetUsername() +const AString & cClientHandle::GetUsername(void) const { - return m_pState->Username.c_str(); + return m_pState->Username; } diff --git a/source/cClientHandle.h b/source/cClientHandle.h index 0011903b1..4e7d8ce91 100644 --- a/source/cClientHandle.h +++ b/source/cClientHandle.h @@ -22,13 +22,14 @@ public: cClientHandle(const cSocket & a_Socket); ~cClientHandle(); - static const int VIEWDISTANCE = 13; // MUST be odd number or CRASH! + static const int VIEWDISTANCE = 15; // MUST be odd number or CRASH! static const int GENERATEDISTANCE = 2; // Server generates this many chunks AHEAD of player sight. const cSocket & GetSocket(); cPlayer* GetPlayer() { return m_Player; } // tolua_export - void Kick( const char* a_Reason ); //tolua_export + void Kick(const AString & a_Reason); //tolua_export + void Authenticate(void); // Called by cAuthenticator when the user passes authentication void AddPacket( cPacket * a_Packet ); void HandlePendingPackets(); @@ -51,9 +52,8 @@ public: static void SendThread( void *lpParam ); static void ReceiveThread( void *lpParam ); - static void AuthenticateThread( void* a_Param ); - const char* GetUsername(); + const AString & GetUsername(void) const; inline short GetPing() { return m_Ping; } private: diff --git a/source/cMonster.cpp b/source/cMonster.cpp index fac25df5d..03e50c4e0 100644 --- a/source/cMonster.cpp +++ b/source/cMonster.cpp @@ -308,7 +308,7 @@ void cMonster::HandlePhysics(float a_Dt) } } *m_Pos = Tracer.RealHit; - *m_Pos += *Tracer.HitNormal * 0.2; + *m_Pos += *Tracer.HitNormal * 0.2f; } else diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp index 982427a86..44b27e14a 100644 --- a/source/cPlayer.cpp +++ b/source/cPlayer.cpp @@ -64,7 +64,7 @@ struct cPlayer::sPlayerState std::string LoadedWorldName; }; -cPlayer::cPlayer(cClientHandle* a_Client, const char* a_PlayerName) +cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) : m_GameMode( 0 ) , m_IP("") , m_LastBlockActionTime( 0 ) @@ -134,7 +134,7 @@ cPlayer::~cPlayer(void) void cPlayer::SpawnOn( cClientHandle* a_Target ) { if( a_Target == m_ClientHandle || !m_bVisible ) return; - LOG("cPlayer::SpawnOn -> Sending %s to %s", m_pState->PlayerName.c_str(), (a_Target)?a_Target->GetUsername():"Everybody" ); + LOG("cPlayer::SpawnOn -> Sending %s to %s", m_pState->PlayerName.c_str(), (a_Target) ? a_Target->GetUsername().c_str() : "Everybody" ); cPacket_NamedEntitySpawn SpawnPacket; SpawnPacket.m_UniqueID = m_UniqueID; SpawnPacket.m_PlayerName = m_pState->PlayerName; @@ -897,16 +897,24 @@ bool cPlayer::SaveToDisk() -const char* cPlayer::GetName() +const AString & cPlayer::GetName(void) const { - return m_pState->PlayerName.c_str(); + return m_pState->PlayerName; } -void cPlayer::SetName( const char* a_Name ) + + + + +void cPlayer::SetName(const AString & a_Name ) { m_pState->PlayerName = a_Name; } + + + + const cPlayer::GroupList & cPlayer::GetGroups() { return m_pState->Groups; @@ -935,7 +943,7 @@ void cPlayer::UseEquippedItem() if(GetGameMode() != 1) //No damage in creative if (GetInventory().GetEquippedItem().DamageItem()) { - LOG("Player %s Broke ID: %i", GetClientHandle()->GetUsername(), GetInventory().GetEquippedItem().m_ItemID); + LOG("Player %s Broke ID: %i", GetClientHandle()->GetUsername().c_str(), GetInventory().GetEquippedItem().m_ItemID); GetInventory().RemoveItem( GetInventory().GetEquippedItem()); } } \ No newline at end of file diff --git a/source/cPlayer.h b/source/cPlayer.h index d18e3ac4f..6f8cbfca6 100644 --- a/source/cPlayer.h +++ b/source/cPlayer.h @@ -19,7 +19,7 @@ class cPlayer : public cPawn //tolua_export public: CLASS_PROTOTYPE(); - cPlayer(cClientHandle* a_Client, const char* a_PlayerName); + cPlayer(cClientHandle* a_Client, const AString & a_PlayerName); virtual ~cPlayer(); virtual void Initialize( cWorld* a_World ); //tolua_export @@ -59,8 +59,8 @@ public: void SendMessage( const char* a_Message ); //tolua_export - const char* GetName(); //tolua_export - void SetName( const char* a_Name ); //tolua_export + const AString & GetName(void) const; //tolua_export + void SetName(const AString & a_Name); //tolua_export typedef std::list< cGroup* > GroupList; typedef std::list< std::string > StringList; diff --git a/source/cRoot.cpp b/source/cRoot.cpp index 73f5a6397..0ccee5f20 100644 --- a/source/cRoot.cpp +++ b/source/cRoot.cpp @@ -31,6 +31,10 @@ struct cRoot::sRootState WorldMap WorldsByName; }; + + + + cRoot::cRoot() : m_Server( 0 ) , m_MonsterConfig( 0 ) @@ -48,12 +52,20 @@ cRoot::cRoot() s_Root = this; } + + + + cRoot::~cRoot() { s_Root = 0; delete m_pState; } + + + + void cRoot::InputThread(void* a_Params) { cRoot& self = *(cRoot*)a_Params; @@ -66,6 +78,10 @@ void cRoot::InputThread(void* a_Params) } } + + + + void cRoot::Start() { if( m_Log ) delete m_Log, m_Log = 0; @@ -88,7 +104,6 @@ void cRoot::Start() return; } - cIniFile WebIniFile("webadmin.ini"); if( WebIniFile.ReadFile() ) { @@ -108,6 +123,7 @@ void cRoot::Start() m_MonsterConfig = new cMonsterConfig(2); // This sets stuff in motion + m_Authenticator.Start(); m_Server->StartListenThread(); //cHeartBeat* HeartBeat = new cHeartBeat(); @@ -137,6 +153,10 @@ void cRoot::Start() delete m_Log; m_Log = 0; } + + + + void cRoot::LoadWorlds() { cIniFile IniFile("settings.ini"); IniFile.ReadFile(); @@ -169,6 +189,10 @@ void cRoot::LoadWorlds() } } + + + + void cRoot::UnloadWorlds() { for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr ) @@ -178,16 +202,28 @@ void cRoot::UnloadWorlds() m_pState->WorldsByName.clear(); } + + + + cWorld* cRoot::GetWorld() { return GetDefaultWorld(); } + + + + cWorld* cRoot::GetDefaultWorld() { return m_pState->pDefaultWorld; } + + + + cWorld* cRoot::GetWorld( const char* a_WorldName ) { WorldMap::iterator itr = m_pState->WorldsByName.find( a_WorldName ); @@ -196,6 +232,10 @@ cWorld* cRoot::GetWorld( const char* a_WorldName ) return 0; } + + + + void cRoot::TickWorlds( float a_Dt ) { for( WorldMap::iterator itr = m_pState->WorldsByName.begin(); itr != m_pState->WorldsByName.end(); ++itr ) @@ -204,6 +244,10 @@ void cRoot::TickWorlds( float a_Dt ) } } + + + + void cRoot::ServerCommand( const char* a_Cmd ) { //LOG("Command: %s", a_Cmd ); @@ -217,3 +261,25 @@ void cRoot::ServerCommand( const char* a_Cmd ) m_bRestart = true; } } + + + + + +void cRoot::KickUser(const AString & iUserName, const AString & iReason) +{ + m_Server->KickUser(iUserName, iReason); +} + + + + + +void cRoot::AuthenticateUser(const AString & iUserName) +{ + m_Server->AuthenticateUser(iUserName); +} + + + + diff --git a/source/cRoot.h b/source/cRoot.h index 86b6ac28a..3179d72b0 100644 --- a/source/cRoot.h +++ b/source/cRoot.h @@ -1,5 +1,15 @@ + #pragma once + + + +#include "cAuthenticator.h" + + + + + class cThread; class cMonsterConfig; class cMCLogger; @@ -10,6 +20,7 @@ class cWebAdmin; class cPluginManager; class cServer; class cWorld; + class cRoot //tolua_export { //tolua_export public: @@ -31,24 +42,31 @@ public: cFurnaceRecipe* GetFurnaceRecipe() { return m_FurnaceRecipe; } //tolua_export cWebAdmin* GetWebAdmin() { return m_WebAdmin; } //tolua_export cPluginManager* GetPluginManager() { return m_PluginManager; } //tolua_export + cAuthenticator & GetAuthenticator() {return m_Authenticator; } - void ServerCommand( const char* a_Cmd ); //tolua_export + void ServerCommand(const char* a_Cmd ); //tolua_export + + void KickUser(const AString & iUserName, const AString & iReason); // Kicks the user, no matter in what world they are. Used from cAuthenticator + void AuthenticateUser(const AString & iUserName); // Called by cAuthenticator to auth the specified user void TickWorlds( float a_Dt ); + private: + void LoadWorlds(); void UnloadWorlds(); - cServer* m_Server; - cMonsterConfig *m_MonsterConfig; + cServer * m_Server; + cMonsterConfig * m_MonsterConfig; - cGroupManager* m_GroupManager; - cRecipeChecker* m_RecipeChecker; - cFurnaceRecipe* m_FurnaceRecipe; - cWebAdmin* m_WebAdmin; - cPluginManager* m_PluginManager; + cGroupManager * m_GroupManager; + cRecipeChecker * m_RecipeChecker; + cFurnaceRecipe * m_FurnaceRecipe; + cWebAdmin * m_WebAdmin; + cPluginManager * m_PluginManager; + cAuthenticator m_Authenticator; - cMCLogger* m_Log; + cMCLogger * m_Log; bool m_bStop; bool m_bRestart; @@ -60,4 +78,8 @@ private: static void InputThread(void* a_Params); static cRoot* s_Root; -}; //tolua_export \ No newline at end of file +}; //tolua_export + + + + diff --git a/source/cServer.cpp b/source/cServer.cpp index 826de3bb3..44dd365c2 100644 --- a/source/cServer.cpp +++ b/source/cServer.cpp @@ -48,6 +48,10 @@ bool g_bWaterPhysics = false; typedef std::list< cClientHandle* > ClientList; + + + + struct cServer::sServerState { sServerState() @@ -67,12 +71,20 @@ struct cServer::sServerState std::string ServerID; }; -cServer*cServer::GetServer() + + + + +cServer * cServer::GetServer() { LOGWARN("WARNING: Using deprecated function cServer::GetServer() use cRoot::Get()->GetServer() instead!"); return cRoot::Get()->GetServer(); } + + + + void cServer::ServerListenThread( void *a_Args ) { LOG("ServerListenThread"); @@ -84,6 +96,10 @@ void cServer::ServerListenThread( void *a_Args ) } } + + + + std::string GetWSAError() { #ifdef _WIN32 @@ -126,6 +142,10 @@ std::string GetWSAError() return "No Error"; } + + + + bool cServer::InitServer( int a_Port ) { if( m_bIsConnected ) @@ -135,7 +155,7 @@ bool cServer::InitServer( int a_Port ) } printf("/============================\\\n"); - printf("| Minecraft Alpha Server |\n"); + printf("| Custom Minecraft Server |\n"); printf("| Created by Kevin Bansberg |\n"); printf("| A.K.A. |\n"); printf("| FakeTruth |\n"); @@ -222,6 +242,10 @@ bool cServer::InitServer( int a_Port ) return true; } + + + + cServer::cServer() : m_pState( new sServerState ) , m_Millisecondsf( 0 ) @@ -232,6 +256,10 @@ cServer::cServer() { } + + + + cServer::~cServer() { if( m_pState->SListenClient ) m_pState->SListenClient.CloseSocket(); @@ -245,6 +273,10 @@ cServer::~cServer() delete m_pState; } + + + + // TODO - Need to modify this or something, so it broadcasts to all worlds? And move this to cWorld? void cServer::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude /* = 0 */ ) { @@ -255,6 +287,10 @@ void cServer::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude /* = } } + + + + void cServer::StartListenClient() { cSocket SClient = m_pState->SListenClient.Accept(); @@ -272,6 +308,10 @@ void cServer::StartListenClient() } } + + + + bool cServer::Tick(float a_Dt) { //LOG("1. Tick %0.2f", a_Dt); @@ -318,6 +358,10 @@ bool cServer::Tick(float a_Dt) } } + + + + void ServerTickThread( void * a_Param ) { LOG("ServerTickThread"); @@ -394,14 +438,18 @@ bool cServer::Command( cClientHandle & a_Client, const char* a_Cmd ) if (split[0].compare("/coords") == 0) { - char c_Str[128]; - sprintf_s( c_Str, 128, "[X:%0.2f] [Y:%0.2f] [Z:%0.2f]", a_Client.GetPlayer()->GetPosX(), a_Client.GetPlayer()->GetPosY(), a_Client.GetPlayer()->GetPosZ() ); - a_Client.Send( cPacket_Chat( cChatColor::Green + c_Str ) ); + AString Pos; + Printf(Pos, "[X:%0.2f] [Y:%0.2f] [Z:%0.2f]", a_Client.GetPlayer()->GetPosX(), a_Client.GetPlayer()->GetPosY(), a_Client.GetPlayer()->GetPosZ() ); + a_Client.Send( cPacket_Chat(cChatColor::Green + Pos)); return true; } return false; } + + + + void cServer::ServerCommand( const char* a_Cmd ) { AString Command( a_Cmd ); @@ -472,6 +520,10 @@ void cServer::ServerCommand( const char* a_Cmd ) //LOG("You didn't enter anything? (%s)", a_Cmd.c_str() ); } + + + + void cServer::SendMessage( const char* a_Message, cPlayer* a_Player /* = 0 */, bool a_bExclude /* = false */ ) { cPacket_Chat Chat( a_Message ); @@ -485,6 +537,10 @@ void cServer::SendMessage( const char* a_Message, cPlayer* a_Player /* = 0 */, b Broadcast( Chat, (a_Player)?a_Player->GetClientHandle():0 ); } + + + + void cServer::Shutdown() { m_bRestarting = true; @@ -503,7 +559,44 @@ void cServer::Shutdown() } -const char* cServer::GetServerID() + + + +const AString & cServer::GetServerID(void) const +{ + return m_pState->ServerID; +} + + + + + +void cServer::KickUser(const AString & iUserName, const AString & iReason) { - return m_pState->ServerID.c_str(); -} \ No newline at end of file + for (ClientList::iterator itr = m_pState->Clients.begin(); itr != m_pState->Clients.end(); ++itr) + { + if ((*itr)->GetUsername() == iUserName) + { + (*itr)->Kick(iReason); + } + } // for itr - m_pState->Clients[] +} + + + + + +void cServer::AuthenticateUser(const AString & iUserName) +{ + for (ClientList::iterator itr = m_pState->Clients.begin(); itr != m_pState->Clients.end(); ++itr) + { + if ((*itr)->GetUsername() == iUserName) + { + (*itr)->Authenticate(); + } + } // for itr - m_pState->Clients[] +} + + + + diff --git a/source/cServer.h b/source/cServer.h index 718ac4c36..b2a46f78a 100644 --- a/source/cServer.h +++ b/source/cServer.h @@ -29,10 +29,13 @@ public: //tolua_export void Shutdown(); void SendMessage( const char* a_Message, cPlayer* a_Player = 0, bool a_bExclude = false ); //tolua_export + + void KickUser(const AString & iUserName, const AString & iReason); + void AuthenticateUser(const AString & iUserName); // Called by cAuthenticator to auth the specified user static void ServerListenThread( void* a_Args ); - const char* GetServerID(); + const AString & GetServerID(void) const; private: friend class cRoot; // so cRoot can create and destroy cServer cServer(); diff --git a/source/cSocket.cpp b/source/cSocket.cpp index c8b651342..bd26fb274 100644 --- a/source/cSocket.cpp +++ b/source/cSocket.cpp @@ -23,28 +23,35 @@ cSocket::cSocket( xSocket a_Socket ) { } + + + + cSocket::~cSocket() { } + + + + cSocket::operator const cSocket::xSocket() const { return m_Socket; } + + + + cSocket::xSocket cSocket::GetSocket() const { return m_Socket; } -bool cSocket::IsValid() -{ -#ifdef _WIN32 - return ( m_Socket != INVALID_SOCKET); -#else - return ( m_Socket >= 0); -#endif -} + + + void cSocket::CloseSocket() { @@ -58,6 +65,10 @@ void cSocket::CloseSocket() #endif } + + + + const char* cSocket::GetLastErrorString() { #define CASE_AND_RETURN( x ) case x: return #x @@ -88,6 +99,10 @@ const char* cSocket::GetLastErrorString() #endif } + + + + int cSocket::SetReuseAddress() { #ifdef _WIN32 @@ -98,6 +113,10 @@ int cSocket::SetReuseAddress() return setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int) ); } + + + + int cSocket::WSAStartup() { #ifdef _WIN32 @@ -109,11 +128,19 @@ int cSocket::WSAStartup() #endif } + + + + cSocket cSocket::CreateSocket() { return socket(AF_INET,SOCK_STREAM,0); } + + + + int cSocket::Bind( SockAddr_In& a_Address ) { sockaddr_in local; @@ -129,11 +156,19 @@ int cSocket::Bind( SockAddr_In& a_Address ) return bind( m_Socket, (sockaddr*)&local, sizeof(local)); } + + + + int cSocket::Listen( int a_Backlog ) { return listen( m_Socket, a_Backlog ); } + + + + cSocket cSocket::Accept() { sockaddr_in from; @@ -150,7 +185,15 @@ cSocket cSocket::Accept() return SClient; } + + + + int cSocket::Receive( char* a_Buffer, unsigned int a_Length, unsigned int a_Flags ) { return recv(m_Socket, a_Buffer, a_Length, a_Flags); -} \ No newline at end of file +} + + + + diff --git a/source/cSocket.h b/source/cSocket.h index 43bb8ee09..44c3bea4b 100644 --- a/source/cSocket.h +++ b/source/cSocket.h @@ -10,15 +10,15 @@ class cSocket typedef SOCKET xSocket; #else typedef int xSocket; + static const int INVALID_SOCKET = 0; #endif public: - cSocket() : m_Socket( 0 ) {} - - cSocket( xSocket a_Socket ); + cSocket(void) : m_Socket(INVALID_SOCKET) {} + cSocket(xSocket a_Socket); ~cSocket(); - bool IsValid(); + bool IsValid(void) const {return (m_Socket != INVALID_SOCKET); } void CloseSocket(); operator const xSocket() const; diff --git a/source/cWebAdmin.cpp b/source/cWebAdmin.cpp index cd663d7b6..efac32866 100644 --- a/source/cWebAdmin.cpp +++ b/source/cWebAdmin.cpp @@ -59,12 +59,6 @@ cWebAdmin::~cWebAdmin() delete m_Event; } -void ReplaceString( std::string & a_HayStack, const std::string & a_Needle, const std::string & a_ReplaceWith ) -{ - size_t pos1 = a_HayStack.find( a_Needle ); - a_HayStack.replace( pos1, a_Needle.size(), a_ReplaceWith ); -} - void cWebAdmin::AddPlugin( cWebPlugin* a_Plugin ) { m_Plugins.remove( a_Plugin ); diff --git a/source/cWorld.cpp b/source/cWorld.cpp index 0d09c76f5..c54347dcd 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -980,6 +980,10 @@ cPlayer* cWorld::GetPlayer( const char* a_PlayerName ) return 0; } + + + + cEntity* cWorld::GetEntity( int a_UniqueID ) { for( EntityList::iterator itr = m_pState->AllEntities.begin(); itr != m_pState->AllEntities.end(); ++itr ) diff --git a/source/packets/cPacket_Disconnect.h b/source/packets/cPacket_Disconnect.h index 42497e639..7dc5ef9a9 100644 --- a/source/packets/cPacket_Disconnect.h +++ b/source/packets/cPacket_Disconnect.h @@ -7,12 +7,12 @@ class cPacket_Disconnect : public cPacket { public: cPacket_Disconnect() { m_PacketID = E_DISCONNECT; } - cPacket_Disconnect(const std::string & a_Reason) { m_PacketID = E_DISCONNECT; m_Reason = a_Reason; } + cPacket_Disconnect(const AString & a_Reason) { m_PacketID = E_DISCONNECT; m_Reason = a_Reason; } virtual cPacket* Clone() const { return new cPacket_Disconnect(*this); } bool Parse( cSocket & a_Socket ); bool Send( cSocket & a_Socket ); - std::string m_Reason; + AString m_Reason; static const unsigned int c_Size = 3; // Minimum size }; \ No newline at end of file -- cgit v1.2.3