KBEngine与Unreal
1.客户端 KbEngine 中
void KBEngineApp::installEvents()
{
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("login", "login", [this](const UKBEventData* pEventData)
{
const UKBEventData_login& data = static_cast(*pEventData);
login(data.username, data.password, data.datas);
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("logout", "logout", [this](const UKBEventData* pEventData)
{
logout();
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("createAccount", "createAccount", [this](const UKBEventData* pEventData)
{
const UKBEventData_createAccount& data = static_cast(*pEventData);
createAccount(data.username, data.password, data.datas);
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("reloginBaseapp", "reloginBaseapp", [this](const UKBEventData* pEventData)
{
reloginBaseapp();
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("resetPassword", "resetPassword", [this](const UKBEventData* pEventData)
{
const UKBEventData_resetPassword& data = static_cast(*pEventData);
resetPassword(data.username);
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("bindAccountEmail", "bindAccountEmail", [this](const UKBEventData* pEventData)
{
const UKBEventData_bindAccountEmail& data = static_cast(*pEventData);
bindAccountEmail(data.email);
});
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("newPassword", "newPassword", [this](const UKBEventData* pEventData)
{
const UKBEventData_newPassword& data = static_cast(*pEventData);
newPassword(data.old_password, data.new_password);
});
// 内部事件
KBENGINE_REGISTER_EVENT_OVERRIDE_FUNC("_closeNetwork", "_closeNetwork", [this](const UKBEventData* pEventData)
{
_closeNetwork();
});
}
注册了一系列事件,本次从创建账号开始
可以看到最终调用
void KBEngineApp::createAccount_loginapp(bool noconnect)
{
if (noconnect)
{
reset();
pNetworkInterface_->connectTo(pArgs_->ip, pArgs_->port, this, 1);
}
else
{
INFO_MSG("KBEngineApp::createAccount_loginapp(): send create! username=%s", *username_);
Bundle* pBundle = Bundle::createObject();
pBundle->newMessage(Messages::messages[TEXT("Loginapp_reqCreateAccount"]));
(*pBundle) << username_;
(*pBundle) << password_;
pBundle->appendBlob(clientdatas_);
pBundle->send(pNetworkInterface_);
}
}
调用登录服务器中的 reqCreateAccount 方法。
登录服务器:最终将数据发送至dbmsr
bool Loginapp::_createAccount(Network::Channel* pChannel, std::string& accountName,
std::string& password, std::string& datas, ACCOUNT_TYPE type)
{
AUTO_SCOPED_PROFILE("createAccount");
ACCOUNT_TYPE oldType = type;
if(!g_kbeSrvConfig.getDBMgr().account_registration_enable)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount({}): not available! modify kbengine[_defs].xml->dbmgr->account_registration.\n",
accountName));
std::string retdatas = "";
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_ACCOUNT_REGISTER_NOT_AVAILABLE;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
accountName = KBEngine::strutil::kbe_trim(accountName);
password = KBEngine::strutil::kbe_trim(password);
if(accountName.size() > ACCOUNT_NAME_MAX_LENGTH)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: accountName too big, size={}, limit={}.\n",
accountName.size(), ACCOUNT_NAME_MAX_LENGTH));
return false;
}
if(password.size() > ACCOUNT_PASSWD_MAX_LENGTH)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: password too big, size={}, limit={}.\n",
password.size(), ACCOUNT_PASSWD_MAX_LENGTH));
return false;
}
if(datas.size() > ACCOUNT_DATA_MAX_LENGTH)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: bindatas too big, size={}, limit={}.\n",
datas.size(), ACCOUNT_DATA_MAX_LENGTH));
return false;
}
std::string retdatas = "";
if(shuttingdown_ != SHUTDOWN_STATE_STOP)
{
WARNING_MSG(fmt::format("Loginapp::_createAccount: shutting down, create {} failed!\n", accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_IN_SHUTTINGDOWN;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
PendingLoginMgr::PLInfos* ptinfos = pendingCreateMgr_.find(const_cast(accountName));
if(ptinfos != NULL)
{
WARNING_MSG(fmt::format("Loginapp::_createAccount: pendingCreateMgr has {}, request create failed!\n",
accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_BUSY;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
{
// 把请求交由脚本处理
SERVER_ERROR_CODE retcode = SERVER_SUCCESS;
SCOPED_PROFILE(SCRIPTCALL_PROFILE);
PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(),
const_cast("onRequestCreateAccount"),
const_cast("ssy#"),
accountName.c_str(),
password.c_str(),
datas.c_str(), datas.length());
if(pyResult != NULL)
{
if(PySequence_Check(pyResult) && PySequence_Size(pyResult) == 4)
{
char* sname;
char* spassword;
char *extraDatas;
Py_ssize_t extraDatas_size = 0;
if(PyArg_ParseTuple(pyResult, "H|s|s|y#", &retcode, &sname, &spassword, &extraDatas, &extraDatas_size) == -1)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: {}.onRequestLogin, Return value error! accountName={}\n",
g_kbeSrvConfig.getLoginApp().entryScriptFile, accountName));
retcode = SERVER_ERR_OP_FAILED;
}
else
{
accountName = sname;
password = spassword;
if (extraDatas && extraDatas_size > 0)
datas.assign(extraDatas, extraDatas_size);
else
SCRIPT_ERROR_CHECK();
}
}
else
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: {}.onRequestLogin, Return value error, must be errorcode or tuple! accountName={}\n",
g_kbeSrvConfig.getLoginApp().entryScriptFile, accountName));
retcode = SERVER_ERR_OP_FAILED;
}
Py_DECREF(pyResult);
}
else
{
SCRIPT_ERROR_CHECK();
retcode = SERVER_ERR_OP_FAILED;
}
if(retcode != SERVER_SUCCESS)
{
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
else
{
if(accountName.size() == 0)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: accountName is empty!\n"));
retcode = SERVER_ERR_NAME;
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
}
}
if(type == ACCOUNT_TYPE_SMART)
{
if (email_isvalid(accountName.c_str()))
{
type = ACCOUNT_TYPE_MAIL;
}
else
{
if(!validName(accountName))
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: invalid accountName({})\n",
accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_NAME;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
type = ACCOUNT_TYPE_NORMAL;
}
}
else if(type == ACCOUNT_TYPE_NORMAL)
{
if(!validName(accountName))
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: invalid accountName({})\n",
accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_NAME;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
}
else if (!email_isvalid(accountName.c_str()))
{
/*
std::string user_name, domain_name;
user_name = regex_replace(accountName, _g_mail_pattern, std::string("$1") );
domain_name = regex_replace(accountName, _g_mail_pattern, std::string("$2") );
*/
WARNING_MSG(fmt::format("Loginapp::_createAccount: invalid email={}\n",
accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_NAME_MAIL;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
DEBUG_MSG(fmt::format("Loginapp::_createAccount: accountName={}, passwordsize={}, type={}, oldType={}.\n",
accountName.c_str(), password.size(), type, oldType));
ptinfos = new PendingLoginMgr::PLInfos;
ptinfos->accountName = accountName;
ptinfos->password = password;
ptinfos->datas = datas;
ptinfos->addr = pChannel->addr();
pendingCreateMgr_.add(ptinfos);
Components::COMPONENTS& cts = Components::getSingleton().getComponents(DBMGR_TYPE);
Components::ComponentInfos* dbmgrinfos = NULL;
if(cts.size() > 0)
dbmgrinfos = &(*cts.begin());
if(dbmgrinfos == NULL || dbmgrinfos->pChannel == NULL || dbmgrinfos->cid == 0)
{
ERROR_MSG(fmt::format("Loginapp::_createAccount: create({}), not found dbmgr!\n",
accountName));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(ClientInterface::onCreateAccountResult);
SERVER_ERROR_CODE retcode = SERVER_ERR_SRV_NO_READY;
(*pBundle) << retcode;
(*pBundle).appendBlob(retdatas);
pChannel->send(pBundle);
return false;
}
pChannel->extra(accountName);
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(DbmgrInterface::reqCreateAccount);
uint8 uatype = uint8(type);
(*pBundle) << accountName << password << uatype;
(*pBundle).appendBlob(datas);
dbmgrinfos->pChannel->send(pBundle);
printf("**********_reqCreateAccount step 2 **********");
return true;
}
dbmgr 服务器 注册账号信息经过一系列的验证将消息压如队列。
最终 DBTaskCreateAccount 这个类里面,最重要的函数是 db_thread_process,是子类真正做的事情。
这个类里,presentMainThread这个函数,是持久化执行完的回调调用,在这里持久化结束以后调用的函数就是onReqCreateAccountResult
bool DBTaskCreateAccount::db_thread_process()
{
ACCOUNT_INFOS info;
success_ = DBTaskCreateAccount::writeAccount(pdbi_, accountName_, password_, postdatas_, info) && info.dbid > 0;
return false;
}
//-------------------------------------------------------------------------------------
bool DBTaskCreateAccount::writeAccount(DBInterface* pdbi, const std::string& accountName,
const std::string& passwd, const std::string& datas, ACCOUNT_INFOS& info)
{
info.dbid = 0;
if(accountName.size() == 0)
{
return false;
}
// 寻找dblog是否有此账号, 如果有则创建失败
// 如果没有则向account表新建一个entity数据同时在accountlog表写入一个log关联dbid
EntityTables& entityTables = EntityTables::findByInterfaceName(pdbi->name());
KBEAccountTable* pTable = static_cast(entityTables.findKBETable(KBE_TABLE_PERFIX "_accountinfos"));
KBE_ASSERT(pTable);
ScriptDefModule* pModule = EntityDef::findScriptModule(DBUtil::accountScriptName());
if(pModule == NULL)
{
ERROR_MSG(fmt::format("DBTaskCreateAccount::writeAccount(): not found account script[{}], create[{}] error!\n",
DBUtil::accountScriptName(), accountName));
return false;
}
if(pTable->queryAccount(pdbi, accountName, info) && (info.flags & ACCOUNT_FLAG_NOT_ACTIVATED) <= 0)
{
if(pdbi->getlasterror() > 0)
{
WARNING_MSG(fmt::format("DBTaskCreateAccount::writeAccount({}): queryAccount error: {}\n",
accountName, pdbi->getstrerror()));
}
return false;
}
bool hasset = (info.dbid != 0);
if(!hasset)
{
info.flags = g_kbeSrvConfig.getDBMgr().accountDefaultFlags;
info.deadline = g_kbeSrvConfig.getDBMgr().accountDefaultDeadline;
}
DBID entityDBID = info.dbid;
if(entityDBID == 0)
{
// 防止多线程问题, 这里做一个拷贝。
MemoryStream copyAccountDefMemoryStream(pTable->accountDefMemoryStream());
entityDBID = EntityTables::findByInterfaceName(pdbi->name()).writeEntity(pdbi, 0, -1,
©AccountDefMemoryStream, pModule);
if (entityDBID <= 0)
{
WARNING_MSG(fmt::format("DBTaskCreateAccount::writeAccount({}): writeEntity error: {}\n",
accountName, pdbi->getstrerror()));
return false;
}
}
info.name = accountName;
info.email = accountName + "@0.0";
info.password = passwd;
info.dbid = entityDBID;
info.datas = datas;
if(!hasset)
{
if(!pTable->logAccount(pdbi, info))
{
if(pdbi->getlasterror() > 0)
{
WARNING_MSG(fmt::format("DBTaskCreateAccount::writeAccount(): logAccount error:{}\n",
pdbi->getstrerror()));
}
return false;
}
}
else
{
if(!pTable->setFlagsDeadline(pdbi, accountName, info.flags & ~ACCOUNT_FLAG_NOT_ACTIVATED, info.deadline))
{
if(pdbi->getlasterror() > 0)
{
WARNING_MSG(fmt::format("DBTaskCreateAccount::writeAccount(): logAccount error:{}\n",
pdbi->getstrerror()));
}
return false;
}
}
return true;
}
//-------------------------------------------------------------------------------------
thread::TPTask::TPTaskState DBTaskCreateAccount::presentMainThread()
{
DEBUG_MSG(fmt::format("Dbmgr::reqCreateAccount: {}, success={}.\n", registerName_.c_str(), success_));
Network::Bundle* pBundle = Network::Bundle::createPoolObject(OBJECTPOOL_POINT);
(*pBundle).newMessage(LoginappInterface::onReqCreateAccountResult);
SERVER_ERROR_CODE failedcode = SERVER_SUCCESS;
if(!success_)
failedcode = SERVER_ERR_ACCOUNT_CREATE_FAILED;
(*pBundle) << failedcode << registerName_ << password_;
(*pBundle).appendBlob(getdatas_);
if(!this->send(pBundle))
{
ERROR_MSG(fmt::format("DBTaskCreateAccount::presentMainThread: channel({}) not found.\n", addr_.c_str()));
Network::Bundle::reclaimPoolObject(pBundle);
}
return thread::TPTask::TPTASK_STATE_COMPLETED;
}
可以看到最终调用 loginapp 中LoginappInterface::onReqCreateAccountResult 将数据发送至客户端