增加ACE安全测试工程
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
std::string buildReportRequestUrl();
|
||||
@@ -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
|
||||
)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
int32_t curlRequest(const std::string& url, const std::string& body, std::string& output, bool jsonBody);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct GameClient;
|
||||
namespace Game
|
||||
{
|
||||
class NetbaraStatusReq;
|
||||
};
|
||||
|
||||
class NetbarInterface
|
||||
{
|
||||
public:
|
||||
static bool onReceiveNetbarReportRequest(GameClient* client, Game::NetbaraStatusReq* request);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user