增加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
+123
View File
@@ -0,0 +1,123 @@
#include "stdafx.h"
#include "AceClientInterface.h"
#include <ace_sdk_client.h>
#include <ace_sdk_client_anti_cheat_core.h>
#include <ace_sdk_protocol_binding.h>
bool AceClientInterface::init()
{
//init ace sdk client protocol binding
m_protoBindingInitRetCode = AceProtocolBindingSDK::__ace_sdk_protocol_binding_init();
if (m_protoBindingInitRetCode != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk client proto binding, ret : %d\n", m_protoBindingInitRetCode);
//continue even failed...
}
printf(">>ACE SDK client proto binding init success.\n");
//init ace sdk
AceSdkResult ret = ace_sdk_client_init();
if(ret!= ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk client, ret : %d\n", ret);
return false;
}
return true;
}
void AceClientInterface::deinit()
{
AceSdkResult ret = ace_sdk_client_deinit();
}
bool AceClientInterface::onServerLoginReply(const char* accountID, uint32_t worldID,
const char* loginToken,
const char* lightFeatureName, uint32_t lightFeatureDataCRC,
const uint8_t* lightFeatureData, uint32_t lightFeatureDataLengh)
{
//call ace client login
AceSdkResult ret = ace_sdk_client_log_in(
accountID, ACE_SDK_ACCOUNT_TYPE_QQ,
worldID, loginToken
);
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_log_in, ret : %d\n", ret);
return false;
}
//call ace client light feature data
AceProtocolBindingSDK::g__ace_sdk_on_receive_signature(
lightFeatureName,
lightFeatureData,
lightFeatureDataLengh,
lightFeatureDataCRC
);
return true;
}
void AceClientInterface::onServerLogout()
{
AceSdkResult ret = ace_sdk_client_log_out();
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_log_out, ret : %d\n", ret);
}
}
void AceClientInterface::getClientTickPacket(uint8_t* out_buffer, uint32_t& out_len)
{
int64_t timeNow = cyclone::sys_api::utc_time_now();
if(timeNow - m_lastTickTime < 100ll*1000ll)
{
out_len = 0;
return;
}
m_lastTickTime = timeNow;
AceSdkClientPacket packet;
AceSdkResult ret = ace_sdk_client_get_packet(&packet);
if (ret == ACE_SDK_RESULT_OK)
{
printf(">>ACE ace_sdk_client_get_packet, len : %d\n", packet.len);
out_len = packet.len;
memcpy(out_buffer, packet.buffer, packet.len);
}
else
{
out_len = 0;
return;
}
}
void AceClientInterface::onServerTickPacket(const uint8_t* input_buffer, uint32_t input_len)
{
AceSdkResult ret = ace_sdk_client_on_packet_received(input_buffer, input_len);
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_on_packet_received, ret : %d\n", ret);
}
}
uint32_t AceClientInterface::getProtoBindingData(uint8_t* bindDataBuf, uint32_t buffSize)
{
AceProtocolBindingSDK::AceSdkAntiDataInfo bindingData;
memset(&bindingData, 0, sizeof(bindingData));
AceProtocolBindingSDK::g__ace_sdk_get_report_data3(&bindingData);
uint32_t dataLength = bindingData.anti_data_len_;
if (bindingData.anti_data_len_ <= buffSize)
{
memcpy(bindDataBuf, bindingData.anti_data_, bindingData.anti_data_len_);
}
else
{
printf(">>ACE fail to get proto binding data, buffer size too small!\n");
}
AceProtocolBindingSDK::g__ace_sdk_del_report_data(&bindingData);
return dataLength;
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
class AceClientInterface
{
public:
bool init();
void deinit();
uint32_t getPbRetCode() const {
return m_protoBindingInitRetCode;
}
bool onServerLoginReply(const char* accountID, uint32_t worldID,
const char* loginToken,
const char* lightFeatureName, uint32_t lightFeatureDataCRC,
const uint8_t* lightFeatureData, uint32_t lightFeatureDataLengh);
void onServerLogout();
void getClientTickPacket(uint8_t* out_buffer, uint32_t& out_len);
void onServerTickPacket(const uint8_t* input_buffer, uint32_t input_len);
uint32_t getProtoBindingData(uint8_t* bindDataBuf, uint32_t buffSize);
protected:
uint32_t m_protoBindingInitRetCode = 0;
int64_t m_lastTickTime = 0;
};
+85
View File
@@ -0,0 +1,85 @@
#include "stdafx.h"
#include "AceReportInterface.h"
#include "GameProto.h"
#include "GameProto.pb.h"
#include "GameClient.h"
struct ACEReportStruct
{
int32_t id;
Game::GameReportReq reportRequest;
ACEReport::CallbackFunction callback;
};
ACEReport::ACEReport()
{
m_nextID = 1;
}
ACEReport::~ACEReport()
{
}
void ACEReport::init(GameClient* client)
{
m_client = client;
}
ACEReportContext ACEReport::createReportContext(
const char* account,
int32_t worldID,
const char* reported_name,
const char* reported_roldid,
ACEReportScene scene,
ACEReportCategory category,
const ACEReportReasonArray& reasons,
DNFReportEntranceID entranceID
)
{
ACEReportStruct* ctx = new ACEReportStruct();
ctx->id = m_nextID++;
ctx->callback = nullptr;
ctx->reportRequest.set_ctx_id(ctx->id);
ctx->reportRequest.set_reported_account_id(account);
ctx->reportRequest.set_reported_world_id(worldID);
ctx->reportRequest.set_reported_name(reported_name);
ctx->reportRequest.set_reported_roleid(reported_roldid);
ctx->reportRequest.set_report_scene(static_cast<int32_t>(scene));
ctx->reportRequest.set_report_category(static_cast<int32_t>(category));
ctx->reportRequest.set_report_entrance(static_cast<int32_t>(entranceID));
for(ACEReportReason reason: reasons)
{
ctx->reportRequest.add_report_reason(static_cast<int32_t>(reason));
}
m_reportStructMap.insert(std::make_pair(ctx->id, ctx));
return ctx;
}
ACEReportStruct* ACEReport::getReport(ACEReportContext ctx)
{
if (ctx == nullptr) return nullptr;
ReportStructMap::iterator it = m_reportStructMap.find(ctx->id);
if (it == m_reportStructMap.end()) return nullptr;
return it->second;
}
bool ACEReport::uploadReport(ACEReportContext ctx, CallbackFunction callback)
{
ACEReportStruct* report = getReport(ctx);
if (report == nullptr) return false;
Game::GameReportReq& reportReq = report->reportRequest;
if(reportReq.report_reason_size() == 0)
{
return false;
}
report->callback = callback;
m_client->sendProtobufMessage(GAME_PROTO_REPORT_REQ, &reportReq);
return true;
}
+161
View File
@@ -0,0 +1,161 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <functional>
enum ACEReportScene
{
REPORT_SCENE_UGC = 1,
REPORT_SCENE_INFORMATION=2,
REPORT_SCENE_BATTLE=3,
REPORT_SCENE_ARTICLE=4,
REPORT_SCENE_COMMENT=5,
REPORT_SCENE_IMAGE=6,
REPORT_SCENE_ORGANIZE=7,
REPORT_SCENE_OTHER=8,
};
enum ACEReportCategory
{
REPORT_CATEGORY_ILLEGAL = 1,
REPORT_CATEGORY_BEHAVIOR = 2,
REPORT_CATEGORY_CHEAT = 3,
REPORT_CATEGORY_STUDIO = 4,
REPORT_CATEGORY_UGC = 7,
REPORT_CATEGORY_ORGANIZE = 8,
REPORT_CATEGORY_PERSONAL = 9,
};
enum ACEReportReason
{
//发布违规信息 REPORT_CATEGORY_ILLEGAL
REPORT_REASON_ILLEGAL_ABUSE = 101,
REPORT_REASON_ILLEGAL_ADVERTISEMENT = 102,
REPORT_REASON_ILLEGAL_PORN = 103,
REPORT_REASON_ILLEGAL_POLITICS = 104,
REPORT_REASON_ILLEGAL_HARASS = 105,
REPORT_REASON_ILLEGAL_VIOLENT = 106,
REPORT_REASON_ILLEGAL_GAMBLE = 107,
REPORT_REASON_ILLEGAL_CHEAT = 108,
REPORT_REASON_ILLEGAL_PRIVACY_LEAKS = 109,
REPORT_REASON_IULEGAL_INFRINGEMENT = 110,
REPORT_REASON_ILLEGAL_OTHER = 199,
//恶意游戏行为 REPORT_CATEGORY BEHAVIOR
REPORT_REASON_BEHAVIOR_FRIENDLYFIRE = 201,
REPORT_REASON_BEHAVIOR_FORM_CHEATER_TEAM = 202,
REPORT_REASON_BEHAVIOR_JOIN_CHEATER_TEAM = 203,
REPORT_REASON_BEHAVIOR_GUARDED_BY_CHEATER = 204,
REPORT_REASON_BEHAVIOR_EXPLOITING = 205,
REPORT_REASON_BEHAVIOR_AUTO_ROBOT = 206,
REPORT_REASON_BEHAVIOR_PASSIVE_PLAY = 207,
REPORT_REASON_BEHAVIOR_MALICIOUS_REPEAT = 208,
REPORT_REASON_BEHAVIOR_REFUSE_COOPERATE = 210,
REPORT_REASON_BEHAVIOR_OTHER=299,
//使用作弊工具REPORT_CATEGORY_CHEAT
REPORT_REASON_CHEAT_SEE_THROUTH = 301,
REPORT_REASON_CHEAT_AUTO_AIM = 302,
REPORT_REASON_CHEAT_NO_RECOIL = 303,
REPORT_REASON_CHEAT_SPEED_UP = 304,
REPORT_REASON_CHEAT_DAMAGE_RANGE = 305,
REPORT_REASON_CHEAT_WALL_THROUGH = 306,
REPORT_REASON_CHEAT_FLYING = 307,
REPORT_REASON_CHEAT_TELEPORT = 308,
REPORT_REASON_CHEAT_INSTANT_KILLING = 309,
REPORT_REASON_CHEAT_AUTO_FIRING = 310,
REPORT_REASON_CHEAT_MACRO = 311,
REPORT_REASON_CHEAT_INF_PROJECTILES = 312,
REPORT_REASON_CHEAT_SHOOTING_SPEED = 313,
REPORT_REASON_CHEAT_INF_BULLETS = 314,
REPORT_REASON_CHEAT_EXTERNAL_DEVICE = 315,
REPORT_REASON_CHEAT_REMOTE_PICKING = 316,
REPORT_REASON_CHEAT_REMOTE_KILLING = 317,
REPORT_REASON_CHEAT_OTHER=399,
//工作室行为REPORT_CATEGORY_STUDIO
REPORT_REASON_STUDIO_COMPETE_RESOURCE = 401,
REPORT_REASON_STUDIO_OFFLINE_DEAL = 402,
REPORT_REASON_STUDIO_ILLEGAL_BENEFITS = 403,
REPORT_REASON_STUDIO_TEAM = 404,
REPORT_REASON_STUDIO_MULTI_PLAVING = 405,
REPORT_REASON_STUDIO_OTHER=499,
//自定义内容违规REPORT_CATEGORY_UGC
REPORT_REASON_UGC_ILLEGAL_NAME = 701,
REPORT_REASON_UGC_ILLEGAL_BRIEF = 702,
REPORT_REASON_UGC_PORN_CONTENT = 703,
REPORT_REASON_UGC_POLITICAL_CONTENT = 704,
REPORT_REASON_UGC_ABUSIVE_CONTENT = 705,
REPORT_REASON_UGC_FRAUDULENT_CONTENT = 706,
REPORT_REASON_UGC_OTHER=799,
};
enum DNFReportEntranceID
{
DNF_REPORT_ENTRANCE_TEST = 0,
};
typedef std::vector<ACEReportReason> ACEReportReasonArray;
struct ACEReportStruct;
typedef ACEReportStruct* ACEReportContext;
class GameClient;
class ACEReport
{
public:
ACEReport();
~ACEReport();
void init(GameClient* client);
public:
ACEReportContext createReportContext(
const char* account,
int32_t worldID,
const char* reported_name,
const char* reported_roldid,
ACEReportScene scene,
ACEReportCategory category,
const ACEReportReasonArray& reasons,
DNFReportEntranceID entranceID = DNF_REPORT_ENTRANCE_TEST
);
//设置对局ID和时间,如果要举报和战局有关的信息,这两条必须同时设置
void setReportBattleID(ACEReportContext ctx, const char* battle_id, int32_t battle_time);
//设置举报的描述信息,这里举报者自己描述的文本信息
void setReportDesc(ACEReportContext ctx, const char* desc);
//设置举报内容,这里是指要举报的目标内容
void setContent(ACEReportContext ctx, const char* content);
//设置举报的公会、战队、房间等组织的ID和名称
void setGroupID(ACEReportContext ctx, const char* groupID, const char* groupName);
//设置举报者的头像URL,最大长度4096字寸,要求外网或者IDC个的多访问下载
void setReportedProfileUrl(ACEReportContext ctx, const char* profileURL);
//添加举报的图片URL,可以添加多个(最多12个),单条最人长度4096字节,要求外网或者IDC能够访问下载
void addReportedPictureURL(ACEReportContext ctx, const char* profileURL);
//添加举报的视频URL,可以添加多个(最务1个),单条最人长度4096字节,要求外网或者IDC能够访问下载
void addReportedVideoURL(ACEReportContext ctx, const char* profileuRL);
//添加举报的语音URL,可以添加多个(最多12个),单条最大长度409
void addReportedVoiceURL(ACEReportContext tx, const char* profileURL);
//添加其他需要添加的ID,例如文章T,房间T0等,每种类型都可以添加多个, addReportcontent(ctx, "room id",“123456");
void addReportIDContent(ACEReportContext ctx, const char* idTyne, const char* idContent);
//上报结果回调
typedef std::function<void(ACEReportContext ctx, int32_t result, const char* error_message)> CallbackFunction;
bool uploadReport(ACEReportContext ctx, CallbackFunction callback);
private:
void onReportResult(int32_t reportID, uint32_t result, const char* errorMessage);
ACEReportStruct* getReport(ACEReportContext ctx);
private:
GameClient* m_client = nullptr;
typedef std::map<int32_t, ACEReportContext> ReportStructMap;
ReportStructMap m_reportStructMap;
int32_t m_nextID = 0;
};
+71
View File
@@ -0,0 +1,71 @@
set(ACLIENT_SOURCE_FILES
stdafx.h
main.cpp
MainDialog.h
MainDialog.cpp
GameClient.h
GameClient.cpp
AceClientInterface.h
AceClientInterface.cpp
AceReportInterface.h
AceReportInterface.cpp
NetbarInterface.h
NetbarInterface.cpp
)
set(ACLIENT_RC_FILES
aClient.rc
)
source_group("Resource Files" FILES ${ACLIENT_RC_FILES})
set(ACLIENT_PRECOMPILE_FILE
stdafx.cpp
)
foreach(filename ${ACLIENT_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(${ACLIENT_PRECOMPILE_FILE}
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
add_executable(aClient WIN32
${ACLIENT_SOURCE_FILES}
${ACLIENT_RC_FILES}
${ACLIENT_PRECOMPILE_FILE}
)
target_include_directories(aClient
PRIVATE
${ACE_CLIENT_DIR}/include
${WTL_DIR}/include
${CYCLONE_DIR}/include
${GAME_PROTO_DIR}
)
target_link_directories(aClient
PRIVATE
${CYCLONE_DIR}/lib
)
target_link_libraries(aClient
PRIVATE
aGameProto
cyclone.lib
ws2_32.lib
shlwapi.lib
winmm.lib
)
+285
View File
@@ -0,0 +1,285 @@
#include "stdafx.h"
#include "GameClient.h"
#include <strsafe.h>
const char* GameClient::s_default_account_id = "979591";
const uint32_t GameClient::s_default_world_id = 160;
GameClient::GameClient()
: m_status(STATUS_DISCONNECTED)
, m_client(nullptr)
, m_looper(nullptr)
{
m_clientTickBuffer = new uint8_t[2048];
}
GameClient::~GameClient()
{
m_client = nullptr;
cyclone::Looper::destroy_looper(m_looper);
m_looper = nullptr;
delete[] m_clientTickBuffer;
m_clientTickBuffer = nullptr;
}
bool GameClient::init()
{
assert(m_status == STATUS_DISCONNECTED);
m_reportInterface.init(this);
m_clientNetbarInterface.init(this);
return m_aceClientInterface.init();
}
void GameClient::deinit()
{
m_aceClientInterface.deinit();
}
void GameClient::connectToGameServer(const std::string& server_ip, uint16_t server_port)
{
assert(m_status == STATUS_DISCONNECTED);
m_server_ip = server_ip;
m_server_port = server_port;
CY_LOG(cyclone::L_DEBUG, "connect to %s:%d...", server_ip.c_str(), server_port);
m_looper = cyclone::Looper::create_looper();
m_client = std::make_shared<cyclone::TcpClient>(m_looper, nullptr);
m_client->m_listener.on_connected = std::bind(&GameClient::onConnected, this, std::placeholders::_1, std::placeholders::_3);
m_client->m_listener.on_message = std::bind(&GameClient::onMessage, this, std::placeholders::_2);
m_client->m_listener.on_close = std::bind(&GameClient::onClose, this);
m_client->connect(cyclone::Address(m_server_ip.c_str(), m_server_port));
m_status = STATUS_CONNECTING;
}
void GameClient::disconnectFromGameServer()
{
if (m_client)
{
m_client->disconnect();
m_status = STATUS_LOGGING_OUT;
}
}
void GameClient::tick()
{
if (m_looper)
{
m_looper->step();
}
if (m_status == STATUS_LOGGED_IN)
{
uint32_t packetLen = 0;
m_aceClientInterface.getClientTickPacket(m_clientTickBuffer, packetLen);
if (packetLen > 0)
{
Game::ClientTickPacket clientTickPacket;
clientTickPacket.mutable_client_packet()->assign((const char*)m_clientTickBuffer, packetLen);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_CLIENT_PACKET, &clientTickPacket, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
sendHeartBeat();
}
m_clientNetbarInterface.tick();
}
uint32_t GameClient::onConnected(cyclone::TcpClientPtr client, bool success)
{
assert(m_status == STATUS_CONNECTING);
CY_LOG(cyclone::L_DEBUG, "connect to %s:%d %s.",
client->get_server_address().get_ip(), client->get_server_address().get_port(),
success ? "OK" : "FAILED");
if (success)
{
m_status = STATUS_CONNECTED;
sendLoginRequest(s_default_account_id, s_default_world_id);
return 0;
}
else
{
return 1000 * 5;
}
}
void GameClient::sendLoginRequest(const char* accountID, int32_t worldID)
{
assert(m_status == STATUS_CONNECTED);
Game::LoginRequest loginRequest;
loginRequest.set_accound_id(accountID);
loginRequest.set_world_id(worldID);
loginRequest.set_pb_retcode(m_aceClientInterface.getPbRetCode());
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_LOGIN_REQUEST, &loginRequest, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
m_status = STATUS_LOGGING_IN;
}
void GameClient::onMessage(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_REPLY:
{
Game::LoginReply* loginReply = dynamic_cast<Game::LoginReply*>(message);
onServerLoginReply(conn, loginReply);
}
break;
case GAME_PROTO_SERVER_PACKET:
{
Game::ServerTickPacket* serverTickPacket = dynamic_cast<Game::ServerTickPacket*>(message);
onServerTickPacket(conn, serverTickPacket);
}
break;
case GAME_PROTO_UGC_REPLY:
{
Game::UGCReply* ugcReply = dynamic_cast<Game::UGCReply*>(message);
onServerUGCReply(conn, ugcReply);
}
break;
case GAME_PROTO_NETBAR_RES:
{
Game::NetbarStatusRes* netbarResponse = dynamic_cast<Game::NetbarStatusRes*>(message);
onServerNetbarResponse(conn, netbarResponse);
}
break;
}
}
}
void GameClient::onServerLoginReply(cyclone::TcpConnectionPtr conn, Game::LoginReply* reply)
{
assert(m_status == STATUS_LOGGING_IN);
m_aceClientInterface.onServerLoginReply(s_default_account_id, s_default_world_id,
reply->ace_token().c_str(),
reply->light_feature().name().c_str(),
reply->light_feature().data_crc(),
(const uint8_t*)reply->light_feature().data().data(),
(uint32_t)reply->light_feature().data().size()
);
m_status = STATUS_LOGGED_IN;
}
void GameClient::onServerTickPacket(cyclone::TcpConnectionPtr conn, Game::ServerTickPacket* reply)
{
assert(m_status == STATUS_LOGGED_IN || m_status==STATUS_LOGGING_IN);
m_aceClientInterface.onServerTickPacket(
(const uint8_t*)(reply->server_packet().data()),
(uint32_t)(reply->server_packet().size())
);
}
void GameClient::sendHeartBeat()
{
assert(m_status == STATUS_LOGGED_IN);
uint64_t timeNow = cyclone::sys_api::utc_time_now();
if(timeNow-m_lastHeartBeatTime < 60 * 1000ll*1000ll)
{
return;
}
m_lastHeartBeatTime = timeNow;
uint8_t bindBuffer[1024];
uint32_t bindDataLength = m_aceClientInterface.getProtoBindingData(bindBuffer, sizeof(bindBuffer));
Game::HeartBeat heartBeat;
heartBeat.set_timestamp((int32_t)timeGetTime());
heartBeat.mutable_pb_data()->assign((const char*)bindBuffer, bindDataLength);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_HEART_BEAT, &heartBeat, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onServerUGCReply(cyclone::TcpConnectionPtr conn, Game::UGCReply* reply)
{
assert(m_status == STATUS_LOGGED_IN);
wchar_t wszTemp[2048];
UINT btn = MB_OK;
if (reply->result() == 0)
{
StringCchPrintfW(wszTemp, sizeof(wszTemp)/sizeof(wszTemp[0]),
L"UGC Reply: ContextID=%d, ErrorCode=%d, Result=%d",
reply->ugc_ctx_id(),
reply->error_code(),
reply->result()
);
}
else
{
btn = MB_OK | MB_ICONERROR;
wchar_t wszFiltedContent[1024];
::MultiByteToWideChar(CP_UTF8, 0, reply->filted_content().c_str(), -1,
wszFiltedContent, sizeof(wszFiltedContent) / sizeof(wszFiltedContent[0]));
StringCchPrintfW(wszTemp, sizeof(wszTemp)/sizeof(wszTemp[0]),
L"UGC Reply: ContextID=%d, ErrorCode=%d, Result=%d, FiltedText='%s'",
reply->ugc_ctx_id(),
reply->error_code(),
reply->result(),
wszFiltedContent
);
}
MessageBoxW(NULL, wszTemp, L"UGC Reply", btn);
}
void GameClient::sendUGCContent(int32_t ugcSceneID, const char* content)
{
assert(m_status == STATUS_LOGGED_IN);
Game::UGCRequest ugcRequest;
ugcRequest.set_ugc_ctx_id(m_nextUGCContextID++);
ugcRequest.set_ugc_scene_id(ugcSceneID);
ugcRequest.set_ugc_content(content);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_UGC_REQUEST, &ugcRequest, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onClose(void)
{
m_aceClientInterface.onServerLogout();
m_status = STATUS_LOGGED_OUT;
}
void GameClient::sendProtobufMessage(uint16_t id, ::google::protobuf::Message* message)
{
cyclone::Packet packet;
serializeProtoMessage(id, message, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onServerNetbarResponse(cyclone::TcpConnectionPtr conn, Game::NetbarStatusRes* reply)
{
m_clientNetbarInterface.onReceiveNetbarReportRequest(reply);
}
+81
View File
@@ -0,0 +1,81 @@
#pragma once
#include "GameProto.h"
#include "GameProto.pb.h"
#include "AceClientInterface.h"
#include "AceReportInterface.h"
#include "NetbarInterface.h"
class GameClient
{
public:
enum Status
{
STATUS_DISCONNECTED = 0,
//call connectToGameServer...
STATUS_CONNECTING,
//onConnected
STATUS_CONNECTED,
//call sendLoginRequest...
STATUS_LOGGING_IN,
//onServerLoginReply
STATUS_LOGGED_IN,
//call sendLogoutRequest...
STATUS_LOGGING_OUT,
//socket closed
STATUS_LOGGED_OUT,
STATUS_FAILED,
};
const static char* s_default_account_id;
const static uint32_t s_default_world_id;
public:
bool init();
void deinit();
void connectToGameServer(const std::string& server_ip, uint16_t server_port);
void disconnectFromGameServer();
void sendProtobufMessage(uint16_t id, ::google::protobuf::Message* message);
void sendUGCContent(int32_t ugcSceneID, const char* content);
ACEReport* getAceReportInterface(void) { return &m_reportInterface; }
TencentNetbarInterface* getNetbarInterface(void) { return &m_clientNetbarInterface; }
void tick();
cyclone::TcpClientPtr get_client(void) { return m_client; }
protected:
uint32_t onConnected(cyclone::TcpClientPtr client, bool success);
void onMessage(cyclone::TcpConnectionPtr conn);
void onClose(void);
protected:
void sendLoginRequest(const char* accountID, int32_t worldID);
void onServerLoginReply(cyclone::TcpConnectionPtr conn, Game::LoginReply* reply);
void onServerTickPacket(cyclone::TcpConnectionPtr conn, Game::ServerTickPacket* reply);
void onServerUGCReply(cyclone::TcpConnectionPtr conn, Game::UGCReply* reply);
void onServerNetbarResponse(cyclone::TcpConnectionPtr conn, Game::NetbarStatusRes* reply);
void sendHeartBeat();
private:
Status m_status = STATUS_DISCONNECTED;
cyclone::TcpClientPtr m_client;
cyclone::Looper* m_looper;
std::string m_server_ip;
uint16_t m_server_port;
uint64_t m_lastHeartBeatTime = 0;
AceClientInterface m_aceClientInterface;
uint8_t* m_clientTickBuffer = nullptr;
ACEReport m_reportInterface;
int32_t m_nextUGCContextID = 1;
TencentNetbarInterface m_clientNetbarInterface;
public:
GameClient();
~GameClient();
};
+170
View File
@@ -0,0 +1,170 @@
#include "stdafx.h"
#include "MainDialog.h"
#include "AceReportInterface.h"
#include <tlhelp32.h>
#include <psapi.h>
LRESULT CMainDialog::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CenterWindow(GetParent());
if(m_gameClient.init()==false)
{
MessageBoxA("Failed to init Ace SDK client interface!", "Error", MB_OK|MB_ICONERROR);
CloseDialog(IDCANCEL);
return FALSE;
}
return TRUE;
}
LRESULT CMainDialog::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CloseDialog(wID);
return 0;
}
LRESULT CMainDialog::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CloseDialog(wID);
return 0;
}
void CMainDialog::CloseDialog(int nVal)
{
m_gameClient.deinit();
DestroyWindow();
::PostQuitMessage(nVal);
}
LRESULT CMainDialog::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(wParam==101)
{
m_gameClient.tick();
}
return 0;
}
LRESULT CMainDialog::OnConnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
m_gameClient.connectToGameServer("127.0.0.1", 2025);
this->SetTimer(101, 100, NULL);
return 0;
}
LRESULT CMainDialog::OnDisconnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
this->KillTimer(101);
m_gameClient.disconnectFromGameServer();
return 0;
}
LRESULT CMainDialog::OnSendUGCContent(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// To be implemented
wchar_t wszUgcContent[2048];
::GetDlgItemTextW(m_hWnd, IDC_EDIT_UGC_CONTENT, wszUgcContent, sizeof(wszUgcContent)/sizeof(wchar_t));
char szUtf8UgcContent[2048] = { 0 };
::WideCharToMultiByte(CP_UTF8, 0, wszUgcContent, -1, szUtf8UgcContent, sizeof(szUtf8UgcContent), NULL, NULL);
m_gameClient.sendUGCContent(101, szUtf8UgcContent);
return 0;
}
LRESULT CMainDialog::OnSendReport(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
ACEReport* reportInterface = m_gameClient.getAceReportInterface();
auto ctx = reportInterface->createReportContext(
"reporter_account",
1,
"reported_name",
"reported_roleid",
ACEReportScene::REPORT_SCENE_UGC,
ACEReportCategory::REPORT_CATEGORY_BEHAVIOR,
ACEReportReasonArray{ ACEReportReason::REPORT_REASON_ILLEGAL_ABUSE, ACEReportReason::REPORT_REASON_ILLEGAL_ADVERTISEMENT },
DNF_REPORT_ENTRANCE_TEST
);
reportInterface->uploadReport(ctx, [this](ACEReportContext ctx, int32_t result, const char* error_message) {
if (result == 0) {
::MessageBoxA(m_hWnd, "Report uploaded successfully!", "Info", MB_OK | MB_ICONINFORMATION);
}
else {
::MessageBoxA(m_hWnd, error_message, "Error", MB_OK | MB_ICONERROR);
}
}
);
return 0;
}
LRESULT CMainDialog::OnNetbarClientLoad(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
TencentNetbarInterface* netbarInterface = m_gameClient.getNetbarInterface();
netbarInterface->beginRequestNetbarStatus(
[this](TencentNetbarInterface::RequestStatus status)
{
// Handle the request status update here
switch (status) {
case TencentNetbarInterface::RS_RequestDone:
::MessageBoxA(m_hWnd, "Netbar status request completed successfully!", "Info", MB_OK | MB_ICONINFORMATION);
break;
case TencentNetbarInterface::RS_ReqestFailed:
::MessageBoxA(m_hWnd, "Netbar status request failed!", "Error", MB_OK | MB_ICONERROR);
break;
default:
// Other statuses can be handled as needed
break;
}
});
return 0;
}
bool IsProcessRunning(DWORD pid)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
return false;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
bool isRunning = false;
if (Process32First(hSnapshot, &pe)) {
do {
if (pe.th32ProcessID == pid) {
isRunning = true;
break;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return isRunning;
}
LRESULT CMainDialog::OnCheckMainPlayProcess(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
wchar_t wszPid[64];
::GetDlgItemTextW(m_hWnd, IDC_EDIT_MAINPLAY_PID, wszPid, sizeof(wszPid)/sizeof(wchar_t));
DWORD pid = _wtoi(wszPid);
if (pid == 0)
{
::MessageBoxA(m_hWnd, "Invalid PID!", "Error", MB_OK | MB_ICONERROR);
return 0;
}
bool isRunning = IsProcessRunning(pid);
if (isRunning)
{
::MessageBoxA(m_hWnd, "MainPlay process is running.", "Info", MB_OK | MB_ICONINFORMATION);
}
else
{
::MessageBoxA(m_hWnd, "MainPlay process is not running.", "Info", MB_OK | MB_ICONSTOP);
}
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include "resource.h"
#include "GameClient.h"
class CMainDialog : public CDialogImpl<CMainDialog>
{
public:
enum { IDD = IDD_DIALOG_MAIN };
BEGIN_MSG_MAP(CMainDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
COMMAND_ID_HANDLER(IDC_BUTTON_CONNECT_GAME_SERVER, OnConnectToGameServer)
COMMAND_ID_HANDLER(IDC_BUTTON_DISCONNECT_GAME_SERVER, OnDisconnectToGameServer)
COMMAND_ID_HANDLER(IDC_BUTTON_UGC_SEND, OnSendUGCContent)
COMMAND_ID_HANDLER(IDC_BUTTON_REPORT_SEND, OnSendReport)
COMMAND_ID_HANDLER(IDC_BUTTON_NETBAR_CLIENTLOAD, OnNetbarClientLoad)
COMMAND_ID_HANDLER(IDC_BUTTON_CHECK_MAINPLAY_PROCESS, OnCheckMainPlayProcess)
END_MSG_MAP()
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
return ::IsDialogMessage(m_hWnd, pMsg);
}
private:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnConnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnDisconnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSendUGCContent(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSendReport(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnNetbarClientLoad(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCheckMainPlayProcess(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
void CloseDialog(int nVal);
protected:
GameClient m_gameClient;
};
+177
View File
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "NetbarInterface.h"
#include "iigw_api_client.h"
#include "GameProto.h"
#include "GameProto.pb.h"
#include "GameClient.h"
TencentNetbarInterface::TencentNetbarInterface()
{
m_requestStatus.store(RS_NotRequest);
m_workThread = NULL;
m_netbarStatus = NS_Unknown;
m_clientErrorCode = 0;
m_serverErrorCode = 0;
m_serverErrorMessage.clear();
m_netbarLevel = -1;
m_clientNetbarReq = new Game::NetbaraStatusReq();
}
TencentNetbarInterface::~TencentNetbarInterface()
{
delete m_clientNetbarReq;
m_clientNetbarReq = nullptr;
}
void TencentNetbarInterface::init(GameClient* client)
{
m_client = client;
}
void TencentNetbarInterface::tick()
{
switch (m_requestStatus)
{
case RequestStatus::RS_ClientRequest_Done:
{
m_client->sendProtobufMessage(GameProto::GAME_PROTO_NETBAR_REQ, m_clientNetbarReq);
m_requestStatus = RequestStatus::RS_ServerRequesting;
}
break;
case RequestStatus::RS_ClientRequest_Failed:
{
m_requestStatus = RequestStatus::RS_ReqestFailed;
}
break;
}
}
bool TencentNetbarInterface::beginRequestNetbarStatus(RequestCallback callback)
{
if(m_requestStatus==RequestStatus::RS_RequestDone || m_requestStatus==RequestStatus::RS_ReqestFailed)
{
//already done
if(callback)
{
callback(m_requestStatus.load());
}
return true;
}
if(m_requestStatus != RequestStatus::RS_NotRequest)
{
//already requesting
return false;
}
m_requestStatus = RequestStatus::RS_ClientRequesting;
unsigned int threadID = 0;
m_workThread = (HANDLE)_beginthreadex(NULL, 0, TencentNetbarInterface::_workingThreadEntry, this, 0,&threadID);
if(m_workThread == NULL)
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
return false;
}
m_requestCallback = callback;
return true;
}
unsigned int TencentNetbarInterface::_workingThreadEntry(void* param)
{
TencentNetbarInterface* pThis = (TencentNetbarInterface*)param;
if(pThis)
{
pThis->workThreadEntry();
}
::CloseHandle(pThis->m_workThread);
pThis->m_workThread = NULL;
return 0;
}
bool TencentNetbarInterface::workThreadEntry()
{
HMODULE hNetbarDllHandle = NULL;
bool isSuccess = false;
do {
hNetbarDllHandle = ::LoadLibraryW(L"iigw_client_api.dll");
if (hNetbarDllHandle == NULL)
{
m_clientErrorCode = GetLastError();
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
//create interface
iepm_qqwb::IQQNetbarIIGWPlugin *pProxy = iepm_qqwb::CreateQQNetbarIIGWPlugin(hNetbarDllHandle);
if(pProxy == nullptr)
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
//call client interfae
int ret = pProxy->IsNetbarMachine(TENCENT_NETBAR_DNF_CLIENT_GAME_ID, GameClient::s_default_account_id, iepm_qqwb::at_qq);
bool isNetbar = (ret == IIGW_MSG_STATUS_NETBAR_PC);
iepm_qqwb::NetbarLv netbarlv = {0};
memset(&netbarlv, 0, sizeof(netbarlv));
m_clientErrorCode = pProxy->ReqNetbarLv2(
TENCENT_NETBAR_DNF_CLIENT_GAME_ID,
GameClient::s_default_world_id,
GameClient::s_default_account_id,
iepm_qqwb::at_qq,
nullptr,
0,
&netbarlv,
5000
);
if (m_clientErrorCode != 0 || netbarlv.tokenLen<=0 )
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
m_clientNetbarReq->Clear();
m_clientNetbarReq->set_is_netbar_machine(isNetbar);
m_clientNetbarReq->set_token((const char*)netbarlv.tokenBuff, (size_t)netbarlv.tokenLen);
m_clientNetbarReq->set_macs(netbarlv.macs);
m_requestStatus = RequestStatus::RS_ClientRequest_Done;
isSuccess = true;
} while (false);
if(hNetbarDllHandle)
{
::FreeLibrary(hNetbarDllHandle);
hNetbarDllHandle = NULL;
}
return isSuccess;
}
void TencentNetbarInterface::onReceiveNetbarReportRequest(Game::NetbarStatusRes* response)
{
m_netbarLevel = response->netbar_level();
m_serverErrorCode = response->error_code();
m_serverErrorMessage = response->error_message();
if (m_serverErrorCode == 0)
{
m_serverErrorCode = NetbarStatus::NS_Netbar;
}
else
{
m_serverErrorCode = NetbarStatus::NS_ServerFailed;
}
m_requestStatus = RequestStatus::RS_RequestDone;
if (m_requestCallback)
{
m_requestCallback(m_requestStatus);
}
}
+69
View File
@@ -0,0 +1,69 @@
#pragma once
#include <functional>
namespace Game
{
class NetbaraStatusReq;
class NetbarStatusRes;
};
class GameClient;
class TencentNetbarInterface
{
public:
TencentNetbarInterface();
~TencentNetbarInterface();
public:
enum RequestStatus
{
RS_NotRequest=0,
RS_ClientRequesting,
RS_ClientRequest_Done,
RS_ClientRequest_Failed,
RS_ServerRequesting,
RS_ReqestFailed,
RS_RequestDone,
};
enum NetbarStatus
{
NS_Unknown = 0,
NS_Netbar,
NS_ClientFailed,
NS_ServerFailed,
};
typedef std::function<void(RequestStatus)> RequestCallback;
bool beginRequestNetbarStatus(RequestCallback callback);
void onReceiveNetbarReportRequest(Game::NetbarStatusRes* response);
void init(GameClient* client);
void tick();
private:
static unsigned int _workingThreadEntry(void* param);
bool workThreadEntry();
private:
enum { TENCENT_NETBAR_DNF_CLIENT_GAME_ID = 20 };
private:
GameClient* m_client = nullptr;
std::atomic<RequestStatus> m_requestStatus;
HANDLE m_workThread;
NetbarStatus m_netbarStatus;
int32_t m_clientErrorCode;
int32_t m_serverErrorCode;
std::string m_serverErrorMessage;
int32_t m_netbarLevel;
RequestCallback m_requestCallback;
Game::NetbaraStatusReq* m_clientNetbarReq = nullptr;
};
Binary file not shown.
Binary file not shown.
+580
View File
@@ -0,0 +1,580 @@
/************************************************************
Copyright (C), 2008-2018, Tencent Tech. Co., Ltd.
FileName: iigw_api_client.h
Author: cooperli Version : 1.0 Date: 2008-03-25
Description: 信息网关API头文件
History:
<author> <time> <version > <desc>
cooperli 2008-03-27 1.0 build
***********************************************************/
#ifndef _ITC_CLIENT_H_
#define _ITC_CLIENT_H_
// VC动态库
#ifdef iigw_client_api_EXPORTS
#define IIGW_DLL_EXPORT __declspec(dllexport)
#else
#define IIGW_DLL_EXPORT
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#define SVR_PROT 5692 // IIGW SERVER 的端口
#define INFOGW_MAX_MSG_LEN 2048 // 最大消息长度为512 BYTE
#define INFOGW_MAX_TO_GAME_SVR_STR_LEN 256 // 最大送到GAME SERVER的串长度为256 BYTE
#define INFOGW_MIN_ERR_BUF_LEN 256 // 最小消息长度为256 BYTE
#define INFOGW_OPEN_ID_LEN 64
// 消息类型定义INFOGW_MSG_TYPE
enum
{
INFOGW_MSG_TYPE_REQ = 1, // 请求消息
INFOGW_MSG_TYPE_ACK = 2, // 回应消息
INFOGW_MSG_TYPE_BOTTOM // 底部,无效值
};
// 消息错误类型定义
enum IIGW_MSG_STATUS
{
IIGW_MSG_STATUS_OK = 0, // 正确消息
IIGW_MSG_STATUS_UNKNOWN_VER_ERR = 1, // MAGIC KEY出错
IIGW_MSG_STATUS_MSG_TYPE_ERR = 2, // 消息类型错误
IIGW_MSG_STATUS_OPT_ERR = 3, // 业务类型出错
IIGW_MSG_STATUS_NO_RETURN = 4, // 没有收到对端的回应
IIGW_MSG_STATUS_CRYPT_LEN_ERR = 5, // TO GAME SVR的消息长度出错
IIGW_MSG_STATUS_MSG_LEN_ERR = 6, // 消息长度出错
IIGW_MSG_STATUS_BUF_LEN_ERR = 7, // 输入BUFFFER长度太少
IIGW_MSG_STATUS_RD_CFG_ERR = 8, // 读配置出错
IIGW_MSG_STATUS_CONNECT_ERR = 9, // 连接出错
IIGW_MSG_STATUS_SENT_MSG_ERR = 10, // 发送消息出错
IIGW_MSG_STATUS_DNS_RESOLVE_ERR = 30, // DNS解释出错,不能把域名解释成IP
IIGW_MSG_STATUS_PARSE_RSP_ERR = 11, // 解析返回包出错
IIGW_MSG_STATUS_PARA_ERR = -1, // 参数出错
// 服务端发现的错误lix
IIGW_MSG_STATUS_UNKNOWN_VER_ERR_R = 101, // MAGIC KEY出错
IIGW_MSG_STATUS_MSG_TYPE_ERR_R = 102, // 消息类型错误
IIGW_MSG_STATUS_OPT_ERR_R = 103, // 业务类型出错
IIGW_MSG_STATUS_HEARD_LEN_ERR_R = 104, // 消息协议头长度出错
IIGW_MSG_STATUS_OPT_LEN_ERR = 105, // 业务信息长度出错
IIGW_MSG_STATUS_OPT_COUNT_ERR = 106, // 业务信息长度出错
IIGW_MSG_STATUS_NET_ERR_R = 107, // 网络通讯出错
IIGW_MSG_STATUS_RES_LIMIT_R = 110, // 资源受限
IIGW_MSG_STATUS_BJ_NEW_USER = 200, // CF !!! 北京新用户,禁止登陆
IIGW_MSG_STATUS_NETBAR_PC = 256, // 是网吧机器
IIGW_MSG_STATUS_NOT_IN_NETBAR = 300, // 非网吧环境
IIGW_MSG_STATUS_NOT_A_CHINESE_OS = 301, // 非中文操作系统
IIGW_MSG_STATUS_VMP_CRC_ERROR = 400,
IIGW_MSG_STATUS_VMP_DEBUG_ERROR = 401,
IIGW_MSG_STATUS_OS_SEH_ERROR = 402,
IIGW_MSG_STATUS_CPP_SEH_ERROR = 403,
IIGW_MSG_STATUS_UNKNOW_ERROR = 404,
IIGW_MSG_STATUS_BOTTOM // 底部,无效值
};
// 业务ID定义 INFOGW_OPERATION_ID
enum
{
INFOGW_OPERATION_CF = 10, // CF查询网吧等级业务ID
INFOGW_OPERATION_DNF = 20, // DNF查询网吧等级业务ID
INFOGW_OPERATION_ID_BOTTOM // 底部,无效值
};
typedef unsigned int UINT;
typedef struct infoGWReqMsgHeader_st
{
UINT uiVersion; // 版本号,认证头
UINT uiMsgType; // 消息类型,可以表示客户端消息,服务后台消息等
UINT uiSeqNo; //
UINT uiTime; // 本地时间戳
UINT uiOperationId; // 查询的业务类型 .参看 enum INFOGW_OPERATION_ID
UINT uiStatus; // 当为接收的信息时有效
UINT uiMsgBodyLen; // 业务消息长度
} INFOGW_INTF_CLIENT_MSG_HEADER;
typedef struct infoGWReqMsg_st
{
INFOGW_INTF_CLIENT_MSG_HEADER stMsgHd;
char szMsgBody[INFOGW_MAX_MSG_LEN]; // 业务相关消息体
} INFOGW_INTF_CLIENT_MSG;
typedef struct infoGWReqNetbarLv_st
{
unsigned int uiUni;
unsigned int ulNetbarIP;
} INFOGW_REQ_NETBAR_LV;
typedef struct infoGWReqNetbarLvOpenid_st
{
unsigned int uiType;
char open_id[INFOGW_OPEN_ID_LEN];
unsigned int ulNetbarIP;
} INFOGW_REQ_NETBAR_LV_OPENID;
// TO GAME SERVER 的的加密串的明文结构
typedef struct IIGWNetbar_st
{
unsigned int ulInfoGWTimeStamp; // 时间截
unsigned int uiUni; // QQ号码
unsigned int ulNetbarIP; // 网吧ip
unsigned char ucNetbarLv; // 网吧等级
//unsigned int ulNetbarLv; // 网吧等级v2
unsigned char ucCreditRank; // 荣誉等级
unsigned char ucTeamRank; // 战队等级
unsigned char ucVIP; // 会员VIP
unsigned char ucCampaign; // 活动
unsigned char ucReserve[15]; // 备用
} INFOGW_NETBAR;
//==============================================================
#define IIGE_MAX_OP_COUNT 15 // 批量查询每次查询的最大业务数量
#define IIGW_CRYPT_BUF_LEN 128 // 批量查询返回加密串缓存区长度
typedef struct IIGW_OPERATIONS
{
int count;
unsigned int uiOperationId[IIGE_MAX_OP_COUNT];
} INFOGW_OPIDS;
typedef struct IIGW_NETBAR_INFO_
{
unsigned int uiOperationId;
int iStatus; // 返回状态:1-正常,0-非正常
unsigned int ucCryptBufLen;
unsigned char szCryptBuf[IIGW_CRYPT_BUF_LEN];
} IIGW_NETBAR_INFO;
typedef struct IIGW_NETBAR_INFO_BATCH_ {
int count;
IIGW_NETBAR_INFO stNetbarInfo[IIGE_MAX_OP_COUNT];
} IIGW_NETBAR_INFO_BATCH;
//==============================================================
/*************************************************
Function: INFOGW_api_req_netbar_lv
Description: 请求查询网吧等级,并等待回应的加密包
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
anselyang 2008-03-25 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen // error buffer size
);
/*************************************************
Function: INFOGW_api_req_netbar_lv_ext
Description: 请求查询网吧等级,并等待回应的加密包 CF活动是否弹出
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
char *op_buf, -- 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len -- 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
anselyang 2009-07-14 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv_ext
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen, // error buffer size
char *op_buf, // 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len // 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
);
/*************************************************
Function: INFOGW_api_req_platinum_netbar_lv
Description: 请求查询铂金网吧等级
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码,没有可填0
Output:
int &level, -- 铂金网吧等级
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2016-11-29 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_platinum_netbar_lv
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
int &level // 铂金网吧等级
);
/*************************************************
Function: INFOGW_api_req_platinum_netbar_lv_ext
Description: 请求查询铂金网吧等级
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码,没有可填0
unsigned int zone_id, -- 游戏大区,没有可填0
Output:
int &level, -- 铂金网吧等级
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2016-11-29 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_platinum_netbar_lv_ext
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
unsigned int zone_id, //游戏大区
int &level // 铂金网吧等级
);
/*************************************************
Function: INFOGW_api_req_netbar_lv_ext_with_zone_id
Description: 请求查询网吧等级,并等待回应的加密包 CF活动是否弹出
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
unsigned long zone_id, -- 大区ID
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
char *op_buf, -- 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len -- 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2017-01-19 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv_ext_with_zone_id
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
unsigned int zone_id, // 游戏大区.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen, // error buffer size
char *op_buf, // 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len, // 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
const int time_out=5000 // 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
);
//////////////////////////////////////////////////////////////////////////
/** QQ网吧插件接口*/
namespace iepm_qqwb{
enum account_type{
at_qq, //0
at_wechart, // 1
at_facebook, //2
at_email, // 3
at_steam, //4
at_gopenid,//5
at_topenid, // 6 手机号对应的openid
};
/**
* @brief NetbarLv QQ网吧签名结构体
* @param tokenBuf 用来存放QQ网吧签名的buff
* @param tokenLen QQ网吧签名的长度
* @param ip PC的ip地址
* @param macs PC的mac地址列表
* @param macSize PC的mac地址个数
*/
struct NetbarLv {
unsigned char tokenBuff[1024];
int tokenLen;
char ip[32];
char macs[128];
int macSize;
};
/**
* @brief notify_req_netbarlv_result 回调函数,返回获取签名的结果和内容
* @param game_id 游戏ID
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id
* @param ret_code 获取签名的结果,返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
* @param netbarlv NetbarLv信息,当ret_code=0时返回
*/
typedef void(*notify_req_netbarlv_result)(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
int ret_code,
NetbarLv *netbarlv
);
struct IQQNetbarIIGWPlugin{
/**
* @brief 获取网吧机器信息
* @param game_id 游戏ID,由网吧项目组这边分配
* @param uin 用户登录游戏的QQ号
* @param zone_id 登录游戏的大区号
* @param cryptInfoBuf 用来存放网吧机器信息的加密串
* @param bufLen 加密串长度
* @param time_out 阻塞时间,单位->毫秒,范围1~10000 ,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int GetNetbarMachineContent(
unsigned int game_id,
unsigned int uin,
unsigned int zone_id,
unsigned char *cryptInfoBuf,
int *bufLen,
const int time_out=5000
) = 0;
/**
* @brief 获取机器是否在网吧
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @return int 返回IIGW_MSG_STATUS_NETBAR_PC表示是网吧机器, IIGW_MSG_STATUS_NOT_IN_NETBAR表示非网吧机器,其他为错误码
*/
virtual int IsNetbarMachine(unsigned int game_id,
const char open_id[INFOGW_OPEN_ID_LEN],
account_type type) = 0;
/**
* @brief 获取机器是否在网吧,该接口仅为pubg使用
* @return bool 返回true表示在网吧
*/
virtual int IsNetbarMachine() = 0;
/**
* @brief ReqNetbarLv 获取网吧等级
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param ticketBuf, TGP票据,若不需要填空
* @param ticketLen, TGP票据长度,若不需要填0
* @param cryptInfoBuf 用来存放网吧机器信息的加密串
* @param bufLen 加密串长度
* @param error, 错误的msg
* @param errBufLen, error buffer size
* @param op_buf, 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
* @param op_buf_len, 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @param type 保留字段,open_id帐号类型,0是QQ号,1是微信,【2是facebook,3是邮箱账号,这2个都是wegame自己的opend_id】
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
const unsigned char *ticketBuf,
const int ticketLen,
unsigned char *cryptInfoBuf,
int *bufLen,
char *error,
unsigned long errBufLen,
char *op_buf,
int *op_buf_len,
const int time_out=5000,
unsigned int type = 1
) = 0;
/**
* @brief ReqNetbarLv2 获取网吧等级
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是msdk的gopen_id
* @param ticketBuff, 用户登录游戏时的token,用于登录校验
* @param ticketLen, 用户登录游戏时的token长度
* @param netbarlv 输出参数,参考NetbarLv的声明
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv2(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
unsigned int type,
const char *ticketBuff,
const int ticketLen,
NetbarLv *netbarlv,
const int time_out = 5000
) = 0;
/**
* @brief 获取机器是否在网吧,给PUBG用的接口,其他业务请调用IsNetbarMachine
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @return bool 返回true表示在网吧
*/
virtual int IsNetbar_ForPubg(const char open_id[INFOGW_OPEN_ID_LEN], account_type type) = 0;
/**
* @brief 获取网吧签名token,给PUBG用的接口
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @param opt_token 存储token用的buff,建议长度512
* @param opt_token_len 返回的token 长度
* @return int 返回0成功,返回IIGW_MSG_STATUS_NOT_IN_NETBAR(300)表示非网吧环境,并且opt_token会为空,
其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarToken_ForPubg(const char open_id[INFOGW_OPEN_ID_LEN], account_type type,
char *opt_token, int *opt_token_len) = 0;
/*************************************************
Function: SetProxy
Description: 设置代理,在所有获取等级接口之前调用
History:
<author> <time> <version > <desc>
cooperli 2019-6-11 1.0 build
*************************************************/
virtual void SetProxy(
const char url[INFOGW_OPEN_ID_LEN], // 代理URL
const char user[INFOGW_OPEN_ID_LEN], // 代理账号
const char pwd[INFOGW_OPEN_ID_LEN] // 代理密码
) = 0;
/**
* @brief RegNetbarLvCallback 注册异步获取网吧等级的回调函数,只需调用一次
* @param handle_result 回调函数
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int RegNetbarLvCallback(notify_req_netbarlv_result handle_result) = 0;
/**
* @brief ReqNetbarLv2_Asyn 异步获取网吧等级,调用该函数之前需调用RegNetbarLvCallback注册回调
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是msdk的gopen_id
* @param ticketBuff, 用户登录游戏时的token,用于登录校验
* @param ticketLen, 用户登录游戏时的token长度
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv2_Asyn(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
unsigned int type,
const char *ticketBuff,
const int ticketLen,
const int time_out = 5000
) = 0;
};
/**
* @brief 创建QQ网吧插件接口
* @param hDll LoadLibrary返回的HMODULE
* @return IQQNetbarIIGWPlugin 失败返回nullptr。该接口内存由插件管理,无需外部释放
*/
inline IQQNetbarIIGWPlugin *CreateQQNetbarIIGWPlugin(HMODULE hDll){
if (!hDll) {
return nullptr;
}
typedef HRESULT (WINAPI *QUERYPLUGININTERFACE)(const char*, void**);
#ifdef _WIN64
QUERYPLUGININTERFACE qpi = (QUERYPLUGININTERFACE)GetProcAddress(hDll,
"QueryPluginInterface");
#else
QUERYPLUGININTERFACE qpi = (QUERYPLUGININTERFACE)GetProcAddress(hDll,
"_QueryPluginInterface@8");
#endif
if (qpi) {
IQQNetbarIIGWPlugin* plugin = nullptr;
HRESULT hresult = qpi("IQQNetbarIIGWPlugin", reinterpret_cast<void**>(&plugin));
if (SUCCEEDED(hresult)) {
return plugin;
}
}
return nullptr;
}
}
#ifdef __cplusplus
}
#endif
#endif // _ITC_CLIENT_H_
+46
View File
@@ -0,0 +1,46 @@
#include "stdafx.h"
#include "MainDialog.h"
CAppModule _Module;
int Run(LPTSTR /*lpCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop);
CMainDialog dlgMain;
if (dlgMain.Create(NULL) == NULL)
{
ATLTRACE(_T("Main dialog creation failed!\n"));
return 0;
}
dlgMain.ShowWindow(nCmdShow);
int nRet = theLoop.Run();
_Module.RemoveMessageLoop();
return nRet;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
HRESULT hRes = ::CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
::DefWindowProc(NULL, 0, 0, 0L);
AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); // add flags to support other controls
hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));
int nRet = Run(lpstrCmdLine, nCmdShow);
_Module.Term();
::CoUninitialize();
return nRet;
}
+26
View File
@@ -0,0 +1,26 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by aClient.rc
//
#define IDD_DIALOG_MAIN 101
#define IDC_BUTTON_CONNECT_GAME_SERVER 1001
#define IDC_BUTTON_DISCONNECT_GAME_SERVER 1002
#define IDC_BUTTON_UGC_SEND 1003
#define IDC_EDIT1 1004
#define IDC_EDIT_UGC_CONTENT 1004
#define IDC_BUTTON_REPORT_SEND 1005
#define IDC_BUTTON_NETBAR_CLIENTLOAD 1006
#define IDC_EDIT_MAINPLAY_PID 1007
#define IDC_BUTTON1 1008
#define IDC_BUTTON_CHECK_MAINPLAY_PROCESS 1008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1009
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+2
View File
@@ -0,0 +1,2 @@
#include "stdafx.h"
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include <cy_core.h>
#include <cy_event.h>
#include <cy_network.h>
#include <atlbase.h>
#include <atlapp.h>
#include <atldlgs.h>