修复session会话 bug 使之重复提交 不会死循环(没找到那里死循环)

确定了是get_session 返回错误
This commit is contained in:
dongl 2023-05-18 10:50:33 +08:00
parent d71c675680
commit 68b3d8e95d
16 changed files with 252 additions and 77 deletions

View File

@ -24,34 +24,38 @@ static constexpr ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema* schemas = n
static constexpr ::PROTOBUF_NAMESPACE_ID::Message* const* file_default_instances = nullptr;
const char descriptor_table_protodef_mp_2emp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
"\n\013mp.mp.proto\022\002mp*\243\002\n\007MP_TYPE\022\024\n\020MP_REQU"
"\n\013mp.mp.proto\022\002mp*\360\002\n\007MP_TYPE\022\024\n\020MP_REQU"
"EST_LOGIN\020\000\022\025\n\021MP_REQUEST_LOGOUT\020\001\022\027\n\023MP"
"_REQUEST_REGISTER\020\002\022\023\n\017MP_REQUEST_CODE\020\003"
"\022\026\n\022MP_REQUEST_FRIENDS\020\004\022\025\n\021MP_REQUEST_G"
"ROUPS\020\005\022\025\n\021MP_RESPONSE_LOGIN\020\024\022\026\n\022MP_RES"
"PONSE_LOGOUT\020\025\022\030\n\024MP_RESPONSE_REGISTER\020\026"
"\022\024\n\020MP_RESPONSE_CODE\020\027\022\027\n\023MP_RESPONSE_FR"
"IENDS\020\030\022\026\n\022MP_RESPONSE_GROUPS\020\031*\205\006\n\013MP_S"
"UB_TYPE\022\022\n\016MP_LOGIN_EMAIL\020\000\022\022\n\016MP_LOGIN_"
"PHONE\020\001\022\024\n\020MP_LOGIN_ACCOUNT\020\002\022\025\n\021MP_REGI"
"STER_EMAIL\020\003\022\025\n\021MP_REGISTER_PHONE\020\004\022\024\n\020M"
"P_LOGIN_SUCCESS\020\005\022\021\n\rMP_LOGIN_FAIL\020\006\022\027\n\023"
"MP_REGISTER_SUCCESS\020\007\022\024\n\020MP_REGISTER_FAI"
"L\020\010\022\021\n\rMP_CODE_EMAIL\020\017\022\021\n\rMP_CODE_PHONE\020"
"\020\022\023\n\017MP_CODE_SUCCESS\020\021\022\020\n\014MP_CODE_FAIL\020\034"
"\022\024\n\020MP_ADD_FRIENDS_0\0203\022\024\n\020MP_ADD_FRIENDS"
"_1\0204\022\024\n\020MP_ADD_FRIENDS_2\0205\022\032\n\026MP_ADD_FRI"
"ENDS_ACCOUNT\0206\022\030\n\024MP_ADD_FRIENDS_EMAIL\0207"
"\022\030\n\024MP_ADD_FRIENDS_PHONE\0208\022\025\n\021MP_ADD_BLA"
"CK_LIST\020;\022\025\n\021MP_ADD_WHITE_LIST\020<\022\024\n\020MP_R"
"EMOVE_FRIEND\020=\022\022\n\016MP_GET_FRIENDS\020>\022\022\n\016MP"
"_ADD_GROUP_0\020\?\022\022\n\016MP_ADD_GROUP_1\020@\022\022\n\016MP"
"_ADD_GROUP_2\020A\022\020\n\014MP_ADD_GROUP\020B\022\023\n\017MP_R"
"EMOVE_GROUP\020C\022\021\n\rMP_GET_GROUPS\020D\022\022\n\016MP_A"
"DD_SUCCESS\020E\022\025\n\021MP_REMOVE_SUCCESS\020F\022\022\n\016M"
"P_GET_SUCCESS\020G\022\017\n\013MP_ADD_FAIL\020H\022\022\n\016MP_R"
"EMOVE_FAIL\020I\022\017\n\013MP_GET_FAIL\020J\022\020\n\014MP_ADD_"
"CHECK\020Pb\006proto3"
"IENDS\020\030\022\026\n\022MP_RESPONSE_GROUPS\020\031\022\021\n\014MP_IM"
"_NOTICE\020\310\001\022\023\n\016MP_IM_PUSH_MSG\020\311\001\022\023\n\016MP_IM"
"_PULL_MSG\020\312\001\022\016\n\tMP_IM_MSG\020\313\001*\353\006\n\013MP_SUB_"
"TYPE\022\022\n\016MP_LOGIN_EMAIL\020\000\022\022\n\016MP_LOGIN_PHO"
"NE\020\001\022\024\n\020MP_LOGIN_ACCOUNT\020\002\022\025\n\021MP_REGISTE"
"R_EMAIL\020\003\022\025\n\021MP_REGISTER_PHONE\020\004\022\024\n\020MP_L"
"OGIN_SUCCESS\020\005\022\021\n\rMP_LOGIN_FAIL\020\006\022\027\n\023MP_"
"REGISTER_SUCCESS\020\007\022\024\n\020MP_REGISTER_FAIL\020\010"
"\022\021\n\rMP_CODE_EMAIL\020\017\022\021\n\rMP_CODE_PHONE\020\020\022\023"
"\n\017MP_CODE_SUCCESS\020\021\022\020\n\014MP_CODE_FAIL\020\034\022\024\n"
"\020MP_ADD_FRIENDS_0\0203\022\024\n\020MP_ADD_FRIENDS_1\020"
"4\022\024\n\020MP_ADD_FRIENDS_2\0205\022\032\n\026MP_ADD_FRIEND"
"S_ACCOUNT\0206\022\030\n\024MP_ADD_FRIENDS_EMAIL\0207\022\030\n"
"\024MP_ADD_FRIENDS_PHONE\0208\022\025\n\021MP_ADD_BLACK_"
"LIST\020;\022\025\n\021MP_ADD_WHITE_LIST\020<\022\024\n\020MP_REMO"
"VE_FRIEND\020=\022\022\n\016MP_GET_FRIENDS\020>\022\022\n\016MP_AD"
"D_GROUP_0\020\?\022\022\n\016MP_ADD_GROUP_1\020@\022\022\n\016MP_AD"
"D_GROUP_2\020A\022\020\n\014MP_ADD_GROUP\020B\022\023\n\017MP_REMO"
"VE_GROUP\020C\022\021\n\rMP_GET_GROUPS\020D\022\022\n\016MP_ADD_"
"SUCCESS\020E\022\025\n\021MP_REMOVE_SUCCESS\020F\022\022\n\016MP_G"
"ET_SUCCESS\020G\022\017\n\013MP_ADD_FAIL\020H\022\022\n\016MP_REMO"
"VE_FAIL\020I\022\017\n\013MP_GET_FAIL\020J\022\020\n\014MP_ADD_CHE"
"CK\020P\022\017\n\nMP_IM_TEXT\020\310\001\022\020\n\013MP_IM_PHOTO\020\311\001\022"
"\020\n\013MP_IM_AUDIO\020\312\001\022\020\n\013MP_IM_VIDEO\020\313\001\022\016\n\tM"
"P_FRIEND\020\254\002\022\r\n\010MP_GROUP\020\255\002b\006proto3"
;
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_mp_2emp_2eproto_deps[1] = {
};
@ -59,7 +63,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_mp_
};
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_mp_2emp_2eproto_once;
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_mp_2emp_2eproto = {
false, false, descriptor_table_protodef_mp_2emp_2eproto, "mp.mp.proto", 1095,
false, false, descriptor_table_protodef_mp_2emp_2eproto, "mp.mp.proto", 1274,
&descriptor_table_mp_2emp_2eproto_once, descriptor_table_mp_2emp_2eproto_sccs, descriptor_table_mp_2emp_2eproto_deps, 0, 0,
schemas, file_default_instances, TableStruct_mp_2emp_2eproto::offsets,
file_level_metadata_mp_2emp_2eproto, 0, file_level_enum_descriptors_mp_2emp_2eproto, file_level_service_descriptors_mp_2emp_2eproto,
@ -86,6 +90,10 @@ bool MP_TYPE_IsValid(int value) {
case 23:
case 24:
case 25:
case 200:
case 201:
case 202:
case 203:
return true;
default:
return false;
@ -134,6 +142,12 @@ bool MP_SUB_TYPE_IsValid(int value) {
case 73:
case 74:
case 80:
case 200:
case 201:
case 202:
case 203:
case 300:
case 301:
return true;
default:
return false;

View File

@ -70,12 +70,16 @@ enum MP_TYPE : int {
MP_RESPONSE_CODE = 23,
MP_RESPONSE_FRIENDS = 24,
MP_RESPONSE_GROUPS = 25,
MP_IM_NOTICE = 200,
MP_IM_PUSH_MSG = 201,
MP_IM_PULL_MSG = 202,
MP_IM_MSG = 203,
MP_TYPE_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
MP_TYPE_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
};
bool MP_TYPE_IsValid(int value);
constexpr MP_TYPE MP_TYPE_MIN = MP_REQUEST_LOGIN;
constexpr MP_TYPE MP_TYPE_MAX = MP_RESPONSE_GROUPS;
constexpr MP_TYPE MP_TYPE_MAX = MP_IM_MSG;
constexpr int MP_TYPE_ARRAYSIZE = MP_TYPE_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MP_TYPE_descriptor();
@ -129,12 +133,18 @@ enum MP_SUB_TYPE : int {
MP_REMOVE_FAIL = 73,
MP_GET_FAIL = 74,
MP_ADD_CHECK = 80,
MP_IM_TEXT = 200,
MP_IM_PHOTO = 201,
MP_IM_AUDIO = 202,
MP_IM_VIDEO = 203,
MP_FRIEND = 300,
MP_GROUP = 301,
MP_SUB_TYPE_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
MP_SUB_TYPE_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
};
bool MP_SUB_TYPE_IsValid(int value);
constexpr MP_SUB_TYPE MP_SUB_TYPE_MIN = MP_LOGIN_EMAIL;
constexpr MP_SUB_TYPE MP_SUB_TYPE_MAX = MP_ADD_CHECK;
constexpr MP_SUB_TYPE MP_SUB_TYPE_MAX = MP_GROUP;
constexpr int MP_SUB_TYPE_ARRAYSIZE = MP_SUB_TYPE_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MP_SUB_TYPE_descriptor();

24
MP/protohuf/mp.im.proto Normal file
View File

@ -0,0 +1,24 @@
syntax = "proto3";
package mp.im;
import "mp.mp.proto";
/// 使message_id ***************************************************************////
//************************************/
/***** 只通知id 无论 push pull *****/
/*************************************/
// []
message notice { // pull push
string message_id = 1; // id[] uint64
}
// / []
message data {
MP_SUB_TYPE msg_type = 1; // [] //
MP_SUB_TYPE session_type = 2; // [] // /
string message_id = 3; // [] // id uint64
uint64 account = 4; // [] // /
string msg_data = 5; // [] //
}

View File

@ -21,7 +21,10 @@ enum MP_TYPE {
// 200
// MP_IM
MP_IM_NOTICE = 200; //
MP_IM_PUSH_MSG = 201; // ---> /
MP_IM_PULL_MSG = 202; // ---> /
MP_IM_MSG = 203; //
}
enum MP_SUB_TYPE {
@ -80,4 +83,17 @@ enum MP_SUB_TYPE {
MP_ADD_CHECK = 80; // /
///***********************************************************************************///
/// 200+ IM ***********************************************************************************///
MP_IM_TEXT = 200; //
MP_IM_PHOTO = 201; //
MP_IM_AUDIO = 202; //
MP_IM_VIDEO = 203; //
MP_FRIEND = 300; //
MP_GROUP = 301; //
///***********************************************************************************///
}

View File

@ -1,11 +1,11 @@
project(MS)
aux_source_directory(pool/thread DIR_THREAD_POOL)
aux_source_directory(pool/mem DIR_MEM_POOL)
aux_source_directory(pool/thread DIR_THREAD_POOL)
aux_source_directory(pool/object DIR_OBJECT_POOL)
aux_source_directory(mmm DIR_MMM)
aux_source_directory(tools DIR_TOOLS)
aux_source_directory(smtp DIR_EMAIL)
aux_source_directory(message DIR_MESSAGE)
include_directories(${CMAKE_SOURCE_DIR}/include/libevent)
include_directories(${CMAKE_SOURCE_DIR}/include/ini)
@ -31,12 +31,12 @@ add_executable(MS
main.cpp
MS.cpp
MS.cpp
${DIR_THREAD_POOL}
${DIR_EMAIL}
${DIR_MESSAGE}
${DIR_MMM}
${DIR_THREAD_POOL}
${DIR_MEM_POOL}
${DIR_OBJECT_POOL}
${DIR_TOOLS}
${DIR_EMAIL}
)
target_link_libraries(MS

5
MS/message/TimeLine.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// Created by dongl on 23-5-17.
//
#include "TimeLine.h"

39
MS/message/TimeLine.h Normal file
View File

@ -0,0 +1,39 @@
//
// Created by dongl on 23-5-17.
//
#ifndef IM2_TIMELINE_H
#define IM2_TIMELINE_H
/**
* Timeline模型
* Timeline可以简单理解为是一个消息队列
*
* IDSeqIdSeqId一定比前面的消息的SeqId大SeqId一定是增长的
* SeqId永远比已经存在队列中的消息都大
* SeqId随机定位到具体的某条消息进行读取
*/
/**
*
*
* Timeline来很简单的实现ABB存在多个接收端B1B2和B3
* A向B发送消息B的多个端Timeline来进行交换A向B发送的所有消息Timeline中
* B的每个接收端都是独立的从这个Timeline中拉取消息SeqId
*
*/
/**
*
* Timeline
* Timeline内的所有数据进行
*/
/// 每个会话 通过 TimeLine 维护
class TimeLine {
};
#endif //IM2_TIMELINE_H

View File

@ -22,8 +22,6 @@ agreement_response::~agreement_response() {}
void agreement_response::set(mp::sri* sri, bufferevent* bev) {
auto resp = std::make_shared<mp::response>(mp::response());
std::cout << "set" << sri->account() << std::endl;
m_sri = resp->sri();
m_sri.set_subcommand(sri->subcommand());
m_sri.set_account(sri->account());
@ -34,8 +32,6 @@ void agreement_response::set(mp::sri* sri, bufferevent* bev) {
m_sri.set_email(sri->email());
m_sri.set_phone(sri->phone());
std::cout << "set" << m_sri.account() << std::endl;
m_bev = bev;
}

View File

@ -29,6 +29,11 @@ void handler::resp(const std::shared_ptr<agreement_request>& request,
auto ret = resp->packet();
// auto user = session->find_user(response->m_sri.account());
// if (user.has_value()) {
// printf("%s\n", user.value()->ip);
// }
bufferevent_write(request->m_bev, ret.c_str(), ret.size());
delete resp;
}
@ -66,6 +71,10 @@ std::optional<std::string> handler::get_session(bufferevent *bev, const std::str
return session->get_session(bev, session_key);
}
void handler::remove_session(bufferevent *bev, const std::string &session_key) {
session->remove_session(bev, session_key);
}

View File

@ -22,6 +22,7 @@ public:
public:
static void remove_user(bufferevent* bev);
static void remove_session(bufferevent* bev, const std::string &session_key);
static std::optional<std::string> get_session(bufferevent* bev, const std::string &session_key);
protected:

View File

@ -9,6 +9,13 @@
//std::map<uint64_t, userinfo*> session::user_fd;
//std::map<bufferevent*, std::map<std::string, std::string>> session::session_map;
session::session() {
printf("timing begin");
timing();
printf("timing end");
fflush(stdout);
}
/// curr mem user curd user session
void session::add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request) {
if (sri->subcommand() == mp::MP_LOGIN_SUCCESS) {
@ -41,17 +48,20 @@ void session::remove_user(const std::shared_ptr<agreement_request>& request) {
bufferevent_free(request->m_bev);
}
bool session::is_user(const std::string& account) {
if( user_fd.find(strtol(account.c_str(), nullptr, 0)) == user_fd.cend() ){
bool session::is_user(uint64_t account) {
if( user_fd.find(account) == user_fd.cend() ){
return false;
}
return true;
}
bool session::is_user(const std::string& account) {
return session::is_user(strtol(account.c_str(), nullptr, 0));
}
std::optional<std::pair<uint64_t, userinfo*>> session::find_user_fd(uint64_t account) {
auto ret = user_fd.find(account);
if (ret != user_fd.cend()) {
// return std::make_optional<std::pair<uint64_t, userinfo*>>(ret->first, ret->second);
return {{ret->first, ret->second} };
} else {
return std::nullopt;
@ -82,24 +92,25 @@ void session::set_session(bufferevent* bev, const std::string &session_key, cons
// 添加时间轮 定时器
time_t t = time(nullptr);
auto retwheel = session_time_wheel.find(t);
std::list<bev_key*> list;
// 看看 此时间点 有没有 任务
if (retwheel != session_time_wheel.cend()) {
auto list = session_time_wheel.find(t)->second;
list.emplace_back(bev, session_key);
session_time_wheel.insert({t, list});
} else {
std::list<std::pair<bufferevent*/*bev*/, std::string/*key*/>> list;
list.emplace_back(bev, session_key);
session_time_wheel.insert({t, list});
list = session_time_wheel.find(t)->second;
}
auto bk = new bev_key();
bk->bev = bev;
bk->key = session_key;
bk->value = session_value;
list.emplace_back(bk);
session_time_wheel.insert({t, list});
}
// 给用户 查询会话信息
std::optional<std::string> session::get_session(bufferevent* bev, const std::string &session_key) {
auto sess = session_map.find(bev);
std::map<std::string, std::string> sub_sess;
if (sess != session_map.cend()) {
auto ret = sess->second.find(session_key);
if (ret != sub_sess.cend()) {
if (ret != sess->second.cend()) {
return ret->second;
}
}
@ -108,13 +119,38 @@ std::optional<std::string> session::get_session(bufferevent* bev, const std::str
void session::remove_session(bufferevent *bev, const std::string &session_key) {
auto ret = session_map.find(bev);
std::map<std::string, std::string> sub_sess;
if (ret != session_map.cend()) {
auto sub = ret->second.find(session_key);
if (sub != sub_sess.cend()) {
if (sub != ret->second.cend()) {
ret->second.erase(sub);
}
}
// 同时删除时间轮内的 注册session
// 这里的实现 太垃圾了
bool remove_state = false;
std::list<bev_key>::iterator iterator;
for (const auto &item: session_time_wheel) {
for (auto mem = item.second.begin(); mem != item.second.end(); ++mem) {
if (mem.operator*()->key == session_key) {
auto i = item.second;
i.remove(mem.operator*());
if (i.empty()) {
session_time_wheel.erase(item.first);
remove_state = true;
}
break;
}
}
if (remove_state) {
break;
}
}
}
void session::remove_session(userinfo *user) {
}
@ -122,17 +158,35 @@ void session::remove_session(bufferevent *bev, const std::string &session_key) {
void session::timing() {
time_wheel.run([&]() {
while (true) {
if (!session_time_wheel.empty()) {
while (!session_time_wheel.empty()) {
auto wheel = session_time_wheel.begin();
if (wheel->first > time(nullptr) + 300000) { // 5分钟
// 超时5分钟就删除
for (const auto &item: wheel->second) {
remove_session(item.first, item.second);
remove_session(item->bev, item->key);
}
}
printf("session time %ld\n", wheel->first);
std::this_thread::sleep_for(std::chrono::seconds(1));
break;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});
}
std::optional<userinfo*> session::find_user(uint64_t account) {
auto temp = user_fd.find(account);
if (temp == user_fd.cend()) {
return std::nullopt;
} else {
return temp->second;
}
}

View File

@ -19,28 +19,50 @@ struct userinfo {
std::map<std::string, std::string> session; // 用户的 seesion;
};
struct bev_key {
bufferevent* bev;
std::string key;
std::string value;
};
class session {
public:
// 用户不在线时应 删除 user fd 映射
session();
public:
// 添加用户
void add_user(mp::sri* sri, std::shared_ptr<agreement_request>& request);
void remove_user(const std::shared_ptr<agreement_request>& request);
void remove_user(bufferevent* bev);
bool is_user(const std::string& account);
// 查找用户
std::optional<userinfo*> find_user(uint64_t account);
// 查找用户
std::optional<std::pair<uint64_t, userinfo*>> find_user_fd(uint64_t account);
// 删除用户
void remove_user(const std::shared_ptr<agreement_request> &request);
// 删除用户
void remove_user(bufferevent* bev);
// 是否有这个用户
bool is_user(const std::string& account);
// 是否有这个用户
bool is_user(uint64_t account);
// 初始化 session
void init_session(bufferevent* bev);
// 设置 session
void set_session(bufferevent* bev, const std::string& session_key, const std::string& session_value);
// 获取 session
std::optional<std::string> get_session(bufferevent* bev, const std::string& session_key);
// 删除 session
void remove_session(bufferevent* bev, const std::string& session_key);
void remove_session(userinfo* user);
// 时间轮思路的 定时器
void timing();
protected:
tbb::task_group time_wheel; // 时间轮 线程池
std::map<uint64_t, userinfo*> user_fd; // 用户的链接 暂时是一直链接 交给libevent 管理
std::map<bufferevent*, std::map<std::string, std::string>> session_map; // 当前链接的 存在的 seesion;
std::map<time_t, std::list< std::pair<bufferevent*/*bev*/, std::string/*key*/> > > session_time_wheel; // session 有效期 超时轮 映射
std::map<time_t, std::list<bev_key*>> session_time_wheel; // session 有效期 超时轮 映射
};

View File

@ -1,5 +0,0 @@
//
// Created by dongl on 23-4-26.
//
#include "hash.h"

View File

@ -1,14 +0,0 @@
//
// Created by dongl on 23-4-26.
//
#ifndef IM2_HASH_H
#define IM2_HASH_H
class hash {
};
#endif //IM2_HASH_H

View File

@ -22,6 +22,7 @@ void CodeController::run(std::shared_ptr<agreement_request> request, std::shared
} else {
sri->set_subcommand(mp::MP_SUB_TYPE::MP_CODE_FAIL);
sri->set_msg("未知问题,验证码获取失败");
session->remove_session(request->m_bev, "code");
}
}

View File

@ -24,6 +24,9 @@ void UserController::run(std::shared_ptr<agreement_request> request, std::shared
request->m_body.password(), request->m_body.data(), session_code);
response->set(sri, request->m_bev);
if (session_code.has_value())
session->remove_session(request->m_bev, "code");
}
// 退出登陆
else if (request->m_mph->mp_type() == mp::MP_REQUEST_LOGOUT) {