Compare commits
1 Commits
master
...
new_online
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1706a55959 |
15
.gitmodules
vendored
15
.gitmodules
vendored
@ -1,3 +1,9 @@
|
||||
[submodule "third_party/a8engine"]
|
||||
path = third_party/a8engine
|
||||
url = git@git.kingsome.cn:server_common/a8engine.git
|
||||
[submodule "third_party/framework"]
|
||||
path = third_party/framework
|
||||
url = git@git.kingsome.cn:server_common/framework.git
|
||||
[submodule "third_party/tools"]
|
||||
path = third_party/tools
|
||||
url = git@git.kingsome.cn:server_common/tools.git
|
||||
@ -7,12 +13,3 @@
|
||||
[submodule "third_party/recastnavigation"]
|
||||
path = third_party/recastnavigation
|
||||
url = git@git.kingsome.cn:libs/recastnavigation.git
|
||||
[submodule "third_party/a8"]
|
||||
path = third_party/a8
|
||||
url = git@git.kingsome.cn:server_common/a8.git
|
||||
[submodule "third_party/f8"]
|
||||
path = third_party/f8
|
||||
url = git@git.kingsome.cn:server_common/f8.git
|
||||
[submodule "third_party/kcp"]
|
||||
path = third_party/kcp
|
||||
url = git@git.kingsome.cn:libs/kcp.git
|
||||
|
@ -10,7 +10,6 @@ enum SSMessageId_e
|
||||
_SS_MS_ResponseTargetServer = 12;
|
||||
_SS_ForceCloseSocket = 13;
|
||||
|
||||
_SS_CMKcpHandshake = 99;
|
||||
_SS_CMPing = 101;
|
||||
_SS_SMRpcError = 102;
|
||||
_SS_CMLogin = 103;
|
||||
|
@ -8,42 +8,17 @@ message SS_CMPing
|
||||
{
|
||||
}
|
||||
|
||||
message SS_SMPing
|
||||
{
|
||||
optional int32 param1 = 1; optional int32 source = 2 [default = 0]; //0:tcp 1:udp
|
||||
}
|
||||
|
||||
message SS_CMLogin_CMReConnect_CommonHead
|
||||
{
|
||||
optional int32 server_id = 1;
|
||||
}
|
||||
|
||||
message SS_CMKcpHandshake
|
||||
{
|
||||
optional int32 proto_version = 1; //协议版本号Constant_e.ProtoVersion
|
||||
optional string account_id = 2; //账号id
|
||||
optional string session_id = 3; //session id
|
||||
optional string team_uuid = 4; //保留
|
||||
optional int32 secret_key_place = 5; //私钥存放位置 0:存在用户协议前(老) 1:存在kcp底层协议头之后(新)
|
||||
}
|
||||
|
||||
message SS_SMKcpHandshake
|
||||
{
|
||||
optional int32 errcode = 1; //errcode != 0时表示不支持kcp
|
||||
optional string errmsg = 2; //errmsg
|
||||
optional int32 conv = 3; //用来作为客户端的conv
|
||||
optional bytes secret_key = 4; //secret key客户端每次上报的时候加在包头之前
|
||||
optional string remote_host = 5; //host
|
||||
optional int32 remote_port = 6; //port
|
||||
}
|
||||
|
||||
message SS_CMLogin
|
||||
{
|
||||
optional int32 server_id = 1; //保留
|
||||
optional string team_uuid = 2; //保留
|
||||
optional string account_id = 3; //账号id
|
||||
optional int32 proto_version = 5; //协议版本号Constant_e.ProtoVersion
|
||||
optional string session_id = 20; //账号id
|
||||
}
|
||||
|
||||
message SS_CMReconnect
|
||||
@ -64,9 +39,6 @@ message SS_WSP_RequestTargetServer
|
||||
optional string server_info = 4;
|
||||
optional int32 is_reconnect = 5;
|
||||
optional int32 proto_version = 6; //协议版本号Constant_e.ProtoVersion
|
||||
optional string url = 7;
|
||||
optional string query_str = 8;
|
||||
optional string session_id = 9;
|
||||
}
|
||||
|
||||
message SS_MS_ResponseTargetServer
|
||||
|
@ -4,11 +4,23 @@ cmake_minimum_required(VERSION 2.8)
|
||||
if (${GAME_ID})
|
||||
message(GAME_ID: ${GAME_ID})
|
||||
else()
|
||||
message(FATAL_ERROR "GAME_ID error")
|
||||
set(GAME_ID 1008)
|
||||
message(GAME_ID: ${GAME_ID})
|
||||
endif()
|
||||
|
||||
set(LIB_DIR "ubuntu20.04_g++-9")
|
||||
message(LIB_DIR: ${LIB_DIR})
|
||||
if (${MASTER_MODE})
|
||||
message(MASTER_MODE: 1)
|
||||
else()
|
||||
set(MASTER_MODE 0)
|
||||
message(MASTER_MODE: 0)
|
||||
endif()
|
||||
|
||||
if (${ASYNC_TCPCLIENT})
|
||||
message(ASYNC_TCPCLIENT: 1)
|
||||
else()
|
||||
set(ASYNC_TCPCLIENT 0)
|
||||
message(ASYNC_TCPCLIENT: 0)
|
||||
endif()
|
||||
|
||||
if (${RELEASE})
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
@ -17,18 +29,12 @@ else()
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
message("debug mode")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g -std=gnu++1z -DGAME_ID=${GAME_ID} -DNDEBUG")
|
||||
if (${ASAN})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -std=gnu++1z -DGAME_ID=${GAME_ID} -DDEBUG -fsanitize=address -fno-omit-frame-pointer")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -std=gnu++1z -DGAME_ID=${GAME_ID} -DDEBUG")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wall -g -std=gnu++11 -DGAME_ID=${GAME_ID} -DMASTER_MODE=${MASTER_MODE} -DASYNC_TCPCLIENT=${ASYNC_TCPCLIENT} -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -std=gnu++11 -DGAME_ID=${GAME_ID} -DMASTER_MODE=${MASTER_MODE} -DASYNC_TCPCLIENT=${ASYNC_TCPCLIENT} -DDEBUG")
|
||||
|
||||
include_directories(
|
||||
AFTER
|
||||
../../third_party/a8
|
||||
../../third_party/f8
|
||||
../../third_party/a8engine
|
||||
/usr/include/mysql
|
||||
/usr/include/jsoncpp
|
||||
/usr/include/hiredis
|
||||
@ -44,14 +50,14 @@ include_directories(
|
||||
link_directories(
|
||||
/usr/lib64/mysql
|
||||
/usr/local/lib
|
||||
../../third_party/behaviac/lib/${LIB_DIR}
|
||||
../../third_party/behaviac/lib
|
||||
)
|
||||
|
||||
aux_source_directory(../../third_party/a8/a8
|
||||
aux_source_directory(../../third_party/a8engine/a8
|
||||
SRC_LIST
|
||||
)
|
||||
|
||||
aux_source_directory(../../third_party/f8/f8
|
||||
aux_source_directory(../../third_party/framework/cpp
|
||||
SRC_LIST
|
||||
)
|
||||
|
||||
@ -88,6 +94,7 @@ add_custom_command(TARGET script_pb_protocol
|
||||
)
|
||||
add_dependencies(wsproxy${GAME_ID} script_pb_protocol)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_link_libraries(
|
||||
wsproxy${GAME_ID}
|
||||
pthread
|
||||
@ -102,16 +109,24 @@ target_link_libraries(
|
||||
curl
|
||||
hiredis
|
||||
tinyxml2
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_link_libraries(
|
||||
wsproxy${GAME_ID}
|
||||
tcmalloc
|
||||
behaviac_gcc_debug
|
||||
)
|
||||
else()
|
||||
target_link_libraries(
|
||||
wsproxy${GAME_ID}
|
||||
pthread
|
||||
mysqlclient
|
||||
protobuf
|
||||
rt
|
||||
dl
|
||||
util
|
||||
crypto
|
||||
ssl
|
||||
jsoncpp
|
||||
curl
|
||||
hiredis
|
||||
tinyxml2
|
||||
tcmalloc
|
||||
behaviac_gcc_release
|
||||
)
|
||||
|
@ -1,14 +1,10 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <a8/websocketsession.h>
|
||||
#include <a8/tcplistener.h>
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
#include <f8/udplog.h>
|
||||
#include <f8/msgqueue.h>
|
||||
#include "framework/cpp/netmsghandler.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "GCListener.h"
|
||||
@ -37,8 +33,7 @@ public:
|
||||
p->msgid,
|
||||
p->seqid,
|
||||
&buf[offset + sizeof(f8::PackHead)],
|
||||
p->packlen,
|
||||
ST_Tcp);
|
||||
p->packlen);
|
||||
offset += sizeof(f8::PackHead) + p->packlen;
|
||||
} else {
|
||||
warning = true;
|
||||
@ -48,61 +43,57 @@ public:
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
f8::UdpLog::Instance()->Warning("收到client非法数据包", {});
|
||||
a8::UdpLog::Instance()->Warning("收到client非法数据包", {});
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnRawHttpGet(const std::string& url, const std::string& querystr,
|
||||
std::string& response) override
|
||||
{
|
||||
f8::MsgQueue::Instance()->PostMsg
|
||||
(
|
||||
IM_ExecGM,
|
||||
a8::Args
|
||||
(
|
||||
{
|
||||
(int)socket_handle,
|
||||
(std::string)(url + ""),
|
||||
(std::string)(querystr + ""),
|
||||
(unsigned long)saddr
|
||||
}
|
||||
)
|
||||
);
|
||||
App::Instance()->AddIMMsg(IM_ExecGM,
|
||||
a8::XParams()
|
||||
.SetSender(socket_handle)
|
||||
.SetParam1(url)
|
||||
.SetParam2(querystr)
|
||||
.SetParam3(saddr));
|
||||
}
|
||||
|
||||
virtual bool HandleRedirect(const std::string& url, const std::string& querystr,
|
||||
std::string& location) override
|
||||
{
|
||||
#ifdef DEBUG
|
||||
f8::MsgQueue::Instance()->PostMsg
|
||||
(
|
||||
IM_HandleRedirect,
|
||||
a8::Args
|
||||
(
|
||||
#if MASTER_MODE
|
||||
a8::HTTPRequest request;
|
||||
a8::ParserUrlQueryString(querystr.c_str(), request);
|
||||
if (a8::Get(request, "c").GetString() == "Ops" &&
|
||||
a8::Get(request, "a").GetString() == "join") {
|
||||
std::string team_uuid = a8::Get(request, "team_uuid").GetString();
|
||||
std::vector<std::string> strings;
|
||||
a8::Split(team_uuid, strings, '_');
|
||||
if (strings.size() >= 2) {
|
||||
int node_id = a8::XValue(strings[0]);
|
||||
if (node_id != App::Instance()->node_id) {
|
||||
std::string host;
|
||||
if (JsonDataMgr::Instance()->GetNodeHost(node_id, host)) {
|
||||
location = a8::Format("wss://%s/webapp/index.php?c=Ops&a=join&team_uuid=%s",
|
||||
{
|
||||
(int)socket_handle,
|
||||
(std::string)(url + ""),
|
||||
(std::string)(querystr + ""),
|
||||
(unsigned long)saddr
|
||||
host,
|
||||
team_uuid
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnDisConnect() override
|
||||
{
|
||||
f8::MsgQueue::Instance()->PostMsg
|
||||
(
|
||||
IM_ClientSocketDisconnect,
|
||||
a8::Args
|
||||
(
|
||||
{
|
||||
(int)socket_handle
|
||||
}
|
||||
)
|
||||
);
|
||||
App::Instance()->AddIMMsg(IM_ClientSocketDisconnect,
|
||||
a8::XParams()
|
||||
.SetSender(socket_handle)
|
||||
.SetParam1(1));
|
||||
}
|
||||
|
||||
};
|
||||
@ -114,7 +105,7 @@ static void CreateGameClientSocket(a8::TcpSession **p)
|
||||
|
||||
static void GSListeneron_error(a8::TcpListener*, int type, int errorid)
|
||||
{
|
||||
f8::UdpLog::Instance()->Debug("GCListeneron_error %d %d", {type, errorid});
|
||||
a8::UdpLog::Instance()->Debug("GCListeneron_error %d %d", {type, errorid});
|
||||
}
|
||||
|
||||
void GCListener::Init()
|
||||
@ -126,24 +117,6 @@ void GCListener::Init()
|
||||
tcp_listener_->bind_address = "0.0.0.0";
|
||||
tcp_listener_->bind_port = JsonDataMgr::Instance()->GetConf()->At("listen_port")->AsXValue();
|
||||
tcp_listener_->Open();
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_HandleRedirect,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
int socket_handle = args.Get<int>(0);
|
||||
std::string url = args.Get<std::string>(1);
|
||||
std::string query_str = args.Get<std::string>(2);
|
||||
websocket_url_hash_[socket_handle] = std::make_tuple(url, query_str);
|
||||
});
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_ClientSocketDisconnect,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
int socket_handle = args.Get<int>(0);
|
||||
websocket_url_hash_.erase(socket_handle);
|
||||
});
|
||||
}
|
||||
|
||||
void GCListener::UnInit()
|
||||
@ -152,9 +125,21 @@ void GCListener::UnInit()
|
||||
tcp_listener_ = nullptr;
|
||||
}
|
||||
|
||||
void GCListener::SendBuf(unsigned short sockhandle, char* buf, int buflen)
|
||||
void GCListener::ForwardTargetConnMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
tcp_listener_->SendClientMsg(sockhandle, buf, buflen);
|
||||
char* buff = (char*)malloc(sizeof(f8::PackHead) + hdr.buflen);
|
||||
f8::PackHead* head = (f8::PackHead*)buff;
|
||||
head->packlen = hdr.buflen;
|
||||
head->msgid = hdr.msgid;
|
||||
head->seqid = hdr.seqid;
|
||||
head->magic_code = f8::MAGIC_CODE;
|
||||
head->ext_len = hdr.buflen >> 16;
|
||||
if (hdr.buflen > 0) {
|
||||
memmove(buff + sizeof(f8::PackHead), hdr.buf, hdr.buflen);
|
||||
}
|
||||
|
||||
tcp_listener_->SendClientMsg(hdr.socket_handle, buff, sizeof(f8::PackHead) + head->packlen);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
void GCListener::SendText(unsigned short sockhandle, const std::string& text)
|
||||
@ -181,20 +166,3 @@ long long GCListener::GetSentBytesNum()
|
||||
{
|
||||
return tcp_listener_->sent_bytes_num;
|
||||
}
|
||||
|
||||
bool GCListener::GetWebSocketUrl(int socket_handle, std::string& url, std::string& query_str)
|
||||
{
|
||||
auto itr = websocket_url_hash_.find(socket_handle);
|
||||
if (itr != websocket_url_hash_.end()) {
|
||||
url = std::get<0>(itr->second);
|
||||
query_str = std::get<1>(itr->second);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int GCListener::GetSocketCount()
|
||||
{
|
||||
return tcp_listener_->GetClientSocketCount();
|
||||
}
|
||||
|
@ -23,26 +23,17 @@ class GCListener : public a8::Singleton<GCListener>
|
||||
void SendMsg(unsigned short socket_handle, T& msg)
|
||||
{
|
||||
static int msgid = f8::Net_GetMessageId(msg);
|
||||
SendMsgEx(socket_handle, msgid, msg);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SendMsgEx(unsigned short socket_handle, int msgid, T& msg)
|
||||
{
|
||||
f8::Net_SendMsg(tcp_listener_, socket_handle, 0, msgid, msg);
|
||||
}
|
||||
|
||||
void SendBuf(unsigned short sockhandle, char* buf, int buflen);
|
||||
void ForwardTargetConnMsg(f8::MsgHdr& hdr);
|
||||
void SendText(unsigned short sockhandle, const std::string& text);
|
||||
|
||||
void ForceCloseClient(unsigned short sockhandle);
|
||||
void MarkClient(unsigned short sockhandle, bool is_active);
|
||||
long long GetSendNodeNum();
|
||||
long long GetSentBytesNum();
|
||||
bool GetWebSocketUrl(int socket_handle, std::string& url, std::string& query_str);
|
||||
int GetSocketCount();
|
||||
|
||||
private:
|
||||
a8::TcpListener *tcp_listener_ = nullptr;
|
||||
std::map<int, std::tuple<std::string, std::string>> websocket_url_hash_;
|
||||
};
|
||||
|
@ -6,31 +6,29 @@
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#include <a8/xtimer.h>
|
||||
#include <a8/redis.h>
|
||||
#include <a8/timer.h>
|
||||
#include <a8/uuid.h>
|
||||
#include <a8/udplistener.h>
|
||||
#include <a8/ioloop.h>
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
#include <f8/udplog.h>
|
||||
#include <f8/msgqueue.h>
|
||||
#include "framework/cpp/netmsghandler.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "GCListener.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "handlermgr.h"
|
||||
#include "downstream.h"
|
||||
#include "downstreammgr.h"
|
||||
|
||||
#include "upstream.h"
|
||||
#include "upstreammgr.h"
|
||||
#include "master.h"
|
||||
#include "mastermgr.h"
|
||||
|
||||
#include "longsessionmgr.h"
|
||||
|
||||
#include "gameclient.h"
|
||||
#include "gameclientmgr.h"
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
#include "target_conn.h"
|
||||
#include "target_conn_mgr.h"
|
||||
#if MASTER_MODE
|
||||
#include "mastersvr.h"
|
||||
#include "mastersvrmgr.h"
|
||||
#endif
|
||||
|
||||
struct MsgNode
|
||||
{
|
||||
SocketFrom_e sockfrom;
|
||||
@ -40,14 +38,15 @@ struct MsgNode
|
||||
long ip_saddr;
|
||||
char* buf;
|
||||
int buflen;
|
||||
int tag;
|
||||
MsgNode* next;
|
||||
};
|
||||
|
||||
struct UdpMsgNode
|
||||
struct IMMsgNode
|
||||
{
|
||||
a8::UdpPacket* pkt;
|
||||
UdpMsgNode* next;
|
||||
unsigned short msgid;
|
||||
a8::XParams params;
|
||||
IMMsgNode* next = nullptr;
|
||||
|
||||
};
|
||||
|
||||
const char* const PROJ_LOG_ROOT_FMT = "/data/logs/%s/logs";
|
||||
@ -55,127 +54,149 @@ const char* const PROJ_LOG_FILENAME_FMT = "log_$pid_%Y%m%d.log";
|
||||
|
||||
static void SavePerfLog()
|
||||
{
|
||||
f8::UdpLog::Instance()->Info("max_run_delay_time:%d max_timer_idle:%d "
|
||||
"in_data_size:%d out_data_size:%d msgnode_size:%d udp_msgnode_size:%d "
|
||||
"read_count:%d max_login_time:%d "
|
||||
"max_join_time:%d tcp_count:%d udp_count:%d down_stream_count:%d",
|
||||
a8::UdpLog::Instance()->Info(" max_run_delay_time:%d max_timer_idle:%d "
|
||||
"in_data_size:%d out_data_size:%d msgnode_size:%d read_count:%d max_login_time:%d "
|
||||
"max_join_time:%d",
|
||||
{
|
||||
App::Instance()->GetPerf().max_run_delay_time,
|
||||
App::Instance()->GetPerf().max_timer_idle,
|
||||
App::Instance()->GetPerf().in_data_size,
|
||||
App::Instance()->GetPerf().out_data_size,
|
||||
App::Instance()->GetMsgNodeSize(),
|
||||
App::Instance()->GetUdpMsgNodeSize(),
|
||||
App::Instance()->GetPerf().read_count,
|
||||
App::Instance()->GetPerf().max_login_time,
|
||||
App::Instance()->GetPerf().max_join_time,
|
||||
GCListener::Instance()->GetSocketCount(),
|
||||
LongSessionMgr::Instance()->GetLongSessionCount(),
|
||||
DownStreamMgr::Instance()->GetDownStreamCount()
|
||||
App::Instance()->perf.max_run_delay_time,
|
||||
App::Instance()->perf.max_timer_idle,
|
||||
App::Instance()->perf.in_data_size,
|
||||
App::Instance()->perf.out_data_size,
|
||||
App::Instance()->msgnode_size_,
|
||||
App::Instance()->perf.read_count,
|
||||
App::Instance()->perf.max_login_time,
|
||||
App::Instance()->perf.max_join_time,
|
||||
});
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
a8::UdpLog::Instance()->Info(" run_times:%d timer_times:%d event_times:%d free_times:%d "
|
||||
" shutdown_times:%d connect_times:%d close_times:%d "
|
||||
" send_times:%d recv_times:%d error_times:%d immsg_times:%d",
|
||||
{
|
||||
(long long)a8::IoLoop::Instance()->run_times,
|
||||
(long long)a8::IoLoop::Instance()->timer_times,
|
||||
(long long)a8::IoLoop::Instance()->event_times,
|
||||
(long long)a8::IoLoop::Instance()->free_times,
|
||||
(long long)a8::IoLoop::Instance()->shutdown_times,
|
||||
(long long)a8::IoLoop::Instance()->connect_times,
|
||||
(long long)a8::IoLoop::Instance()->close_times,
|
||||
(long long)a8::IoLoop::Instance()->send_times,
|
||||
(long long)a8::IoLoop::Instance()->recv_times,
|
||||
(long long)a8::IoLoop::Instance()->error_times,
|
||||
(long long)a8::IoLoop::Instance()->immsg_times
|
||||
});
|
||||
#endif
|
||||
if (App::Instance()->HasFlag(2)) {
|
||||
a8::XPrintf("mainloop_time:%d netmsg_time:%d send_node_num:%d sent_bytes_num:%d\n",
|
||||
{
|
||||
App::Instance()->GetPerf().max_run_delay_time,
|
||||
App::Instance()->GetPerf().max_dispatchmsg_time,
|
||||
App::Instance()->perf.max_run_delay_time,
|
||||
App::Instance()->perf.max_dispatchmsg_time,
|
||||
GCListener::Instance()->GetSendNodeNum(),
|
||||
GCListener::Instance()->GetSentBytesNum()
|
||||
});
|
||||
}
|
||||
App::Instance()->GetPerf().max_run_delay_time = 0;
|
||||
App::Instance()->GetPerf().max_timer_idle = 0;
|
||||
App::Instance()->GetPerf().max_login_time = 0;
|
||||
App::Instance()->GetPerf().max_join_time = 0;
|
||||
#if 1
|
||||
App::Instance()->perf.max_run_delay_time = 0;
|
||||
App::Instance()->perf.max_timer_idle = 0;
|
||||
App::Instance()->perf.max_login_time = 0;
|
||||
App::Instance()->perf.max_join_time = 0;
|
||||
#else
|
||||
App::Instance()->perf = PerfMonitor();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool App::Init(int argc, char* argv[])
|
||||
{
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
this->argc_ = argc;
|
||||
this->argv_ = argv;
|
||||
this->argc = argc;
|
||||
this->argv = argv;
|
||||
|
||||
if (!ParseOpt()) {
|
||||
terminated_ = true;
|
||||
if (node_id_ <= 0) {
|
||||
terminated = true;
|
||||
#if MASTER_MODE
|
||||
if (node_id <= 0) {
|
||||
a8::XPrintf("gameserver启动失败,缺少-n参数\n", {});
|
||||
} else if (node_id_ > MAX_NODE_ID) {
|
||||
} else if (node_id > MAX_NODE_ID) {
|
||||
a8::XPrintf("gameserver启动失败,-n参数不能大于%d\n", {MAX_NODE_ID});
|
||||
} else if (instance_id_ <= 0) {
|
||||
} else if (instance_id <= 0) {
|
||||
a8::XPrintf("gameserver启动失败,缺少-i参数\n", {});
|
||||
} else if (instance_id_ > MAX_INSTANCE_ID) {
|
||||
} else if (instance_id > MAX_INSTANCE_ID) {
|
||||
a8::XPrintf("gameserver启动失败,-i参数不能大于%d\n", {MAX_INSTANCE_ID});
|
||||
}
|
||||
#else
|
||||
a8::XPrintf("wsproxy启动失败,缺少-i参数\n", {});
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
a8::XPrintf("wsproxy starting node_id:%d instance_id:%d pid:%d\n",
|
||||
a8::XPrintf("wsproxy starting node_id:%d instance_id:%d pid:%d master_mode:%d async_tcpclient:%d\n",
|
||||
{
|
||||
node_id_,
|
||||
instance_id_,
|
||||
getpid()
|
||||
node_id,
|
||||
instance_id,
|
||||
getpid(),
|
||||
MASTER_MODE,
|
||||
ASYNC_TCPCLIENT
|
||||
});
|
||||
|
||||
uuid_ = std::make_shared<a8::uuid::SnowFlake>();
|
||||
loop_mutex_ = new std::mutex();
|
||||
loop_cond_ = new std::condition_variable();
|
||||
msg_mutex_ = new std::mutex();
|
||||
udp_msg_mutex_ = new std::mutex();
|
||||
im_msg_mutex_ = new std::mutex();
|
||||
|
||||
srand(time(nullptr));
|
||||
InitLog();
|
||||
f8::MsgQueue::Instance()->Init();
|
||||
HandlerMgr::Instance()->Init();
|
||||
f8::Timer::Instance()->Init();
|
||||
a8::Timer::Instance()->Init();
|
||||
a8::IoLoop::Instance()->Init(1);
|
||||
JsonDataMgr::Instance()->Init();
|
||||
uuid_->SetMachineId((node_id_ - 1) * MAX_NODE_ID + instance_id_);
|
||||
DownStreamMgr::Instance()->Init();
|
||||
MasterMgr::Instance()->Init();
|
||||
UpStreamMgr::Instance()->Init();
|
||||
LongSessionMgr::Instance()->Init();
|
||||
#if MASTER_MODE
|
||||
uuid.SetMachineId((node_id - 1) * MAX_NODE_ID + instance_id);
|
||||
#else
|
||||
uuid.SetMachineId(instance_id);
|
||||
#endif
|
||||
GameClientMgr::Instance()->Init();
|
||||
#if MASTER_MODE
|
||||
MasterSvrMgr::Instance()->Init();
|
||||
#endif
|
||||
TargetConnMgr::Instance()->Init();
|
||||
GCListener::Instance()->Init();
|
||||
|
||||
f8::UdpLog::Instance()->Info("wsproxy starting instance_id:%d pid:%d",
|
||||
a8::UdpLog::Instance()->Info("wsproxy starting instance_id:%d pid:%d async_tcpclient:%d",
|
||||
{
|
||||
instance_id_,
|
||||
instance_id,
|
||||
getpid(),
|
||||
ASYNC_TCPCLIENT
|
||||
});
|
||||
{
|
||||
int perf_log_time = 1000 * 60 * 5;
|
||||
if (getenv("is_dev_env")) {
|
||||
perf_log_time = 1000 * 10;
|
||||
}
|
||||
f8::Timer::Instance()->SetInterval
|
||||
(perf_log_time,
|
||||
[] (int event, const a8::Args* args)
|
||||
a8::Timer::Instance()->AddRepeatTimer(perf_log_time,
|
||||
a8::XParams(),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
SavePerfLog();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (HasFlag(1)) {
|
||||
f8::Timer::Instance()->SetTimeout
|
||||
(
|
||||
a8::Timer::Instance()->AddDeadLineTimer(
|
||||
1000 * 60,
|
||||
[] (int event, const a8::Args* args)
|
||||
a8::XParams(),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
App::Instance()->terminated_ = true;
|
||||
App::Instance()->terminated = true;
|
||||
App::Instance()->NotifyLoopCond();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (HasFlag(4)) {
|
||||
f8::Timer::Instance()->SetTimeout
|
||||
(
|
||||
a8::Timer::Instance()->AddDeadLineTimer(
|
||||
1000 * 30,
|
||||
[] (int event, const a8::Args* args)
|
||||
a8::XParams(),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
App::Instance()->shutdowned_ = true;
|
||||
App::Instance()->shutdowned = true;
|
||||
a8::XPrintf("shutdowned\n", {});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return true;
|
||||
@ -183,42 +204,43 @@ bool App::Init(int argc, char* argv[])
|
||||
|
||||
void App::UnInit()
|
||||
{
|
||||
a8::XPrintf("wsproxy terminating instance_id:%d pid:%d\n", {instance_id_, getpid()});
|
||||
a8::XPrintf("wsproxy terminating instance_id:%d pid:%d\n", {instance_id, getpid()});
|
||||
GCListener::Instance()->UnInit();
|
||||
LongSessionMgr::Instance()->UnInit();
|
||||
MasterMgr::Instance()->UnInit();
|
||||
UpStreamMgr::Instance()->UnInit();
|
||||
DownStreamMgr::Instance()->UnInit();
|
||||
#if MASTER_MODE
|
||||
MasterSvrMgr::Instance()->UnInit();
|
||||
#endif
|
||||
TargetConnMgr::Instance()->UnInit();
|
||||
GameClientMgr::Instance()->UnInit();
|
||||
JsonDataMgr::Instance()->UnInit();
|
||||
f8::Timer::Instance()->UnInit();
|
||||
f8::MsgQueue::Instance()->UnInit();
|
||||
a8::IoLoop::Instance()->UnInit();
|
||||
a8::Timer::Instance()->UnInit();
|
||||
HandlerMgr::Instance()->UnInit();
|
||||
UnInitLog();
|
||||
|
||||
FreeSocketMsgQueue();
|
||||
FreeUdpMsgQueue();
|
||||
FreeIMMsgQueue();
|
||||
delete im_msg_mutex_;
|
||||
im_msg_mutex_ = nullptr;
|
||||
delete msg_mutex_;
|
||||
msg_mutex_ = nullptr;
|
||||
delete udp_msg_mutex_;
|
||||
udp_msg_mutex_ = nullptr;
|
||||
delete loop_cond_;
|
||||
loop_cond_ = nullptr;
|
||||
delete loop_mutex_;
|
||||
loop_mutex_ = nullptr;
|
||||
a8::XPrintf("wsproxy terminated instance_id:%d pid:%d\n", {instance_id_, getpid()});
|
||||
a8::XPrintf("wsproxy terminated instance_id:%d pid:%d\n", {instance_id, getpid()});
|
||||
}
|
||||
|
||||
int App::Run()
|
||||
{
|
||||
int ret = 0;
|
||||
f8::UdpLog::Instance()->Info("wsproxy running", {});
|
||||
while (!terminated_) {
|
||||
a8::UdpLog::Instance()->Info("wsproxy running", {});
|
||||
while (!terminated) {
|
||||
a8::tick_t begin_tick = a8::XGetTickCount();
|
||||
QuickExecute();
|
||||
SlowerExecute();
|
||||
a8::tick_t end_tick = a8::XGetTickCount();
|
||||
if (end_tick - begin_tick > GetPerf().max_run_delay_time) {
|
||||
GetPerf().max_run_delay_time = end_tick - begin_tick;
|
||||
if (end_tick - begin_tick > perf.max_run_delay_time) {
|
||||
perf.max_run_delay_time = end_tick - begin_tick;
|
||||
}
|
||||
Schedule();
|
||||
}
|
||||
@ -231,8 +253,7 @@ void App::AddSocketMsg(SocketFrom_e sockfrom,
|
||||
unsigned short msgid,
|
||||
unsigned int seqid,
|
||||
const char *msgbody,
|
||||
int bodylen,
|
||||
int tag)
|
||||
int bodylen)
|
||||
{
|
||||
MsgNode *p = (MsgNode*) malloc(sizeof(MsgNode));
|
||||
memset(p, 0, sizeof(MsgNode));
|
||||
@ -243,7 +264,6 @@ void App::AddSocketMsg(SocketFrom_e sockfrom,
|
||||
p->seqid = seqid;
|
||||
p->buf = nullptr;
|
||||
p->buflen = bodylen;
|
||||
p->tag = tag;
|
||||
if (bodylen > 0) {
|
||||
p->buf = (char*)malloc(bodylen);
|
||||
memmove(p->buf, msgbody, bodylen);
|
||||
@ -261,13 +281,29 @@ void App::AddSocketMsg(SocketFrom_e sockfrom,
|
||||
NotifyLoopCond();
|
||||
}
|
||||
|
||||
void App::AddIMMsg(unsigned short imcmd, a8::XParams params)
|
||||
{
|
||||
IMMsgNode *p = new IMMsgNode;
|
||||
p->msgid = imcmd;
|
||||
p->params = params;
|
||||
p->next = nullptr;
|
||||
im_msg_mutex_->lock();
|
||||
if (im_bot_node_) {
|
||||
im_bot_node_->next = p;
|
||||
im_bot_node_ = p;
|
||||
} else {
|
||||
im_top_node_ = p;
|
||||
im_bot_node_ = p;
|
||||
}
|
||||
im_msg_mutex_->unlock();
|
||||
NotifyLoopCond();
|
||||
}
|
||||
|
||||
void App::QuickExecute()
|
||||
{
|
||||
f8::Timer::Instance()->Update();
|
||||
f8::MsgQueue::Instance()->Update();
|
||||
ProcessIMMsg();
|
||||
DispatchMsg();
|
||||
DispatchUdpMsg();
|
||||
LongSessionMgr::Instance()->Update();
|
||||
a8::Timer::Instance()->Update();
|
||||
}
|
||||
|
||||
void App::SlowerExecute()
|
||||
@ -284,21 +320,30 @@ void App::Schedule()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(*loop_mutex_);
|
||||
if (!HasTask()) {
|
||||
#if 1
|
||||
int sleep_time = 1;
|
||||
loop_cond_->wait_for(lk, std::chrono::milliseconds(sleep_time));
|
||||
#else
|
||||
int sleep_time = f8::Timer::Instance()->GetIdleableMillSeconds();
|
||||
int sleep_time = a8::Timer::Instance()->GetIdleableMillSeconds();
|
||||
loop_cond_->wait_for(lk, std::chrono::milliseconds(sleep_time));
|
||||
if (sleep_time > perf.max_timer_idle) {
|
||||
perf.max_timer_idle = sleep_time;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool App::HasTask()
|
||||
{
|
||||
{
|
||||
if (!im_work_node_) {
|
||||
im_msg_mutex_->lock();
|
||||
if (!im_work_node_ && im_top_node_) {
|
||||
im_work_node_ = im_top_node_;
|
||||
im_top_node_ = nullptr;
|
||||
im_bot_node_ = nullptr;
|
||||
}
|
||||
im_msg_mutex_->unlock();
|
||||
}
|
||||
if (im_work_node_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!work_node_) {
|
||||
msg_mutex_->lock();
|
||||
@ -313,20 +358,6 @@ bool App::HasTask()
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!udp_work_node_) {
|
||||
udp_msg_mutex_->lock();
|
||||
if (!udp_work_node_ && udp_top_node_) {
|
||||
udp_work_node_ = udp_top_node_;
|
||||
udp_top_node_ = nullptr;
|
||||
udp_bot_node_ = nullptr;
|
||||
}
|
||||
udp_msg_mutex_->unlock();
|
||||
}
|
||||
if (udp_work_node_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -356,17 +387,17 @@ void App::DispatchMsg()
|
||||
switch (pdelnode->sockfrom) {
|
||||
case SF_Client:
|
||||
{
|
||||
ProcessClientMsg(hdr, pdelnode->tag);
|
||||
ProcessClientMsg(hdr);
|
||||
}
|
||||
break;
|
||||
case SF_TargetServer:
|
||||
{
|
||||
ProcessTargetServerMsg(hdr, pdelnode->tag);
|
||||
ProcessTargetServerMsg(hdr);
|
||||
}
|
||||
break;
|
||||
case SF_MasterServer:
|
||||
{
|
||||
ProcessMasterServerMsg(hdr, pdelnode->tag);
|
||||
ProcessMasterServerMsg(hdr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -385,24 +416,24 @@ void App::DispatchMsg()
|
||||
}
|
||||
}
|
||||
|
||||
void App::ProcessClientMsg(f8::MsgHdr& hdr, int tag)
|
||||
void App::ProcessClientMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
if (hdr.msgid == ss::_SS_CMLogin ||
|
||||
hdr.msgid == ss::_SS_CMReconnect ||
|
||||
hdr.msgid == ss::_SS_CMKcpHandshake) {
|
||||
auto down_wp = DownStreamMgr::Instance()->GetDownStream(hdr.socket_handle);
|
||||
if (down_wp.expired()) {
|
||||
if (hdr.msgid < 100) {
|
||||
return;
|
||||
}
|
||||
#if MASTER_MODE
|
||||
if (hdr.msgid == ss::_SS_CMLogin || hdr.msgid == ss::_SS_CMReconnect) {
|
||||
GameClient* client = GameClientMgr::Instance()->GetGameClientBySocket(hdr.socket_handle);
|
||||
if (!client) {
|
||||
switch (hdr.msgid) {
|
||||
case ss::_SS_CMLogin:
|
||||
{
|
||||
ss::SS_CMLogin msg;
|
||||
bool ok = msg.ParseFromArray(hdr.buf + hdr.offset, hdr.buflen - hdr.offset);
|
||||
if (ok) {
|
||||
MasterMgr::Instance()->RequestTargetServer
|
||||
(hdr,
|
||||
MasterSvrMgr::Instance()->RequestTargetServer(hdr,
|
||||
msg.team_uuid(),
|
||||
msg.account_id(),
|
||||
msg.session_id(),
|
||||
"",
|
||||
0,
|
||||
msg.proto_version());
|
||||
@ -414,67 +445,136 @@ void App::ProcessClientMsg(f8::MsgHdr& hdr, int tag)
|
||||
ss::SS_CMReconnect msg;
|
||||
bool ok = msg.ParseFromArray(hdr.buf + hdr.offset, hdr.buflen - hdr.offset);
|
||||
if (ok) {
|
||||
MasterMgr::Instance()->RequestTargetServer
|
||||
(hdr,
|
||||
MasterSvrMgr::Instance()->RequestTargetServer(hdr,
|
||||
msg.team_uuid(),
|
||||
msg.account_id(),
|
||||
msg.session_id(),
|
||||
msg.server_info(),
|
||||
1,
|
||||
0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ss::_SS_CMKcpHandshake:
|
||||
{
|
||||
ss::SS_CMKcpHandshake msg;
|
||||
bool ok = msg.ParseFromArray(hdr.buf + hdr.offset, hdr.buflen - hdr.offset);
|
||||
if (ok) {
|
||||
LongSessionMgr::Instance()->_SS_CMKcpHandshake(hdr, msg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
#if 0
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto down_wp = DownStreamMgr::Instance()->GetDownStream(hdr.socket_handle);
|
||||
if (auto down = down_wp.lock(); !down_wp.expired()) {
|
||||
down->ProcCMMsg(hdr, tag);
|
||||
GameClient* client = GameClientMgr::Instance()->GetGameClientBySocket(hdr.socket_handle);
|
||||
if (client && client->conn) {
|
||||
if (client->conn) {
|
||||
client->conn->ForwardClientMsg(hdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
TargetConn* conn = nullptr;
|
||||
if (hdr.msgid == ss::_SS_CMLogin || hdr.msgid == ss::_SS_CMReConnect) {
|
||||
ss::SS_CMLogin_CMReConnect_CommonHead msg;
|
||||
bool ok = msg.ParseFromArray(hdr.buf + hdr.offset, hdr.buflen - hdr.offset);
|
||||
if (ok) {
|
||||
conn = TargetConnMgr::Instance()->GetConnById(msg.server_id());
|
||||
if (!conn) {
|
||||
ss::SS_SMRpcError respmsg;
|
||||
respmsg.set_error_code(10);
|
||||
GCListener::Instance()->SendMsg(hdr.socket_handle, respmsg);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
GameClient* client = GameClientMgr::Instance()->GetGameClientBySocket(hdr.socket_handle);
|
||||
if (client) {
|
||||
conn = client->conn;
|
||||
}
|
||||
}
|
||||
if (conn) {
|
||||
conn->ForwardClientMsg(hdr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::ProcessMasterServerMsg(f8::MsgHdr& hdr, int tag)
|
||||
void App::ProcessMasterServerMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
#if MASTER_MODE
|
||||
f8::NetMsgHandler* handler = f8::GetNetMsgHandler(&HandlerMgr::Instance()->msmsghandler,
|
||||
hdr.msgid);
|
||||
if (handler) {
|
||||
switch (handler->handlerid) {
|
||||
case HID_MasterMgr:
|
||||
ProcessNetMsg(handler, MasterMgr::Instance(), hdr);
|
||||
case HID_MasterSvrMgr:
|
||||
ProcessNetMsg(handler, MasterSvrMgr::Instance(), hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::ProcessTargetServerMsg(f8::MsgHdr& hdr, int tag)
|
||||
void App::ProcessTargetServerMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
if (hdr.msgid == ss::_SS_ForceCloseSocket) {
|
||||
GCListener::Instance()->ForceCloseClient(hdr.socket_handle);
|
||||
return;
|
||||
}
|
||||
if (hdr.msgid < 100) {
|
||||
return;
|
||||
}
|
||||
if (hdr.msgid == ss::_SS_CMLogin || hdr.msgid == ss::_SS_CMReconnect) {
|
||||
DownStreamMgr::Instance()->BindUpStream(hdr.socket_handle, hdr.ip_saddr);
|
||||
GameClientMgr::Instance()->BindTargetConn(hdr.socket_handle, hdr.ip_saddr);
|
||||
GCListener::Instance()->MarkClient(hdr.socket_handle, true);
|
||||
}
|
||||
auto down_wp = DownStreamMgr::Instance()->GetDownStream(hdr.socket_handle);
|
||||
if (!down_wp.expired()) {
|
||||
down_wp.lock()->ForwardUpStreamMsg(hdr);
|
||||
GCListener::Instance()->ForwardTargetConnMsg(hdr);
|
||||
}
|
||||
|
||||
void App::ProcessIMMsg()
|
||||
{
|
||||
if (!im_work_node_ && im_top_node_) {
|
||||
im_msg_mutex_->lock();
|
||||
im_work_node_ = im_top_node_;
|
||||
im_top_node_ = nullptr;
|
||||
im_bot_node_ = nullptr;
|
||||
im_msg_mutex_->unlock();
|
||||
}
|
||||
while (im_work_node_) {
|
||||
IMMsgNode *pdelnode = im_work_node_;
|
||||
switch (im_work_node_->msgid) {
|
||||
case IM_ClientSocketDisconnect:
|
||||
{
|
||||
GameClientMgr::Instance()->OnClientDisconnect(pdelnode->params);
|
||||
#if MASTER_MODE
|
||||
MasterSvrMgr::Instance()->RemoveRequest(pdelnode->params.param1, pdelnode->params.sender, true);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case IM_TargetConnConnect:
|
||||
{
|
||||
GameClientMgr::Instance()->OnTargetServerConnect(pdelnode->params);
|
||||
TargetConn* conn = TargetConnMgr::Instance()->GetConnById(pdelnode->params.sender);
|
||||
if (conn && conn->Connected()) {
|
||||
conn->SendStockMsg();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IM_TargetConnDisconnect:
|
||||
{
|
||||
GameClientMgr::Instance()->OnTargetServerDisconnect(pdelnode->params);
|
||||
}
|
||||
break;
|
||||
case IM_ExecGM:
|
||||
{
|
||||
HandlerMgr::Instance()->ProcGMMsg(pdelnode->params.param3,
|
||||
pdelnode->params.sender,
|
||||
pdelnode->params.param1.GetString(),
|
||||
pdelnode->params.param2.GetString()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
im_work_node_ = im_work_node_->next;
|
||||
delete pdelnode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,31 +590,31 @@ void App::InitLog()
|
||||
|
||||
a8::MkDir(proj_root_dir);
|
||||
a8::MkDir(proj_log_root_dir);
|
||||
f8::UdpLog::Instance()->SetLogFileName(log_file_name);
|
||||
f8::UdpLog::Instance()->Init();
|
||||
f8::UdpLog::Instance()->Info("proj_root_dir:%s", {proj_root_dir});
|
||||
f8::UdpLog::Instance()->Info("proj_log_root_dir:%s", {proj_log_root_dir});
|
||||
f8::UdpLog::Instance()->Info("log_file_name:%s", {log_file_name});
|
||||
a8::UdpLog::Instance()->SetLogFileName(log_file_name);
|
||||
a8::UdpLog::Instance()->Init();
|
||||
a8::UdpLog::Instance()->Info("proj_root_dir:%s", {proj_root_dir});
|
||||
a8::UdpLog::Instance()->Info("proj_log_root_dir:%s", {proj_log_root_dir});
|
||||
a8::UdpLog::Instance()->Info("log_file_name:%s", {log_file_name});
|
||||
}
|
||||
|
||||
void App::UnInitLog()
|
||||
{
|
||||
f8::UdpLog::Instance()->UnInit();
|
||||
a8::UdpLog::Instance()->UnInit();
|
||||
}
|
||||
|
||||
bool App::ParseOpt()
|
||||
{
|
||||
int ch = 0;
|
||||
while ((ch = getopt(argc_, argv_, "n:i:f:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "n:i:f:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
{
|
||||
node_id_ = a8::XValue(optarg);
|
||||
node_id = a8::XValue(optarg);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
{
|
||||
instance_id_ = a8::XValue(optarg);
|
||||
instance_id = a8::XValue(optarg);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
@ -522,18 +622,39 @@ bool App::ParseOpt()
|
||||
std::vector<std::string> strings;
|
||||
a8::Split(optarg, strings, ',');
|
||||
for (auto& str : strings) {
|
||||
flags_.insert(a8::XValue(str).GetInt());
|
||||
flags.insert(a8::XValue(str).GetInt());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return instance_id_ > 0 && node_id_ > 0;
|
||||
#if MASTER_MODE
|
||||
return instance_id > 0 && node_id > 0;
|
||||
#else
|
||||
return instance_id > 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
a8::XParams* App::AddContext(long long context_id)
|
||||
{
|
||||
context_hash_[context_id] = a8::XParams();
|
||||
return GetContext(context_id);
|
||||
}
|
||||
|
||||
void App::DelContext(long long context_id)
|
||||
{
|
||||
context_hash_.erase(context_id);
|
||||
}
|
||||
|
||||
a8::XParams* App::GetContext(long long context_id)
|
||||
{
|
||||
auto itr = context_hash_.find(context_id);
|
||||
return itr != context_hash_.end() ? &(itr->second) : nullptr;
|
||||
}
|
||||
|
||||
bool App::HasFlag(int flag)
|
||||
{
|
||||
return flags_.find(flag) != flags_.end();
|
||||
return flags.find(flag) != flags.end();
|
||||
}
|
||||
|
||||
void App::FreeSocketMsgQueue()
|
||||
@ -560,86 +681,27 @@ void App::FreeSocketMsgQueue()
|
||||
msg_mutex_->unlock();
|
||||
}
|
||||
|
||||
void App::FreeUdpMsgQueue()
|
||||
void App::FreeIMMsgQueue()
|
||||
{
|
||||
udp_msg_mutex_->lock();
|
||||
if (!udp_work_node_) {
|
||||
udp_work_node_ = udp_top_node_;
|
||||
udp_top_node_ = nullptr;
|
||||
udp_bot_node_ = nullptr;
|
||||
im_msg_mutex_->lock();
|
||||
if (!im_work_node_) {
|
||||
im_work_node_ = im_top_node_;
|
||||
im_top_node_ = nullptr;
|
||||
im_bot_node_ = nullptr;
|
||||
}
|
||||
while (udp_work_node_) {
|
||||
UdpMsgNode* pdelnode = udp_work_node_;
|
||||
udp_work_node_ = udp_work_node_->next;
|
||||
{
|
||||
if (pdelnode->pkt->buf) {
|
||||
free((void*)pdelnode->pkt->buf);
|
||||
while (im_work_node_) {
|
||||
IMMsgNode* pdelnode = im_work_node_;
|
||||
im_work_node_ = im_work_node_->next;
|
||||
if (pdelnode->msgid == f8::IM_SysMsgQueue) {
|
||||
a8::XParams* param = (a8::XParams*)pdelnode->params.param1.GetUserData();
|
||||
delete param;
|
||||
}
|
||||
delete pdelnode->pkt;
|
||||
free(pdelnode);
|
||||
}
|
||||
if (!udp_work_node_) {
|
||||
udp_work_node_ = udp_top_node_;
|
||||
udp_top_node_ = nullptr;
|
||||
udp_bot_node_ = nullptr;
|
||||
delete pdelnode;
|
||||
if (!im_work_node_) {
|
||||
im_work_node_ = im_top_node_;
|
||||
im_top_node_ = nullptr;
|
||||
im_bot_node_ = nullptr;
|
||||
}
|
||||
}
|
||||
udp_msg_mutex_->unlock();
|
||||
}
|
||||
|
||||
void App::AddUdpMsg(a8::UdpPacket* pkt)
|
||||
{
|
||||
UdpMsgNode *p = (UdpMsgNode*) malloc(sizeof(UdpMsgNode));
|
||||
memset(p, 0, sizeof(UdpMsgNode));
|
||||
p->pkt = pkt;
|
||||
udp_msg_mutex_->lock();
|
||||
if (udp_bot_node_) {
|
||||
udp_bot_node_->next = p;
|
||||
udp_bot_node_ = p;
|
||||
} else {
|
||||
udp_top_node_ = p;
|
||||
udp_bot_node_ = p;
|
||||
}
|
||||
++udp_msgnode_size_;
|
||||
udp_msg_mutex_->unlock();
|
||||
NotifyLoopCond();
|
||||
}
|
||||
|
||||
void App::DispatchUdpMsg()
|
||||
{
|
||||
long long starttick = a8::XGetTickCount();
|
||||
if (!udp_work_node_ && udp_top_node_) {
|
||||
udp_msg_mutex_->lock();
|
||||
udp_work_node_ = udp_top_node_;
|
||||
udp_top_node_ = nullptr;
|
||||
udp_bot_node_ = nullptr;
|
||||
udp_working_msgnode_size_ = udp_msgnode_size_;
|
||||
udp_msg_mutex_->unlock();
|
||||
}
|
||||
|
||||
while (udp_work_node_) {
|
||||
UdpMsgNode *pdelnode = udp_work_node_;
|
||||
LongSessionMgr::Instance()->ProcUdpPacket(pdelnode->pkt);
|
||||
udp_work_node_ = pdelnode->next;
|
||||
{
|
||||
if (pdelnode->pkt->buf) {
|
||||
free((void*)pdelnode->pkt->buf);
|
||||
}
|
||||
delete pdelnode->pkt;
|
||||
free(pdelnode);
|
||||
}
|
||||
udp_working_msgnode_size_--;
|
||||
if (a8::XGetTickCount() - starttick > 200) {
|
||||
break;
|
||||
}
|
||||
}//end while
|
||||
|
||||
if (!udp_work_node_) {
|
||||
udp_working_msgnode_size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
long long App::NewUuid()
|
||||
{
|
||||
return uuid_->Generate();
|
||||
im_msg_mutex_->unlock();
|
||||
}
|
||||
|
@ -1,18 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/singleton.h>
|
||||
|
||||
namespace a8
|
||||
{
|
||||
struct UdpPacket;
|
||||
namespace uuid
|
||||
{
|
||||
class SnowFlake;
|
||||
}
|
||||
}
|
||||
#include <a8/uuid.h>
|
||||
|
||||
struct MsgNode;
|
||||
struct UdpMsgNode;
|
||||
struct IMMsgNode;
|
||||
class App : public a8::Singleton<App>
|
||||
{
|
||||
private:
|
||||
@ -32,19 +23,15 @@ public:
|
||||
unsigned short msgid,
|
||||
unsigned int seqid,
|
||||
const char *msgbody,
|
||||
int bodylen,
|
||||
int tag = ST_Tcp);
|
||||
|
||||
void AddUdpMsg(a8::UdpPacket* pkt);
|
||||
int bodylen);
|
||||
void AddIMMsg(unsigned short imcmd, a8::XParams params);
|
||||
|
||||
void NotifyLoopCond();
|
||||
|
||||
a8::XParams* AddContext(long long context_id);
|
||||
void DelContext(long long context_id);
|
||||
a8::XParams* GetContext(long long context_id);
|
||||
bool HasFlag(int flag);
|
||||
long long NewUuid();
|
||||
int GetNodeId() { return node_id_; }
|
||||
int GetInstanceId() { return instance_id_; }
|
||||
PerfMonitor& GetPerf() { return perf_; }
|
||||
int GetMsgNodeSize() { return msgnode_size_;}
|
||||
int GetUdpMsgNodeSize() { return udp_msgnode_size_;}
|
||||
|
||||
private:
|
||||
void QuickExecute();
|
||||
@ -53,31 +40,33 @@ private:
|
||||
bool HasTask();
|
||||
|
||||
void DispatchMsg();
|
||||
void DispatchUdpMsg();
|
||||
void ProcessIMMsg();
|
||||
|
||||
void ProcessClientMsg(f8::MsgHdr& hdr, int tag);
|
||||
void ProcessMasterServerMsg(f8::MsgHdr& hdr, int tag);
|
||||
void ProcessTargetServerMsg(f8::MsgHdr& hdr, int tag);
|
||||
void ProcessClientMsg(f8::MsgHdr& hdr);
|
||||
void ProcessMasterServerMsg(f8::MsgHdr& hdr);
|
||||
void ProcessTargetServerMsg(f8::MsgHdr& hdr);
|
||||
|
||||
void InitLog();
|
||||
void UnInitLog();
|
||||
|
||||
bool ParseOpt();
|
||||
void FreeSocketMsgQueue();
|
||||
void FreeUdpMsgQueue();
|
||||
void FreeIMMsgQueue();
|
||||
|
||||
public:
|
||||
int argc = 0;
|
||||
char** argv = nullptr;
|
||||
volatile bool terminated = false;
|
||||
volatile bool shutdowned = false;
|
||||
std::set<int> flags;
|
||||
PerfMonitor perf;
|
||||
a8::uuid::SnowFlake uuid;
|
||||
|
||||
public:
|
||||
int node_id = 0;
|
||||
int instance_id = 0;
|
||||
|
||||
private:
|
||||
int argc_ = 0;
|
||||
char** argv_ = nullptr;
|
||||
PerfMonitor perf_;
|
||||
volatile bool terminated_ = false;
|
||||
volatile bool shutdowned_ = false;
|
||||
|
||||
int node_id_ = 0;
|
||||
int instance_id_ = 0;
|
||||
std::set<int> flags_;
|
||||
|
||||
std::shared_ptr<a8::uuid::SnowFlake> uuid_;
|
||||
std::mutex *loop_mutex_ = nullptr;
|
||||
std::condition_variable *loop_cond_ = nullptr;
|
||||
|
||||
@ -86,14 +75,15 @@ private:
|
||||
MsgNode* bot_node_ = nullptr;
|
||||
MsgNode* work_node_ = nullptr;
|
||||
|
||||
std::mutex* udp_msg_mutex_ = nullptr;
|
||||
UdpMsgNode* udp_top_node_ = nullptr;
|
||||
UdpMsgNode* udp_bot_node_ = nullptr;
|
||||
UdpMsgNode* udp_work_node_ = nullptr;
|
||||
std::mutex* im_msg_mutex_ = nullptr;
|
||||
IMMsgNode* im_top_node_ = nullptr;
|
||||
IMMsgNode* im_bot_node_ = nullptr;
|
||||
IMMsgNode* im_work_node_ = nullptr;
|
||||
|
||||
std::map<long long, a8::XParams> context_hash_;
|
||||
|
||||
public:
|
||||
int msgnode_size_ = 0 ;
|
||||
int udp_msgnode_size_ = 0 ;
|
||||
int working_msgnode_size_ = 0;
|
||||
int udp_working_msgnode_size_ = 0;
|
||||
|
||||
};
|
||||
|
@ -7,33 +7,37 @@ enum SocketFrom_e
|
||||
SF_MasterServer,
|
||||
};
|
||||
|
||||
enum SocketTag_e
|
||||
{
|
||||
ST_Tcp = 1,
|
||||
ST_Udp,
|
||||
};
|
||||
|
||||
enum InnerMesssage_e
|
||||
{
|
||||
IM_ClientSocketDisconnect = 100,
|
||||
IM_PlayerOffline,
|
||||
IM_ExecGM,
|
||||
IM_UpStreamDisconnect,
|
||||
IM_UpStreamConnect,
|
||||
IM_HandleRedirect
|
||||
IM_TargetConnDisconnect,
|
||||
IM_MasterSvrDisconnect,
|
||||
IM_TargetConnConnect,
|
||||
};
|
||||
|
||||
//网络处理对象
|
||||
enum NetHandler_e
|
||||
{
|
||||
HID_GCListener,
|
||||
HID_MasterMgr,
|
||||
HID_MasterSvrMgr,
|
||||
};
|
||||
|
||||
enum PlayerState_e
|
||||
{
|
||||
PS_None,
|
||||
PS_InRoom,
|
||||
PS_Matching,
|
||||
PS_WaitingMatch
|
||||
};
|
||||
|
||||
const char* const PROJ_NAME_FMT = "game%d_wsproxy";
|
||||
const char* const PROJ_ROOT_FMT = "/data/logs/%s";
|
||||
|
||||
const int POSTFIX_LEN = 7;
|
||||
|
||||
const int MAX_NODE_ID = 8;
|
||||
const int MAX_INSTANCE_ID = 500;
|
||||
|
||||
const int ALLOC_TARGET_SERVER_SUCCESS_TIMER_EVENT = a8::TIMER_USER_EVENT + 1;
|
||||
const char* const azw_account_id = "6001_2001_oJqfX5c4pvW-wlarmcrvEO6BQjd8";
|
||||
|
@ -1,89 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include "downstream.h"
|
||||
#include "upstream.h"
|
||||
#include "longsessionmgr.h"
|
||||
#include "GCListener.h"
|
||||
#include "longsession.h"
|
||||
#include "kcpsession.h"
|
||||
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
void DownStream::Init(int socket_handle, std::weak_ptr<UpStream> up)
|
||||
{
|
||||
socket_handle_ = socket_handle;
|
||||
up_ = up;
|
||||
long_session_wp_ = LongSessionMgr::Instance()->GetSession(socket_handle_);
|
||||
is_long_session_ = !long_session_wp_.expired();
|
||||
}
|
||||
|
||||
void DownStream::ReBindUpStream(std::weak_ptr<UpStream> up)
|
||||
{
|
||||
up_ = up;
|
||||
}
|
||||
|
||||
void DownStream::ForwardUpStreamMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
char* buff = (char*)malloc(sizeof(f8::PackHead) + hdr.buflen);
|
||||
f8::PackHead* head = (f8::PackHead*)buff;
|
||||
head->packlen = hdr.buflen;
|
||||
head->msgid = hdr.msgid;
|
||||
head->seqid = hdr.seqid;
|
||||
head->magic_code = f8::MAGIC_CODE;
|
||||
head->ext_len = hdr.buflen >> 16;
|
||||
if (hdr.buflen > 0) {
|
||||
memmove(buff + sizeof(f8::PackHead), hdr.buf, hdr.buflen);
|
||||
}
|
||||
|
||||
if (auto long_session = long_session_wp_.lock(); !long_session_wp_.expired()) {
|
||||
if (hdr.msgid == ss::_SS_CMPing) {
|
||||
ss::SS_SMPing msg;
|
||||
msg.set_source(1);
|
||||
{
|
||||
free(buff);
|
||||
|
||||
buff = (char*)malloc(sizeof(f8::PackHead) + msg.ByteSize());
|
||||
f8::PackHead* head = (f8::PackHead*)buff;
|
||||
head->packlen = msg.ByteSize();
|
||||
head->msgid = hdr.msgid;
|
||||
head->seqid = hdr.seqid;
|
||||
head->magic_code = f8::MAGIC_CODE;
|
||||
head->ext_len = hdr.buflen >> 16;
|
||||
msg.SerializeToArray(buff + sizeof(f8::PackHead), head->packlen);
|
||||
long_session->GetKcpSession()->SendClientMsg(buff, sizeof(f8::PackHead) + head->packlen);
|
||||
}
|
||||
} else {
|
||||
long_session->GetKcpSession()->SendClientMsg(buff, sizeof(f8::PackHead) + head->packlen);
|
||||
}
|
||||
} else {
|
||||
GCListener::Instance()->SendBuf(hdr.socket_handle, buff, sizeof(f8::PackHead) + head->packlen);
|
||||
}
|
||||
free(buff);
|
||||
}
|
||||
|
||||
void DownStream::OnClose()
|
||||
{
|
||||
if (!GetUpStream().expired()) {
|
||||
ss::SS_WSP_SocketDisconnect msg;
|
||||
GetUpStream().lock()->SendMsg(socket_handle_, msg);
|
||||
}
|
||||
if (!long_session_wp_.expired()) {
|
||||
LongSessionMgr::Instance()->DelSession(socket_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
void DownStream::ProcCMMsg(f8::MsgHdr& hdr, int tag)
|
||||
{
|
||||
if (hdr.msgid == ss::_SS_CMPing && IsLongSession() && tag == ST_Tcp) {
|
||||
ss::SS_SMPing msg;
|
||||
GCListener::Instance()->SendMsgEx(socket_handle_, ss::_SS_CMPing, msg);
|
||||
if (!long_session_wp_.expired()) {
|
||||
long_session_wp_.lock()->UpdatePing();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!GetUpStream().expired()) {
|
||||
GetUpStream().lock()->ForwardClientMsg(hdr);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class UpStream;
|
||||
class LongSession;
|
||||
class DownStream
|
||||
{
|
||||
public:
|
||||
|
||||
void Init(int socket_handle, std::weak_ptr<UpStream> up);
|
||||
|
||||
int GetSocketHandle() const { return socket_handle_; }
|
||||
std::weak_ptr<UpStream> GetUpStream() const { return up_; }
|
||||
void ReBindUpStream(std::weak_ptr<UpStream> up);
|
||||
bool IsLongSession() { return is_long_session_; }
|
||||
void ProcCMMsg(f8::MsgHdr& hdr, int tag);
|
||||
|
||||
void ForwardUpStreamMsg(f8::MsgHdr& hdr);
|
||||
void OnClose();
|
||||
|
||||
private:
|
||||
int socket_handle_ = a8::INVALID_SOCKET_HANDLE;
|
||||
std::weak_ptr<UpStream> up_;
|
||||
bool is_long_session_ = false;
|
||||
std::weak_ptr<LongSession> long_session_wp_;
|
||||
};
|
@ -1,159 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <f8/udplog.h>
|
||||
#include <f8/msgqueue.h>
|
||||
|
||||
#include "downstreammgr.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
#include "downstream.h"
|
||||
#include "upstream.h"
|
||||
#include "upstreammgr.h"
|
||||
#include "GCListener.h"
|
||||
#include "app.h"
|
||||
#include "mastermgr.h"
|
||||
|
||||
struct PendingAccount
|
||||
{
|
||||
int socket_handle = 0;
|
||||
std::string account_id;
|
||||
long long add_tick = 0;
|
||||
f8::TimerWp timer_wp;
|
||||
};
|
||||
|
||||
void DownStreamMgr::Init()
|
||||
{
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_ClientSocketDisconnect,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
int socket_handle = args.Get<int>(0);
|
||||
OnClientDisconnect(socket_handle);
|
||||
});
|
||||
}
|
||||
|
||||
void DownStreamMgr::UnInit()
|
||||
{
|
||||
socket_hash_.clear();
|
||||
pending_account_hash_.clear();
|
||||
}
|
||||
|
||||
void DownStreamMgr::OnClientDisconnect(int socket_handle)
|
||||
{
|
||||
auto down_wp = GetDownStream(socket_handle);
|
||||
if (auto down = down_wp.lock(); !down_wp.expired()) {
|
||||
down->OnClose();
|
||||
socket_hash_.erase(socket_handle);
|
||||
}
|
||||
RemovePendingAccount(socket_handle);
|
||||
MasterMgr::Instance()->RemoveRequest(socket_handle);
|
||||
}
|
||||
|
||||
void DownStreamMgr::OnUpStreamDisconnect(int instance_id)
|
||||
{
|
||||
std::list<std::shared_ptr<DownStream>> delete_client;
|
||||
for (auto& pair : socket_hash_) {
|
||||
if (!pair.second->GetUpStream().expired() &&
|
||||
pair.second->GetUpStream().lock()->instance_id == instance_id) {
|
||||
delete_client.push_back(pair.second);
|
||||
}
|
||||
}
|
||||
for (auto& client : delete_client) {
|
||||
RemovePendingAccount(client->GetSocketHandle());
|
||||
GCListener::Instance()->ForceCloseClient(client->GetSocketHandle());
|
||||
socket_hash_.erase(client->GetSocketHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void DownStreamMgr::OnUpStreamConnect(int instance_id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::weak_ptr<DownStream> DownStreamMgr::GetDownStream(int sockhandle)
|
||||
{
|
||||
auto itr = socket_hash_.find(sockhandle);
|
||||
return itr != socket_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void DownStreamMgr::BindUpStream(int socket_handle, int instance_id)
|
||||
{
|
||||
std::weak_ptr<UpStream> up_wp = UpStreamMgr::Instance()->GetUpStreamById(instance_id);
|
||||
if (!up_wp.expired()) {
|
||||
auto down_wp = GetDownStream(socket_handle);
|
||||
if (auto down = down_wp.lock(); !down_wp.expired()) {
|
||||
down->ReBindUpStream(up_wp);
|
||||
} else {
|
||||
down = std::make_shared<DownStream>();
|
||||
down->Init(socket_handle, up_wp);
|
||||
socket_hash_[down->GetSocketHandle()] = down;
|
||||
f8::UdpLog::Instance()->Info("BindUpStream socket_handle:%d",
|
||||
{
|
||||
socket_handle
|
||||
});
|
||||
{
|
||||
if (auto pending_account = GetPendingAccount(socket_handle)) {
|
||||
long long cur_tick = a8::XGetTickCount();
|
||||
if (cur_tick - pending_account->add_tick > App::Instance()->GetPerf().max_join_time) {
|
||||
App::Instance()->GetPerf().max_join_time = cur_tick - pending_account->add_tick;
|
||||
}
|
||||
f8::UdpLog::Instance()->Info("BindUpStream account_id:%s",
|
||||
{
|
||||
pending_account->account_id
|
||||
});
|
||||
RemovePendingAccount(socket_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownStreamMgr::AddPendingAccount(const std::string& account_id, int socket_handle, long long req_tick)
|
||||
{
|
||||
f8::UdpLog::Instance()->Info("AddPendingAccount %s %d", {account_id, socket_handle});
|
||||
if (!GetPendingAccount(socket_handle)){
|
||||
auto timer_wp = f8::Timer::Instance()->SetTimeoutWpEx
|
||||
(
|
||||
1000 * 10,
|
||||
[this, socket_handle] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
pending_account_hash_.erase(socket_handle);
|
||||
App::Instance()->GetPerf().max_join_time =
|
||||
std::max((long long)1000 * 10, App::Instance()->GetPerf().max_join_time);
|
||||
}
|
||||
},
|
||||
&timer_attacher_
|
||||
);
|
||||
auto p = std::make_shared<PendingAccount>();
|
||||
p->socket_handle = socket_handle;
|
||||
p->account_id = account_id;
|
||||
p->add_tick = req_tick;
|
||||
p->timer_wp = timer_wp;
|
||||
pending_account_hash_[socket_handle] = p;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<PendingAccount> DownStreamMgr::GetPendingAccount(int socket_handle)
|
||||
{
|
||||
auto itr = pending_account_hash_.find(socket_handle);
|
||||
return itr != pending_account_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void DownStreamMgr::RemovePendingAccount(int socket_handle)
|
||||
{
|
||||
auto itr = pending_account_hash_.find(socket_handle);
|
||||
if (itr != pending_account_hash_.end()) {
|
||||
f8::UdpLog::Instance()->Info("RemovePendingAccount %d", {socket_handle});
|
||||
if (!itr->second->timer_wp.expired()) {
|
||||
f8::Timer::Instance()->Delete(itr->second->timer_wp);
|
||||
}
|
||||
pending_account_hash_.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
int DownStreamMgr::GetDownStreamCount()
|
||||
{
|
||||
return socket_hash_.size();
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <f8/timer.h>
|
||||
|
||||
class DownStream;
|
||||
struct PendingAccount;
|
||||
class DownStreamMgr : public a8::Singleton<DownStreamMgr>
|
||||
{
|
||||
private:
|
||||
DownStreamMgr() {};
|
||||
friend class a8::Singleton<DownStreamMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
void OnUpStreamDisconnect(int instance_id);
|
||||
void OnUpStreamConnect(int instance_id);
|
||||
std::weak_ptr<DownStream> GetDownStream(int sockhande);
|
||||
void BindUpStream(int socket_handle, int instance_id);
|
||||
void AddPendingAccount(const std::string& account_id, int socket_handle, long long req_tick);
|
||||
int GetDownStreamCount();
|
||||
|
||||
private:
|
||||
|
||||
void OnClientDisconnect(int socket_handle);
|
||||
std::shared_ptr<PendingAccount> GetPendingAccount(int socket_handle);
|
||||
void RemovePendingAccount(int socket_handle);
|
||||
|
||||
private:
|
||||
f8::Attacher timer_attacher_;
|
||||
std::map<int, std::shared_ptr<DownStream>> socket_hash_;
|
||||
std::map<int, std::shared_ptr<PendingAccount>> pending_account_hash_;
|
||||
};
|
3
server/wsproxy/gameclient.cc
Normal file
3
server/wsproxy/gameclient.cc
Normal file
@ -0,0 +1,3 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include "gameclient.h"
|
10
server/wsproxy/gameclient.h
Normal file
10
server/wsproxy/gameclient.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
class TargetConn;
|
||||
class GameClient
|
||||
{
|
||||
public:
|
||||
int socket_handle = a8::INVALID_SOCKET_HANDLE;
|
||||
TargetConn* conn = nullptr;
|
||||
|
||||
};
|
134
server/wsproxy/gameclientmgr.cc
Normal file
134
server/wsproxy/gameclientmgr.cc
Normal file
@ -0,0 +1,134 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include "gameclientmgr.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
#include "gameclient.h"
|
||||
#include "target_conn.h"
|
||||
#include "target_conn_mgr.h"
|
||||
#include "GCListener.h"
|
||||
#include "app.h"
|
||||
|
||||
void GameClientMgr::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void GameClientMgr::UnInit()
|
||||
{
|
||||
for (auto& pair : socket_hash_) {
|
||||
delete pair.second;
|
||||
}
|
||||
socket_hash_.clear();
|
||||
pending_account_hash_.clear();
|
||||
}
|
||||
|
||||
void GameClientMgr::OnClientDisconnect(a8::XParams& param)
|
||||
{
|
||||
GameClient* client = GetGameClientBySocket(param.sender);
|
||||
if (client) {
|
||||
if (client->conn) {
|
||||
ss::SS_WSP_SocketDisconnect msg;
|
||||
client->conn->SendMsg(param.sender, msg);
|
||||
}
|
||||
socket_hash_.erase(param.sender);
|
||||
delete client;
|
||||
}
|
||||
RemovePendingAccount(param.sender);
|
||||
}
|
||||
|
||||
void GameClientMgr::OnTargetServerDisconnect(a8::XParams& param)
|
||||
{
|
||||
std::list<GameClient*> delete_client;
|
||||
for (auto& pair : socket_hash_) {
|
||||
if (pair.second->conn && pair.second->conn->instance_id == param.sender.GetInt()) {
|
||||
delete_client.push_back(pair.second);
|
||||
}
|
||||
}
|
||||
for (auto& client : delete_client) {
|
||||
RemovePendingAccount(client->socket_handle);
|
||||
GCListener::Instance()->ForceCloseClient(client->socket_handle);
|
||||
socket_hash_.erase(client->socket_handle);
|
||||
delete client;
|
||||
}
|
||||
}
|
||||
|
||||
void GameClientMgr::OnTargetServerConnect(a8::XParams& param)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GameClient* GameClientMgr::GetGameClientBySocket(int sockhandle)
|
||||
{
|
||||
auto itr = socket_hash_.find(sockhandle);
|
||||
return itr != socket_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void GameClientMgr::BindTargetConn(int socket_handle, int conn_instance_id)
|
||||
{
|
||||
TargetConn* conn = TargetConnMgr::Instance()->GetConnById(conn_instance_id);
|
||||
if (conn) {
|
||||
GameClient* client = GetGameClientBySocket(socket_handle);
|
||||
if (client) {
|
||||
client->conn = conn;
|
||||
} else {
|
||||
client = new GameClient();
|
||||
client->socket_handle = socket_handle;
|
||||
client->conn = conn;
|
||||
socket_hash_[client->socket_handle] = client;
|
||||
a8::UdpLog::Instance()->Info("BindTargetConn socket_handle:%d", {socket_handle});
|
||||
{
|
||||
auto itr = pending_account_hash_.find(socket_handle);
|
||||
if (itr != pending_account_hash_.end()) {
|
||||
std::string account_id = std::get<0>(itr->second);
|
||||
long long req_tick = std::get<1>(itr->second);
|
||||
long long cur_tick = a8::XGetTickCount();
|
||||
if (cur_tick - req_tick > App::Instance()->perf.max_join_time) {
|
||||
App::Instance()->perf.max_join_time = cur_tick - req_tick;
|
||||
}
|
||||
if (account_id == azw_account_id) {
|
||||
a8::UdpLog::Instance()->Info("%s join time:%d",
|
||||
{
|
||||
account_id,
|
||||
cur_tick - req_tick
|
||||
});
|
||||
}
|
||||
a8::UdpLog::Instance()->Info("BindTargetConn account_id:%s", {account_id});
|
||||
RemovePendingAccount(socket_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameClientMgr::AddPendingAccount(const std::string& account_id, int socket_handle, long long req_tick)
|
||||
{
|
||||
a8::UdpLog::Instance()->Info("AddPendingAccount %s %d", {account_id, socket_handle});
|
||||
auto itr = pending_account_hash_.find(socket_handle);
|
||||
if (itr == pending_account_hash_.end()){
|
||||
timer_list* timer = a8::Timer::Instance()->AddDeadLineTimerAndAttach(1000 * 10,
|
||||
a8::XParams()
|
||||
.SetSender(socket_handle),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
GameClientMgr::Instance()->pending_account_hash_.erase(param.sender);
|
||||
App::Instance()->perf.max_join_time = std::max((long long)1000 * 10, App::Instance()->perf.max_join_time);
|
||||
},
|
||||
&timer_attacher_.timer_list_
|
||||
);
|
||||
pending_account_hash_[socket_handle] = std::make_tuple(
|
||||
account_id,
|
||||
req_tick,
|
||||
timer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void GameClientMgr::RemovePendingAccount(int socket_handle)
|
||||
{
|
||||
a8::UdpLog::Instance()->Info("RemovePendingAccount %d", {socket_handle});
|
||||
auto itr = pending_account_hash_.find(socket_handle);
|
||||
if (itr != pending_account_hash_.end()) {
|
||||
a8::Timer::Instance()->DeleteTimer(std::get<2>(itr->second));
|
||||
pending_account_hash_.erase(itr);
|
||||
}
|
||||
}
|
32
server/wsproxy/gameclientmgr.h
Normal file
32
server/wsproxy/gameclientmgr.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/timer.h>
|
||||
|
||||
class GameClient;
|
||||
class GameClientMgr : public a8::Singleton<GameClientMgr>
|
||||
{
|
||||
private:
|
||||
GameClientMgr() {};
|
||||
friend class a8::Singleton<GameClientMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
void OnClientDisconnect(a8::XParams& param);
|
||||
void OnTargetServerDisconnect(a8::XParams& param);
|
||||
void OnTargetServerConnect(a8::XParams& param);
|
||||
GameClient* GetGameClientBySocket(int sockhande);
|
||||
void BindTargetConn(int socket_handle, int conn_instance_id);
|
||||
void AddPendingAccount(const std::string& account_id, int socket_handle, long long req_tick);
|
||||
|
||||
private:
|
||||
|
||||
void RemovePendingAccount(int socket_handle);
|
||||
|
||||
private:
|
||||
a8::TimerAttacher timer_attacher_;
|
||||
std::map<int, GameClient*> socket_hash_;
|
||||
std::map<int, std::tuple<std::string, long long, timer_list*>> pending_account_hash_;
|
||||
};
|
@ -1,19 +1,16 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <a8/mutable_xobject.h>
|
||||
#include <f8/msgqueue.h>
|
||||
#include <f8/jsonhttprequest.h>
|
||||
|
||||
#include "handlermgr.h"
|
||||
|
||||
#include "GCListener.h"
|
||||
#include "mastermgr.h"
|
||||
#include "mastersvrmgr.h"
|
||||
#include "app.h"
|
||||
#include "jsondatamgr.h"
|
||||
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
static void _GMOpsSelfChecking(std::shared_ptr<f8::JsonHttpRequest> request)
|
||||
static void _GMOpsSelfChecking(f8::JsonHttpRequest* request)
|
||||
{
|
||||
request->resp_xobj->SetVal("errcode", 0);
|
||||
request->resp_xobj->SetVal("errmsg", "");
|
||||
@ -21,28 +18,11 @@ static void _GMOpsSelfChecking(std::shared_ptr<f8::JsonHttpRequest> request)
|
||||
request->resp_xobj->SetVal("max_rundelay", 10);
|
||||
}
|
||||
|
||||
static void _GMOpsGetNodeId(std::shared_ptr<f8::JsonHttpRequest> request)
|
||||
static void _GMOpsGetNodeId(f8::JsonHttpRequest* request)
|
||||
{
|
||||
request->resp_xobj->SetVal("errcode", 0);
|
||||
request->resp_xobj->SetVal("errmsg", "");
|
||||
request->resp_xobj->SetVal("node_id", App::Instance()->GetNodeId());
|
||||
}
|
||||
|
||||
static void _GMOpsSetKcpSwitch(std::shared_ptr<f8::JsonHttpRequest> request)
|
||||
{
|
||||
request->resp_xobj->SetVal("errcode", 0);
|
||||
request->resp_xobj->SetVal("errmsg", "");
|
||||
if (request->params->HasKey("open")) {
|
||||
JsonDataMgr::Instance()->SetKcpSwitch(request->params->At("open")->AsXValue().GetInt());
|
||||
}
|
||||
request->resp_xobj->SetVal("is_open", JsonDataMgr::Instance()->GetKcpConf().open);
|
||||
}
|
||||
|
||||
static void _GMOpsGetKcpSwitch(std::shared_ptr<f8::JsonHttpRequest> request)
|
||||
{
|
||||
request->resp_xobj->SetVal("errcode", 0);
|
||||
request->resp_xobj->SetVal("errmsg", "");
|
||||
request->resp_xobj->SetVal("is_open", JsonDataMgr::Instance()->GetKcpConf().open);
|
||||
request->resp_xobj->SetVal("node_id", App::Instance()->node_id);
|
||||
}
|
||||
|
||||
void HandlerMgr::Init()
|
||||
@ -50,19 +30,6 @@ void HandlerMgr::Init()
|
||||
RegisterNetMsgHandlers();
|
||||
RegisterGMMsgHandler("Ops$selfChecking", _GMOpsSelfChecking);
|
||||
RegisterGMMsgHandler("Ops$getNodeId", _GMOpsGetNodeId);
|
||||
RegisterGMMsgHandler("Ops$setKcpSwitch", _GMOpsSetKcpSwitch);
|
||||
RegisterGMMsgHandler("Ops$getKcpSwitch", _GMOpsGetKcpSwitch);
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_ExecGM,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
int socket_handle = args.Get<int>(0);
|
||||
std::string url = args.Get<std::string>(1);
|
||||
std::string query_str = args.Get<std::string>(2);
|
||||
unsigned long saddr = args.Get<unsigned long>(3);
|
||||
ProcGMMsg(saddr, socket_handle, url, query_str);
|
||||
});
|
||||
}
|
||||
|
||||
void HandlerMgr::UnInit()
|
||||
@ -71,7 +38,7 @@ void HandlerMgr::UnInit()
|
||||
|
||||
void HandlerMgr::RegisterNetMsgHandlers()
|
||||
{
|
||||
RegisterNetMsgHandler(&msmsghandler, &MasterMgr::_SS_MS_ResponseTargetServer);
|
||||
RegisterNetMsgHandler(&msmsghandler, &MasterSvrMgr::_SS_MS_ResponseTargetServer);
|
||||
}
|
||||
|
||||
void HandlerMgr::ProcGMMsg(unsigned long saddr, int sockhandle,
|
||||
@ -88,17 +55,19 @@ void HandlerMgr::ProcGMMsg(unsigned long saddr, int sockhandle,
|
||||
std::string msgname = a8::Get(request, "c").GetString() + "$" + a8::Get(request, "a").GetString();
|
||||
auto itr = gmhandlers_.find(msgname);
|
||||
if (itr != gmhandlers_.end()) {
|
||||
auto request = std::make_shared<f8::JsonHttpRequest>();
|
||||
f8::JsonHttpRequest* request = new f8::JsonHttpRequest;
|
||||
request->saddr = saddr;
|
||||
request->socket_handle = sockhandle;
|
||||
request->query_str = querystr;
|
||||
request->params->ReadFromUrlQueryString(querystr);
|
||||
request->request.ReadFromUrlQueryString(querystr);
|
||||
itr->second(request);
|
||||
|
||||
if (!request->pending){
|
||||
std::string response;
|
||||
request->resp_xobj->ToJsonStr(response);
|
||||
GCListener::Instance()->SendText(sockhandle, a8::HttpResponse(response));
|
||||
|
||||
delete request;
|
||||
}
|
||||
} else {
|
||||
GCListener::Instance()->SendText(sockhandle, a8::HttpResponse("{}"));
|
||||
@ -106,7 +75,7 @@ void HandlerMgr::ProcGMMsg(unsigned long saddr, int sockhandle,
|
||||
}
|
||||
|
||||
void HandlerMgr::RegisterGMMsgHandler(const std::string& msgname,
|
||||
void (*handler)(std::shared_ptr<f8::JsonHttpRequest>))
|
||||
void (*handler)(f8::JsonHttpRequest*))
|
||||
{
|
||||
gmhandlers_[msgname] = handler;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <a8/basehttpsession.h>
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
#include "framework/cpp/netmsghandler.h"
|
||||
|
||||
namespace a8
|
||||
{
|
||||
@ -30,7 +30,7 @@ class HandlerMgr : public a8::Singleton<HandlerMgr>
|
||||
private:
|
||||
void RegisterNetMsgHandlers();
|
||||
void RegisterGMMsgHandler(const std::string& msgname,
|
||||
void (*)(std::shared_ptr<f8::JsonHttpRequest>));
|
||||
void (*)(f8::JsonHttpRequest*));
|
||||
|
||||
std::map<std::string, void (*)(std::shared_ptr<f8::JsonHttpRequest>)> gmhandlers_;
|
||||
std::map<std::string, void (*)(f8::JsonHttpRequest*)> gmhandlers_;
|
||||
};
|
||||
|
@ -1 +0,0 @@
|
||||
../../third_party/kcp/ikcp.c
|
@ -1 +0,0 @@
|
||||
../../third_party/kcp/ikcp.h
|
@ -2,114 +2,129 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <f8/utils.h>
|
||||
#include <f8/udplog.h>
|
||||
|
||||
#include "jsondatamgr.h"
|
||||
#include "app.h"
|
||||
|
||||
void JsonDataMgr::Init()
|
||||
{
|
||||
#if MASTER_MODE
|
||||
node_host_mutex_ = new std::mutex();
|
||||
#endif
|
||||
|
||||
if (!f8::IsOnlineEnv()) {
|
||||
work_path_ = a8::Format
|
||||
("../../../conf_test/game%d/%s",
|
||||
if (f8::IsTestEnv()) {
|
||||
work_path_ = a8::Format("/root/pub/%d/%d/conf_test/game%d/wsproxy.test",
|
||||
{
|
||||
GAME_ID,
|
||||
f8::IsTestEnv() ? "wsproxy.test" : "wsproxy.dev"
|
||||
});
|
||||
}
|
||||
|
||||
std::string wsproxy_cluster_json_file;
|
||||
std::string master_cluster_json_file;
|
||||
std::string kcp_conf_json_file;
|
||||
wsproxy_cluster_json_file = a8::Format
|
||||
("%s/node%d/game%d.wsproxy.cluster.json",
|
||||
{
|
||||
work_path_,
|
||||
App::Instance()->GetNodeId(),
|
||||
App::Instance()->instance_id,
|
||||
GAME_ID
|
||||
});
|
||||
master_cluster_json_file = a8::Format
|
||||
("%s/node%d/game%d.masterserver.cluster.json",
|
||||
} else {
|
||||
work_path_ = a8::Format("/root/pub/%d/%d/conf_test/game%d/wsproxy.dev",
|
||||
{
|
||||
work_path_,
|
||||
App::Instance()->GetNodeId(),
|
||||
GAME_ID,
|
||||
App::Instance()->instance_id,
|
||||
GAME_ID
|
||||
});
|
||||
kcp_conf_json_file = a8::Format
|
||||
("%s/kcp_conf.json",
|
||||
}
|
||||
}
|
||||
|
||||
std::string wsproxyserver_cluster_json_file;
|
||||
#if MASTER_MODE
|
||||
std::string masterserver_cluster_json_file;
|
||||
std::string routing_tables_json_file;
|
||||
wsproxyserver_cluster_json_file = a8::Format("%s/node%d/game%d.wsproxy.cluster.json",
|
||||
{
|
||||
work_path_,
|
||||
App::Instance()->node_id,
|
||||
GAME_ID
|
||||
});
|
||||
|
||||
wsproxy_cluster_json_.ReadFromFile(wsproxy_cluster_json_file);
|
||||
master_cluster_json_.ReadFromFile(master_cluster_json_file);
|
||||
kcp_conf_json_.ReadFromFile(kcp_conf_json_file);
|
||||
udp_host_ = GetConf()->At("listen_udp_host")->AsXValue().GetString();
|
||||
udp_port_ = GetConf()->At("listen_udp_port")->AsXValue();
|
||||
masterserver_cluster_json_file = a8::Format("%s/node%d/game%d.masterserver.cluster.json",
|
||||
{
|
||||
kcp_conf_.open = kcp_conf_json_.At("open")->AsXValue();
|
||||
|
||||
kcp_conf_.sndwnd = kcp_conf_json_.At("sndwnd")->AsXValue();
|
||||
kcp_conf_.rcvwnd = kcp_conf_json_.At("rcvwnd")->AsXValue();
|
||||
|
||||
kcp_conf_.nodelay = kcp_conf_json_.At("nodelay")->AsXValue();
|
||||
kcp_conf_.interval = kcp_conf_json_.At("interval")->AsXValue();
|
||||
kcp_conf_.resend = kcp_conf_json_.At("resend")->AsXValue();
|
||||
kcp_conf_.nc = kcp_conf_json_.At("nc")->AsXValue();
|
||||
|
||||
kcp_conf_.rx_minrto = kcp_conf_json_.At("rx_minrto")->AsXValue();
|
||||
kcp_conf_.fastresend = kcp_conf_json_.At("fastresend")->AsXValue();
|
||||
|
||||
f8::UdpLog::Instance()->Info
|
||||
(" kcp_conf open:%d sndwnd:%d rcvwnd:%d "
|
||||
"nodelay:%d interval:%d resend:%d nc:%d "
|
||||
"rx_minrto:%d fastresend:%d",
|
||||
{
|
||||
kcp_conf_.open,
|
||||
|
||||
kcp_conf_.sndwnd,
|
||||
kcp_conf_.rcvwnd,
|
||||
|
||||
kcp_conf_.nodelay,
|
||||
kcp_conf_.interval,
|
||||
kcp_conf_.resend,
|
||||
kcp_conf_.nc,
|
||||
|
||||
kcp_conf_.rx_minrto,
|
||||
kcp_conf_.fastresend
|
||||
work_path_,
|
||||
App::Instance()->node_id,
|
||||
GAME_ID
|
||||
});
|
||||
routing_tables_json_file = a8::Format("%s/routing_tables.json",
|
||||
{
|
||||
work_path_
|
||||
});
|
||||
#else
|
||||
std::string targetserver_cluster_json_file;
|
||||
wsproxyserver_cluster_json_file = a8::Format("%s/game%d.wsproxy.cluster.json",
|
||||
{
|
||||
work_path_,
|
||||
GAME_ID
|
||||
});
|
||||
targetserver_cluster_json_file = a8::Format("%s/game%d.gameserver.cluster.json",
|
||||
{
|
||||
work_path_,
|
||||
GAME_ID
|
||||
});
|
||||
#endif
|
||||
|
||||
wsproxyserver_cluster_json_.ReadFromFile(wsproxyserver_cluster_json_file);
|
||||
#if MASTER_MODE
|
||||
masterserver_cluster_json_.ReadFromFile(masterserver_cluster_json_file);
|
||||
routing_tables_json_.ReadFromFile(routing_tables_json_file);
|
||||
node_host_mutex_->lock();
|
||||
for (int i = 0; i < routing_tables_json_.Size(); ++i) {
|
||||
auto node_conf = routing_tables_json_.At(i);
|
||||
int node_id = node_conf->At("node_id")->AsXValue();
|
||||
std::string host = node_conf->At("host")->AsXValue();
|
||||
if (node_host_hash_.find(node_id) != node_host_hash_.end()) {
|
||||
abort();
|
||||
}
|
||||
node_host_hash_[node_id] = host;
|
||||
}
|
||||
node_host_mutex_->unlock();
|
||||
#else
|
||||
targetserver_cluster_json_.ReadFromFile(targetserver_cluster_json_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
void JsonDataMgr::UnInit()
|
||||
{
|
||||
#if MASTER_MODE
|
||||
delete node_host_mutex_;
|
||||
node_host_mutex_ = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<a8::XObject> JsonDataMgr::GetConf()
|
||||
{
|
||||
for (int i = 0; i < wsproxy_cluster_json_.Size(); ++i) {
|
||||
std::shared_ptr<a8::XObject> conf = wsproxy_cluster_json_.At(i);
|
||||
if (conf->At("instance_id")->AsXValue().GetInt() == App::Instance()->GetInstanceId()) {
|
||||
return conf;
|
||||
if (App::Instance()->instance_id < 1 || App::Instance()->instance_id > wsproxyserver_cluster_json_.Size()) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
A8_ABORT();
|
||||
return wsproxyserver_cluster_json_[App::Instance()->instance_id - 1];
|
||||
}
|
||||
|
||||
void JsonDataMgr::TraverseMaster(std::function<void (int, std::string, int)> cb)
|
||||
std::shared_ptr<a8::XObject> JsonDataMgr::GetMasterServerClusterConf()
|
||||
{
|
||||
for (int i = 0; i < master_cluster_json_.Size(); ++i) {
|
||||
auto master_svr_conf = master_cluster_json_.At(i);
|
||||
int instance_id = master_svr_conf->At("instance_id")->AsXValue();
|
||||
std::string remote_ip = master_svr_conf->At("ip")->AsXValue();
|
||||
int remote_port = master_svr_conf->At("port")->AsXValue();
|
||||
cb(instance_id, remote_ip, remote_port);
|
||||
}
|
||||
return std::make_shared<a8::XObject>(masterserver_cluster_json_);
|
||||
}
|
||||
|
||||
void JsonDataMgr::SetKcpSwitch(int is_open)
|
||||
#if MASTER_MODE
|
||||
|
||||
bool JsonDataMgr::GetNodeHost(int node_id, std::string& host)
|
||||
{
|
||||
kcp_conf_.open = is_open ? 1 : 0;
|
||||
bool found = false;
|
||||
node_host_mutex_->lock();
|
||||
auto itr = node_host_hash_.find(node_id);
|
||||
if (itr != node_host_hash_.end()) {
|
||||
//!!!因为std::string基于引用计数多线程下直接复制的话会有问题,所以要用这种方式赋值
|
||||
host = itr->second.c_str();
|
||||
found = true;
|
||||
}
|
||||
node_host_mutex_->unlock();
|
||||
return found;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::shared_ptr<a8::XObject> JsonDataMgr::GetTargetServerClusterConf()
|
||||
{
|
||||
return std::make_shared<a8::XObject>(targetserver_cluster_json_);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,23 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/singleton.h>
|
||||
|
||||
struct KcpConf
|
||||
{
|
||||
int open = 0;
|
||||
|
||||
int sndwnd = 0;
|
||||
int rcvwnd = 0;
|
||||
|
||||
int nodelay = 0;
|
||||
int interval = 0;
|
||||
int resend = 0;
|
||||
int nc = 0;
|
||||
|
||||
int rx_minrto = 0;
|
||||
int fastresend = 0;
|
||||
};
|
||||
|
||||
class JsonDataMgr : public a8::Singleton<JsonDataMgr>
|
||||
{
|
||||
private:
|
||||
@ -28,19 +10,23 @@ class JsonDataMgr : public a8::Singleton<JsonDataMgr>
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
std::string GetUdpHost() { return udp_host_; }
|
||||
int GetUdpPort() { return udp_port_; }
|
||||
std::shared_ptr<a8::XObject> GetConf();
|
||||
void TraverseMaster(std::function<void (int, std::string, int)> cb);
|
||||
const KcpConf& GetKcpConf() { return kcp_conf_; }
|
||||
void SetKcpSwitch(int is_open);
|
||||
std::shared_ptr<a8::XObject> GetMasterServerClusterConf();
|
||||
#if MASTER_MODE
|
||||
bool GetNodeHost(int node_id, std::string& host);
|
||||
#else
|
||||
std::shared_ptr<a8::XObject> GetTargetServerClusterConf();
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::string work_path_ = "../config";
|
||||
a8::XObject wsproxy_cluster_json_;
|
||||
a8::XObject master_cluster_json_;
|
||||
a8::XObject kcp_conf_json_;
|
||||
std::string udp_host_;
|
||||
int udp_port_ = 0;
|
||||
KcpConf kcp_conf_ = {};
|
||||
a8::XObject wsproxyserver_cluster_json_;
|
||||
a8::XObject masterserver_cluster_json_;
|
||||
#if MASTER_MODE
|
||||
std::mutex* node_host_mutex_ = nullptr;
|
||||
a8::XObject routing_tables_json_;
|
||||
std::map<int, std::string> node_host_hash_;
|
||||
#else
|
||||
a8::XObject targetserver_cluster_json_;
|
||||
#endif
|
||||
};
|
||||
|
@ -1,185 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
#include <f8/udplog.h>
|
||||
|
||||
#include "kcpsession.h"
|
||||
#include "longsessionmgr.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "app.h"
|
||||
|
||||
static const int DEFAULT_MAX_RECV_BUFFERSIZE = 1024 * 64;
|
||||
|
||||
static int UdpOutput(const char *buf, int len, ikcpcb *kcp, void *user)
|
||||
{
|
||||
KcpSession* session = (KcpSession*)user;
|
||||
a8::UdpPacket pkt;
|
||||
pkt.buf = buf;
|
||||
pkt.buf_len = len;
|
||||
pkt.remote_addr = session->GetAddr();
|
||||
LongSessionMgr::Instance()->GetUdpListener()->SendUdpPacket(&pkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
KcpSession::KcpSession()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KcpSession::~KcpSession()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KcpSession::Init(int socket_handle, int secret_key_place)
|
||||
{
|
||||
socket_handle_ = socket_handle;
|
||||
secret_key_ = App::Instance()->NewUuid();
|
||||
kcp_ = ikcp_create(socket_handle_, (void*)this);
|
||||
const KcpConf& kcp_conf = JsonDataMgr::Instance()->GetKcpConf();
|
||||
ikcp_wndsize(kcp_, kcp_conf.sndwnd, kcp_conf.rcvwnd);
|
||||
ikcp_nodelay(kcp_, kcp_conf.nodelay, kcp_conf.interval, kcp_conf.resend, kcp_conf.nc);
|
||||
kcp_->rx_minrto = kcp_conf.rx_minrto;
|
||||
kcp_->fastresend = kcp_conf.fastresend;
|
||||
secret_key_place_ = secret_key_place;
|
||||
if (secret_key_place_ > 0) {
|
||||
secret_key_place_ = 1;
|
||||
} else if (secret_key_place_ < 0) {
|
||||
secret_key_place_ = 0;
|
||||
}
|
||||
kcp_->output = UdpOutput;
|
||||
init_tick_ = a8::XGetTickCount();
|
||||
}
|
||||
|
||||
void KcpSession::UnInit()
|
||||
{
|
||||
if (kcp_) {
|
||||
ikcp_release(kcp_);
|
||||
kcp_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void KcpSession::Update(long long tick)
|
||||
{
|
||||
ikcp_update(kcp_, tick - init_tick_);
|
||||
UpdateInput();
|
||||
}
|
||||
|
||||
void KcpSession::SendClientMsg(char* buf, int buf_len)
|
||||
{
|
||||
ikcp_send(kcp_, buf, buf_len);
|
||||
}
|
||||
|
||||
void KcpSession::OnRecvPacket(a8::UdpPacket* pkt)
|
||||
{
|
||||
const int IKCP_OVERHEAD = 24;
|
||||
|
||||
remote_addr_ = pkt->remote_addr;
|
||||
if (GetSecretKeyPlace()) {
|
||||
char* buf = (char*)malloc(pkt->buf_len - GetSecretKeyLen());
|
||||
int buflen = pkt->buf_len - GetSecretKeyLen();
|
||||
memmove(buf, pkt->buf, IKCP_OVERHEAD);
|
||||
if (pkt->buf_len > IKCP_OVERHEAD + GetSecretKeyLen()) {
|
||||
memmove(buf + IKCP_OVERHEAD, pkt->buf + IKCP_OVERHEAD + GetSecretKeyLen(), buflen - IKCP_OVERHEAD);
|
||||
}
|
||||
ikcp_input(kcp_, buf, buflen);
|
||||
free(buf);
|
||||
} else {
|
||||
ikcp_input(kcp_, pkt->buf, pkt->buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
void KcpSession::UpdateInput()
|
||||
{
|
||||
char buf[DEFAULT_MAX_RECV_BUFFERSIZE];
|
||||
int buflen = ikcp_recv(kcp_, buf, DEFAULT_MAX_RECV_BUFFERSIZE - 10);
|
||||
if (buflen <= 0) {
|
||||
return;
|
||||
}
|
||||
OnSocketRead(buf, buflen);
|
||||
}
|
||||
|
||||
void KcpSession::DecodeUserPacket(char* buf, int& offset, unsigned int buflen)
|
||||
{
|
||||
if (GetSecretKeyPlace()) {
|
||||
DecodeUserPacketNew(buf, offset, buflen);
|
||||
} else {
|
||||
DecodeUserPacketOld(buf, offset, buflen);
|
||||
}
|
||||
}
|
||||
|
||||
int KcpSession::GetSecretKeyPlace()
|
||||
{
|
||||
return secret_key_place_;
|
||||
}
|
||||
|
||||
void KcpSession::DecodeUserPacketOld(char* buf, int& offset, unsigned int buflen)
|
||||
{
|
||||
bool warning = false;
|
||||
while (buflen - offset >= sizeof(f8::PackHead) + GetSecretKeyLen()) {
|
||||
long long secret_key = KcpSession::ReadSecretKey(&buf[offset], buflen);
|
||||
if (secret_key != secret_key_) {
|
||||
warning = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
f8::PackHead* p = (f8::PackHead*)&buf[offset + GetSecretKeyLen()];
|
||||
if (p->magic_code == f8::MAGIC_CODE) {
|
||||
if (buflen - offset < sizeof(f8::PackHead) + p->packlen + GetSecretKeyLen()) {
|
||||
break;
|
||||
}
|
||||
App::Instance()->AddSocketMsg(SF_Client,
|
||||
socket_handle_,
|
||||
0,
|
||||
//saddr,
|
||||
p->msgid,
|
||||
p->seqid,
|
||||
&buf[offset + sizeof(f8::PackHead) + GetSecretKeyLen()],
|
||||
p->packlen,
|
||||
ST_Udp);
|
||||
offset += sizeof(f8::PackHead) + p->packlen + GetSecretKeyLen();
|
||||
} else {
|
||||
warning = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
f8::UdpLog::Instance()->Warning("收到kcp client非法数据包1", {});
|
||||
}
|
||||
}
|
||||
|
||||
void KcpSession::DecodeUserPacketNew(char* buf, int& offset, unsigned int buflen)
|
||||
{
|
||||
bool warning = false;
|
||||
while (buflen - offset >= sizeof(f8::PackHead)) {
|
||||
f8::PackHead* p = (f8::PackHead*)&buf[offset];
|
||||
if (p->magic_code == f8::MAGIC_CODE) {
|
||||
if (buflen - offset < sizeof(f8::PackHead) + p->packlen) {
|
||||
break;
|
||||
}
|
||||
App::Instance()->AddSocketMsg(SF_Client,
|
||||
socket_handle_,
|
||||
0,
|
||||
//saddr,
|
||||
p->msgid,
|
||||
p->seqid,
|
||||
&buf[offset + sizeof(f8::PackHead)],
|
||||
p->packlen,
|
||||
ST_Udp);
|
||||
offset += sizeof(f8::PackHead) + p->packlen;
|
||||
} else {
|
||||
warning = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
f8::UdpLog::Instance()->Warning("收到kcp client非法数据包2", {});
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/udpsession.h>
|
||||
#include <a8/udplistener.h>
|
||||
|
||||
#include "ikcp.h"
|
||||
|
||||
class KcpSession : public a8::UdpSession
|
||||
{
|
||||
public:
|
||||
KcpSession();
|
||||
~KcpSession();
|
||||
|
||||
void Init(int socket_handle, int secret_key_place);
|
||||
void UnInit();
|
||||
void Update(long long tick);
|
||||
|
||||
const sockaddr_in& GetAddr() const { return remote_addr_; }
|
||||
int GetSocketHandle() { return socket_handle_; }
|
||||
long long GetSecretKey() { return secret_key_; }
|
||||
void* GetSecretKeyDataPtr() { return &secret_key_; }
|
||||
int GetSecretKeyPlace();
|
||||
|
||||
void SendClientMsg(char* buf, int buf_len);
|
||||
virtual void OnRecvPacket(a8::UdpPacket* pkt) override;
|
||||
|
||||
static int GetSecretKeyLen() { return sizeof(long long); }
|
||||
static long long ReadSecretKey(const char* buf, int buf_len)
|
||||
{
|
||||
return buf_len < GetSecretKeyLen() ? 0 : *((long long*)buf);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DecodeUserPacket(char* buf, int& offset, unsigned int buflen) override;
|
||||
void DecodeUserPacketOld(char* buf, int& offset, unsigned int buflen);
|
||||
void DecodeUserPacketNew(char* buf, int& offset, unsigned int buflen);
|
||||
|
||||
private:
|
||||
void UpdateInput();
|
||||
|
||||
private:
|
||||
int secret_key_place_ = 0;
|
||||
int socket_handle_ = 0;
|
||||
long long secret_key_ = 0;
|
||||
ikcpcb* kcp_ = nullptr;
|
||||
|
||||
long long init_tick_ = 0;
|
||||
sockaddr_in remote_addr_ = {};
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
|
||||
#include "longsession.h"
|
||||
#include "kcpsession.h"
|
||||
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
void LongSession::Init(f8::MsgHdr& hdr, const ss::SS_CMKcpHandshake& msg)
|
||||
{
|
||||
kcp_session_ = std::make_shared<KcpSession>();
|
||||
kcp_session_->Init(hdr.socket_handle, msg.secret_key_place());
|
||||
}
|
||||
|
||||
void LongSession::UnInit()
|
||||
{
|
||||
kcp_session_->UnInit();
|
||||
}
|
||||
|
||||
void LongSession::Update(long long tick)
|
||||
{
|
||||
GetKcpSession()->Update(tick);
|
||||
}
|
||||
|
||||
void LongSession::UpdatePing()
|
||||
{
|
||||
last_ping_tick_ = a8::XGetTickCount();
|
||||
}
|
||||
|
||||
int LongSession::GetSecretKeyPlace()
|
||||
{
|
||||
return kcp_session_->GetSecretKeyPlace();
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace ss
|
||||
{
|
||||
class SS_CMKcpHandshake;
|
||||
}
|
||||
|
||||
class KcpSession;
|
||||
class LongSession
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void Init(f8::MsgHdr& hdr, const ss::SS_CMKcpHandshake& msg);
|
||||
void UnInit();
|
||||
void Update(long long tick);
|
||||
|
||||
std::shared_ptr<KcpSession> GetKcpSession() { return kcp_session_; }
|
||||
void UpdatePing();
|
||||
int GetSecretKeyPlace();
|
||||
|
||||
private:
|
||||
long long last_ping_tick_ = 0;
|
||||
std::shared_ptr<KcpSession> kcp_session_;
|
||||
};
|
@ -1,182 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <a8/udplistener.h>
|
||||
|
||||
#include <f8/netmsghandler.h>
|
||||
#include <f8/udplog.h>
|
||||
|
||||
#include "longsessionmgr.h"
|
||||
#include "app.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "longsession.h"
|
||||
#include "kcpsession.h"
|
||||
#include "GCListener.h"
|
||||
#include "downstreammgr.h"
|
||||
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "ss_proto.pb.h"
|
||||
|
||||
static void GSUdpListeneron_error(int errorid)
|
||||
{
|
||||
f8::UdpLog::Instance()->Debug("GCUdpListeneron_error %d", {errorid});
|
||||
}
|
||||
|
||||
static void GSUdpListeneron_recv_packet(a8::UdpPacket* pkt)
|
||||
{
|
||||
App::Instance()->AddUdpMsg(pkt);
|
||||
}
|
||||
|
||||
void LongSessionMgr::Init()
|
||||
{
|
||||
udp_listener_ = std::make_shared<a8::UdpListener>();
|
||||
udp_listener_->on_error = GSUdpListeneron_error;
|
||||
udp_listener_->on_recv_packet = GSUdpListeneron_recv_packet;
|
||||
|
||||
udp_listener_->bind_address = "0.0.0.0";
|
||||
udp_listener_->bind_port = JsonDataMgr::Instance()->GetUdpPort();
|
||||
udp_listener_->Open();
|
||||
}
|
||||
|
||||
void LongSessionMgr::UnInit()
|
||||
{
|
||||
for (auto& pair : socket_handle_hash_) {
|
||||
pair.second->UnInit();
|
||||
}
|
||||
socket_handle_hash_.clear();
|
||||
}
|
||||
|
||||
void LongSessionMgr::Update()
|
||||
{
|
||||
long long tick = a8::XGetTickCount();
|
||||
for (auto& pair : socket_handle_hash_) {
|
||||
pair.second->Update(tick);
|
||||
}
|
||||
}
|
||||
|
||||
void LongSessionMgr::_SS_CMKcpHandshake(f8::MsgHdr& hdr, const ss::SS_CMKcpHandshake& msg)
|
||||
{
|
||||
ss::SS_SMKcpHandshake respmsg;
|
||||
respmsg.set_errcode(0);
|
||||
if (!JsonDataMgr::Instance()->GetKcpConf().open) {
|
||||
respmsg.set_errcode(1);
|
||||
respmsg.set_errmsg("not support kcp");
|
||||
GCListener::Instance()->SendMsgEx(hdr.socket_handle, ss::_SS_CMKcpHandshake, respmsg);
|
||||
return;
|
||||
}
|
||||
if (GetSession(hdr.socket_handle)) {
|
||||
#ifdef DEBUG
|
||||
abort();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
auto session = std::make_shared<LongSession>();
|
||||
session->Init(hdr, msg);
|
||||
socket_handle_hash_[session->GetKcpSession()->GetSocketHandle()] = session;
|
||||
|
||||
respmsg.set_conv(session->GetKcpSession()->GetSocketHandle());
|
||||
respmsg.set_secret_key(session->GetKcpSession()->GetSecretKeyDataPtr(), KcpSession::GetSecretKeyLen());
|
||||
respmsg.set_remote_host(JsonDataMgr::Instance()->GetUdpHost());
|
||||
respmsg.set_remote_port(JsonDataMgr::Instance()->GetUdpPort());
|
||||
GCListener::Instance()->SendMsgEx(hdr.socket_handle, ss::_SS_CMKcpHandshake, respmsg);
|
||||
{
|
||||
int socket_handle = hdr.socket_handle;
|
||||
f8::Timer::Instance()->SetTimeout
|
||||
(
|
||||
1000 * 30,
|
||||
[this, socket_handle] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
if (DownStreamMgr::Instance()->GetDownStream(socket_handle).expired()) {
|
||||
GCListener::Instance()->ForceCloseClient(socket_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<LongSession> LongSessionMgr::GetSession(int socket_handle)
|
||||
{
|
||||
auto itr = socket_handle_hash_.find(socket_handle);
|
||||
return itr != socket_handle_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void LongSessionMgr::ProcUdpPacket(a8::UdpPacket* pkt)
|
||||
{
|
||||
#if 0
|
||||
f8::UdpLog::Instance()->Debug("ProcUdpPacket host:%s port:%d buflen:%d",
|
||||
{
|
||||
inet_ntoa(pkt->remote_addr.sin_addr),
|
||||
pkt->remote_addr.sin_port,
|
||||
pkt->buf_len
|
||||
});
|
||||
#endif
|
||||
const int IKCP_OVERHEAD = 24;
|
||||
|
||||
if (pkt->buf_len < IKCP_OVERHEAD) {
|
||||
f8::UdpLog::Instance()->Warning("ProcUdpPacket host:%s port:%d buflen:%d over_head_error",
|
||||
{
|
||||
inet_ntoa(pkt->remote_addr.sin_addr),
|
||||
pkt->remote_addr.sin_port,
|
||||
pkt->buf_len
|
||||
});
|
||||
return;
|
||||
}
|
||||
int socket_handle = ikcp_getconv(pkt->buf);
|
||||
auto session = GetSession(socket_handle);
|
||||
if (!session) {
|
||||
f8::UdpLog::Instance()->Warning("ProcUdpPacket host:%s socket_handle:%d session_error",
|
||||
{
|
||||
inet_ntoa(pkt->remote_addr.sin_addr),
|
||||
pkt->remote_addr.sin_port,
|
||||
socket_handle
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (session->GetSecretKeyPlace()) {
|
||||
if (pkt->buf_len >= IKCP_OVERHEAD + KcpSession::GetSecretKeyLen()) {
|
||||
long long secret_key = KcpSession::ReadSecretKey(pkt->buf + IKCP_OVERHEAD, pkt->buf_len);
|
||||
if (secret_key == session->GetKcpSession()->GetSecretKey()) {
|
||||
session->GetKcpSession()->OnRecvPacket(pkt);
|
||||
} else {
|
||||
f8::UdpLog::Instance()->Warning("ProcUdpPacket host:%s port:%d socket_handle%d secret_key:%d secret_error",
|
||||
{
|
||||
inet_ntoa(pkt->remote_addr.sin_addr),
|
||||
pkt->remote_addr.sin_port,
|
||||
socket_handle,
|
||||
secret_key
|
||||
});
|
||||
}
|
||||
} else {
|
||||
f8::UdpLog::Instance()->Warning("ProcUdpPacket host:%s port:%d buflen:%d bufflen_error",
|
||||
{
|
||||
inet_ntoa(pkt->remote_addr.sin_addr),
|
||||
pkt->remote_addr.sin_port,
|
||||
pkt->buf_len
|
||||
});
|
||||
}
|
||||
} else {
|
||||
session->GetKcpSession()->OnRecvPacket(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void LongSessionMgr::DelSession(int socket_handle)
|
||||
{
|
||||
{
|
||||
auto session = GetSession(socket_handle);
|
||||
if (session) {
|
||||
if (session.use_count() != 2) {
|
||||
#ifdef DEBUG
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
session->UnInit();
|
||||
}
|
||||
}
|
||||
socket_handle_hash_.erase(socket_handle);
|
||||
}
|
||||
|
||||
int LongSessionMgr::GetLongSessionCount()
|
||||
{
|
||||
return socket_handle_hash_.size();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/singleton.h>
|
||||
|
||||
namespace a8
|
||||
{
|
||||
class UdpListener;
|
||||
struct UdpPacket;
|
||||
}
|
||||
|
||||
namespace ss
|
||||
{
|
||||
class SS_CMKcpHandshake;
|
||||
}
|
||||
|
||||
class LongSession;
|
||||
class LongSessionMgr : public a8::Singleton<LongSessionMgr>
|
||||
{
|
||||
private:
|
||||
LongSessionMgr() {};
|
||||
friend class a8::Singleton<LongSessionMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
void Update();
|
||||
|
||||
void _SS_CMKcpHandshake(f8::MsgHdr& hdr, const ss::SS_CMKcpHandshake& msg);
|
||||
void ProcUdpPacket(a8::UdpPacket* pkt);
|
||||
std::shared_ptr<LongSession> GetSession(int socket_handle);
|
||||
std::shared_ptr<a8::UdpListener> GetUdpListener() { return udp_listener_; }
|
||||
void DelSession(int socket_handle);
|
||||
int GetLongSessionCount();
|
||||
|
||||
private:
|
||||
std::shared_ptr<a8::UdpListener> udp_listener_;
|
||||
std::map<int, std::shared_ptr<LongSession>> socket_handle_hash_;
|
||||
};
|
@ -1,160 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <a8/tcpclient.h>
|
||||
|
||||
#include <f8/udplog.h>
|
||||
#include <f8/timer.h>
|
||||
|
||||
#include "ss_proto.pb.h"
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "master.h"
|
||||
|
||||
#include "app.h"
|
||||
|
||||
const int PACK_MAX = 1024 * 64;
|
||||
|
||||
void Master::Init(int instance_id, const std::string& remote_ip, int remote_port)
|
||||
{
|
||||
this->instance_id = instance_id;
|
||||
this->remote_ip = remote_ip;
|
||||
this->remote_port = remote_port;
|
||||
|
||||
recv_bufflen_ = 0;
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
recv_buff_ = (char*) malloc(PACK_MAX * 2);
|
||||
tcp_client_ = std::make_shared<a8::TcpClient>();
|
||||
tcp_client_->remote_address = remote_ip;
|
||||
tcp_client_->remote_port = remote_port;
|
||||
tcp_client_->on_error = std::bind(&Master::on_error, this, std::placeholders::_1, std::placeholders::_2);
|
||||
tcp_client_->on_connect = std::bind(&Master::on_connect, this, std::placeholders::_1);
|
||||
tcp_client_->on_disconnect = std::bind(&Master::on_disconnect, this, std::placeholders::_1);
|
||||
tcp_client_->on_socketread = std::bind(&Master::on_socketread, this ,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
timer_wp_ = f8::Timer::Instance()->SetIntervalWpEx
|
||||
(1000 * 9 + a8::RandEx(500, 150),
|
||||
[this] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
CheckAlive();
|
||||
}
|
||||
},
|
||||
&attacher_);
|
||||
}
|
||||
|
||||
void Master::UnInit()
|
||||
{
|
||||
if (!timer_wp_.expired()) {
|
||||
f8::Timer::Instance()->Delete(timer_wp_);
|
||||
}
|
||||
tcp_client_->Close();
|
||||
if (tcp_client_.use_count() != 1) {
|
||||
abort();
|
||||
}
|
||||
tcp_client_ = nullptr;
|
||||
recv_bufflen_ = 0;
|
||||
free(recv_buff_);
|
||||
recv_buff_ = nullptr;
|
||||
}
|
||||
|
||||
void Master::Open()
|
||||
{
|
||||
tcp_client_->Open();
|
||||
}
|
||||
|
||||
void Master::Close()
|
||||
{
|
||||
tcp_client_->Close();
|
||||
}
|
||||
|
||||
bool Master::Connected()
|
||||
{
|
||||
return tcp_client_->Connected();
|
||||
}
|
||||
|
||||
void Master::on_error(a8::TcpClient* sender, int errorId)
|
||||
{
|
||||
f8::UdpLog::Instance()->Error("Master errorid=%d remote_ip:%s remote_port:%d",
|
||||
{
|
||||
errorId,
|
||||
sender->remote_address,
|
||||
sender->remote_port
|
||||
});
|
||||
}
|
||||
|
||||
void Master::on_connect(a8::TcpClient* sender)
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Info("masterserver connected", {});
|
||||
}
|
||||
|
||||
void Master::on_disconnect(a8::TcpClient* sender)
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Info("masterserver %d disconnected after 10s later reconnect", {instance_id});
|
||||
}
|
||||
|
||||
void Master::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
{
|
||||
#if 0
|
||||
++App::Instance()->perf.read_count;
|
||||
#endif
|
||||
if (recv_bufflen_ + len > 2 * PACK_MAX) {
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Debug("recvied masterserver too long message", {});
|
||||
return;
|
||||
} else {
|
||||
memmove(&recv_buff_[recv_bufflen_], buf, len);
|
||||
recv_bufflen_ += len;
|
||||
}
|
||||
|
||||
bool warning = false;
|
||||
unsigned int offset = 0;
|
||||
while (recv_bufflen_ - offset >= sizeof(f8::PackHead)) {
|
||||
f8::PackHead* p = (f8::PackHead*) &recv_buff_[offset];
|
||||
if (p->magic_code == f8::MAGIC_CODE) {
|
||||
if (recv_bufflen_ - offset < sizeof(f8::PackHead) + p->packlen) {
|
||||
break;
|
||||
}
|
||||
App::Instance()->AddSocketMsg(SF_MasterServer,
|
||||
0,
|
||||
instance_id,
|
||||
p->msgid,
|
||||
p->seqid,
|
||||
&recv_buff_[offset + sizeof(f8::PackHead)],
|
||||
p->packlen);
|
||||
offset += sizeof(f8::PackHead) + p->packlen;
|
||||
} else {
|
||||
warning = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
f8::UdpLog::Instance()->Debug("recvied bad package", {});
|
||||
}
|
||||
if (offset > 0 && offset < recv_bufflen_) {
|
||||
memmove(recv_buff_, recv_buff_ + offset, recv_bufflen_ - offset);
|
||||
}
|
||||
recv_bufflen_ -= offset;
|
||||
#if 1
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Master::CheckAlive()
|
||||
{
|
||||
if (!Connected()) {
|
||||
Open();
|
||||
} else {
|
||||
if (a8::XGetTickCount() - last_pong_tick > 60 * 10 * 1000) {
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
Close();
|
||||
Open();
|
||||
} else {
|
||||
ss::SS_Ping msg;
|
||||
SendMsg(msg);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <a8/openssl.h>
|
||||
|
||||
#include <f8/timer.h>
|
||||
#include <f8/netmsghandler.h>
|
||||
#include <f8/protoutils.h>
|
||||
|
||||
#include "mastermgr.h"
|
||||
#include "master.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "ss_proto.pb.h"
|
||||
#include "upstream.h"
|
||||
#include "upstreammgr.h"
|
||||
#include "app.h"
|
||||
#include "downstreammgr.h"
|
||||
#include "GCListener.h"
|
||||
|
||||
class RequestTarget
|
||||
{
|
||||
public:
|
||||
long long context_id = 0;
|
||||
int socket_handle = 0;
|
||||
std::string account_id;
|
||||
f8::MsgHdr* hdr_copy = nullptr;
|
||||
f8::TimerWp timer_wp;
|
||||
long long req_tick = 0;
|
||||
|
||||
std::weak_ptr<UpStream> conn;
|
||||
};
|
||||
|
||||
void MasterMgr::Init()
|
||||
{
|
||||
curr_context_id_ = a8::MakeInt64(0, time(nullptr) + 1000 * 60 * 10);
|
||||
|
||||
JsonDataMgr::Instance()->TraverseMaster
|
||||
(
|
||||
[this] (int instance_id, std::string remote_ip, int remote_port)
|
||||
{
|
||||
auto conn = std::make_shared<Master>();
|
||||
conn->Init(instance_id, remote_ip, remote_port);
|
||||
mastersvr_hash_[conn->instance_id] = conn;
|
||||
conn->Open();
|
||||
});
|
||||
}
|
||||
|
||||
void MasterMgr::UnInit()
|
||||
{
|
||||
for (auto& pair : mastersvr_hash_) {
|
||||
pair.second->UnInit();
|
||||
}
|
||||
mastersvr_hash_.clear();
|
||||
}
|
||||
|
||||
void MasterMgr::_SS_MS_ResponseTargetServer(f8::MsgHdr& hdr, const ss::SS_MS_ResponseTargetServer& msg)
|
||||
{
|
||||
auto req = GetRequestByContextId(msg.context_id());
|
||||
if (req) {
|
||||
if (msg.error_code() == 0) {
|
||||
std::weak_ptr<UpStream> conn = UpStreamMgr::Instance()->RecreateUpStream
|
||||
(
|
||||
msg.host(),
|
||||
msg.port()
|
||||
);
|
||||
if (!conn.expired()) {
|
||||
conn.lock()->ForwardClientMsgEx(req->hdr_copy);
|
||||
req->conn = conn;
|
||||
req->hdr_copy = nullptr;
|
||||
if (!req->timer_wp.expired()) {
|
||||
f8::Timer::Instance()->FireEvent(req->timer_wp,
|
||||
ALLOC_TARGET_SERVER_SUCCESS_TIMER_EVENT,
|
||||
nullptr);
|
||||
f8::Timer::Instance()->Delete(req->timer_wp);
|
||||
}
|
||||
RemoveRequest(req->socket_handle);
|
||||
return;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
RemoveRequest(req->socket_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Master> MasterMgr::GetConnById(int instance_id)
|
||||
{
|
||||
auto itr = mastersvr_hash_.find(instance_id);
|
||||
return itr != mastersvr_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void MasterMgr::RequestTargetServer(f8::MsgHdr& hdr,
|
||||
const std::string& team_id,
|
||||
const std::string& account_id,
|
||||
const std::string& session_id,
|
||||
const std::string& server_info,
|
||||
int is_reconnect,
|
||||
int proto_version)
|
||||
{
|
||||
if (GetRequestBySocket(hdr.socket_handle)) {
|
||||
return;
|
||||
}
|
||||
unsigned int code = 0;
|
||||
std::string team_uuid = team_id;
|
||||
if (!team_id.empty()) {
|
||||
code = a8::openssl::Crc32((unsigned char*)team_id.data(), team_id.size());
|
||||
} else {
|
||||
std::string data = a8::Format("!%s_%s_%d_%d",
|
||||
{
|
||||
account_id,
|
||||
App::Instance()->NewUuid(),
|
||||
getpid(),
|
||||
rand()
|
||||
});
|
||||
team_uuid = data;
|
||||
code = a8::openssl::Crc32((unsigned char*)data.data(), data.size());
|
||||
}
|
||||
std::shared_ptr<Master> svr = GetConnById(code % mastersvr_hash_.size() + 1);
|
||||
if (svr) {
|
||||
++curr_context_id_;
|
||||
auto req = std::make_shared<RequestTarget>();
|
||||
req->context_id = curr_context_id_;
|
||||
req->socket_handle = hdr.socket_handle;
|
||||
req->account_id = account_id;
|
||||
req->req_tick = a8::XGetTickCount();
|
||||
req->hdr_copy = hdr.Clone();
|
||||
|
||||
ss::SS_WSP_RequestTargetServer msg;
|
||||
msg.set_context_id(curr_context_id_);
|
||||
msg.set_account_id(account_id);
|
||||
msg.set_session_id(session_id);
|
||||
msg.set_team_id(team_uuid);
|
||||
msg.set_server_info(server_info);
|
||||
msg.set_is_reconnect(is_reconnect);
|
||||
msg.set_proto_version(proto_version);
|
||||
#ifdef DEBUG
|
||||
std::string url;
|
||||
std::string query_str;
|
||||
{
|
||||
GCListener::Instance()->GetWebSocketUrl(hdr.socket_handle, url, query_str);
|
||||
}
|
||||
msg.set_url(url);
|
||||
msg.set_query_str(query_str);
|
||||
#endif
|
||||
svr->SendMsg(msg);
|
||||
|
||||
pending_socket_hash_[hdr.socket_handle] = req;
|
||||
assert(pending_context_hash_.find(curr_context_id_) == pending_context_hash_.end());
|
||||
pending_context_hash_[curr_context_id_] = req;
|
||||
req->timer_wp = f8::Timer::Instance()->SetTimeoutWp
|
||||
(1000 * 10,
|
||||
[req] (int event, const a8::Args* args)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
MasterMgr::Instance()->RemoveRequest
|
||||
(
|
||||
req->socket_handle
|
||||
);
|
||||
long long req_handle_time = a8::XGetTickCount() - req->req_tick;
|
||||
if (req_handle_time > App::Instance()->GetPerf().max_login_time) {
|
||||
App::Instance()->GetPerf().max_login_time = req_handle_time;
|
||||
}
|
||||
DownStreamMgr::Instance()->AddPendingAccount(req->account_id, req->socket_handle, req->req_tick);
|
||||
} else if (ALLOC_TARGET_SERVER_SUCCESS_TIMER_EVENT == event) {
|
||||
long long req_handle_time = a8::XGetTickCount() - req->req_tick;
|
||||
if (req_handle_time > App::Instance()->GetPerf().max_login_time) {
|
||||
App::Instance()->GetPerf().max_login_time = req_handle_time;
|
||||
}
|
||||
DownStreamMgr::Instance()->AddPendingAccount(req->account_id, req->socket_handle, req->req_tick);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterMgr::RemoveRequest(int socket_handle)
|
||||
{
|
||||
auto req = GetRequestBySocket(socket_handle);
|
||||
if (req) {
|
||||
if (req->hdr_copy) {
|
||||
f8::MsgHdr::Destroy(req->hdr_copy);
|
||||
req->hdr_copy = nullptr;
|
||||
}
|
||||
pending_context_hash_.erase(req->context_id);
|
||||
pending_socket_hash_.erase(socket_handle);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<RequestTarget> MasterMgr::GetRequestBySocket(int socket_handle)
|
||||
{
|
||||
auto itr = pending_socket_hash_.find(socket_handle);
|
||||
return itr != pending_socket_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<RequestTarget> MasterMgr::GetRequestByContextId(long long context_id)
|
||||
{
|
||||
auto itr = pending_context_hash_.find(context_id);
|
||||
return itr != pending_context_hash_.end() ? itr->second : nullptr;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace f8
|
||||
{
|
||||
struct MsgHdr;
|
||||
}
|
||||
|
||||
namespace ss
|
||||
{
|
||||
class SS_MS_ResponseTargetServer;
|
||||
}
|
||||
|
||||
class RequestTarget;
|
||||
class Master;
|
||||
class MasterMgr : public a8::Singleton<MasterMgr>
|
||||
{
|
||||
public:
|
||||
enum { HID = HID_MasterMgr };
|
||||
|
||||
private:
|
||||
MasterMgr() {};
|
||||
friend class a8::Singleton<MasterMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
void _SS_MS_ResponseTargetServer(f8::MsgHdr& hdr, const ss::SS_MS_ResponseTargetServer& msg);
|
||||
void RequestTargetServer(f8::MsgHdr& hdr,
|
||||
const std::string& team_id,
|
||||
const std::string& account_id,
|
||||
const std::string& session_id,
|
||||
const std::string& server_info,
|
||||
int is_reconnect,
|
||||
int proto_version);
|
||||
void RemoveRequest(int socket_handle);
|
||||
|
||||
private:
|
||||
std::shared_ptr<RequestTarget> GetRequestBySocket(int socket_handle);
|
||||
std::shared_ptr<RequestTarget> GetRequestByContextId(long long context_id);
|
||||
std::shared_ptr<Master> GetConnById(int instance_id);
|
||||
|
||||
private:
|
||||
long long curr_context_id_ = 0;
|
||||
std::map<int, std::shared_ptr<Master>> mastersvr_hash_;
|
||||
std::map<int, std::shared_ptr<RequestTarget>> pending_socket_hash_;
|
||||
std::map<long long, std::shared_ptr<RequestTarget>> pending_context_hash_;
|
||||
|
||||
};
|
182
server/wsproxy/mastersvr.cc
Normal file
182
server/wsproxy/mastersvr.cc
Normal file
@ -0,0 +1,182 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ss_proto.pb.h"
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "mastersvr.h"
|
||||
#include <a8/tcpclient.h>
|
||||
#include <a8/asynctcpclient.h>
|
||||
#include <a8/ioloop.h>
|
||||
#include <a8/udplog.h>
|
||||
#include <a8/timer.h>
|
||||
#include "app.h"
|
||||
|
||||
const int PACK_MAX = 1024 * 64;
|
||||
|
||||
void MasterSvr::Init(int instance_id, const std::string& remote_ip, int remote_port)
|
||||
{
|
||||
this->instance_id = instance_id;
|
||||
this->remote_ip = remote_ip;
|
||||
this->remote_port = remote_port;
|
||||
|
||||
recv_bufflen_ = 0;
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
recv_buff_ = (char*) malloc(PACK_MAX * 2);
|
||||
#if ASYNC_TCPCLIENT
|
||||
tcp_client_ = a8::IoLoop::Instance()->CreateAsyncTcpClient();
|
||||
#else
|
||||
tcp_client_ = new a8::TcpClient();
|
||||
#endif
|
||||
tcp_client_->remote_address = remote_ip;
|
||||
tcp_client_->remote_port = remote_port;
|
||||
tcp_client_->on_error = std::bind(&MasterSvr::on_error, this, std::placeholders::_1, std::placeholders::_2);
|
||||
tcp_client_->on_connect = std::bind(&MasterSvr::on_connect, this, std::placeholders::_1);
|
||||
tcp_client_->on_disconnect = std::bind(&MasterSvr::on_disconnect, this, std::placeholders::_1);
|
||||
tcp_client_->on_socketread = std::bind(&MasterSvr::on_socketread, this ,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
timer_ = a8::Timer::Instance()->AddRepeatTimer(1000 * 9 + a8::RandEx(500, 150),
|
||||
a8::XParams().SetSender(this),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
MasterSvr* conn = (MasterSvr*)param.sender.GetUserData();
|
||||
conn->CheckAlive();
|
||||
});
|
||||
}
|
||||
|
||||
void MasterSvr::UnInit()
|
||||
{
|
||||
a8::Timer::Instance()->DeleteTimer(timer_);
|
||||
timer_ = nullptr;
|
||||
tcp_client_->Close();
|
||||
#if ASYNC_TCPCLIENT
|
||||
a8::IoLoop::Instance()->DestoryAsyncTcpClient(tcp_client_);
|
||||
#else
|
||||
delete tcp_client_;
|
||||
#endif
|
||||
tcp_client_ = nullptr;
|
||||
recv_bufflen_ = 0;
|
||||
free(recv_buff_);
|
||||
recv_buff_ = nullptr;
|
||||
}
|
||||
|
||||
void MasterSvr::Open()
|
||||
{
|
||||
tcp_client_->Open();
|
||||
}
|
||||
|
||||
void MasterSvr::Close()
|
||||
{
|
||||
tcp_client_->Close();
|
||||
}
|
||||
|
||||
bool MasterSvr::Connected()
|
||||
{
|
||||
return tcp_client_->Connected();
|
||||
}
|
||||
|
||||
#if ASYNC_TCPCLIENT
|
||||
void MasterSvr::on_error(a8::AsyncTcpClient* sender, int errorId)
|
||||
#else
|
||||
void MasterSvr::on_error(a8::TcpClient* sender, int errorId)
|
||||
#endif
|
||||
{
|
||||
a8::UdpLog::Instance()->Error("MasterSvr errorid=%d remote_ip:%s remote_port:%d",
|
||||
{
|
||||
errorId,
|
||||
sender->remote_address,
|
||||
sender->remote_port
|
||||
});
|
||||
}
|
||||
|
||||
#if ASYNC_TCPCLIENT
|
||||
void MasterSvr::on_connect(a8::AsyncTcpClient* sender)
|
||||
#else
|
||||
void MasterSvr::on_connect(a8::TcpClient* sender)
|
||||
#endif
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
a8::UdpLog::Instance()->Info("masterserver connected", {});
|
||||
}
|
||||
|
||||
#if ASYNC_TCPCLIENT
|
||||
void MasterSvr::on_disconnect(a8::AsyncTcpClient* sender)
|
||||
#else
|
||||
void MasterSvr::on_disconnect(a8::TcpClient* sender)
|
||||
#endif
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
a8::UdpLog::Instance()->Info("masterserver %d disconnected after 10s later reconnect", {instance_id});
|
||||
App::Instance()->AddIMMsg(IM_MasterSvrDisconnect,
|
||||
a8::XParams()
|
||||
.SetSender(instance_id)
|
||||
);
|
||||
}
|
||||
|
||||
#if ASYNC_TCPCLIENT
|
||||
void MasterSvr::on_socketread(a8::AsyncTcpClient* sender, char* buf, unsigned int len)
|
||||
#else
|
||||
void MasterSvr::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
#endif
|
||||
{
|
||||
#if 0
|
||||
++App::Instance()->perf.read_count;
|
||||
#endif
|
||||
if (recv_bufflen_ + len > 2 * PACK_MAX) {
|
||||
recv_bufflen_ = 0;
|
||||
a8::UdpLog::Instance()->Debug("recvied masterserver too long message", {});
|
||||
return;
|
||||
} else {
|
||||
memmove(&recv_buff_[recv_bufflen_], buf, len);
|
||||
recv_bufflen_ += len;
|
||||
}
|
||||
|
||||
bool warning = false;
|
||||
unsigned int offset = 0;
|
||||
while (recv_bufflen_ - offset >= sizeof(f8::PackHead)) {
|
||||
f8::PackHead* p = (f8::PackHead*) &recv_buff_[offset];
|
||||
if (p->magic_code == f8::MAGIC_CODE) {
|
||||
if (recv_bufflen_ - offset < sizeof(f8::PackHead) + p->packlen) {
|
||||
break;
|
||||
}
|
||||
App::Instance()->AddSocketMsg(SF_MasterServer,
|
||||
0,
|
||||
instance_id,
|
||||
p->msgid,
|
||||
p->seqid,
|
||||
&recv_buff_[offset + sizeof(f8::PackHead)],
|
||||
p->packlen);
|
||||
offset += sizeof(f8::PackHead) + p->packlen;
|
||||
} else {
|
||||
warning = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
a8::UdpLog::Instance()->Debug("recvied bad package", {});
|
||||
}
|
||||
if (offset > 0 && offset < recv_bufflen_) {
|
||||
memmove(recv_buff_, recv_buff_ + offset, recv_bufflen_ - offset);
|
||||
}
|
||||
recv_bufflen_ -= offset;
|
||||
#if 1
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MasterSvr::CheckAlive()
|
||||
{
|
||||
if (!Connected()) {
|
||||
Open();
|
||||
} else {
|
||||
if (a8::XGetTickCount() - last_pong_tick > 60 * 10 * 1000) {
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
Close();
|
||||
Open();
|
||||
} else {
|
||||
ss::SS_Ping msg;
|
||||
SendMsg(msg);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <f8/protoutils.h>
|
||||
#include "framework/cpp/protoutils.h"
|
||||
|
||||
namespace a8
|
||||
{
|
||||
class TcpClient;
|
||||
class AsyncTcpClient;
|
||||
}
|
||||
|
||||
class Master
|
||||
struct timer_list;
|
||||
class MasterSvr
|
||||
{
|
||||
public:
|
||||
int instance_id = 0;
|
||||
@ -27,21 +29,31 @@ class Master
|
||||
void SendMsg(T& msg)
|
||||
{
|
||||
static int msgid = f8::Net_GetMessageId(msg);
|
||||
f8::Net_SendMsg(tcp_client_.get(), 0, msgid, msg);
|
||||
f8::Net_SendMsg(tcp_client_, 0, msgid, msg);
|
||||
}
|
||||
|
||||
private:
|
||||
#if ASYNC_TCPCLIENT
|
||||
void on_error(a8::AsyncTcpClient* sender, int errorId);
|
||||
void on_connect(a8::AsyncTcpClient* sender);
|
||||
void on_disconnect(a8::AsyncTcpClient* sender);
|
||||
void on_socketread(a8::AsyncTcpClient* sender, char* buf, unsigned int len);
|
||||
#else
|
||||
void on_error(a8::TcpClient* sender, int errorId);
|
||||
void on_connect(a8::TcpClient* sender);
|
||||
void on_disconnect(a8::TcpClient* sender);
|
||||
void on_socketread(a8::TcpClient* sender, char* buf, unsigned int len);
|
||||
#endif
|
||||
|
||||
void CheckAlive();
|
||||
|
||||
private:
|
||||
char *recv_buff_ = nullptr;
|
||||
unsigned int recv_bufflen_ = 0;
|
||||
std::shared_ptr<a8::TcpClient> tcp_client_;
|
||||
f8::TimerWp timer_wp_;
|
||||
f8::Attacher attacher_;
|
||||
#if ASYNC_TCPCLIENT
|
||||
a8::AsyncTcpClient* tcp_client_ = nullptr;
|
||||
#else
|
||||
a8::TcpClient* tcp_client_ = nullptr;
|
||||
#endif
|
||||
timer_list* timer_ = nullptr;
|
||||
};
|
208
server/wsproxy/mastersvrmgr.cc
Normal file
208
server/wsproxy/mastersvrmgr.cc
Normal file
@ -0,0 +1,208 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <a8/openssl.h>
|
||||
#include <a8/timer.h>
|
||||
|
||||
#include "mastersvrmgr.h"
|
||||
#include "mastersvr.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "ss_proto.pb.h"
|
||||
#include "target_conn.h"
|
||||
#include "target_conn_mgr.h"
|
||||
#include "app.h"
|
||||
#include "gameclientmgr.h"
|
||||
|
||||
#include "framework/cpp/netmsghandler.h"
|
||||
|
||||
void MasterSvrMgr::Init()
|
||||
{
|
||||
curr_context_id_ = a8::MakeInt64(0, time(nullptr) + 1000 * 60 * 10);
|
||||
|
||||
#if MASTER_MODE
|
||||
auto master_svr_cluster_conf = JsonDataMgr::Instance()->GetMasterServerClusterConf();
|
||||
for (int i = 0; i < master_svr_cluster_conf->Size(); ++i) {
|
||||
auto master_svr_conf = master_svr_cluster_conf->At(i);
|
||||
int instance_id = master_svr_conf->At("instance_id")->AsXValue();
|
||||
std::string remote_ip = master_svr_conf->At("ip")->AsXValue();
|
||||
int remote_port = master_svr_conf->At("port")->AsXValue();
|
||||
{
|
||||
MasterSvr* conn = new MasterSvr();
|
||||
conn->Init(instance_id, remote_ip, remote_port);
|
||||
mastersvr_hash_[conn->instance_id] = conn;
|
||||
conn->Open();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MasterSvrMgr::UnInit()
|
||||
{
|
||||
}
|
||||
|
||||
void MasterSvrMgr::_SS_MS_ResponseTargetServer(f8::MsgHdr& hdr, const ss::SS_MS_ResponseTargetServer& msg)
|
||||
{
|
||||
f8::MsgHdr* context_hdr = GetHdrByContextId(msg.context_id());
|
||||
if (context_hdr) {
|
||||
int socket_handle = context_hdr->socket_handle;
|
||||
if (msg.error_code() == 0) {
|
||||
TargetConn* conn = TargetConnMgr::Instance()->RecreateTargetConn(
|
||||
msg.host(),
|
||||
msg.port()
|
||||
);
|
||||
assert(conn);
|
||||
if (conn) {
|
||||
RemoveRequest(socket_handle, msg.context_id(), false);
|
||||
conn->ForwardClientMsgEx(context_hdr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RemoveRequest(socket_handle, msg.context_id(), true);
|
||||
}
|
||||
}
|
||||
|
||||
MasterSvr* MasterSvrMgr::GetConnById(int instance_id)
|
||||
{
|
||||
auto itr = mastersvr_hash_.find(instance_id);
|
||||
return itr != mastersvr_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
void MasterSvrMgr::RequestTargetServer(f8::MsgHdr& hdr,
|
||||
const std::string& team_id,
|
||||
const std::string& account_id,
|
||||
const std::string& server_info,
|
||||
int is_reconnect,
|
||||
int proto_version)
|
||||
{
|
||||
#if GAME_ID == 9003
|
||||
{
|
||||
TargetConn* conn = TargetConnMgr::Instance()->RecreateTargetConn(
|
||||
"10.10.4.4",
|
||||
8951
|
||||
);
|
||||
if (conn) {
|
||||
f8::MsgHdr* new_hdr = hdr.Clone();
|
||||
conn->ForwardClientMsgEx(new_hdr);
|
||||
return;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (GetContextIdBySocket(hdr.socket_handle) != 0) {
|
||||
return;
|
||||
}
|
||||
unsigned int code = 0;
|
||||
std::string team_uuid = team_id;
|
||||
if (!team_id.empty()) {
|
||||
code = a8::openssl::Crc32((unsigned char*)team_id.data(), team_id.size());
|
||||
} else {
|
||||
std::string data = a8::Format("!%s_%s_%d_%d",
|
||||
{
|
||||
account_id,
|
||||
App::Instance()->uuid.Generate(),
|
||||
getpid(),
|
||||
rand()
|
||||
});
|
||||
team_uuid = data;
|
||||
code = a8::openssl::Crc32((unsigned char*)data.data(), data.size());
|
||||
}
|
||||
MasterSvr* svr = GetConnById(code % mastersvr_hash_.size() + 1);
|
||||
if (svr) {
|
||||
++curr_context_id_;
|
||||
a8::TimerAttacher* timer_attacher = new a8::TimerAttacher();
|
||||
f8::MsgHdr* new_hdr = hdr.Clone();
|
||||
new_hdr->user_data = timer_attacher;
|
||||
|
||||
ss::SS_WSP_RequestTargetServer msg;
|
||||
msg.set_context_id(curr_context_id_);
|
||||
msg.set_account_id(account_id);
|
||||
msg.set_team_id(team_uuid);
|
||||
msg.set_server_info(server_info);
|
||||
msg.set_is_reconnect(is_reconnect);
|
||||
msg.set_proto_version(proto_version);
|
||||
svr->SendMsg(msg);
|
||||
|
||||
pending_socket_hash_[hdr.socket_handle] = curr_context_id_;
|
||||
assert(pending_request_hash_.find(curr_context_id_) == pending_request_hash_.end());
|
||||
pending_request_hash_[curr_context_id_] = new_hdr;
|
||||
if (account_id == azw_account_id) {
|
||||
a8::UdpLog::Instance()->Info("%s request", {account_id});
|
||||
}
|
||||
auto timer_func =
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (param.param2.GetString() == azw_account_id) {
|
||||
a8::UdpLog::Instance()->Info("%s timeout",
|
||||
{
|
||||
param.param2.GetString()
|
||||
});
|
||||
}
|
||||
a8::Timer::Instance()->RemoveTimerAfterFunc(a8::Timer::Instance()->GetRunningTimer());
|
||||
MasterSvrMgr::Instance()->RemoveRequest(
|
||||
param.param1,
|
||||
param.sender,
|
||||
true
|
||||
);
|
||||
};
|
||||
auto timer_after_func =
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (param.param2.GetString() == azw_account_id) {
|
||||
a8::UdpLog::Instance()->Info("%s response time:%d",
|
||||
{
|
||||
param.param2.GetString(),
|
||||
a8::XGetTickCount() - param.param3.GetInt64()
|
||||
});
|
||||
}
|
||||
long long req_handle_time = a8::XGetTickCount() - param.param3.GetInt64();
|
||||
if (req_handle_time > App::Instance()->perf.max_login_time) {
|
||||
App::Instance()->perf.max_login_time = req_handle_time;
|
||||
}
|
||||
GameClientMgr::Instance()->AddPendingAccount(param.param2.GetString(), param.param1, param.param3);
|
||||
};
|
||||
a8::Timer::Instance()->AddDeadLineTimerAndAttach(1000 * 10,
|
||||
a8::XParams()
|
||||
.SetSender(curr_context_id_)
|
||||
.SetParam1(hdr.socket_handle)
|
||||
.SetParam2(account_id)
|
||||
.SetParam3(a8::XGetTickCount()),
|
||||
timer_func,
|
||||
&timer_attacher->timer_list_,
|
||||
timer_after_func
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterSvrMgr::RemoveRequest(int socket_handle, long long context_id, bool auto_free)
|
||||
{
|
||||
if (context_id == GetContextIdBySocket(socket_handle)) {
|
||||
f8::MsgHdr* hdr = GetHdrByContextId(context_id);
|
||||
if (hdr) {
|
||||
a8::TimerAttacher* timer_attacher = (a8::TimerAttacher*)hdr->user_data;
|
||||
delete timer_attacher;
|
||||
hdr->user_data = nullptr;
|
||||
if (auto_free) {
|
||||
if (hdr->buf) {
|
||||
free((char*)hdr->buf);
|
||||
}
|
||||
free(hdr);
|
||||
}
|
||||
}
|
||||
pending_request_hash_.erase(context_id);
|
||||
pending_socket_hash_.erase(socket_handle);
|
||||
}
|
||||
}
|
||||
|
||||
long long MasterSvrMgr::GetContextIdBySocket(int socket_handle)
|
||||
{
|
||||
auto itr = pending_socket_hash_.find(socket_handle);
|
||||
return itr != pending_socket_hash_.end() ? itr->second : 0;
|
||||
}
|
||||
|
||||
f8::MsgHdr* MasterSvrMgr::GetHdrByContextId(long long context_id)
|
||||
{
|
||||
auto itr = pending_request_hash_.find(context_id);
|
||||
return itr != pending_request_hash_.end() ? itr->second : nullptr;
|
||||
}
|
49
server/wsproxy/mastersvrmgr.h
Normal file
49
server/wsproxy/mastersvrmgr.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
namespace f8
|
||||
{
|
||||
struct MsgHdr;
|
||||
}
|
||||
|
||||
namespace ss
|
||||
{
|
||||
class SS_MS_ResponseTargetServer;
|
||||
}
|
||||
|
||||
class MasterSvr;
|
||||
class MasterSvrMgr : public a8::Singleton<MasterSvrMgr>
|
||||
{
|
||||
public:
|
||||
enum { HID = HID_MasterSvrMgr };
|
||||
|
||||
private:
|
||||
MasterSvrMgr() {};
|
||||
friend class a8::Singleton<MasterSvrMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
void _SS_MS_ResponseTargetServer(f8::MsgHdr& hdr, const ss::SS_MS_ResponseTargetServer& msg);
|
||||
void RequestTargetServer(f8::MsgHdr& hdr,
|
||||
const std::string& team_id,
|
||||
const std::string& account_id,
|
||||
const std::string& server_info,
|
||||
int is_reconnect,
|
||||
int proto_version);
|
||||
void RemoveRequest(int socket_handle, long long context_id, bool auto_free);
|
||||
|
||||
private:
|
||||
long long GetContextIdBySocket(int socket_handle);
|
||||
f8::MsgHdr* GetHdrByContextId(long long context_id);
|
||||
MasterSvr* GetConnById(int instance_id);
|
||||
|
||||
private:
|
||||
int target_conn_id_ = 100;
|
||||
long long curr_context_id_ = 0;
|
||||
std::map<int, MasterSvr*> mastersvr_hash_;
|
||||
std::map<int, long long> pending_socket_hash_;
|
||||
std::map<long long, f8::MsgHdr*> pending_request_hash_;
|
||||
|
||||
};
|
@ -1,8 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <a8/a8.h>
|
||||
#include <f8/f8.h>
|
||||
#include <f8/timer.h>
|
||||
#include <a8/udplog.h>
|
||||
|
||||
#include "constant.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace google
|
||||
{
|
||||
namespace protobuf
|
||||
{
|
||||
class Message;
|
||||
}
|
||||
}
|
||||
|
||||
#include "framework/cpp/types.h"
|
||||
#include "framework/cpp/utils.h"
|
||||
#include "framework/cpp/protoutils.h"
|
||||
|
@ -2,21 +2,19 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <a8/tcpclient.h>
|
||||
|
||||
#include <f8/udplog.h>
|
||||
#include <f8/timer.h>
|
||||
#include <f8/msgqueue.h>
|
||||
|
||||
#include "ss_proto.pb.h"
|
||||
#include "ss_msgid.pb.h"
|
||||
#include "upstream.h"
|
||||
|
||||
#include "target_conn.h"
|
||||
#include <a8/tcpclient.h>
|
||||
#include <a8/udplog.h>
|
||||
#include <a8/timer.h>
|
||||
#include <a8/ioloop.h>
|
||||
#include <a8/asynctcpclient.h>
|
||||
#include "app.h"
|
||||
|
||||
const int PACK_MAX = 1024 * 64 * 2;
|
||||
|
||||
void UpStream::Init(int instance_id, const std::string& remote_ip, int remote_port)
|
||||
void TargetConn::Init(int instance_id, const std::string& remote_ip, int remote_port)
|
||||
{
|
||||
if (remote_ip.empty()) {
|
||||
abort();
|
||||
@ -28,88 +26,94 @@ void UpStream::Init(int instance_id, const std::string& remote_ip, int remote_po
|
||||
recv_bufflen_ = 0;
|
||||
last_pong_tick = a8::XGetTickCount();
|
||||
recv_buff_ = (char*) malloc(PACK_MAX * 2);
|
||||
tcp_client_ = std::make_shared<a8::TcpClient>();
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
tcp_client_ = a8::IoLoop::Instance()->CreateAsyncTcpClient();
|
||||
#else
|
||||
tcp_client_ = new a8::TcpClient();
|
||||
#endif
|
||||
tcp_client_->remote_address = remote_ip;
|
||||
tcp_client_->remote_port = remote_port;
|
||||
tcp_client_->on_error = std::bind(&UpStream::on_error, this, std::placeholders::_1, std::placeholders::_2);
|
||||
tcp_client_->on_connect = std::bind(&UpStream::on_connect, this, std::placeholders::_1);
|
||||
tcp_client_->on_disconnect = std::bind(&UpStream::on_disconnect, this, std::placeholders::_1);
|
||||
tcp_client_->on_socketread = std::bind(&UpStream::on_socketread, this ,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
timer_wp_ = f8::Timer::Instance()->SetIntervalWpEx
|
||||
(1000 * 9 + a8::RandEx(500, 150),
|
||||
[this] (int event, const a8::Args* args)
|
||||
tcp_client_->on_error = std::bind(&TargetConn::on_error, this, std::placeholders::_1, std::placeholders::_2);
|
||||
tcp_client_->on_connect = std::bind(&TargetConn::on_connect, this, std::placeholders::_1);
|
||||
tcp_client_->on_disconnect = std::bind(&TargetConn::on_disconnect, this, std::placeholders::_1);
|
||||
tcp_client_->on_socketread = std::bind(&TargetConn::on_socketread, this ,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
timer_ = a8::Timer::Instance()->AddRepeatTimer(1000 * 9 + a8::RandEx(500, 150),
|
||||
a8::XParams().SetSender(this),
|
||||
[] (const a8::XParams& param)
|
||||
{
|
||||
if (a8::TIMER_EXEC_EVENT == event) {
|
||||
CheckAlive();
|
||||
}
|
||||
},
|
||||
&attacher_);
|
||||
TargetConn* conn = (TargetConn*)param.sender.GetUserData();
|
||||
conn->CheckAlive();
|
||||
});
|
||||
}
|
||||
|
||||
void UpStream::UnInit()
|
||||
void TargetConn::UnInit()
|
||||
{
|
||||
UpStreamMsgNode* work_node;
|
||||
TargetConnMsgNode* work_node;
|
||||
work_node = top_node_;
|
||||
top_node_ = nullptr;
|
||||
bot_node_ = nullptr;
|
||||
while (work_node) {
|
||||
UpStreamMsgNode* pdelnode = work_node;
|
||||
TargetConnMsgNode* pdelnode = work_node;
|
||||
work_node = work_node->next_node;
|
||||
delete pdelnode->msg;
|
||||
delete pdelnode;
|
||||
}
|
||||
|
||||
if (!timer_wp_.expired()) {
|
||||
f8::Timer::Instance()->Delete(timer_wp_);
|
||||
}
|
||||
a8::Timer::Instance()->DeleteTimer(timer_);
|
||||
timer_ = nullptr;
|
||||
tcp_client_->Close();
|
||||
if(tcp_client_.use_count() != 1) {
|
||||
abort();
|
||||
}
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
a8::IoLoop::Instance()->DestoryAsyncTcpClient(tcp_client_);
|
||||
#else
|
||||
delete tcp_client_;
|
||||
#endif
|
||||
tcp_client_ = nullptr;
|
||||
recv_bufflen_ = 0;
|
||||
free(recv_buff_);
|
||||
recv_buff_ = nullptr;
|
||||
}
|
||||
|
||||
void UpStream::Open()
|
||||
void TargetConn::Open()
|
||||
{
|
||||
tcp_client_->Open();
|
||||
}
|
||||
|
||||
void UpStream::Close()
|
||||
void TargetConn::Close()
|
||||
{
|
||||
tcp_client_->Close();
|
||||
}
|
||||
|
||||
bool UpStream::Connected()
|
||||
bool TargetConn::Connected()
|
||||
{
|
||||
return tcp_client_->Connected();
|
||||
}
|
||||
|
||||
void UpStream::SendStockMsg()
|
||||
void TargetConn::SendStockMsg()
|
||||
{
|
||||
UpStreamMsgNode* work_node;
|
||||
TargetConnMsgNode* work_node;
|
||||
work_node = top_node_;
|
||||
top_node_ = nullptr;
|
||||
bot_node_ = nullptr;
|
||||
while (work_node) {
|
||||
UpStreamMsgNode* pdelnode = work_node;
|
||||
TargetConnMsgNode* pdelnode = work_node;
|
||||
work_node = work_node->next_node;
|
||||
|
||||
if (pdelnode->msg) {
|
||||
f8::Net_SendProxyCMsg(tcp_client_.get(), pdelnode->socket_handle, pdelnode->msgid, *pdelnode->msg);
|
||||
f8::Net_SendProxyCMsg(tcp_client_, pdelnode->socket_handle, pdelnode->msgid, *pdelnode->msg);
|
||||
delete pdelnode->msg;
|
||||
}
|
||||
if (pdelnode->hdr) {
|
||||
ForwardClientMsg(*pdelnode->hdr);
|
||||
f8::MsgHdr::Destroy(pdelnode->hdr);
|
||||
pdelnode->hdr = nullptr;
|
||||
if (pdelnode->hdr->buf) {
|
||||
free((char*)pdelnode->hdr->buf);
|
||||
}
|
||||
free(pdelnode->hdr);
|
||||
}
|
||||
delete pdelnode;
|
||||
}
|
||||
}
|
||||
|
||||
void UpStream::ForwardClientMsg(f8::MsgHdr& hdr)
|
||||
void TargetConn::ForwardClientMsg(f8::MsgHdr& hdr)
|
||||
{
|
||||
char* buff = (char*)malloc(sizeof(f8::WSProxyPackHead_C) + hdr.buflen);
|
||||
memset(buff, 0, sizeof(f8::WSProxyPackHead_C));
|
||||
@ -132,7 +136,7 @@ void UpStream::ForwardClientMsg(f8::MsgHdr& hdr)
|
||||
free(buff);
|
||||
}
|
||||
|
||||
void UpStream::ForwardClientMsgEx(f8::MsgHdr* hdr)
|
||||
void TargetConn::ForwardClientMsgEx(f8::MsgHdr* hdr)
|
||||
{
|
||||
if (Connected()) {
|
||||
if (top_node_) {
|
||||
@ -148,9 +152,13 @@ void UpStream::ForwardClientMsgEx(f8::MsgHdr* hdr)
|
||||
}
|
||||
}
|
||||
|
||||
void UpStream::on_error(a8::TcpClient* sender, int errorId)
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
void TargetConn::on_error(a8::AsyncTcpClient* sender, int errorId)
|
||||
#else
|
||||
void TargetConn::on_error(a8::TcpClient* sender, int errorId)
|
||||
#endif
|
||||
{
|
||||
f8::UdpLog::Instance()->Error("target server errorid=%d remote_ip:%s remote_port:%d",
|
||||
a8::UdpLog::Instance()->Error("target server errorid=%d remote_ip:%s remote_port:%d",
|
||||
{
|
||||
errorId,
|
||||
sender->remote_address,
|
||||
@ -158,56 +166,56 @@ void UpStream::on_error(a8::TcpClient* sender, int errorId)
|
||||
});
|
||||
}
|
||||
|
||||
void UpStream::on_connect(a8::TcpClient* sender)
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
void TargetConn::on_connect(a8::AsyncTcpClient* sender)
|
||||
#else
|
||||
void TargetConn::on_connect(a8::TcpClient* sender)
|
||||
#endif
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Info("target server connected remote_ip:%s remote_port:%d",
|
||||
a8::UdpLog::Instance()->Info("target server connected remote_ip:%s remote_port:%d",
|
||||
{
|
||||
sender->remote_address,
|
||||
sender->remote_port
|
||||
});
|
||||
f8::MsgQueue::Instance()->PostMsg
|
||||
(
|
||||
IM_UpStreamConnect,
|
||||
a8::Args
|
||||
(
|
||||
{
|
||||
instance_id
|
||||
}
|
||||
)
|
||||
App::Instance()->AddIMMsg(IM_TargetConnConnect,
|
||||
a8::XParams()
|
||||
.SetSender(instance_id)
|
||||
);
|
||||
}
|
||||
|
||||
void UpStream::on_disconnect(a8::TcpClient* sender)
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
void TargetConn::on_disconnect(a8::AsyncTcpClient* sender)
|
||||
#else
|
||||
void TargetConn::on_disconnect(a8::TcpClient* sender)
|
||||
#endif
|
||||
{
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Info("target server %d disconnected after 10s later reconnect "
|
||||
a8::UdpLog::Instance()->Info("target server %d disconnected after 10s later reconnect "
|
||||
"remote_ip:%s remote_port:%d",
|
||||
{
|
||||
instance_id,
|
||||
sender->remote_address,
|
||||
sender->remote_port
|
||||
});
|
||||
f8::MsgQueue::Instance()->PostMsg
|
||||
(
|
||||
IM_UpStreamDisconnect,
|
||||
a8::Args
|
||||
(
|
||||
{
|
||||
instance_id
|
||||
}
|
||||
)
|
||||
App::Instance()->AddIMMsg(IM_TargetConnDisconnect,
|
||||
a8::XParams()
|
||||
.SetSender(instance_id)
|
||||
);
|
||||
}
|
||||
|
||||
void UpStream::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
void TargetConn::on_socketread(a8::AsyncTcpClient* sender, char* buf, unsigned int len)
|
||||
#else
|
||||
void TargetConn::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
#endif
|
||||
{
|
||||
#if 0
|
||||
++App::Instance()->perf.read_count;
|
||||
#endif
|
||||
if (recv_bufflen_ + len > 2 * PACK_MAX) {
|
||||
recv_bufflen_ = 0;
|
||||
f8::UdpLog::Instance()->Debug("recvied target server too long message", {});
|
||||
a8::UdpLog::Instance()->Debug("recvied target server too long message", {});
|
||||
return;
|
||||
} else {
|
||||
memmove(&recv_buff_[recv_bufflen_], buf, len);
|
||||
@ -239,7 +247,7 @@ void UpStream::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
f8::UdpLog::Instance()->Debug("recvied bad package", {});
|
||||
a8::UdpLog::Instance()->Debug("recvied bad package", {});
|
||||
}
|
||||
if (offset > 0 && offset < recv_bufflen_) {
|
||||
memmove(recv_buff_, recv_buff_ + offset, recv_bufflen_ - offset);
|
||||
@ -250,7 +258,7 @@ void UpStream::on_socketread(a8::TcpClient* sender, char* buf, unsigned int len)
|
||||
#endif
|
||||
}
|
||||
|
||||
void UpStream::CheckAlive()
|
||||
void TargetConn::CheckAlive()
|
||||
{
|
||||
if (!Connected()) {
|
||||
Open();
|
||||
@ -265,10 +273,10 @@ void UpStream::CheckAlive()
|
||||
}
|
||||
}
|
||||
|
||||
void UpStream::AddStockMsg(unsigned short socket_handle, int msgid, ::google::protobuf::Message* msg,
|
||||
void TargetConn::AddStockMsg(unsigned short socket_handle, int msgid, ::google::protobuf::Message* msg,
|
||||
f8::MsgHdr* hdr)
|
||||
{
|
||||
UpStreamMsgNode* node = new UpStreamMsgNode();
|
||||
TargetConnMsgNode* node = new TargetConnMsgNode();
|
||||
node->socket_handle = socket_handle;
|
||||
node->msgid = msgid;
|
||||
node->msg = msg;
|
@ -1,23 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <f8/protoutils.h>
|
||||
#include "framework/cpp/protoutils.h"
|
||||
|
||||
namespace a8
|
||||
{
|
||||
class TcpClient;
|
||||
class AsyncTcpClient;
|
||||
}
|
||||
|
||||
struct UpStreamMsgNode
|
||||
struct TargetConnMsgNode
|
||||
{
|
||||
unsigned short socket_handle = 0;
|
||||
int msgid = 0;
|
||||
::google::protobuf::Message* msg = nullptr;
|
||||
f8::MsgHdr* hdr = nullptr;
|
||||
|
||||
UpStreamMsgNode* next_node = nullptr;
|
||||
TargetConnMsgNode* next_node = nullptr;
|
||||
};
|
||||
|
||||
class UpStream
|
||||
struct timer_list;
|
||||
class TargetConn
|
||||
{
|
||||
public:
|
||||
int instance_id = 0;
|
||||
@ -41,7 +43,7 @@ class UpStream
|
||||
if (top_node_) {
|
||||
SendStockMsg();
|
||||
}
|
||||
f8::Net_SendProxyCMsg(tcp_client_.get(), socket_handle, msgid, msg);
|
||||
f8::Net_SendProxyCMsg(tcp_client_, socket_handle, msgid, msg);
|
||||
} else {
|
||||
T* new_msg = new T();
|
||||
*new_msg = msg;
|
||||
@ -54,10 +56,17 @@ class UpStream
|
||||
void ForwardClientMsgEx(f8::MsgHdr* hdr);
|
||||
|
||||
private:
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
void on_error(a8::AsyncTcpClient* sender, int errorId);
|
||||
void on_connect(a8::AsyncTcpClient* sender);
|
||||
void on_disconnect(a8::AsyncTcpClient* sender);
|
||||
void on_socketread(a8::AsyncTcpClient* sender, char* buf, unsigned int len);
|
||||
#else
|
||||
void on_error(a8::TcpClient* sender, int errorId);
|
||||
void on_connect(a8::TcpClient* sender);
|
||||
void on_disconnect(a8::TcpClient* sender);
|
||||
void on_socketread(a8::TcpClient* sender, char* buf, unsigned int len);
|
||||
#endif
|
||||
|
||||
void CheckAlive();
|
||||
void AddStockMsg(unsigned short socket_handle, int msgid, ::google::protobuf::Message* msg,
|
||||
@ -66,10 +75,13 @@ class UpStream
|
||||
private:
|
||||
char *recv_buff_ = nullptr;
|
||||
unsigned int recv_bufflen_ = 0;
|
||||
std::shared_ptr<a8::TcpClient> tcp_client_;
|
||||
f8::TimerWp timer_wp_;
|
||||
f8::Attacher attacher_;
|
||||
#if ASYNC_TCPCLIENT && GAME_ID == 2002
|
||||
a8::AsyncTcpClient* tcp_client_ = nullptr;
|
||||
#else
|
||||
a8::TcpClient* tcp_client_ = nullptr;
|
||||
#endif
|
||||
timer_list* timer_ = nullptr;
|
||||
|
||||
UpStreamMsgNode* top_node_ = nullptr;
|
||||
UpStreamMsgNode* bot_node_ = nullptr;
|
||||
TargetConnMsgNode* top_node_ = nullptr;
|
||||
TargetConnMsgNode* bot_node_ = nullptr;
|
||||
};
|
72
server/wsproxy/target_conn_mgr.cc
Normal file
72
server/wsproxy/target_conn_mgr.cc
Normal file
@ -0,0 +1,72 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include "target_conn_mgr.h"
|
||||
#include "target_conn.h"
|
||||
#include "jsondatamgr.h"
|
||||
#include "app.h"
|
||||
|
||||
void TargetConnMgr::Init()
|
||||
{
|
||||
#if MASTER_MODE
|
||||
#else
|
||||
auto target_server_cluster_conf = JsonDataMgr::Instance()->GetTargetServerClusterConf();
|
||||
for (int i = 0; i < target_server_cluster_conf->Size(); ++i) {
|
||||
auto target_server_conf = target_server_cluster_conf->At(i);
|
||||
int instance_id = target_server_conf->At("instance_id")->AsXValue();
|
||||
std::string remote_ip = target_server_conf->At("ip")->AsXValue();
|
||||
int remote_port = target_server_conf->At("port")->AsXValue();
|
||||
if (App::Instance()->HasFlag(3)) {
|
||||
remote_ip = "127.0.0.1";
|
||||
}
|
||||
{
|
||||
TargetConn* conn = new TargetConn();
|
||||
conn->Init(instance_id, remote_ip, remote_port);
|
||||
id_hash_[conn->instance_id] = conn;
|
||||
conn->Open();
|
||||
}
|
||||
if (App::Instance()->HasFlag(3)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TargetConnMgr::UnInit()
|
||||
{
|
||||
for (auto& pair : id_hash_) {
|
||||
pair.second->UnInit();
|
||||
delete pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
TargetConn* TargetConnMgr::GetConnByKey(const std::string& key)
|
||||
{
|
||||
auto itr = key_hash_.find(key);
|
||||
return itr != key_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
TargetConn* TargetConnMgr::GetConnById(int instance_id)
|
||||
{
|
||||
auto itr = id_hash_.find(instance_id);
|
||||
return itr != id_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
TargetConn* TargetConnMgr::RecreateTargetConn(const std::string& host, int port)
|
||||
{
|
||||
std::string key = host + ":" + a8::XValue(port).GetString();
|
||||
TargetConn* conn = GetConnByKey(key);
|
||||
if (conn) {
|
||||
return conn;
|
||||
}
|
||||
while (GetConnById(++curr_id_)) {};
|
||||
int instance_id = curr_id_;
|
||||
std::string remote_ip = host;
|
||||
int remote_port = port;
|
||||
|
||||
conn = new TargetConn();
|
||||
conn->Init(instance_id, remote_ip, remote_port);
|
||||
id_hash_[conn->instance_id] = conn;
|
||||
key_hash_[key] = conn;
|
||||
conn->Open();
|
||||
return conn;
|
||||
}
|
23
server/wsproxy/target_conn_mgr.h
Normal file
23
server/wsproxy/target_conn_mgr.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
class TargetConn;
|
||||
class TargetConnMgr : public a8::Singleton<TargetConnMgr>
|
||||
{
|
||||
private:
|
||||
TargetConnMgr() {};
|
||||
friend class a8::Singleton<TargetConnMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
TargetConn* GetConnByKey(const std::string& key);
|
||||
TargetConn* GetConnById(int instance_id);
|
||||
TargetConn* RecreateTargetConn(const std::string& host, int port);
|
||||
|
||||
private:
|
||||
unsigned short curr_id_ = 1000;
|
||||
std::map<std::string, TargetConn*> key_hash_;
|
||||
std::map<int, TargetConn*> id_hash_;
|
||||
};
|
@ -1,65 +0,0 @@
|
||||
#include "precompile.h"
|
||||
|
||||
#include <f8/msgqueue.h>
|
||||
|
||||
#include "upstreammgr.h"
|
||||
#include "upstream.h"
|
||||
|
||||
void UpStreamMgr::Init()
|
||||
{
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_UpStreamConnect,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
int instance_id = args.Get<int>(0);
|
||||
std::weak_ptr<UpStream> up_wp = GetUpStreamById(instance_id);
|
||||
if (!up_wp.expired() && up_wp.lock()->Connected()) {
|
||||
up_wp.lock()->SendStockMsg();
|
||||
}
|
||||
});
|
||||
f8::MsgQueue::Instance()->RegisterCallBack
|
||||
(
|
||||
IM_UpStreamDisconnect,
|
||||
[this] (const a8::Args& args)
|
||||
{
|
||||
});
|
||||
}
|
||||
|
||||
void UpStreamMgr::UnInit()
|
||||
{
|
||||
for (auto& pair : id_hash_) {
|
||||
pair.second->UnInit();
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<UpStream> UpStreamMgr::GetUpStreamByKey(const std::string& key)
|
||||
{
|
||||
auto itr = key_hash_.find(key);
|
||||
return itr != key_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
std::weak_ptr<UpStream> UpStreamMgr::GetUpStreamById(int instance_id)
|
||||
{
|
||||
auto itr = id_hash_.find(instance_id);
|
||||
return itr != id_hash_.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
std::weak_ptr<UpStream> UpStreamMgr::RecreateUpStream(const std::string& host, int port)
|
||||
{
|
||||
std::string key = host + ":" + a8::XValue(port).GetString();
|
||||
if (!GetUpStreamByKey(key).expired()) {
|
||||
return GetUpStreamByKey(key);
|
||||
}
|
||||
while (!GetUpStreamById(++curr_id_).expired()) {};
|
||||
int instance_id = curr_id_;
|
||||
std::string remote_ip = host;
|
||||
int remote_port = port;
|
||||
|
||||
std::shared_ptr<UpStream> conn = std::make_shared<UpStream>();
|
||||
conn->Init(instance_id, remote_ip, remote_port);
|
||||
id_hash_[conn->instance_id] = conn;
|
||||
key_hash_[key] = conn;
|
||||
conn->Open();
|
||||
return conn;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <a8/singleton.h>
|
||||
|
||||
class UpStream;
|
||||
class UpStreamMgr : public a8::Singleton<UpStreamMgr>
|
||||
{
|
||||
private:
|
||||
UpStreamMgr() {};
|
||||
friend class a8::Singleton<UpStreamMgr>;
|
||||
|
||||
public:
|
||||
|
||||
void Init();
|
||||
void UnInit();
|
||||
|
||||
std::weak_ptr<UpStream> GetUpStreamByKey(const std::string& key);
|
||||
std::weak_ptr<UpStream> GetUpStreamById(int instance_id);
|
||||
std::weak_ptr<UpStream> RecreateUpStream(const std::string& host, int port);
|
||||
|
||||
private:
|
||||
unsigned short curr_id_ = 1000;
|
||||
std::map<std::string, std::shared_ptr<UpStream>> key_hash_;
|
||||
std::map<int, std::shared_ptr<UpStream>> id_hash_;
|
||||
};
|
1
third_party/a8
vendored
1
third_party/a8
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 1e577389c8a2870db9ddbf18577bfca24def049b
|
1
third_party/a8engine
vendored
Submodule
1
third_party/a8engine
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4e4d8e3c95910407a11a24765a915883d973b281
|
2
third_party/behaviac
vendored
2
third_party/behaviac
vendored
@ -1 +1 @@
|
||||
Subproject commit 8cd7e2432785bf4027e89c5dc74cb4980e4cd3c1
|
||||
Subproject commit 240414570ee2848291d24ff8d3102dc43d4104a3
|
1
third_party/f8
vendored
1
third_party/f8
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 243bbe515ef4a01089f9a6cf608c93d4097018de
|
1
third_party/framework
vendored
Submodule
1
third_party/framework
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9ba2696e52664c9f5b7a1e09a4a5516359d330b0
|
1
third_party/kcp
vendored
1
third_party/kcp
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 10ee2b30c8739408c0db98211df4ebce7b01c0ed
|
2
third_party/recastnavigation
vendored
2
third_party/recastnavigation
vendored
@ -1 +1 @@
|
||||
Subproject commit 0165dc279d62af5536f122ea30c3cd3f642f34ee
|
||||
Subproject commit 35ca2eadc32161cd6ab479d1a2626759a73bb5a3
|
2
third_party/tools
vendored
2
third_party/tools
vendored
@ -1 +1 @@
|
||||
Subproject commit d38ce0b86c7b9262391f48108d808ddb62854760
|
||||
Subproject commit 04a0bc939eeae0090fd0e8964dddf3863a551154
|
Loading…
x
Reference in New Issue
Block a user