00001 #include "Common/Ini.h"
00002 #include "Common/Error.h"
00003 #include "Common/Console.h"
00004 #include "Common/Time.h"
00005 #include "Common/Md5.h"
00006 #include "Common/Command.h"
00007 #include "Protocol/ProtocolDefs.h"
00008 #include "Game/ClientGameManager.h"
00009 #include "Interface/Interface.h"
00010 #include "Mod/Mod.h"
00011 #include "Game/ServerInfo.h"
00012 #include "Client/GameClient.h"
00013 #include "Client/NetClient.h"
00014
00015
00016 KNetClient::KNetClient()
00017 : KUDPClientSocket()
00018 {
00019 m_LastStatsTime = 0;
00020 m_bShowStats = false;
00021 m_pLocalAddr = NULL;
00022 m_nLocalAddr = 0;
00023 }
00024
00025
00026 bool KNetClient::Init()
00027 {
00028
00029 if( !KSocket::StartNetwork() )
00030 return false;
00031
00032 if( !Create() )
00033 return false;
00034
00035
00036 if( !m_LobbySocket.Create( KNST_UDP ) )
00037 return false;
00038
00039 const char* pLobbyRequestHost = g_pGame->GetpIniFile()->ReadString( "NETWORK", "LobbyRequestHost", "localhost" );
00040 u16 LobbyRequestPort = (u16)g_pGame->GetpIniFile()->ReadInt( "NETWORK", "LobbyRequestPort", 28001 );
00041
00042 if( !KSocket::GetAddrByName( KStr( pLobbyRequestHost ), m_LobbyAddr ) )
00043 {
00044 KError::Error( NULL, "KNetClient::Init() : GetHostByName [%s] failed", pLobbyRequestHost );
00045 return false;
00046 }
00047
00048 m_LobbyAddr.SetPort( LobbyRequestPort );
00049
00050
00051 char pHostName[1024];
00052 hostent* pHostent;
00053
00054 KSocket::GetHostName( pHostName, sizeof( pHostName ) );
00055 if( pHostent = KSocket::GetHostByName( pHostName ) )
00056 {
00057 char* pAddrList;
00058
00059 m_nLocalAddr = 0;
00060 while( pHostent->h_addr_list[m_nLocalAddr] )
00061 {
00062 m_nLocalAddr ++;
00063 }
00064
00065 if( m_nLocalAddr )
00066 {
00067 m_pLocalAddr = new KInetAddr[m_nLocalAddr];
00068 for( u32 h = 0; h < m_nLocalAddr; h ++ )
00069 {
00070 pAddrList = pHostent->h_addr_list[h];
00071
00072 m_pLocalAddr[h].SetInAddr( *((in_addr*)&pAddrList[h]) );
00073 }
00074 }
00075 }
00076
00077
00078 GetSocket().EnableBroadcast( true );
00079
00080 g_pGame->GetpCommand()->RegisterCommand( "getserverslist", CommandGetServersList, "Ask to lobby the servers list", this );
00081
00082 return true;
00083 }
00084
00085
00086 bool KNetClient::Connect( KStr sHostName, u16 Port )
00087 {
00088
00089
00090
00091 const char* pServerHost;
00092 u16 ServerPort;
00093 u32 ServerAddr;
00094
00095 g_Console << "Starting connection..." << KENDL;
00096
00097 if( sHostName.GetLength() )
00098 pServerHost = sHostName.GetpString();
00099 else
00100 pServerHost = g_pGame->GetpIniFile()->ReadString( "NETWORK", "ServerHost", "localhost" );
00101
00102 if( Port )
00103 ServerPort = Port;
00104 else
00105 ServerPort = (u16)g_pGame->GetpIniFile()->ReadInt( "NETWORK", "ServerPort", 28100 );
00106
00107
00108 HOSTENT* pHostent;
00109
00110 pHostent = KSocket::GetHostByName( (char*)pServerHost );
00111 if( !pHostent || !pHostent->h_addr_list[0] )
00112 {
00113 KError::Error( NULL, "KNetClient::Init() : GetHostByName() failed [%s]", pServerHost );
00114 return false;
00115 }
00116
00117 ServerAddr = *((u32*)(pHostent->h_addr_list[0]));
00118
00119
00120 if( !KUDPClientSocket::Connect( KInetAddr( ServerAddr, ServerPort ) ) )
00121 return false;
00122
00123 return true;
00124 }
00125
00126
00127 bool KNetClient::Disconnect()
00128 {
00129 g_Console << "Disconnection..." << KENDL;
00130
00131 return KUDPClientSocket::Disconnect();
00132 }
00133
00134
00135 bool KNetClient::End()
00136 {
00137 g_pGame->GetpCommand()->UnregisterCommand( "getserverslist" );
00138
00139
00140 if( IsConnected() )
00141 {
00142 if( !Disconnect() )
00143 return false;
00144 }
00145
00146 if( !Close() )
00147 return false;
00148
00149 if( !m_LobbySocket.Close() )
00150 return false;
00151
00152
00153 if( !KSocket::StopNetwork() )
00154 return false;
00155
00156 SafeDeletev( m_pLocalAddr );
00157
00158 return true;
00159 }
00160
00161
00162 void KNetClient::OnConnect( KInetAddr& Addr )
00163 {
00164 KUDPClientSocket::OnConnect( Addr );
00165 }
00166
00167
00168 void KNetClient::OnDisconnect( KInetAddr& Addr )
00169 {
00170 KUDPClientSocket::OnDisconnect( Addr );
00171
00172 if( ((KGameClient*)g_pGame)->GetClientGameManager() )
00173 ((KGameClient*)g_pGame)->GetClientGameManager()->OnDisconnect();
00174 }
00175
00176
00177 bool KNetClient::Manage()
00178 {
00179 if( !KUDPClientSocket::Manage() )
00180 return false;
00181
00182 bool bStats = false;
00183 u32 nBytesSent = 0;
00184 u32 nBytesReceived = 0;
00185
00186 if( m_LastStatsTime + 1000 < g_Time.GetTime() )
00187 {
00188 bStats = true;
00189 m_LastStatsTime = g_Time.GetTime();
00190 }
00191
00192 if( bStats )
00193 {
00194 nBytesSent += GetnBytesSent();
00195 nBytesReceived += GetnBytesReceived();
00196 ResetStats();
00197 }
00198
00199 if( bStats && m_bShowStats )
00200 g_Console << "SENT : " << nBytesSent << " RECEIVED : " << nBytesReceived << KENDL;
00201
00202 if( !ManageLobbySocket() )
00203 return false;
00204
00205 return true;
00206 }
00207
00208
00209 void KNetClient::OnMessage( KInetAddr& Addr, KNetMsg& Msg )
00210 {
00211 KPGENERALMESSAGE MsgType;
00212 KGameClient* pGameClient = (KGameClient*)g_pGame;
00213
00214 MsgType = KP_ReadGM( Msg );
00215
00216 switch( MsgType )
00217 {
00218 case KPGM_GETAUTHENTICITY:
00219 {
00220
00221 KNetMsg Msg2;
00222 KP_WriteGM( Msg2, KPGM_AUTHENTICITY );
00223
00224 const char* pLogin = g_pGame->GetpIniFile()->ReadString( "LOGIN", "login", "" );
00225 const char* pPass = g_pGame->GetpIniFile()->ReadString( "LOGIN", "password", "" );
00226
00227 KStr sCryptedPass = md5( KStr( pPass ) );
00228
00229 Msg2.WriteString( KStr( pLogin ) );
00230 Msg2.WriteString( sCryptedPass );
00231 SendMessage( Msg2 );
00232 g_Console << "Checking authenticity..." << KENDL;
00233 return;
00234 }
00235
00236 case KPGM_AUTHENTICITYRESULT:
00237 {
00238
00239 bool bResult;
00240 Msg >> bResult;
00241
00242 if( bResult )
00243 g_Console << "Authenticity succeded!" << KENDL;
00244 else
00245 g_Console << "Authenticity failed!" << KENDL;
00246 return;
00247 }
00248
00249 case KPGM_GETCLIENTINFOS:
00250 {
00251
00252 KNetMsg Msg2;
00253 KP_WriteGM( Msg2, KPGM_CLIENTINFOS );
00254
00255 Msg2.WriteString( KStr( pGameClient->GetpName() ) );
00256 SendMessage( Msg2 );
00257 g_Console << "Sending client infos." << KENDL;
00258 return;
00259 }
00260
00261 case KPGM_STARTGAMEENGINE:
00262 {
00263
00264 if( pGameClient->GetClientGameManager() )
00265 pGameClient->GetClientGameManager()->OnConnect();
00266 g_Console << "Starting game manager..." << KENDL;
00267 return;
00268 }
00269
00270 case KPGM_GAMEMESSAGE:
00271 {
00272 KGAMEMSGTYPE MsgType;
00273 u8 Byte;
00274 Msg >> Byte;
00275 MsgType = (KGAMEMSGTYPE)Byte;
00276 if( pGameClient->GetClientGameManager() )
00277 pGameClient->GetClientGameManager()->OnMessage( MsgType, Msg );
00278 return;
00279 }
00280
00281 case KPGM_TEXTMESSAGE:
00282 {
00283 KStr sText;
00284 KStr sChat;
00285
00286 Msg.ReadString( sText );
00287 sChat = sText;
00288
00289 g_Console << sChat << KENDL;
00290 if( pGameClient->GetInterface() )
00291 pGameClient->GetInterface()->AddChatLine( sChat.GetpString(), KRGB( 150, 25, 107 ) );
00292 return;
00293 }
00294
00295 default:
00296 KError::Warning( NULL, "KNetClient::OnMessage() : Unknown KPGENERALMESSAGE type %i", MsgType );
00297 return;
00298 }
00299 }
00300
00301
00302 bool KNetClient::RequestServersList()
00303 {
00304 if( g_pInterface )
00305 g_pInterface->OnFlushServersList();
00306
00307
00308 KLobbyRequest Request( KPGM_GETSERVERSLIST );
00309
00310 m_LobbyRequestId = Request.m_RequestId;
00311
00312 if( !m_LobbySocket.SendTo( m_LobbyAddr, &Request, sizeof( Request ) ) )
00313 {
00314 KError::Error( NULL, GetLastError(), "KNetClient::RequestServersList() : SendTo failed" );
00315 return false;
00316 }
00317
00318
00319 KNetMsg Msg;
00320 KInetAddr Addr;
00321
00322 Msg << m_LobbyRequestId;
00323
00324 u16 ServerPort = (u16)g_pGame->GetpIniFile()->ReadInt( "NETWORK", "ServerPort", 28100 );
00325
00326 {
00327
00328
00329
00330
00331
00332
00333
00334 Addr.SetAddress( "255.255.255.255" );
00335 Addr.SetPort( ServerPort );
00336 BroadCastMessage( Addr, Msg );
00337 }
00338
00339 return true;
00340 }
00341
00342
00343 bool KNetClient::ManageLobbySocket()
00344 {
00345
00346 while( m_LobbySocket.SelectRead() )
00347 {
00348 u32 ByteRead = 0;
00349 char pBuffer[1024];
00350
00351 if( !m_LobbySocket.ReceiveFrom( m_LobbyAddr, pBuffer, sizeof( pBuffer ), &ByteRead ) )
00352 return false;
00353
00354 KNetMsg Msg;
00355 Msg.WriteBuffer( pBuffer, ByteRead );
00356 ReadServerInfo( Msg );
00357 }
00358
00359 return true;
00360 }
00361
00362
00363 void KNetClient::ReadServerInfo( KNetMsg& Msg )
00364 {
00365 u16 RequestId;
00366 KStr sHostName;
00367 u16 Port;
00368 u32 Players;
00369 u32 MaxPlayers;
00370 u32 Version;
00371 KStr sName;
00372
00373 Msg >> RequestId;
00374 Msg.ReadString( sHostName );
00375 Msg >> Port
00376 >> Players
00377 >> MaxPlayers
00378 >> Version;
00379 Msg.ReadString( sName );
00380
00381 if( RequestId == m_LobbyRequestId )
00382 {
00383 KServerInfo ServerInfo;
00384
00385 ServerInfo.SetsHostName( sHostName );
00386 ServerInfo.SetListenPort( Port );
00387 ServerInfo.SetsName( sName );
00388 ServerInfo.SetPlayers( Players );
00389 ServerInfo.SetMaxPlayers( MaxPlayers );
00390 ServerInfo.SetVersion( Version );
00391
00392 if( g_pInterface )
00393 g_pInterface->OnAddServersList( ServerInfo );
00394 }
00395 }
00396
00397
00398 void KNetClient::CommandGetServersList( KStr Argument, void* pContext )
00399 {
00400 ((KNetClient*)&((KGameClient*)g_pGame)->GetNet())->RequestServersList();
00401 }
00402
00403
00404 void KNetClient::OnUCMessage( KInetAddr& Addr, char* pBuffer, u32 Size )
00405 {
00406 KNetMsg Msg;
00407
00408 Msg.WriteBuffer( pBuffer, Size );
00409
00410 ReadServerInfo( Msg );
00411 }
00412