void LoginServer::Update() { m_ClientsLock.lock(); /* * This is our heavy weight champion * we itterate over any connected players and perform network io with * the clients here. * Future imporvments would be to impliment threaded pools of clients. */ for (unsigned int i = 0; i < m_Clients.size(); i++) { LoginClient* client = m_Clients.at(i); assert(client); // TODO: Move this to a better place if (GW2BlackList::CheckBlacklist(client->m_ClientIP)) { printf("Client forcefully disconnected as they were on the ban list.\n"); client->Close(); } // Only interact with the client if its connected duh if (client->IsConnected()) { client->Tick(this); } else { m_Clients.erase(m_Clients.begin()+i); printf("Client Disconnected: %s\n", client->m_ClientIP); printf("Connected Clients: %zu\n", m_Clients.size()); } } m_ClientsLock.unlock(); }
NetworkClient* LoginManager::handleSessionConnect(Session* session, Service* service) { LoginClient* newClient = new(mLoginClientPool.malloc()) LoginClient(); newClient->setSession(session); newClient->setState(LCSTATE_ServerHelloSent); mLoginClientList.push_back(newClient); return newClient; }
//====================================================================================================================== void LoginManager::handleSessionDisconnect(NetworkClient* client) { LoginClient* loginClient = reinterpret_cast<LoginClient*>(client); // Client has disconnected. Update the db to show they are no longer authenticated. mDatabase->executeProcedureAsync(0, 0, "UPDATE %s.account SET account_authenticated = 0 WHERE account_id=%u;",mDatabase->galaxy(), loginClient->getAccountId()); LoginClientList::iterator iter = mLoginClientList.begin(); while(iter != mLoginClientList.end()) { if(loginClient == (*iter)) { mLoginClientPool.free(*iter); mLoginClientList.erase(iter); break; } ++iter; } }
void LoginManager::handleSessionDisconnect(NetworkClient* client) { LoginClient* loginClient = reinterpret_cast<LoginClient*>(client); //gLogger->logMsgF("handleSessionDisconnect account %u",MSG_HIGH,loginClient->getAccountId()); // Client has disconnected. Update the db to show they are no longer authenticated. mDatabase->ExecuteSqlAsync(0, 0, "UPDATE account SET authenticated=0 WHERE account_id=%u;", loginClient->getAccountId()); LoginClientList::iterator iter = mLoginClientList.begin(); while(iter != mLoginClientList.end()) { if(loginClient == (*iter)) { mLoginClientPool.free(*iter); mLoginClientList.erase(iter); break; } ++iter; } }
//====================================================================================================================== void LoginManager::handleDatabaseJobComplete(void* ref, database::DatabaseResult* result) { // Stupid simple hack since we don't have a client for this query if (ref == (void*)1) { _updateServerStatus(result); return; } // This assumes only authentication calls are async right now. Will change as needed. LoginClient* client = (LoginClient*)ref; switch (client->getState()) { case LCSTATE_QueryServerList: { // Auth was successful, now send the server list. _sendServerList(client, result); // Execute our query client->setState(LCSTATE_QueryCharacterList); mDatabase->executeProcedureAsync(this, ref, "CALL %s.sp_ReturnAccountCharacters(%u);",mDatabase->galaxy(), client->getAccountId()); break; } case LCSTATE_QueryCharacterList: { // Query done for the character list, send it out. _sendCharacterList(client, result); break; } case LCSTATE_DeleteCharacter: { // TODO: check returncodes, when using sf database::DataBinding* binding = mDatabase->createDataBinding(1); binding->addField(database::DFT_uint32,0,4); uint32 queryResult; result->getNextRow(binding,&queryResult); uint32 deleteFailed = 1; if (queryResult == 1) { deleteFailed = 0; } mDatabase->destroyDataBinding(binding); _sendDeleteCharacterReply(deleteFailed,client); // _sendDeleteCharacterReply(0,client); } case LCSTATE_RetrieveAccountId: { //check to see if we have an account id _getLauncherSessionKey(client, result); break; } break; default: break; } }
void LoginManager::handleDatabaseJobComplete(void* ref, DatabaseResult* result) { // Stupid simple hack since we don't have a client for this query if (ref == (void*)1) { _updateServerStatus(result); return; } // This assumes only authentication calls are async right now. Will change as needed. LoginClient* client = (LoginClient*)ref; switch (client->getState()) { case LCSTATE_QueryAuth: { // Check authentication _authenticateClient(client, result); break; } case LCSTATE_QueryServerList: { // Auth was successful, now send the server list. _sendServerList(client, result); // Execute our query client->setState(LCSTATE_QueryCharacterList); mDatabase->ExecuteSqlAsync(this, ref, "SELECT characters.id, characters.firstname, characters.lastname, characters.galaxy_id, character_appearance.base_model_string FROM characters JOIN (character_appearance) ON (characters.id = character_appearance.character_id) WHERE characters.account_id=%u AND characters.archived=0;", client->getAccountId()); break; } case LCSTATE_QueryCharacterList: { // Query done for the character list, send it out. _sendCharacterList(client, result); break; } case LCSTATE_DeleteCharacter: { // TODO: check returncodes, when using sf DataBinding* binding = mDatabase->CreateDataBinding(1); binding->addField(DFT_uint32,0,4); uint32 queryResult; result->GetNextRow(binding,&queryResult); uint32 deleteFailed = 1; if (queryResult == 1) { deleteFailed = 0; } mDatabase->DestroyDataBinding(binding); _sendDeleteCharacterReply(deleteFailed,client); // _sendDeleteCharacterReply(0,client); } break; default:break; } }
int GmModule::doLogin() { int ok = 0; apLog_Verbose((LOG_CHANNEL, LOG_CONTEXT, "")); if (!hasGmLoginData()) { bLoginOnRegister_ = 1; ok = doRegister(); } else { if (nLoginRequests_ > Apollo::getModuleConfig(MODULE_NAME, "Login/MaxRetries", 1000000000)) { apLog_Error((LOG_CHANNEL, LOG_CONTEXT, "Login/MaxRetries=%d exceeded, giving up", nLoginRequests_)); } else { String sUrl = Apollo::getModuleConfig(MODULE_NAME, "Srpc/Url", ""); if (sUrl.empty()) { apLog_Error((LOG_CHANNEL, LOG_CONTEXT, "Missing Srpc/Url")); } else { Apollo::KeyValueList kvClientInfo; Msg_Core_GetLoadedModules msgCGLM; if (msgCGLM.Request()) { for (Apollo::ValueElem* e = 0; (e = msgCGLM.vlModules.nextElem(e)) != 0; ) { Msg_Core_GetModuleInfo msgCGMI; msgCGMI.sModuleName = e->getString(); if (msgCGMI.Request()) { Apollo::KeyValueElem* e = msgCGMI.kvInfo.find("Version"); if (e) { kvClientInfo.add(msgCGMI.sModuleName, e->getString()); } else { kvClientInfo.add(msgCGMI.sModuleName, ""); } } } } kvClientInfo.add("Instance", getInstanceId()); kvClientInfo.add("Machine", getMachineId()); SrpcMessage srpc; srpc.set(Srpc::Key::Method, GmService_Method_Login); srpc.set("Token", Apollo::getModuleConfig(MODULE_NAME, "Srpc/Token", "8uzxXXZTAmHcni6tK3t-Apollo-3")); srpc.set("User", Apollo::getModuleConfig(MODULE_NAME, "User", "")); srpc.set("Password", getPassword()); srpc.set("Client", kvClientInfo.toString()); LoginClient* pClient = new LoginClient(this); if (pClient != 0) { ok = pClient->Post(sUrl, srpc); if (!ok) { apLog_Error((LOG_CHANNEL, LOG_CONTEXT, "LoginClient::Post(%s) failed", _sz(sUrl))); } else { nLoginRequests_++; } } } // sUrl.empty } // nLoginRequests_ } return ok; }
DWORD WINAPI LoginListener::FLS_Thread( LPVOID lpParam ) { struct FLLT_INFO *pinfo = (struct FLLT_INFO *)lpParam; lpParam = NULL; if( !pinfo ) { log_error( LOG_ERROR, "FLS_Thread(): lpParam is NULL! Exit\n" ); return 0; } class LoginListener *cls = pinfo->cls; if( !cls ) { log_error( LOG_ERROR, "FLS_Thread(): pinfo->cls is NULL! Exit\n" ); FLS_Thread_freeInfo( pinfo ); return 0; } cls->m_listen_socket = INVALID_SOCKET; //DWORD wait_res = 0; //SOCKET s = sock_tcp_create(); SOCKET s = L2PNet_TCPsocket_create( true ); if( s == INVALID_SOCKET ) { log_error( LOG_ERROR, "FLS_Thread(): socket create failed!\n" ); FLS_Thread_freeInfo( pinfo ); return 0; } int mb_yes = 0; int bind_fail = 0; ll_bind: bind_fail = L2PNet_bind( s, g_cfg.FakeListenLoginIP, (unsigned short)g_cfg.FakeListenLoginPort ); if( bind_fail ) { log_error( LOG_ERROR, "FLS_Thread(): socket bind at %s:%d failed\n", g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort ); int wsaerr = L2PNet_WSAGetLastError(); if( wsaerr == WSAEADDRINUSE ) { wchar_t errmsg[256]; wsprintfW( errmsg, L"Порт %S:%d уже используется другим процессом!\n" L"Попробовать ещё раз?", g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort ); mb_yes = MessageBoxW( g_radardll_hwnd, errmsg, L"L2Detect: Ошибка!", MB_ICONSTOP | MB_YESNO ); if( mb_yes == IDYES ) goto ll_bind; } FLS_Thread_freeInfo( pinfo ); return 0; } if( L2PNet_listen( s ) ) { log_error( LOG_ERROR, "FLS_Thread(): listen() failed\n" ); FLS_Thread_freeInfo( pinfo ); return 0; } cls->m_listen_socket = s; log_error( LOG_DEBUG, "FLS_Thread(): started, listening at %s:%d\n", g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort ); // raise thread priority if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL ) ) log_error( LOG_WARNING, "FLS_Thread(): raise thread priority failed!\n" ); int r = 0; char clientIP[32] = {0}; unsigned short clientPort = 0; SOCKET scl = INVALID_SOCKET; int rdyR = 0, rdyW = 0; // ready to recv/send unsigned int scode = 0; // signal to thread int should_exit = 0; while( 1 ) { should_exit = 0; //r = sock_tcp_wait_ready_to_recv( s, 0, 500000 ); rdyR = 0; r = L2PNet_select( s, L2PNET_SELECT_READ, 500, &rdyR, &rdyW ); scode = cls->getLastSignal(); if( scode == FLLS_STOP ) { log_error( LOG_DEBUG, "FLS_Thread(): exit signal\n" ); should_exit = 1; } if( should_exit ) break; // break while() if( r == -1 ) { log_error( LOG_ERROR, "FLS_Thread(): socket select() error\n" ); break; } if( r == 1 && rdyR ) { //log_error( LOG_DEBUG, "FLS_Thread(): Somebody connected? :)\n" ); clientIP[0] = 0; clientPort = 0; scl = INVALID_SOCKET; //scl = sock_tcp_accept( s, clientIP, &clientPort ); scl = L2PNet_accept( s, clientIP, &clientPort ); if( scl == INVALID_SOCKET ) { log_error( LOG_ERROR, "FLS_Thread(): accept() failed...\n" ); } else { //log_error( LOG_DEBUG, "FLS_Thread(): accepted client %s:%d\n", clientIP, clientPort ); log_error( LOG_OK, "LoginListener: accepted client %s:%d\n", clientIP, clientPort ); LoginClient lc; if( lc.ProcessClient( scl ) ) { unsigned char sKey1[8] = {0,0,0,0, 0,0,0,0}; unsigned char sKey2[8] = {0,0,0,0, 0,0,0,0}; struct PlayServerInfo sinfo; lc.getSessionKeys( sKey1, sKey2 ); lc.getPlayServerAddress( sinfo.ip, &(sinfo.port) ); // ONLY IN OUTGAME MODE stop listener after successful client acception if( g_cfg.isInGameMode == false ) { // stop listener after successful client acception log_error( LOG_DEBUG, "FLS_Thread(): LoginListener stopping self in outgame mode, " "after client accepted, freeing port %s:%d\n", g_cfg.FakeListenLoginIP, g_cfg.FakeListenLoginPort ); //cls->signalStop(); should_exit = 1; } if( !g_pgame ) { log_error( LOG_ERROR, "FLS_Thread(): Game listener is NULL????" ); } else { // set play server info to game listener g_pgame->setPlayServerInfo( &sinfo ); } } } } // somebody connected? if( should_exit ) break; // break while() } // while(1) //sock_tcp_close_shutdown( s, SD_BOTH ); // network sockets clenup done by FLS_Thread_freeInfo() FLS_Thread_freeInfo( pinfo ); log_error( LOG_DEBUG, "FLS_Thread() ended\n" ); return 0; }