mirror of
https://gitee.com/Zhaoxin59/my-chat_-server.git
synced 2026-02-13 17:11:48 +08:00
1421 lines
85 KiB
C++
1421 lines
85 KiB
C++
#include "data_redis.hpp" // redis数据管理客户端封装
|
||
#include "etcd.hpp" // 服务注册模块封装
|
||
#include "logger.hpp" // 日志模块封装
|
||
#include "channel.hpp" // 信道管理模块封装
|
||
|
||
#include "connection.hpp"
|
||
|
||
#include "user.pb.h" // protobuf框架代码
|
||
#include "base.pb.h" // protobuf框架代码
|
||
#include "file.pb.h" // protobuf框架代码
|
||
#include "friend.pb.h" // protobuf框架代码
|
||
#include "gateway.pb.h" // protobuf框架代码
|
||
#include "message.pb.h" // protobuf框架代码
|
||
#include "speech.pb.h" // protobuf框架代码
|
||
#include "transmite.pb.h" // protobuf框架代码
|
||
#include "notify.pb.h"
|
||
|
||
#include "httplib.h"
|
||
|
||
|
||
namespace bite_im{
|
||
#define GET_PHONE_VERIFY_CODE "/service/user/get_phone_verify_code"
|
||
#define USERNAME_REGISTER "/service/user/username_register"
|
||
#define USERNAME_LOGIN "/service/user/username_login"
|
||
#define PHONE_REGISTER "/service/user/phone_register"
|
||
#define PHONE_LOGIN "/service/user/phone_login"
|
||
#define GET_USERINFO "/service/user/get_user_info"
|
||
#define SET_USER_AVATAR "/service/user/set_avatar"
|
||
#define SET_USER_NICKNAME "/service/user/set_nickname"
|
||
#define SET_USER_DESC "/service/user/set_description"
|
||
#define SET_USER_PHONE "/service/user/set_phone"
|
||
#define FRIEND_GET_LIST "/service/friend/get_friend_list"
|
||
#define FRIEND_APPLY "/service/friend/add_friend_apply"
|
||
#define FRIEND_APPLY_PROCESS "/service/friend/add_friend_process"
|
||
#define FRIEND_REMOVE "/service/friend/remove_friend"
|
||
#define FRIEND_SEARCH "/service/friend/search_friend"
|
||
#define FRIEND_GET_PENDING_EV "/service/friend/get_pending_friend_events"
|
||
#define CSS_GET_LIST "/service/friend/get_chat_session_list"
|
||
#define CSS_CREATE "/service/friend/create_chat_session"
|
||
#define CSS_GET_MEMBER "/service/friend/get_chat_session_member"
|
||
#define MSG_GET_RANGE "/service/message_storage/get_history"
|
||
#define MSG_GET_RECENT "/service/message_storage/get_recent"
|
||
#define MSG_KEY_SEARCH "/service/message_storage/search_history"
|
||
#define NEW_MESSAGE "/service/message_transmit/new_message"
|
||
#define FILE_GET_SINGLE "/service/file/get_single_file"
|
||
#define FILE_GET_MULTI "/service/file/get_multi_file"
|
||
#define FILE_PUT_SINGLE "/service/file/put_single_file"
|
||
#define FILE_PUT_MULTI "/service/file/put_multi_file"
|
||
#define SPEECH_RECOGNITION "/service/speech/recognition"
|
||
class GatewayServer {
|
||
public:
|
||
using ptr = std::shared_ptr<GatewayServer>;
|
||
GatewayServer(
|
||
int websocket_port,
|
||
int http_port,
|
||
const std::shared_ptr<sw::redis::Redis> &redis_client,
|
||
const ServiceManager::ptr &channels,
|
||
const Discovery::ptr &service_discoverer,
|
||
const std::string user_service_name,
|
||
const std::string file_service_name,
|
||
const std::string speech_service_name,
|
||
const std::string message_service_name,
|
||
const std::string transmite_service_name,
|
||
const std::string friend_service_name)
|
||
:_redis_session(std::make_shared<Session>(redis_client)),
|
||
_redis_status(std::make_shared<Status>(redis_client)),
|
||
_mm_channels(channels),
|
||
_service_discoverer(service_discoverer),
|
||
_user_service_name(user_service_name),
|
||
_file_service_name(file_service_name),
|
||
_speech_service_name(speech_service_name),
|
||
_message_service_name(message_service_name),
|
||
_transmite_service_name(transmite_service_name),
|
||
_friend_service_name(friend_service_name),
|
||
_connections(std::make_shared<Connection>()){
|
||
|
||
_ws_server.set_access_channels(websocketpp::log::alevel::none);
|
||
_ws_server.init_asio();
|
||
_ws_server.set_open_handler(std::bind(&GatewayServer::onOpen, this, std::placeholders::_1));
|
||
_ws_server.set_close_handler(std::bind(&GatewayServer::onClose, this, std::placeholders::_1));
|
||
auto wscb = std::bind(&GatewayServer::onMessage, this,
|
||
std::placeholders::_1, std::placeholders::_2);
|
||
_ws_server.set_message_handler(wscb);
|
||
_ws_server.set_reuse_addr(true);
|
||
_ws_server.listen(websocket_port);
|
||
_ws_server.start_accept();
|
||
|
||
_http_server.Post(GET_PHONE_VERIFY_CODE , (httplib::Server::Handler)std::bind(&GatewayServer::GetPhoneVerifyCode , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(USERNAME_REGISTER , (httplib::Server::Handler)std::bind(&GatewayServer::UserRegister , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(USERNAME_LOGIN , (httplib::Server::Handler)std::bind(&GatewayServer::UserLogin , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(PHONE_REGISTER , (httplib::Server::Handler)std::bind(&GatewayServer::PhoneRegister , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(PHONE_LOGIN , (httplib::Server::Handler)std::bind(&GatewayServer::PhoneLogin , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(GET_USERINFO , (httplib::Server::Handler)std::bind(&GatewayServer::GetUserInfo , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(SET_USER_AVATAR , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserAvatar , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(SET_USER_NICKNAME , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserNickname , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(SET_USER_DESC , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserDescription , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(SET_USER_PHONE , (httplib::Server::Handler)std::bind(&GatewayServer::SetUserPhoneNumber , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_GET_LIST , (httplib::Server::Handler)std::bind(&GatewayServer::GetFriendList , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_APPLY , (httplib::Server::Handler)std::bind(&GatewayServer::FriendAdd , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_APPLY_PROCESS , (httplib::Server::Handler)std::bind(&GatewayServer::FriendAddProcess , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_REMOVE , (httplib::Server::Handler)std::bind(&GatewayServer::FriendRemove , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_SEARCH , (httplib::Server::Handler)std::bind(&GatewayServer::FriendSearch , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FRIEND_GET_PENDING_EV , (httplib::Server::Handler)std::bind(&GatewayServer::GetPendingFriendEventList , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(CSS_GET_LIST , (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionList , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(CSS_CREATE , (httplib::Server::Handler)std::bind(&GatewayServer::ChatSessionCreate , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(CSS_GET_MEMBER , (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionMember , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(MSG_GET_RANGE , (httplib::Server::Handler)std::bind(&GatewayServer::GetHistoryMsg , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(MSG_GET_RECENT , (httplib::Server::Handler)std::bind(&GatewayServer::GetRecentMsg , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(MSG_KEY_SEARCH , (httplib::Server::Handler)std::bind(&GatewayServer::MsgSearch , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(NEW_MESSAGE , (httplib::Server::Handler)std::bind(&GatewayServer::NewMessage , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FILE_GET_SINGLE , (httplib::Server::Handler)std::bind(&GatewayServer::GetSingleFile , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FILE_GET_MULTI , (httplib::Server::Handler)std::bind(&GatewayServer::GetMultiFile , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FILE_PUT_SINGLE , (httplib::Server::Handler)std::bind(&GatewayServer::PutSingleFile , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(FILE_PUT_MULTI , (httplib::Server::Handler)std::bind(&GatewayServer::PutMultiFile , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_server.Post(SPEECH_RECOGNITION , (httplib::Server::Handler)std::bind(&GatewayServer::SpeechRecognition , this, std::placeholders::_1, std::placeholders::_2));
|
||
_http_thread = std::thread([this, http_port](){
|
||
_http_server.listen("0.0.0.0", http_port);
|
||
});
|
||
_http_thread.detach();
|
||
}
|
||
void start() {
|
||
_ws_server.run();
|
||
}
|
||
private:
|
||
void onOpen(websocketpp::connection_hdl hdl) {
|
||
LOG_DEBUG("websocket长连接建立成功 {}", (size_t)_ws_server.get_con_from_hdl(hdl).get());
|
||
}
|
||
void onClose(websocketpp::connection_hdl hdl) {
|
||
//长连接断开时做的清理工作
|
||
//0. 通过连接对象,获取对应的用户ID与登录会话ID
|
||
auto conn = _ws_server.get_con_from_hdl(hdl);
|
||
std::string uid, ssid;
|
||
bool ret = _connections->client(conn, uid, ssid);
|
||
if (ret == false) {
|
||
LOG_WARN("长连接断开,未找到长连接对应的客户端信息!");
|
||
return ;
|
||
}
|
||
//1. 移除登录会话信息
|
||
_redis_session->remove(ssid);
|
||
//2. 移除登录状态信息
|
||
_redis_status->remove(uid);
|
||
//3. 移除长连接管理数据
|
||
_connections->remove(conn);
|
||
LOG_DEBUG("{} {} {} 长连接断开,清理缓存数据!", ssid, uid, (size_t)conn.get());
|
||
}
|
||
void keepAlive(server_t::connection_ptr conn) {
|
||
if (!conn || conn->get_state() != websocketpp::session::state::value::open) {
|
||
LOG_DEBUG("非正常连接状态,结束连接保活");
|
||
return;
|
||
}
|
||
conn->ping("");
|
||
_ws_server.set_timer(60000, std::bind(&GatewayServer::keepAlive, this, conn));
|
||
}
|
||
void onMessage(websocketpp::connection_hdl hdl, server_t::message_ptr msg) {
|
||
//收到第一条消息后,根据消息中的会话ID进行身份识别,将客户端长连接添加管理
|
||
//1. 取出长连接对应的连接对象
|
||
auto conn = _ws_server.get_con_from_hdl(hdl);
|
||
//2. 针对消息内容进行反序列化 -- ClientAuthenticationReq -- 提取登录会话ID
|
||
ClientAuthenticationReq request;
|
||
bool ret = request.ParseFromString(msg->get_payload());
|
||
if (ret == false) {
|
||
LOG_ERROR("长连接身份识别失败:正文反序列化失败!");
|
||
_ws_server.close(hdl, websocketpp::close::status::unsupported_data, "正文反序列化失败!");
|
||
return;
|
||
}
|
||
//3. 在会话信息缓存中,查找会话信息
|
||
std::string ssid = request.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
//4. 会话信息不存在则关闭连接
|
||
if (!uid) {
|
||
LOG_ERROR("长连接身份识别失败:未找到会话信息 {}!", ssid);
|
||
_ws_server.close(hdl, websocketpp::close::status::unsupported_data, "未找到会话信息!");
|
||
return;
|
||
}
|
||
//5. 会话信息存在,则添加长连接管理
|
||
_connections->insert(conn, *uid, ssid);
|
||
LOG_DEBUG("新增长连接管理:{}-{}-{}", ssid, *uid, (size_t)conn.get());
|
||
keepAlive(conn);
|
||
}
|
||
void GetPhoneVerifyCode(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
PhoneVerifyCodeReq req;
|
||
PhoneVerifyCodeRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取短信验证码请求正文反序列化失败!");
|
||
return err_response("获取短信验证码请求正文反序列化失败!");
|
||
}
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void UserRegister(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
UserRegisterReq req;
|
||
UserRegisterRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户名注册请求正文反序列化失败!");
|
||
return err_response("用户名注册请求正文反序列化失败!");
|
||
}
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.UserRegister(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void UserLogin(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
UserLoginReq req;
|
||
UserLoginRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户登录请求正文反序列化失败!");
|
||
return err_response("用户登录请求正文反序列化失败!");
|
||
}
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.UserLogin(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void PhoneRegister(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
PhoneRegisterReq req;
|
||
PhoneRegisterRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("手机号注册请求正文反序列化失败!");
|
||
return err_response("手机号注册请求正文反序列化失败!");
|
||
}
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.PhoneRegister(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void PhoneLogin(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
PhoneLoginReq req;
|
||
PhoneLoginRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("手机号登录请求正文反序列化失败!");
|
||
return err_response("手机号登录请求正文反序列化失败!");
|
||
}
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.PhoneLogin(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetUserInfo(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
GetUserInfoReq req;
|
||
GetUserInfoRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取用户信息请求正文反序列化失败!");
|
||
return err_response("获取用户信息请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void SetUserAvatar(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
SetUserAvatarReq req;
|
||
SetUserAvatarRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户头像设置请求正文反序列化失败!");
|
||
return err_response("用户头像设置请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void SetUserNickname(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
SetUserNicknameReq req;
|
||
SetUserNicknameRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户昵称设置请求正文反序列化失败!");
|
||
return err_response("用户昵称设置请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.SetUserNickname(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void SetUserDescription(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
SetUserDescriptionReq req;
|
||
SetUserDescriptionRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户签名设置请求正文反序列化失败!");
|
||
return err_response("用户签名设置请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.SetUserDescription(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void SetUserPhoneNumber(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
SetUserPhoneNumberReq req;
|
||
SetUserPhoneNumberRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户手机号设置请求正文反序列化失败!");
|
||
return err_response("用户手机号设置请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.SetUserPhoneNumber(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return err_response("用户子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetFriendList(const httplib::Request &request, httplib::Response &response) {
|
||
//1. 取出http请求正文,将正文进行反序列化
|
||
GetFriendListReq req;
|
||
GetFriendListRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取好友列表请求正文反序列化失败!");
|
||
return err_response("获取好友列表请求正文反序列化失败!");
|
||
}
|
||
//2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
//2. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetFriendList(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
//3. 得到用户子服务的响应后,将响应内容进行序列化作为http响应正文
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
|
||
std::shared_ptr<GetUserInfoRsp> _GetUserInfo(const std::string &rid, const std::string &uid) {
|
||
GetUserInfoReq req;
|
||
auto rsp = std::make_shared<GetUserInfoRsp>();
|
||
req.set_request_id(rid);
|
||
req.set_user_id(uid);
|
||
//2. 将请求转发给用户子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_user_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return std::shared_ptr<GetUserInfoRsp>();
|
||
}
|
||
bite_im::UserService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetUserInfo(&cntl, &req, rsp.get(), nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 用户子服务调用失败!", req.request_id());
|
||
return std::shared_ptr<GetUserInfoRsp>();
|
||
}
|
||
return rsp;
|
||
}
|
||
void FriendAdd(const httplib::Request &request, httplib::Response &response) {
|
||
// 好友申请的业务处理中,好友子服务其实只是在数据库创建了申请事件
|
||
// 网关需要做的事情:当好友子服务将业务处理完毕后,如果处理是成功的--需要通知被申请方
|
||
// 1. 正文的反序列化,提取关键要素:登录会话ID
|
||
FriendAddReq req;
|
||
FriendAddRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("申请好友请求正文反序列化失败!");
|
||
return err_response("申请好友请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.FriendAdd(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 4. 若业务处理成功 --- 且获取被申请方长连接成功,则向被申请放进行好友申请事件通知
|
||
auto conn = _connections->connection(req.respondent_id());
|
||
if (rsp.success() && conn) {
|
||
LOG_DEBUG("找到被申请人 {} 长连接,对其进行好友申请通知", req.respondent_id());
|
||
auto user_rsp = _GetUserInfo(req.request_id(), *uid);
|
||
if (!user_rsp) {
|
||
LOG_ERROR("{} 获取当前客户端用户信息失败!", req.request_id());
|
||
return err_response("获取当前客户端用户信息失败!");
|
||
}
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::FRIEND_ADD_APPLY_NOTIFY);
|
||
notify.mutable_friend_add_apply()->mutable_user_info()->CopyFrom(user_rsp->user_info());
|
||
conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void FriendAddProcess(const httplib::Request &request, httplib::Response &response) {
|
||
//好友申请的处理-----
|
||
FriendAddProcessReq req;
|
||
FriendAddProcessRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("好友申请处理请求正文反序列化失败!");
|
||
return err_response("好友申请处理请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
|
||
if (rsp.success()) {
|
||
auto process_user_rsp = _GetUserInfo(req.request_id(), *uid);
|
||
if (!process_user_rsp) {
|
||
LOG_ERROR("{} 获取用户信息失败!", req.request_id());
|
||
return err_response("获取用户信息失败!");
|
||
}
|
||
auto apply_user_rsp = _GetUserInfo(req.request_id(), req.apply_user_id());
|
||
if (!process_user_rsp) {
|
||
LOG_ERROR("{} 获取用户信息失败!", req.request_id());
|
||
return err_response("获取用户信息失败!");
|
||
}
|
||
auto process_conn = _connections->connection(*uid);
|
||
if (process_conn) LOG_DEBUG("找到处理人的长连接!");
|
||
else LOG_DEBUG("未找到处理人的长连接!");
|
||
auto apply_conn = _connections->connection(req.apply_user_id());
|
||
if (apply_conn) LOG_DEBUG("找到申请人的长连接!");
|
||
else LOG_DEBUG("未找到申请人的长连接!");
|
||
//4. 将处理结果给申请人进行通知
|
||
if (apply_conn) {
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::FRIEND_ADD_PROCESS_NOTIFY);
|
||
auto process_result = notify.mutable_friend_process_result();
|
||
process_result->mutable_user_info()->CopyFrom(process_user_rsp->user_info());
|
||
process_result->set_agree(req.agree());
|
||
apply_conn->send(notify.SerializeAsString(),
|
||
websocketpp::frame::opcode::value::binary);
|
||
LOG_DEBUG("对申请人进行申请处理结果通知!");
|
||
}
|
||
//5. 若处理结果是同意 --- 会伴随着单聊会话的创建 -- 因此需要对双方进行会话创建的通知
|
||
if (req.agree() && apply_conn) { //对申请人的通知---会话信息就是处理人信息
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
|
||
auto chat_session = notify.mutable_new_chat_session_info();
|
||
chat_session->mutable_chat_session_info()->set_single_chat_friend_id(*uid);
|
||
chat_session->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
|
||
chat_session->mutable_chat_session_info()->set_chat_session_name(process_user_rsp->user_info().nickname());
|
||
chat_session->mutable_chat_session_info()->set_avatar(process_user_rsp->user_info().avatar());
|
||
apply_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
LOG_DEBUG("对申请人进行会话创建通知!");
|
||
}
|
||
if (req.agree() && process_conn) { //对处理人的通知 --- 会话信息就是申请人信息
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
|
||
auto chat_session = notify.mutable_new_chat_session_info();
|
||
chat_session->mutable_chat_session_info()->set_single_chat_friend_id(req.apply_user_id());
|
||
chat_session->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
|
||
chat_session->mutable_chat_session_info()->set_chat_session_name(apply_user_rsp->user_info().nickname());
|
||
chat_session->mutable_chat_session_info()->set_avatar(apply_user_rsp->user_info().avatar());
|
||
process_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
LOG_DEBUG("对处理人进行会话创建通知!");
|
||
}
|
||
}
|
||
//6. 对客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void FriendRemove(const httplib::Request &request, httplib::Response &response) {
|
||
// 1. 正文的反序列化,提取关键要素:登录会话ID
|
||
FriendRemoveReq req;
|
||
FriendRemoveRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("删除好友请求正文反序列化失败!");
|
||
return err_response("删除好友请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.FriendRemove(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 4. 若业务处理成功 --- 且获取被申请方长连接成功,则向被申请放进行好友申请事件通知
|
||
auto conn = _connections->connection(req.peer_id());
|
||
if (rsp.success() && conn) {
|
||
LOG_ERROR("对被删除人 {} 进行好友删除通知!", req.peer_id());
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::FRIEND_REMOVE_NOTIFY);
|
||
notify.mutable_friend_remove()->set_user_id(*uid);
|
||
conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void FriendSearch(const httplib::Request &request, httplib::Response &response) {
|
||
FriendSearchReq req;
|
||
FriendSearchRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("用户搜索请求正文反序列化失败!");
|
||
return err_response("用户搜索请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.FriendSearch(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetPendingFriendEventList(const httplib::Request &request, httplib::Response &response) {
|
||
GetPendingFriendEventListReq req;
|
||
GetPendingFriendEventListRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取待处理好友申请请求正文反序列化失败!");
|
||
return err_response("获取待处理好友申请请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetChatSessionList(const httplib::Request &request, httplib::Response &response) {
|
||
GetChatSessionListReq req;
|
||
GetChatSessionListRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取聊天会话列表请求正文反序列化失败!");
|
||
return err_response("获取聊天会话列表请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetChatSessionMember(const httplib::Request &request, httplib::Response &response) {
|
||
GetChatSessionMemberReq req;
|
||
GetChatSessionMemberRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取聊天会话成员请求正文反序列化失败!");
|
||
return err_response("获取聊天会话成员请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void ChatSessionCreate(const httplib::Request &request, httplib::Response &response) {
|
||
ChatSessionCreateReq req;
|
||
ChatSessionCreateRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("创建聊天会话请求正文反序列化失败!");
|
||
return err_response("创建聊天会话请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_friend_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FriendService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 好友子服务调用失败!", req.request_id());
|
||
return err_response("好友子服务调用失败!");
|
||
}
|
||
// 4. 若业务处理成功 --- 且获取被申请方长连接成功,则向被申请放进行好友申请事件通知
|
||
if (rsp.success()){
|
||
for (int i = 0; i < req.member_id_list_size(); i++) {
|
||
auto conn = _connections->connection(req.member_id_list(i));
|
||
if (!conn) {
|
||
LOG_DEBUG("未找到群聊成员 {} 长连接", req.member_id_list(i));
|
||
continue;
|
||
}
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::CHAT_SESSION_CREATE_NOTIFY);
|
||
auto chat_session = notify.mutable_new_chat_session_info();
|
||
chat_session->mutable_chat_session_info()->CopyFrom(rsp.chat_session_info());
|
||
conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
LOG_DEBUG("对群聊成员 {} 进行会话创建通知", req.member_id_list(i));
|
||
}
|
||
}
|
||
// 5. 向客户端进行响应
|
||
rsp.clear_chat_session_info();
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetHistoryMsg(const httplib::Request &request, httplib::Response &response) {
|
||
GetHistoryMsgReq req;
|
||
GetHistoryMsgRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取区间消息请求正文反序列化失败!");
|
||
return err_response("获取区间消息请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_message_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::MsgStorageService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetHistoryMsg(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 消息存储子服务调用失败!", req.request_id());
|
||
return err_response("消息存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetRecentMsg(const httplib::Request &request, httplib::Response &response) {
|
||
GetRecentMsgReq req;
|
||
GetRecentMsgRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("获取最近消息请求正文反序列化失败!");
|
||
return err_response("获取最近消息请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_message_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::MsgStorageService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 消息存储子服务调用失败!", req.request_id());
|
||
return err_response("消息存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void MsgSearch(const httplib::Request &request, httplib::Response &response) {
|
||
MsgSearchReq req;
|
||
MsgSearchRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("消息搜索请求正文反序列化失败!");
|
||
return err_response("消息搜索请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_message_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::MsgStorageService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.MsgSearch(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 消息存储子服务调用失败!", req.request_id());
|
||
return err_response("消息存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetSingleFile(const httplib::Request &request, httplib::Response &response) {
|
||
GetSingleFileReq req;
|
||
GetSingleFileRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("单文件下载请求正文反序列化失败!");
|
||
return err_response("单文件下载请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_file_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FileService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetSingleFile(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 文件存储子服务调用失败!", req.request_id());
|
||
return err_response("文件存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void GetMultiFile(const httplib::Request &request, httplib::Response &response) {
|
||
GetMultiFileReq req;
|
||
GetMultiFileRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("单文件下载请求正文反序列化失败!");
|
||
return err_response("单文件下载请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_file_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FileService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetMultiFile(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 文件存储子服务调用失败!", req.request_id());
|
||
return err_response("文件存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void PutSingleFile(const httplib::Request &request, httplib::Response &response) {
|
||
PutSingleFileReq req;
|
||
PutSingleFileRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("单文件上传请求正文反序列化失败!");
|
||
return err_response("单文件上传请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_file_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FileService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.PutSingleFile(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 文件存储子服务调用失败!", req.request_id());
|
||
return err_response("文件存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void PutMultiFile(const httplib::Request &request, httplib::Response &response) {
|
||
PutMultiFileReq req;
|
||
PutMultiFileRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("批量文件上传请求正文反序列化失败!");
|
||
return err_response("批量文件上传请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_file_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::FileService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.PutMultiFile(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 文件存储子服务调用失败!", req.request_id());
|
||
return err_response("文件存储子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
void SpeechRecognition(const httplib::Request &request, httplib::Response &response) {
|
||
LOG_DEBUG("收到语音转文字请求!");
|
||
SpeechRecognitionReq req;
|
||
SpeechRecognitionRsp rsp;
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("语音识别请求正文反序列化失败!");
|
||
return err_response("语音识别请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_speech_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::SpeechService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.SpeechRecognition(&cntl, &req, &rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 语音识别子服务调用失败!", req.request_id());
|
||
return err_response("语音识别子服务调用失败!");
|
||
}
|
||
// 5. 向客户端进行响应
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
|
||
void NewMessage(const httplib::Request &request, httplib::Response &response) {
|
||
NewMessageReq req;
|
||
NewMessageRsp rsp;//这是给客户端的响应
|
||
GetTransmitTargetRsp target_rsp;//这是请求子服务的响应
|
||
auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void {
|
||
rsp.set_success(false);
|
||
rsp.set_errmsg(errmsg);
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
};
|
||
bool ret = req.ParseFromString(request.body);
|
||
if (ret == false) {
|
||
LOG_ERROR("新消息请求正文反序列化失败!");
|
||
return err_response("新消息请求正文反序列化失败!");
|
||
}
|
||
// 2. 客户端身份识别与鉴权
|
||
std::string ssid = req.session_id();
|
||
auto uid = _redis_session->uid(ssid);
|
||
if (!uid) {
|
||
LOG_ERROR("{} 获取登录会话关联用户信息失败!", ssid);
|
||
return err_response("获取登录会话关联用户信息失败!");
|
||
}
|
||
req.set_user_id(*uid);
|
||
// 3. 将请求转发给好友子服务进行业务处理
|
||
auto channel = _mm_channels->choose(_transmite_service_name);
|
||
if (!channel) {
|
||
LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点!", req.request_id());
|
||
return err_response("未找到可提供业务处理的用户子服务节点!");
|
||
}
|
||
bite_im::MsgTransmitService_Stub stub(channel.get());
|
||
brpc::Controller cntl;
|
||
stub.GetTransmitTarget(&cntl, &req, &target_rsp, nullptr);
|
||
if (cntl.Failed()) {
|
||
LOG_ERROR("{} 消息转发子服务调用失败!", req.request_id());
|
||
return err_response("消息转发子服务调用失败!");
|
||
}
|
||
// 4. 若业务处理成功 --- 且获取被申请方长连接成功,则向被申请放进行好友申请事件通知
|
||
if (target_rsp.success()){
|
||
for (int i = 0; i < target_rsp.target_id_list_size(); i++) {
|
||
std::string notify_uid = target_rsp.target_id_list(i);
|
||
if (notify_uid == *uid) continue; //不通知自己
|
||
auto conn = _connections->connection(notify_uid);
|
||
if (!conn) { continue;}
|
||
NotifyMessage notify;
|
||
notify.set_notify_type(NotifyType::CHAT_MESSAGE_NOTIFY);
|
||
auto msg_info = notify.mutable_new_message_info();
|
||
msg_info->mutable_message_info()->CopyFrom(target_rsp.message());
|
||
conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
|
||
}
|
||
}
|
||
// 5. 向客户端进行响应
|
||
rsp.set_request_id(req.request_id());
|
||
rsp.set_success(target_rsp.success());
|
||
rsp.set_errmsg(target_rsp.errmsg());
|
||
response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
|
||
}
|
||
private:
|
||
Session::ptr _redis_session;
|
||
Status::ptr _redis_status;
|
||
|
||
std::string _user_service_name;
|
||
std::string _file_service_name;
|
||
std::string _speech_service_name;
|
||
std::string _message_service_name;
|
||
std::string _transmite_service_name;
|
||
std::string _friend_service_name;
|
||
ServiceManager::ptr _mm_channels;
|
||
Discovery::ptr _service_discoverer;
|
||
|
||
Connection::ptr _connections;
|
||
|
||
server_t _ws_server;
|
||
httplib::Server _http_server;
|
||
std::thread _http_thread;
|
||
};
|
||
|
||
class GatewayServerBuilder {
|
||
public:
|
||
//构造redis客户端对象
|
||
void make_redis_object(const std::string &host,
|
||
int port,
|
||
int db,
|
||
bool keep_alive) {
|
||
_redis_client = RedisClientFactory::create(host, port, db, keep_alive);
|
||
}
|
||
//用于构造服务发现客户端&信道管理对象
|
||
void make_discovery_object(const std::string ®_host,
|
||
const std::string &base_service_name,
|
||
const std::string &file_service_name,
|
||
const std::string &speech_service_name,
|
||
const std::string &message_service_name,
|
||
const std::string &friend_service_name,
|
||
const std::string &user_service_name,
|
||
const std::string &transmite_service_name) {
|
||
_file_service_name = file_service_name;
|
||
_speech_service_name = speech_service_name;
|
||
_message_service_name = message_service_name;
|
||
_friend_service_name = friend_service_name;
|
||
_user_service_name = user_service_name;
|
||
_transmite_service_name = transmite_service_name;
|
||
_mm_channels = std::make_shared<ServiceManager>();
|
||
_mm_channels->declared(file_service_name);
|
||
_mm_channels->declared(speech_service_name);
|
||
_mm_channels->declared(message_service_name);
|
||
_mm_channels->declared(friend_service_name);
|
||
_mm_channels->declared(user_service_name);
|
||
_mm_channels->declared(transmite_service_name);
|
||
auto put_cb = std::bind(&ServiceManager::onServiceOnline, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
|
||
auto del_cb = std::bind(&ServiceManager::onServiceOffline, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
|
||
_service_discoverer = std::make_shared<Discovery>(reg_host, base_service_name, put_cb, del_cb);
|
||
}
|
||
void make_server_object(int websocket_port, int http_port) {
|
||
_websocket_port = websocket_port;
|
||
_http_port = http_port;
|
||
}
|
||
//构造RPC服务器对象
|
||
GatewayServer::ptr build() {
|
||
if (!_redis_client) {
|
||
LOG_ERROR("还未初始化Redis客户端模块!");
|
||
abort();
|
||
}
|
||
if (!_service_discoverer) {
|
||
LOG_ERROR("还未初始化服务发现模块!");
|
||
abort();
|
||
}
|
||
if (!_mm_channels) {
|
||
LOG_ERROR("还未初始化信道管理模块!");
|
||
abort();
|
||
}
|
||
GatewayServer::ptr server = std::make_shared<GatewayServer>(
|
||
_websocket_port, _http_port, _redis_client, _mm_channels,
|
||
_service_discoverer, _user_service_name, _file_service_name,
|
||
_speech_service_name, _message_service_name,
|
||
_transmite_service_name, _friend_service_name);
|
||
return server;
|
||
}
|
||
private:
|
||
int _websocket_port;
|
||
int _http_port;
|
||
|
||
std::shared_ptr<sw::redis::Redis> _redis_client;
|
||
|
||
std::string _file_service_name;
|
||
std::string _speech_service_name;
|
||
std::string _message_service_name;
|
||
std::string _friend_service_name;
|
||
std::string _user_service_name;
|
||
std::string _transmite_service_name;
|
||
ServiceManager::ptr _mm_channels;
|
||
Discovery::ptr _service_discoverer;
|
||
};
|
||
} |