增加ACE安全测试工程

This commit is contained in:
2025-12-06 16:42:21 +08:00
parent b78ee53326
commit b38ad590a9
68 changed files with 5385 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
#include "stdafx.h"
#include "AceInterface.h"
#include "GameServer.h"
const wchar_t* AceInterface::kLibraryDir = L"./";
const uint32_t AceInterface::kGameID = 719;
const char* AceInterface::kAuthToken = "79205A21";
const uint32_t AceInterface::kWorldID = 160;
bool AceInterface::initAceInterface()
{
AceSdkServerLibraryInfo library_info;
memset(&library_info, 0, sizeof(AceSdkServerLibraryInfo));
memcpy(library_info.library_dir_, kLibraryDir, wcslen(kLibraryDir)*sizeof(wchar_t));
AceSdkServerAuthInfo auth_info;
memset(&auth_info, 0, sizeof(AceSdkServerAuthInfo));
auth_info.game_id_ = kGameID;
snprintf(auth_info.auth_token_, sizeof(auth_info.auth_token_), "%s", kAuthToken);
AceSdkServerDeploymentInfo deployment_info;
memset(&deployment_info, 0, sizeof(AceSdkServerDeploymentInfo));
deployment_info.region_ = ACE_SDK_REGION_CHINA_MAINLAND;
deployment_info.distributor_ = ACE_SDK_GAME_DISTRIBUTOR_COMMON;
AceSdkResult ret = ace_sdk_server_init(&library_info, &auth_info, &deployment_info);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk server, ret : %d\n", ret);
//return false;
}
//set text judge callback
ret = ace_sdk_server_set_recv_batch_multi_text_result_callback(onAceTextJudgeCallback);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to set text judge callback, ret : %d\n", ret);
//return false;
}
printf(">>ACE SDK server init success.\n");
return true;
}
bool AceInterface::onPlayerLogin(const AceSdkAccount& account, AceSdkTicket& aceTicket, AceSdkLightFeatureResponse& lightFeature)
{
// add player when login
AceSdkPlayerAddInfo add_player_info;
memset(&add_player_info, 0, sizeof(AceSdkPlayerAddInfo));
snprintf(add_player_info.role_name_, sizeof(add_player_info.role_name_) - 1, "qq_%s", account.account_);
AceSdkResult ret = ace_sdk_server_add_player(&account, &add_player_info);
if (ret != 0)
{
printf(">>ACE fail to add player, ret: %d\n", ret);
return false;
}
printf(">>ACE add player success.\n");
// get ticket
memset(&aceTicket, 0, sizeof(AceSdkTicket));
ret = ace_sdk_server_get_ticket(&account, &aceTicket);
if (ret != 0)
{
printf(">>ACE fail to get ace ticket, ret: %d\n", ret);
return false;
}
printf(">>ACE Succ to get ace ticket, len=%u, content=%s\n", aceTicket.ticket_len_, aceTicket.ticket_);
//get light feature
AceSdkLightFeatureRequest lightFeatureReq;
memset(&lightFeatureReq, 0, sizeof(AceSdkLightFeatureRequest));
snprintf(lightFeatureReq.client_version_, sizeof(lightFeatureReq.client_version_) - 1, "%s", "1.0.0");
memset(&lightFeature, 0, sizeof(AceSdkLightFeatureResponse));
ret = ace_sdk_server_get_light_feature(&account, &lightFeatureReq, &lightFeature);
if (ret != 0)
{
printf(">>ACE fail to get ace ticket, ret: %d\n", ret);
return false;
}
printf(">>ACE Succ to get light feature\n");
return true;
}
void AceInterface::onPlayerLogout(const AceSdkAccount& account)
{
AceSdkResult ret = ace_sdk_server_delete_player(&account);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_delete_player, ret : %d\n", ret);
}
}
void AceInterface::onReceiveClientTickPacket(const AceSdkAccount& account, const uint8_t* packet_buffer, uint32_t packet_len)
{
AceSdkServerPacket serverPacket;
memset(&serverPacket, 0, sizeof(AceSdkServerPacket));
memcpy(&(serverPacket.account_), &account, sizeof(AceSdkAccount));
serverPacket.packet_len_ = packet_len;
memcpy(serverPacket.packet_buffer_, packet_buffer, packet_len);
AceSdkResult ret = ace_sdk_server_on_packet_received(&serverPacket);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_on_packet_received, ret : %d\n", ret);
}
}
void AceInterface::getServerTickPacket(AceSdkServerPacketList& serverTickPackets)
{
memset(&serverTickPackets, 0, sizeof(AceSdkServerPacketList));
AceSdkResult ret = ace_sdk_server_get_packet(&serverTickPackets);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_get_packets, ret : %d\n", ret);
}
if (serverTickPackets.packet_num_ > 0)
{
printf(">>ACE call ace_sdk_server_on_packet_received, packet_num : %d\n", serverTickPackets.packet_num_);
}
}
void AceInterface::keepClientAlive(const AceSdkAccount& account)
{
AceSdkResult ret = ace_sdk_server_keep_alive_player(&account);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_keep_alive, ret : %d\n", ret);
}
}
bool AceInterface::onUGCRequest(const AceSdkAccount& account, int32_t ugcSceneID, const char* content,
int32_t ugcCtxID, int32_t clientID)
{
AceSdkBatchMultiTextInputInfo textInputInfo;
memset(&textInputInfo, 0, sizeof(AceSdkBatchMultiTextInputInfo));
textInputInfo.account_info_ = account;
snprintf(textInputInfo.role_name_, ACE_SDK_UIC_MAX_ROLE_NAME_LEN - 1, "qq_%s", account.account_);
textInputInfo.multi_text_cnt_ = 1;
textInputInfo.multi_text_array_[0].scene_id_ = ugcSceneID;
snprintf(textInputInfo.multi_text_array_[0].text_, ACE_SDK_UIC_MAX_MESSAGE_LEN, "%s", content);
AceTextJudgeCallbackData callbackData;
memset(&callbackData, 0, sizeof(AceTextJudgeCallbackData));
callbackData.clientID = clientID;
callbackData.ugcClientCtxID = ugcCtxID;
textInputInfo.callback_len_ = sizeof(AceTextJudgeCallbackData);
memcpy(textInputInfo.callback_data_, &callbackData, sizeof(AceTextJudgeCallbackData));
AceSdkResult ret = ace_sdk_server_judge_batch_multi_text(&textInputInfo);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_judge_batch_multi_text, ret : %d\n", ret);
return false;
}
printf(">>ACE call ace_sdk_server_judge_batch_multi_text\n");
return true;
}
int AceInterface::onAceTextJudgeCallback(const AceSdkUicJudgeResultInfoBatchMultiText* result_info)
{
if (result_info == nullptr) return 0;
if (result_info->callback_len_ != sizeof(AceTextJudgeCallbackData))
{
printf(">>ACE text judge callback data length mismatch, len : %d\n", result_info->callback_len_);
return 0;
}
printf(">>ACE text judge callback received, err_code : %d, multext_result_cnt : %d\n",
result_info->err_code_, result_info->multext_result_cnt_);
AceTextJudgeCallbackData callbackData;
memcpy(&callbackData, result_info->callback_data_, sizeof(AceTextJudgeCallbackData));
GameServer::getSingleton()->onUGCCallback(callbackData.clientID, callbackData.ugcClientCtxID, result_info);
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
class AceInterface
{
public:
const static wchar_t* kLibraryDir;
const static uint32_t kGameID;
const static char* kAuthToken;
const static uint32_t kWorldID;
public:
static bool initAceInterface();
static bool onPlayerLogin(const AceSdkAccount& account, AceSdkTicket& ace_ticket, AceSdkLightFeatureResponse& lightFeature);
static void onPlayerLogout(const AceSdkAccount& account);
static void onReceiveClientTickPacket(const AceSdkAccount& account, const uint8_t* packet_buffer, uint32_t packet_len);
static void getServerTickPacket(AceSdkServerPacketList& serverTickPackets);
static void keepClientAlive(const AceSdkAccount& account);
static bool onUGCRequest(const AceSdkAccount& account, int32_t ugcSceneID, const char* content,
int32_t ugcCtxID, int32_t clientID);
private:
static int onAceTextJudgeCallback(const AceSdkUicJudgeResultInfoBatchMultiText* result_info);
struct AceTextJudgeCallbackData
{
int32_t clientID;
int32_t ugcClientCtxID;
};
};
+8
View File
@@ -0,0 +1,8 @@
#include "stdafx.h"
#include "AceReportInterface.h"
std::string buildReportRequestUrl(const std::string& baseUrl, const std::string& user,
const std::string& token, uint32_t timeStamp, const std::string& body)
{
return "";
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
std::string buildReportRequestUrl();
+62
View File
@@ -0,0 +1,62 @@
set(ASERVER_SOURCE_FILES
stdafx.h
main.cpp
GameServer.h
GameServer.cpp
AceInterface.h
AceInterface.cpp
AceReportInterface.h
AceReportInterface.cpp
NetbarInterface.h
NetbarInterface.cpp
CurlHelper.h
CurlHelper.cpp
)
set(ASERVER_PRECOMPILE_FILE
stdafx.cpp
)
foreach(filename ${ASERVER_SOURCE_FILES})
get_filename_component(ext ${filename} LAST_EXT ABSOLUTE)
string(TOLOWER ${ext} ext_lower)
if(${ext_lower} STREQUAL ".cpp" )
set_source_files_properties(
${filename}
PROPERTIES
COMPILE_FLAGS "/Yustdafx.h"
)
endif()
endforeach()
set_source_files_properties(${ASERVER_PRECOMPILE_FILE}
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
add_executable(aServer
${ASERVER_SOURCE_FILES}
${ASERVER_PRECOMPILE_FILE}
)
target_include_directories(aServer
PRIVATE
${CYCLONE_DIR}/include
${ACE_SERVER_DIR}/include
${RAPIDJSON_INCLUDE_DIRS}
${GAME_PROTO_DIR}
)
target_link_directories(aServer
PRIVATE
${CYCLONE_DIR}/lib
)
target_link_libraries(aServer
PRIVATE
aGameProto
cyclone.lib
ws2_32.lib
shlwapi.lib
CURL::libcurl_static
)
+116
View File
@@ -0,0 +1,116 @@
#include "stdafx.h"
#include "CurlHelper.h"
#include <curl/curl.h>
struct CurlBodyData
{
const char* bodyPtr;
size_t sizeLeft;
};
static size_t curlReadCallback(void* ptr, size_t size, size_t nmemb, void* userdata)
{
CurlBodyData* bodyData = static_cast<CurlBodyData*>(userdata);
size_t bufferSize = size * nmemb;
if(bufferSize < 1) return 0;
if (bodyData->sizeLeft == 0)
return 0;
//we only send one byte at a time
size_t copySize = 1;
memcpy(ptr, bodyData->bodyPtr, copySize);
bodyData->bodyPtr += copySize;
bodyData->sizeLeft -= copySize;
return copySize;
}
static size_t curlWriteCallback(void* ptr, size_t size, size_t nmemb, void* userdata)
{
std::string* output = static_cast<std::string*>(userdata);
size_t newLength = size * nmemb;
size_t oldLength = output->size();
output->resize(oldLength + newLength);
std::copy((char*)ptr, (char*)ptr + newLength, output->begin() + oldLength);
return newLength;
}
int32_t curlRequest(const std::string& url, const std::string& body, std::string& output, bool jsonBody)
{
CURL* curlCtx = curl_easy_init();
if (curlCtx == nullptr) return -1;
curl_easy_reset(curlCtx);
CurlBodyData bodyData;
bodyData.bodyPtr = body.c_str();
bodyData.sizeLeft = body.size();
curl_easy_setopt(curlCtx, CURLOPT_URL, url.c_str());
curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curlCtx, CURLOPT_NOPROXY, "*");
curl_easy_setopt(curlCtx, CURLOPT_TIMEOUT, 3L);
curl_easy_setopt(curlCtx, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curlCtx, CURLOPT_POST, 1L);
curl_easy_setopt(curlCtx, CURLOPT_READFUNCTION, curlReadCallback);
curl_easy_setopt(curlCtx, CURLOPT_READDATA, &bodyData);
curl_easy_setopt(curlCtx, CURLOPT_WRITEFUNCTION, curlWriteCallback);
curl_easy_setopt(curlCtx, CURLOPT_WRITEDATA, &output);
struct curl_slist* headers = nullptr;
if (jsonBody)
{
headers = curl_slist_append(headers, "Content-Type: application/json");
}
if(headers != nullptr)
{
curl_easy_setopt(curlCtx, CURLOPT_HTTPHEADER, headers);
}
curl_easy_setopt(curlCtx, CURLOPT_POSTFIELDSIZE, static_cast<long>(bodyData.sizeLeft));
CURLcode returnCode = curl_easy_perform(curlCtx);
if(returnCode != CURLE_OK)
{
curl_easy_cleanup(curlCtx);
if (headers != nullptr)
{
curl_slist_free_all(headers);
headers = nullptr;
}
return -1;
}
long stateCode = 0;
curl_easy_getinfo(curlCtx, CURLINFO_RESPONSE_CODE, &stateCode);
if (headers != nullptr)
{
curl_slist_free_all(headers);
headers = nullptr;
}
curl_easy_cleanup(curlCtx);
if(stateCode != 200)
{
return static_cast<int32_t>(stateCode);
}
if(output.empty())
{
return -1;
}
return returnCode;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
int32_t curlRequest(const std::string& url, const std::string& body, std::string& output, bool jsonBody);
+299
View File
@@ -0,0 +1,299 @@
#include "stdafx.h"
#include "GameServer.h"
#include "AceInterface.h"
#include "NetbarInterface.h"
#include "GameProto.pb.h"
GameServer* GameServer::getSingleton()
{
static GameServer instance;
return &instance;
}
GameServer::GameServer()
{
}
GameServer::~GameServer()
{
}
void GameServer::startAndJoin(uint16_t server_port)
{
m_clients_lock = cyclone::sys_api::mutex_create();
cyclone::TcpServer server;
server.m_listener.on_connected = std::bind(&GameServer::onClientConnected, this, std::placeholders::_3);
server.m_listener.on_message = std::bind(&GameServer::onClientMessage, this, std::placeholders::_3);
server.m_listener.on_close = std::bind(&GameServer::onClientClose, this, std::placeholders::_3);
if (!server.bind(cyclone::Address(server_port, false), false)) return;
int32_t workerThreads = 1; // cyclone::sys_api::get_cpu_counts();
if (!(server.start(workerThreads))) return;
//server.join();
while (true)
{
tick();
if (m_tickSleepSwitch == 0)
{
cyclone::sys_api::thread_sleep(1);
}
m_tickSleepSwitch = (m_tickSleepSwitch + 1) % 15;
}
cyclone::sys_api::mutex_destroy(m_clients_lock);
}
GameClient* GameServer::getClient(int32_t client_id)
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
std::map< int32_t, GameClient >::iterator it = m_clients.find(client_id);
if(it==m_clients.end())
{
return nullptr;
}
return &(it->second);
}
void GameServer::tick()
{
AceSdkServerPacketList serverTickPackets;
AceInterface::getServerTickPacket(serverTickPackets);
if (serverTickPackets.packet_num_ == 0) return;
for (uint32_t i = 0; i < serverTickPackets.packet_num_; ++i)
{
const AceSdkServerPacket& serverPacket = serverTickPackets.packets_[i];
std::map< std::string, int32_t >::iterator it = m_accountToConnectionID.find(std::string(serverPacket.account_.account_));
if (it == m_accountToConnectionID.end()) continue;
GameClient* client = getClient(it->second);
if (client == nullptr) continue;
Game::ServerTickPacket serverTickPacket;
serverTickPacket.mutable_server_packet()->assign((const char*)serverPacket.packet_buffer_, serverPacket.packet_len_);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_SERVER_PACKET, &serverTickPacket, packet);
client->connection->send(packet.get_memory_buf(), packet.get_memory_size());
}
}
void GameServer::onClientConnected(cyclone::TcpConnectionPtr conn)
{
//new connection
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
m_clients.insert({ conn->get_id(),{ conn->get_id(), conn } });
}
CY_LOG(cyclone::L_DEBUG, "new connection accept, from %s:%d to %s:%d",
conn->get_peer_addr().get_ip(),
conn->get_peer_addr().get_port(),
conn->get_local_addr().get_ip(),
conn->get_local_addr().get_port());
}
void GameServer::onClientMessage(cyclone::TcpConnectionPtr conn)
{
cyclone::RingBuf& buf = conn->get_input_buf();
for (;;)
{
cyclone::Packet packet;
if (!packet.build_from_ringbuf(GAME_PACKET_HEAD_SIZE, buf)) return;
::google::protobuf::Message* message = parserProtoMessage(packet);
switch (packet.get_packet_id())
{
case GAME_PROTO_LOGIN_REQUEST:
{
Game::LoginRequest* loginRequest = dynamic_cast<Game::LoginRequest*>(message);
onClientLoginRequest(conn, loginRequest);
}
break;
case GAME_PROTO_CLIENT_PACKET:
{
Game::ClientTickPacket* clientTickPacket = dynamic_cast<Game::ClientTickPacket*>(message);
onClientTickPacket(conn, clientTickPacket);
}
break;
case GAME_PROTO_HEART_BEAT:
{
Game::HeartBeat* heartPacket = dynamic_cast<Game::HeartBeat*>(message);
onClientHeartBeat(conn, heartPacket);
}
break;
case GAME_PROTO_UGC_REQUEST:
{
Game::UGCRequest* ugcRequest = dynamic_cast<Game::UGCRequest*>(message);
onUGCRequest(conn, ugcRequest);
}
break;
case GAME_PROTO_REPORT_REQ:
{
Game::GameReportReq* reportRequest = dynamic_cast<Game::GameReportReq*>(message);
onReportRequest(conn, reportRequest);
}
break;
case GAME_PROTO_NETBAR_REQ:
{
Game::NetbaraStatusReq* netbarRequest = dynamic_cast<Game::NetbaraStatusReq*>(message);
onNetbarRequest(conn, netbarRequest);
}
}
}
}
void GameServer::onClientClose(cyclone::TcpConnectionPtr conn)
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
GameClient* client = getClient(conn->get_id());
AceInterface::onPlayerLogout(client->aceAccount);
m_accountToConnectionID.erase(std::string(client->aceAccount.account_));
m_clients.erase(conn->get_id());
CY_LOG(cyclone::L_DEBUG, "connection %s:%d closed",
conn->get_peer_addr().get_ip(),
conn->get_peer_addr().get_port());
}
void GameServer::onClientLoginRequest(cyclone::TcpConnectionPtr conn, Game::LoginRequest* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
client->gameAccoundID = request->accound_id();
client->gameWorldID = request->world_id();
m_accountToConnectionID.insert({ request->accound_id(), conn->get_id() });
//create ace account info
AceSdkAccount& account = client->aceAccount;
memset(&account, 0, sizeof(AceSdkAccount));
snprintf(account.account_, sizeof(account.account_) - 1, "%s", request->accound_id().c_str());
account.account_type_ = ACE_SDK_ACCOUNT_TYPE_QQ;
account.plat_id_ = ACE_SDK_PLAT_ID_PC_CLIENT;
account.game_id_ = AceInterface::kGameID;
account.world_id_ = AceInterface::kWorldID;
int32_t pbRetCode = request->pb_retcode();
printf(">>ACE client pb ret code: %d\n", pbRetCode);
AceSdkTicket aceTicket;
AceSdkLightFeatureResponse lightFeature;
if (!AceInterface::onPlayerLogin(account, aceTicket, lightFeature))
{
printf(">>ACE player login failed.\n");
return;
}
Game::LightFeature lightFeatureProto;
lightFeatureProto.set_data_len(lightFeature.data_len_);
lightFeatureProto.set_data_crc(lightFeature.data_crc_);
lightFeatureProto.set_data(std::string((const char*)lightFeature.data_, lightFeature.data_len_));
lightFeatureProto.set_name(std::string(lightFeature.name_));
//send login reply
Game::LoginReply loginReply;
loginReply.set_result(0);
loginReply.set_runtime_id(conn->get_id());
loginReply.set_ace_token(aceTicket.ticket_);
loginReply.mutable_light_feature()->CopyFrom(lightFeatureProto);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_LOGIN_REPLY, &loginReply, outputPacket);
conn->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
}
void GameServer::onClientTickPacket(cyclone::TcpConnectionPtr conn, Game::ClientTickPacket* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::onReceiveClientTickPacket(client->aceAccount,
(const uint8_t*)(request->client_packet().data()), (uint32_t)(request->client_packet().size()));
}
void GameServer::onClientHeartBeat(cyclone::TcpConnectionPtr conn, Game::HeartBeat* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::keepClientAlive(client->aceAccount);
if(request->pb_data().length()>0)
{
//log
printf(">>ACE receive heart beat pb data, len=%zu\n", request->pb_data().length());
}
}
void GameServer::onUGCRequest(cyclone::TcpConnectionPtr conn, Game::UGCRequest* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::onUGCRequest(client->aceAccount,
request->ugc_scene_id(), request->ugc_content().c_str(),
request->ugc_ctx_id(), conn->get_id());
}
void GameServer::onUGCCallback(int32_t connID, int32_t ctxID, const AceSdkUicJudgeResultInfoBatchMultiText* result_info)
{
GameClient* client = getClient(connID);
assert(client);
if (result_info->multext_result_cnt_ < 1)
{
return;
}
Game::UGCReply ugcReply;
ugcReply.set_ugc_ctx_id(ctxID);
ugcReply.set_error_code(result_info->err_code_);
ugcReply.set_result(result_info->multext_result_array_[0].check_result_);
ugcReply.set_filted_content(result_info->multext_result_array_[0].filtered_text_);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_UGC_REPLY, &ugcReply, outputPacket);
client->connection->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
}
void GameServer::onReportRequest(cyclone::TcpConnectionPtr conn, Game::GameReportReq* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
}
void GameServer::onNetbarRequest(cyclone::TcpConnectionPtr conn, Game::NetbaraStatusReq* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
NetbarInterface::onReceiveNetbarReportRequest(client, request);
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include "GameProto.h"
namespace Game
{
class LoginRequest;
class ClientTickPacket;
class HeartBeat;
class UGCRequest;
class GameReportReq;
class NetbaraStatusReq;
}
struct GameClient
{
int32_t agent_id;
cyclone::TcpConnectionPtr connection;
std::string gameAccoundID;
int32_t gameWorldID;
AceSdkAccount aceAccount;
};
class GameServer
{
public:
static GameServer* getSingleton();
public:
void startAndJoin(uint16_t server_port);
GameClient* getClient(int32_t client_id);
void onUGCCallback(int32_t connID, int32_t ctxID, const AceSdkUicJudgeResultInfoBatchMultiText* result_info);
protected:
void onClientConnected(cyclone::TcpConnectionPtr conn);
void onClientMessage(cyclone::TcpConnectionPtr conn);
void onClientClose(cyclone::TcpConnectionPtr conn);
protected:
void tick();
void onClientLoginRequest(cyclone::TcpConnectionPtr conn, Game::LoginRequest* request);
void onClientTickPacket(cyclone::TcpConnectionPtr conn, Game::ClientTickPacket* request);
void onClientHeartBeat(cyclone::TcpConnectionPtr conn, Game::HeartBeat* request);
void onUGCRequest(cyclone::TcpConnectionPtr conn, Game::UGCRequest* request);
void onReportRequest(cyclone::TcpConnectionPtr conn, Game::GameReportReq* request);
void onNetbarRequest(cyclone::TcpConnectionPtr conn, Game::NetbaraStatusReq* request);
private:
std::map< int32_t, GameClient > m_clients;
std::map< std::string, int32_t > m_accountToConnectionID;
cyclone::sys_api::mutex_t m_clients_lock;
int32_t m_tickSleepSwitch = 0;
public:
GameServer();
~GameServer();
};
+119
View File
@@ -0,0 +1,119 @@
#include "stdafx.h"
#include "NetbarInterface.h"
#include "GameServer.h"
#include "GameProto.pb.h"
#include "CurlHelper.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
std::string buildRequestJson(GameClient* client, Game::NetbaraStatusReq* request)
{
rapidjson::Document root;
root.SetObject();
rapidjson::Document::AllocatorType& allocator = root.GetAllocator();
//openid
rapidjson::Value openIDValue(client->gameAccoundID.c_str(), static_cast<rapidjson::SizeType>(client->gameAccoundID.length()), allocator);
root.AddMember("openid", openIDValue, allocator);
//ip
std::string ipStr = client->connection->get_peer_addr().get_ip();
rapidjson::Value ipValue(ipStr.c_str(), static_cast<rapidjson::SizeType>(ipStr.length()), allocator);
root.AddMember("ip", ipValue, allocator);
//mac
rapidjson::Value macArray(rapidjson::kArrayType);
std::stringstream ss(request->macs().c_str());
std::string mac;
while (std::getline(ss, mac, ';'))
{
rapidjson::Value macValue(mac.c_str(), static_cast<rapidjson::SizeType>(mac.length()), allocator);
macArray.PushBack(macValue, allocator);
};
root.AddMember("macs", macArray, allocator);
//netbar token
rapidjson::Value tokenValue(request->token().c_str(), static_cast<rapidjson::SizeType>(request->token().length()), allocator);
root.AddMember("netbar_token", tokenValue, allocator);
//game id
root.AddMember("game_id", 1, allocator);
//game zone
std::string strZoneID = std::to_string(client->gameWorldID);
rapidjson::Value zoneIDValue(strZoneID.c_str(), static_cast<rapidjson::SizeType>(strZoneID.length()), allocator);
root.AddMember("zone", zoneIDValue, allocator);
//request no
std::string strRequestTime = std::to_string(static_cast<uint32_t>(time(nullptr)));
rapidjson::Value requestNumber(strRequestTime.c_str(), static_cast<rapidjson::SizeType>(strRequestTime.length()), allocator);
root.AddMember("reqno", requestNumber, allocator);
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
root.Accept(writer);
std::string outputJson = sb.GetString();
return outputJson;
}
std::string buildRequestUrl()
{
return "http://api-test.netbar.itrpc.woa.com/netbar.cafe.rewards.rewards/Rewards";
}
bool NetbarInterface::onReceiveNetbarReportRequest(GameClient* client, Game::NetbaraStatusReq* request)
{
std::string requestBody = buildRequestJson(client, request);
std::string requestUrl = buildRequestUrl();
std::string result;
int32_t retCode = curlRequest(requestUrl, requestBody, result, true);
int32_t errorCode = 0;
std::string errorInfo;
int32_t netbarLevel = 0;
if(retCode != 0)
{
CY_LOG(cyclone::L_ERROR, "NetbarInterface::onReceiveNetbarReportRequest curlRequest failed, retCode=%d", retCode);
char szTemp[256] = { 0 };
snprintf(szTemp, 256, "Curl request failed, retCode=%d", retCode);
errorInfo = szTemp;
}
else
{
rapidjson::Document document;
rapidjson::ParseResult prserResult = document.Parse(result.c_str());
if(document.HasMember("errcode") && document["errcode"].IsInt())
{
errorCode = document["errcode"].GetInt();
}
if(document.HasMember("errinfo") && document["errinfo"].IsString())
{
errorInfo = document["errinfo"].GetString();
}
if(document.HasMember("rids") && document["rids"].IsInt())
{
netbarLevel = document["rids"].GetInt();
}
}
////send netbar status reply
Game::NetbarStatusRes netbarResponse;
netbarResponse.set_error_code(errorCode);
netbarResponse.set_error_message(errorInfo);
netbarResponse.set_netbar_level(netbarLevel);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_NETBAR_RES, &netbarResponse, outputPacket);
client->connection->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
return true;
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
struct GameClient;
namespace Game
{
class NetbaraStatusReq;
};
class NetbarInterface
{
public:
static bool onReceiveNetbarReportRequest(GameClient* client, Game::NetbaraStatusReq* request);
};
+15
View File
@@ -0,0 +1,15 @@
#include "stdafx.h"
#include "GameServer.h"
#include "AceInterface.h"
int main(int argc, char* argv[])
{
//init ace interface
if (!AceInterface::initAceInterface())
{
return -1;
}
GameServer::getSingleton()->startAndJoin(2025);
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
#include "stdafx.h"
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <cy_core.h>
#include <cy_event.h>
#include <cy_network.h>
#include <ace_sdk_server_ticket.h>
#include <ace_sdk_server_light_feature.h>
#include <ace_sdk_server_anti_cheat_core.h>
#include <ace_sdk_server_text_check.h>
#include <ace_sdk_server.h>
#include <ace_sdk_account.h>
#include <sstream>
#include <string>
#include <iostream>