/* desc: 获取角色数据 角色数据可能存在于GameServer的缓存之中, 如果不在,就去redis缓存中查找, 如果也不在,就去mysql数据库中查找 */ void PlayerMng::GetPlayerData(IConnection* pConnection, const string& strPtName) { Player* pPlayer = NULL; roledata::PBRoleTotalInfo roleData; // 判断此链接是否已经被其他玩家使用了(同一个链接只支持一个玩家) if (m_clientConnMng.IsConnectionUsed(strPtName, pConnection)) { TRACELOG("the connection has already been used by other player, ptname=[" << strPtName << "]"); return; } // 如果玩家在线,那么就直接从内存中获取玩家数据 if (IsPlayerOnline(strPtName)) { pPlayer = GetPlayer(strPtName); if (!pPlayer) { ERRORLOG("get player failed, pt name=[" << strPtName << "]"); return; } // 将玩家数据组织成PB格式 pPlayer->SerializeToPB(roleData); pPlayer->SetPlayerConnection(pConnection); m_clientConnMng.SetPlayerConnection(pPlayer, pConnection); // 重新设置玩家对应的网络连接 // 已经获取到了数据 AchievePlayerData(roleData, "Player In mem"); return; } pPlayer = GetPlayer(strPtName); if (!pPlayer) { // 玩家数据不在内存中 pPlayer = _InitPlayerInfo(strPtName, pConnection); } else { // 更新玩家数据 m_clientConnMng.SetPlayerConnection(pPlayer, pConnection); m_playerInfoMap.insert(make_pair(strPtName, pPlayer)); } if (pPlayer->State() == PLAYER_FETCHING_DATA) // 玩家正在取数据中 { TRACELOG("player rolename=[" << strPtName << "] is in state PLAYER_FETCHING_DATA"); return; } m_playerDataGetter.GetPlayerData(pPlayer); // 从其他途径获取玩家数据(redis, 或者mysql) return; }
// 保存玩家数据 void PlayerMng::_SaveRoleData(Player* pPlayer) { if (!pPlayer) { return; } gtod::SRequestSaveRoleData saveRoleData; roledata::PBRoleTotalInfo* pRoleTotalInfo = saveRoleData.mutable_roledata(); // 增加玩家数据版本号 pPlayer->IncreaseVersion(); pPlayer->SerializeToPB(*pRoleTotalInfo); saveRoleData.set_ptname(pRoleTotalInfo->baseinfo().ptname()); TRACELOG("save player data, ID=[" << pRoleTotalInfo->baseinfo().userid() << "], ptname=[" << pRoleTotalInfo->baseinfo().ptname() << "]"); #ifndef _MSC_VER // 保存到redis中 string strRoleData; pRoleTotalInfo->SerializeToString(&strRoleData); string strSaveKey = KeyGen::GenRoleDataKey(pRoleTotalInfo->baseinfo().ptname()); try { m_pRedisClient->set(strSaveKey, strRoleData); } catch(redis::redis_error& err) { ERRORLOG("redis save role data error=[" << err.what() << "]"); } #endif // 保存到DataServer string strMessage; BuildRequestProto<gtod::SRequestSaveRoleData>(saveRoleData, strMessage, ID_SREQ_SRequestSaveRoleData); g_pDsSession->SendMsg(strMessage.c_str(), strMessage.size()); #ifdef DEBUG_SERVER string strPrint; google::protobuf::TextFormat::PrintToString(saveRoleData, &strPrint); TRACELOG("save roledata proto:" << endl << strPrint); #endif // 释放player if (pPlayer) { ReleasePlayer(pPlayer); } return; }
void PlayerMng::_SResponseVerifyToken(IConnection* pConn, MessageHeader* pMsgHeader) { login::SResponseVerifyToken verifyTokenResponse; verifyTokenResponse.ParseFromString(GetProtoData(pMsgHeader)); TRACELOG("verify token response, ptname=[" << verifyTokenResponse.ptname() << "], ret=[" << verifyTokenResponse.errcode() << "]."); Player* pPlayer = GetPlayer(verifyTokenResponse.ptname()); if (!pPlayer) { ERRORLOG("verify token response, cannot find player ptname=[" << verifyTokenResponse.ptname() << "]"); return; } ctos::ResponseVerifyToken verifyTokenAck; if (verifyTokenResponse.errcode() != ERROR_OP_SUCCESS) // 验证Token失败 { verifyTokenAck.set_errcode(verifyTokenResponse.errcode()); } else { m_tokenVerifyMng.ServerVerifyBack(pPlayer, verifyTokenResponse.errcode()); } string strMessage; BuildRequestProto<ctos::ResponseVerifyToken>(verifyTokenAck, strMessage, ID_ACK_ResponseVerifyToken); pPlayer->SendMsg(strMessage.c_str(), strMessage.size()); return; }
/* 玩家请求角色数据 */ void PlayerMng::_RequestRoleData(IConnection* pConn, MessageHeader* pMsgHeader) { ctos::RequestRoleData roleDataReq; roleDataReq.ParseFromString(GetProtoData(pMsgHeader)); TRACELOG("ptname=[" << roleDataReq.ptname() << "] request role data."); if (roleDataReq.ptname() == "") { TRACELOG("request role data, pt name is NULL"); return; } // 获取角色数据 GetPlayerData(pConn, roleDataReq.ptname()); }
void GsHandler::HandleDisconnect(IConnection* pConn, const BoostErrCode& error) { cout << "gs " << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort() << " disconnect" << endl; TRACELOG("gs " << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort() << " disconnect"); //g_pGsConnection = NULL; gpGsConnMng->SetGsConnection(NULL); }
void GsHandler::HandleConnect(IConnection* pConn) { cout << "gs connect:" << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort() << endl; TRACELOG("gs connect:" << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort()); //g_pGsConnection = pConn; gpGsConnMng->SetGsConnection(pConn); }
void ClientMsgHandler::HandleWrite(const boost::system::error_code& error, size_t bytes_transferred) { if (error) { ERRORLOG("error:" << boost::system::system_error(error).what()); } TRACELOG("bytes_transferred=[" << bytes_transferred << "]"); }
/* 请求验证token : 玩家在登陆之后进入游戏,或者断开连接进入游戏时需要进行Token验证 PS:玩家在每次网络链接断开后,重连的时候,都需要验证token,主要有2个原因 (1) 保证对玩家进行操作的是受过安全校验的 (2) 保证玩家使用的是新的网络连接 */ void PlayerMng::_RequestVerifyToken(IConnection* pConn, MessageHeader* pMsgHeader) { if (!pConn || !pMsgHeader) { return; } ctos::RequestVerifyToken verifyTokenReq; verifyTokenReq.ParseFromString(GetProtoData(pMsgHeader)); TRACELOG("ptname=[" << verifyTokenReq.ptname() << "] request verify token, token=[" << verifyTokenReq.token() << "]"); Player* pPlayer = GetPlayer(verifyTokenReq.ptname()); if (!pPlayer) { // 玩家数据不在内存中 pPlayer = _InitPlayerInfo(verifyTokenReq.ptname(), pConn); m_tokenVerifyMng.VerifyToken(pPlayer, verifyTokenReq.token(), false); return; } if (!verifyTokenReq.reconnect()) // 如果不是重新连接的Token验证(说明就是再次登陆的token验证) { pPlayer->SetPlayerConnection(pConn); m_tokenVerifyMng.VerifyToken(pPlayer, verifyTokenReq.token(), false); return; } // 玩家重新连接的Token验证 ctos::ResponseVerifyToken verifyTokenAck; if (!m_tokenVerifyMng.VerifyToken(pPlayer, verifyTokenReq.token())) { TRACELOG("verify token failed, token=[" << verifyTokenReq.token()); verifyTokenAck.set_errcode(ERROR_VERIFY_TOKEN_FAIL); } else { m_clientConnMng.SetPlayerConnection(pPlayer, pConn); } string strMessage; BuildResponseProto<ctos::ResponseVerifyToken>(verifyTokenAck, strMessage, ID_ACK_ResponseVerifyToken); pConn->SendMsg(strMessage.c_str(), strMessage.size()); return; }
bool TokenVerifyMng::VerifyToken(Player* pPlayer, uint32_t uToken, bool bReconnect/* =true */) { if (!pPlayer) { return false; } // 不是重连需要的Token验证 if (!bReconnect) { pPlayer->SetToken(uToken); _SendVerifyToken(pPlayer->PtName(), uToken); TRACELOG("ptname=[" << pPlayer->PtName() << "] verify token to server, token=[" << uToken << "]"); return true; } bool bRet = pPlayer->VerifyToken(uToken); return bRet; }
// 请求创建角色 void PlayerMng::_RequestCreateRole(IConnection* pConn, MessageHeader* pMsgHeader) { if (!g_pDsSession) { return; } ctos::RequestCreateRole createRoleReq; createRoleReq.ParseFromString(GetProtoData(pMsgHeader)); // 判断此链接是否已经被其他玩家使用了(同一个链接只支持一个玩家) if (m_clientConnMng.IsConnectionUsed(createRoleReq.ptname(), pConn)) { TRACELOG("the connection has already been used by other player."); return; } gtod::SRequestCreateRole sCreateRoleReq; sCreateRoleReq.set_ptname(createRoleReq.ptname()); sCreateRoleReq.set_rolename(createRoleReq.rolename()); // 保存玩家连接信息 Player* pPlayer = GetPlayer(createRoleReq.ptname()); if (!pPlayer) { // 玩家数据不在内存中 pPlayer = _InitPlayerInfo(createRoleReq.ptname(), pConn); } else { // 更新玩家数据 m_clientConnMng.SetPlayerConnection(pPlayer, pConn); m_playerInfoMap.insert(make_pair(createRoleReq.ptname(), pPlayer)); } // 发送消息 string strMessage; BuildRequestProto<gtod::SRequestCreateRole>(sCreateRoleReq, strMessage, ID_SREQ_SRequestCreateRole); g_pDsSession->SendMsg(strMessage.c_str(), strMessage.size()); return; }
// 获取到角色数据之后,回调此函数 void PlayerMng::AchievePlayerData(const roledata::PBRoleTotalInfo& roleData, const string& strDesc) { map<string, Player*>::iterator playerIt = m_playerInfoMap.find(roleData.baseinfo().ptname()); if (playerIt == m_playerInfoMap.end()) { ERRORLOG("cannot find player, ptname=[" << roleData.baseinfo().ptname() << "],desc=[" << strDesc << "]"); return; } Player* pPlayer = playerIt->second; if (!pPlayer) { ERRORLOG("player is NULL"); return; } IConnection* pClientConn = pPlayer->GetPlayerConnection(); if (!pClientConn) { ERRORLOG("player client connection is NULL."); return; } if (!pClientConn->IsConnected()) { ERRORLOG("player client connection=[" << pClientConn <<"] is disconnect."); return; } pPlayer->GetRoleTotalInfo(roleData); pPlayer->SetPlayerState(PLAYER_ONLINE); uint32_t ID = pPlayer->GetPlayerID(); m_playerIdMap.insert(make_pair(pPlayer->GetPlayerID(), pPlayer)); TRACELOG("Achieve player data, ID=[" << ID << "], ptname=[" << pPlayer->PtName() << "] " << strDesc); // 玩家数据可能已经被修改了 roledata::PBRoleTotalInfo newRoleTotalData; pPlayer->SerializeToPB(newRoleTotalData); // 将数据返回给客户端 _SendPlayerDataToClient(pClientConn, newRoleTotalData); }
void ClientHandler::HandleDisconnect(IConnection* pConn, const BoostErrCode& error) { TRACELOG("client " << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort() << " disconnect"); }
void ClientHandler::HandleConnect(IConnection* pConn) { TRACELOG("client connect:" << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort()); }
void ClientMsgHandler::HandleDisconnect(IConnection* pConn, const BoostErrCode& error) { TRACELOG("client " << pConn->GetRemoteIp() << ":" << pConn->GetRemotePort() << " disconnect, error=[" << error.message().c_str() << "]"); }
static int dosdetector_handler(request_rec *r) { //DEBUGLOG("dosdetector_handler is called"); dosdetector_dir_config *cfg = (dosdetector_dir_config *) ap_get_module_config(r->per_dir_config, &dosdetector_module); if(cfg->detection) return DECLINED; if (!ap_is_initial_req(r)) return DECLINED; //char **ignore_contenttype = (char **) cfg->ignore_contenttype->elts; const char *content_type; const char *address_tmp; const char *address = NULL; int i; content_type = ap_sub_req_lookup_uri(r->uri, r, NULL)->content_type; if (!content_type) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) content_type = DefaultContentType; #else content_type = ap_default_type(r); #endif } if (cfg->forwarded){ if ((address_tmp = apr_table_get(r->headers_in, "X-Forwarded-For")) != NULL){ const char *i = address_tmp; while(*i != 0 && *i != ',') i++; address = apr_pstrndup(r->pool, address_tmp, i - address_tmp); } } if (address == NULL) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) address = r->connection->client_ip; #else address = r->connection->remote_ip; #endif } ap_regmatch_t regmatch[AP_MAX_REG_MATCH]; ap_regex_t **contenttype_regexp = (ap_regex_t **) cfg->contenttype_regexp->elts; for (i = 0; i < cfg->contenttype_regexp->nelts; i++) { if(!ap_regexec(contenttype_regexp[i], content_type, AP_MAX_REG_MATCH, regmatch, 0)){ //ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, 0, "ignoring content-type: %s", content_type); return OK; } } DEBUGLOG("dosdetector: processing content-type: %s", content_type); struct in_addr addr; if(!cfg->forwarded) { #if (AP_SERVER_MINORVERSION_NUMBER > 2) addr = r->connection->client_addr->sa.sin.sin_addr; #else addr = r->connection->remote_addr->sa.sin.sin_addr; #endif } if(cfg->forwarded || addr.s_addr == 0){ if (inet_aton(address, &addr) == 0) { TRACELOG("dosdetector: '%s' is not a valid IP addresss", address); return DECLINED; } } if (lock) apr_global_mutex_lock(lock); client_t *client = get_client(client_list, addr, cfg->period); if (lock) apr_global_mutex_unlock(lock); #ifdef _DEBUG int last_count = client->count; #endif count_increment(client, cfg->threshold); DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d", address, last_count, client->count, (int)client->interval); //DEBUGLOG("dosdetector: %s, count: %d -> %d, interval: %d on tid %d, pid %d", address, last_count, client->count, (int)client->interval, gettid(), getpid()); time_t now = time((time_t *)0); if(client->suspected > 0 && client->suspected + cfg->ban_period > now){ apr_table_setn(r->subprocess_env, "SuspectDoS", "1"); //apr_table_setn(r->notes, "SuspectDoS", "1"); DEBUGLOG("dosdetector: '%s' has been still suspected as DoS attack! (suspected %d sec ago)", address, now - client->suspected); if(client->count > cfg->ban_threshold){ if(client->hard_suspected == 0) TRACELOG("dosdetector: '%s' is suspected as Hard DoS attack! (counter: %d)", address, client->count); client->hard_suspected = now; apr_table_setn(r->subprocess_env, "SuspectHardDoS", "1"); //apr_table_setn(r->notes, "SuspectHardDoS", "1"); } } else { if(client->suspected > 0){ client->suspected = 0; client->hard_suspected = 0; client->count = 0; } //int last_count = client->count; //client->count = client->count - client->interval * cfg->threshold; //if(client->count < 0) // client->count = 0; //client->count ++; //DEBUGLOG("client address: %s, count: %d -> %d, interval: %d", address, last_count, client->count, client->interval); if(client->count > cfg->threshold){ client->suspected = now; apr_table_setn(r->subprocess_env, "SuspectDoS", "1"); //apr_table_setn(r->notes, "SuspectDoS", "1"); TRACELOG("dosdetector: '%s' is suspected as DoS attack! (counter: %d)", address, client->count); } } return DECLINED; }