f8/cpp/utils.cc
aozhiwei 98f1d402cb 1
2020-07-30 15:51:13 +08:00

535 lines
22 KiB
C++

#include <a8/a8.h>
#include <a8/stringlist.h>
#include <a8/csvreader.h>
#include <a8/udplog.h>
#include <a8/mysql.h>
#include <a8/openssl.h>
#include <a8/strutils.h>
#include <a8/mutable_xobject.h>
#include <google/protobuf/message.h>
#include "framework/cpp/utils.h"
namespace f8
{
bool ReadCsvMetaFile(const std::string& filename,
google::protobuf::Message* prototype,
std::function<void (google::protobuf::Message*)> push_back_func)
{
const google::protobuf::Descriptor* descriptor = prototype->GetDescriptor();
const google::protobuf::Reflection* reflection = prototype->GetReflection();
a8::CsvReader reader;
reader.Load(filename);
while (reader.NextLine()) {
google::protobuf::Message* msg = prototype->New();
for (int i = 0; i < descriptor->field_count(); ++i) {
const google::protobuf::FieldDescriptor* field_desc = descriptor->field(i);
const std::string& field_name = field_desc->name();
if (field_name.empty() || field_name[0] == '_') {
continue;
}
if (!reader.KeyExists(field_name) && field_desc->is_optional()) {
continue;
}
switch (field_desc->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
reflection->SetString(msg, field_desc, reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
{
reflection->SetInt32(msg, field_desc, reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
{
reflection->SetUInt32(msg, field_desc, reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
{
reflection->SetInt64(msg, field_desc, reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
{
reflection->SetUInt64(msg, field_desc, reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
{
reflection->SetFloat(msg, field_desc, (double)reader.GetValue(field_name));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
{
reflection->SetDouble(msg, field_desc, reader.GetValue(field_name));
}
break;
default:
{
abort();
}
break;
}//end switch
}//end for
push_back_func(msg);
delete msg;
}
return true;
}
static bool JsonToMessage(a8::XObject& jsonobj, google::protobuf::Message* msg)
{
const google::protobuf::Descriptor* descriptor = msg->GetDescriptor();
const google::protobuf::Reflection* reflection = msg->GetReflection();
for (int i = 0; i < descriptor->field_count(); ++i) {
const google::protobuf::FieldDescriptor* field_desc = descriptor->field(i);
const std::string& field_name = field_desc->name();
if (field_name.empty() || field_name[0] == '_') {
continue;
}
if (!jsonobj.HasKey(field_name) && field_desc->is_optional()) {
continue;
}
if (field_desc->is_repeated()) {
std::shared_ptr<a8::XObject> repeated_field = jsonobj.At(field_name);
if (!repeated_field) {
continue;
}
for (int i = 0; i < repeated_field->Size(); ++i) {
auto field_value = repeated_field->At(i);
switch (field_desc->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
reflection->AddString(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
{
reflection->AddInt32(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
{
reflection->AddUInt32(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
{
reflection->AddInt64(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
{
reflection->AddUInt64(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
{
reflection->AddFloat(msg, field_desc, (double)field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
{
reflection->AddDouble(msg, field_desc, field_value->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
{
google::protobuf::Message* p = reflection->AddMessage(msg, field_desc);
JsonToMessage(*field_value, p);
}
break;
default:
{
abort();
}
break;
}//end switch
}
} else {
switch (field_desc->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
reflection->SetString(msg, field_desc, jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
{
reflection->SetInt32(msg, field_desc, jsonobj.At(field_name)->AsXValue()); }
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
{
reflection->SetUInt32(msg, field_desc, jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
{
reflection->SetInt64(msg, field_desc, jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
{
reflection->SetUInt64(msg, field_desc, jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
{
reflection->SetFloat(msg, field_desc, (double)jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
{
reflection->SetDouble(msg, field_desc, jsonobj.At(field_name)->AsXValue());
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
{
google::protobuf::Message* p = reflection->MutableMessage(msg, field_desc);
JsonToMessage(*jsonobj.At(field_name), p);
}
break;
default:
{
abort();
}
break;
}//end switch
}
}
return true;
}
static bool MessageToJson(const google::protobuf::Message* msg, a8::MutableXObject& jsonobj)
{
const google::protobuf::Descriptor* descriptor = msg->GetDescriptor();
const google::protobuf::Reflection* reflection = msg->GetReflection();
for (int i = 0; i < descriptor->field_count(); ++i) {
const google::protobuf::FieldDescriptor* field_desc = descriptor->field(i);
const std::string& field_name = field_desc->name();
if (field_desc->is_repeated()) {
a8::MutableXObject* array_obj = a8::MutableXObject::NewArray();
std::shared_ptr<a8::XObject> repeated_field = jsonobj.At(field_name);
continue;
for (int i = 0; i < reflection->FieldSize(*msg, field_desc); ++i) {
switch (field_desc->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
{
array_obj->Push(reflection->GetRepeatedBool(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
array_obj->Push(reflection->GetRepeatedString(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
{
array_obj->Push(reflection->GetRepeatedInt32(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
{
array_obj->Push(reflection->GetRepeatedUInt32(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
{
array_obj->Push(reflection->GetRepeatedInt64(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
{
array_obj->Push(reflection->GetRepeatedUInt64(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
{
array_obj->Push(reflection->GetRepeatedFloat(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
{
array_obj->Push(reflection->GetRepeatedDouble(*msg, field_desc, i));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
{
a8::MutableXObject* p = a8::MutableXObject::NewObject();
MessageToJson(&reflection->GetRepeatedMessage(*msg, field_desc, i),
*p
);
array_obj->Push(*p);
delete p;
}
break;
default:
{
abort();
}
break;
}//end switch
}
jsonobj.SetVal(field_name, *array_obj);
delete array_obj;
} else {
switch (field_desc->cpp_type()) {
case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
{
jsonobj.SetVal(field_name, reflection->GetBool(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
jsonobj.SetVal(field_name, reflection->GetString(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
{
jsonobj.SetVal(field_name, reflection->GetInt32(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
{
jsonobj.SetVal(field_name, reflection->GetUInt32(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
{
jsonobj.SetVal(field_name, reflection->GetInt64(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
{
jsonobj.SetVal(field_name, reflection->GetUInt64(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
{
jsonobj.SetVal(field_name, reflection->GetFloat(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
{
jsonobj.SetVal(field_name, reflection->GetDouble(*msg, field_desc));
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
{
a8::MutableXObject* p = a8::MutableXObject::NewObject();
MessageToJson(&reflection->GetMessage(*msg, field_desc),
*p
);
jsonobj.SetVal(field_name, *p);
}
break;
default:
{
abort();
}
break;
}//end switch
}
}
return true;
}
bool ReadJsonMetaFile(const std::string& filename,
google::protobuf::Message* prototype,
std::function<void (google::protobuf::Message*)> push_back_func)
{
a8::XObject json_reader;
json_reader.ReadFromJsonFile(filename);
for (int i = 0; i < json_reader.Size(); ++i) {
std::shared_ptr<a8::XObject> p = json_reader.At(i);
google::protobuf::Message* msg = prototype->New();
JsonToMessage(*p, msg);
push_back_func(msg);
delete msg;
}
return true;
}
std::string PbToJson(const google::protobuf::Message* msg)
{
std::string data;
a8::MutableXObject* p = a8::MutableXObject::NewObject();
MessageToJson(msg, *p);
p->ToJsonStr(data);
delete p;
return data;
}
void InitMysqlConnection(a8::mysql::Query* query)
{
a8::UdpLog::Instance()->Info("show variables like 'character%';", {});
a8::UdpLog::Instance()->Info("Variable_name\tValue", {});
#if 1
query->ExecScript("SET character_set_server=utf8;", {});
query->ExecScript("SET NAMES utf8;", {});
#endif
query->ExecQuery("show variables like 'character%';", {});
while (!query->Eof()) {
std::string line;
line = query->GetValue(0).GetString() + "\t" + query->GetValue(1).GetString();
a8::UdpLog::Instance()->Info(line.c_str(), {});
assert(!(query->GetValue(0).GetString() == "character_set_client" &&
query->GetValue(1).GetString() != "utf8"));
assert(!(query->GetValue(0).GetString() == "character_set_connection" &&
query->GetValue(1).GetString() != "utf8"));
assert(!(query->GetValue(0).GetString() == "character_set_database" &&
query->GetValue(1).GetString() != "utf8"));
assert(!(query->GetValue(0).GetString() == "character_set_results" &&
query->GetValue(1).GetString() != "utf8"));
assert(!(query->GetValue(0).GetString() == "character_set_server" &&
query->GetValue(1).GetString() != "utf8"));
assert(!(query->GetValue(0).GetString() == "character_set_system" &&
query->GetValue(1).GetString() != "utf8"));
query->Next();
}
a8::UdpLog::Instance()->Info("show variables like '%collation%';", {});
a8::UdpLog::Instance()->Info("Variable_name\tValue", {});
query->ExecQuery("show variables like '%collation%';", {});
while (!query->Eof()) {
std::string line;
line = query->GetValue(0).GetString() + "\t" + query->GetValue(1).GetString();
a8::UdpLog::Instance()->Info(line.c_str(), {});
assert(query->GetValue(1).GetString() == "utf8_general_ci");
query->Next();
}
}
void CheckMysqlConnection(a8::mysql::Connection* conn, a8::mysql::Query* query,
std::string dbhost, int port, std::string dbuser, std::string dbpasswd, std::string gamedb)
{
if (query->ExecQuery("SELECT 1;", {}) <= 0) {
a8::UdpLog::Instance()->Warning("mysql disconnect", {});
if (conn->Connect(dbhost, 3306, dbuser, dbpasswd, gamedb)) {
f8::InitMysqlConnection(query);
a8::UdpLog::Instance()->Info("mysql reconnect successed", {});
} else {
a8::UdpLog::Instance()->Info("mysql reconnect failed", {});
}
}
}
bool CheckRegisterTimeInSessionId(const std::string& accountid, const std::string& sessionid)
{
std::vector<std::string> strings;
a8::Split(sessionid, strings, '_');
if (strings.size() < 4) {
return false;
}
return true;
}
time_t ExtractRegisterTimeFromSessionId(const std::string& sessionid)
{
std::vector<std::string> strings;
a8::Split(sessionid, strings, '_');
if (strings.size() < 4) {
return 0;
}
std::string session_createtime = strings[0];
std::string account_registertime = strings[1];
std::string md51 = strings[2];
std::string md52 = strings[3];
return a8::XValue(account_registertime);
}
bool IsValidSessionId(const std::string& accountid, const std::string& sessionid)
{
std::vector<std::string> strings;
a8::Split(sessionid, strings, '_');
if (strings.size() < 4) {
return false;
}
return true;
}
bool LoginCheck(const std::string& accountid, const std::string& sessionid)
{
std::vector<std::string> strings;
a8::Split(sessionid, strings, '_');
if (strings.size() < 4) {
return false;
}
if (IsOnlineEnv()) {
//session_createtime account_registertime md51 md52
std::string md5_str = accountid + "f3a6a9a5-217a-4079-ab99-b5d69b8212be" +
strings[1] + strings[0];
return a8::openssl::md5(md5_str) == strings[2];
}
return true;
}
int ExtractGameIdFromAccountId(const std::string& accountid)
{
std::vector<std::string> strings;
a8::Split(accountid, strings, '_');
if (strings.size() < 2) {
return false;
}
std::string channelid = strings[0];
std::string gameid = strings[1];
return a8::XValue(gameid);
}
int ExtractChannelIdFromAccountId(const std::string& accountid)
{
std::vector<std::string> strings;
a8::Split(accountid, strings, '_');
if (strings.size() < 2) {
return false;
}
std::string channelid = strings[0];
std::string gameid = strings[1];
return a8::XValue(channelid);
}
bool IsOnlineEnv()
{
static bool is_online = !getenv("SERVER_ENV");
return is_online;
}
bool IsTestEnv()
{
static bool is_test = a8::SafeStrCmp(getenv("SERVER_ENV"), "TEST") == 0;
return is_test;
}
bool IsValidNormalConfig(a8::XObject& conf, std::vector<std::string> fields)
{
if (conf.GetType() != a8::XOT_ARRAY) {
abort();
}
for (int i = 0; i < conf.Size(); ++i) {
std::shared_ptr<a8::XObject> node = conf.At(i);
if (node->At("instance_id")->AsXValue().GetInt() != i + 1) {
abort();
}
for (std::string& field_name : fields) {
if (!node->HasKey(field_name)) {
abort();
}
}
}
return true;
}
}