Beispiel #1
0
/* 
	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;
}
Beispiel #2
0
// 保存玩家数据
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/*
	玩家请求角色数据
*/
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());
}
Beispiel #5
0
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);
}
Beispiel #6
0
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 << "]");
}
Beispiel #8
0
/* 
	请求验证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; 
}
Beispiel #9
0
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;
}
Beispiel #10
0
// 请求创建角色
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;
}
Beispiel #11
0
// 获取到角色数据之后,回调此函数
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;
}