uint32_t CClientConn::sendMessage(uint32_t nFromId, uint32_t nToId, IM::BaseDefine::MsgType nType, const string& strMsgData) { CImPdu cPdu; IM::Message::IMMsgData msg; msg.set_from_user_id(nFromId); msg.set_to_session_id(nToId); msg.set_msg_id(0); msg.set_create_time(time(NULL)); msg.set_msg_type(nType); msg.set_msg_data(strMsgData); cPdu.SetPBMsg(&msg); cPdu.SetServiceId(IM::BaseDefine::SID_MSG); cPdu.SetCommandId(IM::BaseDefine::CID_MSG_DATA); uint32_t nSeqNo = m_pSeqAlloctor->getSeq(ALLOCTOR_PACKET); cPdu.SetSeqNum(nSeqNo); SendPdu(&cPdu); return nSeqNo; }
void getUnreadMsgCounter(CImPdu* pPdu, uint32_t conn_uuid) { IM::Message::IMUnreadMsgCntReq msg; IM::Message::IMUnreadMsgCntRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { CImPdu* pPduResp = new CImPdu; uint32_t nUserId = msg.user_id(); list<IM::BaseDefine::UnreadInfo> lsUnreadCount; uint32_t nTotalCnt = 0; CMessageModel::getInstance()->getUnreadMsgCount(nUserId, nTotalCnt, lsUnreadCount); CGroupMessageModel::getInstance()->getUnreadMsgCount(nUserId, nTotalCnt, lsUnreadCount); msgResp.set_user_id(nUserId); msgResp.set_total_cnt(nTotalCnt); for(auto it= lsUnreadCount.begin(); it!=lsUnreadCount.end(); ++it) { IM::BaseDefine::UnreadInfo* pInfo = msgResp.add_unreadinfo_list(); // *pInfo = *it; pInfo->set_session_id(it->session_id()); pInfo->set_session_type(it->session_type()); pInfo->set_unread_cnt(it->unread_cnt()); pInfo->set_latest_msg_id(it->latest_msg_id()); pInfo->set_latest_msg_data(it->latest_msg_data()); pInfo->set_latest_msg_type(it->latest_msg_type()); pInfo->set_latest_msg_from_user_id(it->latest_msg_from_user_id()); } log("userId=%d, unreadCnt=%u, totalCount=%u", nUserId, msgResp.unreadinfo_list_size(), nTotalCnt); msgResp.set_attach_data(msg.attach_data()); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_MSG); pPduResp->SetCommandId(IM::BaseDefine::CID_MSG_UNREAD_CNT_RESPONSE); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); } else { log("parse pb failed"); } }
void CImUser::HandleKickUser(CMsgConn* pConn, uint32_t reason) { map<uint32_t, CMsgConn*>::iterator it = m_conn_map.find(pConn->GetHandle()); if (it != m_conn_map.end()) { CMsgConn* pConn = it->second; if(pConn) { log("kick service user, user_id=%u.", m_user_id); IM::Login::IMKickUser msg; msg.set_user_id(m_user_id); msg.set_kick_reason((::IM::BaseDefine::KickReasonType)reason); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_LOGIN); pdu.SetCommandId(CID_LOGIN_KICK_USER); pConn->SendPdu(&pdu); pConn->SetKickOff(); pConn->Close(); } } }
uint32_t ClientConn::login(const string &strName, const string &strPass) { CImPdu cPdu; IM::Login::IMLoginReq msg; msg.set_user_name(strName); msg.set_password(strPass); msg.set_online_status(IM::BaseDefine::USER_STATUS_ONLINE); msg.set_client_type(IM::BaseDefine::CLIENT_TYPE_WINDOWS); msg.set_client_version("100.0.0"); cPdu.SetPBMsg(&msg); cPdu.SetServiceId(IM::BaseDefine::DFFX_SID_LOGIN); cPdu.SetCommandId(IM::BaseDefine::DFFX_CID_LOGIN_REQ_USERLOGIN); printf("login %d\n",cPdu.GetCommandId()); uint32_t nSeqNo = m_pSeqAlloctor->getSeq(ALLOCTOR_PACKET); cPdu.SetSeqNum(nSeqNo); SendPdu(&cPdu); return nSeqNo; }
uint32_t ClientConn::getGroupInfo(uint32_t nUserId , const list<IM::BaseDefine::GroupVersionInfo> &lsGroupVersionInfo) { CImPdu cPdu; IM::Group::IMGroupInfoListReq msg; msg.set_user_id(nUserId); for(const auto &vi:lsGroupVersionInfo) { IM::BaseDefine::GroupVersionInfo* pGroupVersionInfo = msg.add_group_version_list(); pGroupVersionInfo->set_group_id(vi.group_id()); pGroupVersionInfo->set_version(0); } cPdu.SetPBMsg(&msg); cPdu.SetServiceId(IM::BaseDefine::SID_GROUP); cPdu.SetCommandId(IM::BaseDefine::CID_GROUP_INFO_REQUEST); uint32_t nSeqNo = m_pSeqAlloctor->getSeq(ALLOCTOR_PACKET); cPdu.SetSeqNum(nSeqNo); SendPdu(&cPdu); return nSeqNo; }
void getChgedDepart(CImPdu* pPdu, uint32_t conn_uuid) { IM::Buddy::IMDepartmentReq msg; IM::Buddy::IMDepartmentRsp msgResp; if (msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { CImPdu* pPduRes = new CImPdu; uint32_t nUserId = msg.user_id(); uint32_t nLastUpdate = msg.latest_update_time(); list<uint32_t> lsChangedIds; CDepartModel::getInstance()->getChgedDeptId(nLastUpdate, lsChangedIds); list<IM::BaseDefine::DepartInfo> lsDeparts; CDepartModel::getInstance()->getDepts(lsChangedIds, lsDeparts); msgResp.set_user_id(nUserId); msgResp.set_latest_update_time(nLastUpdate); for(auto it=lsDeparts.begin(); it!=lsDeparts.end(); ++it) { IM::BaseDefine::DepartInfo* pDeptInfo = msgResp.add_dept_list(); pDeptInfo->set_dept_id(it->dept_id()); pDeptInfo->set_priority(it->priority()); pDeptInfo->set_dept_name(it->dept_name()); pDeptInfo->set_parent_dept_id(it->parent_dept_id()); pDeptInfo->set_dept_status(it->dept_status()); } log("userId=%u, last_update=%u, cnt=%u", nUserId, nLastUpdate, lsDeparts.size()); msgResp.set_attach_data(msg.attach_data()); pPduRes->SetPBMsg(&msgResp); pPduRes->SetSeqNum(pPdu->GetSeqNum()); pPduRes->SetServiceId(IM::BaseDefine::SID_BUDDY_LIST); pPduRes->SetCommandId(IM::BaseDefine::CID_BUDDY_LIST_DEPARTMENT_RESPONSE); CProxyConn::AddResponsePdu(conn_uuid, pPduRes); } else { log("parse pb failed"); } }
void CLoginConn::OnTimer(uint64_t curr_tick) { if (m_conn_type == LOGIN_CONN_TYPE_CLIENT) { if (curr_tick > m_last_recv_tick + CLIENT_TIMEOUT) { Close(); } } else { if (curr_tick > m_last_send_tick + SERVER_HEARTBEAT_INTERVAL) { IM::Other::IMHeartBeat msg; CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_HEARTBEAT); SendPdu(&pdu); } if (curr_tick > m_last_recv_tick + SERVER_TIMEOUT) { log("connection to MsgServer timeout "); Close(); } } }
/** * 设置群组信息推送,屏蔽或者取消屏蔽 * * @param pPdu 收到的packet包指针 * @param conn_uuid 该包过来的socket 描述符 */ void setGroupPush(CImPdu* pPdu, uint32_t conn_uuid) { IM::Group::IMGroupShieldReq msg; IM::Group::IMGroupShieldRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { uint32_t nUserId = msg.user_id(); uint32_t nGroupId = msg.group_id(); uint32_t nStatus = msg.shield_status(); if(CGroupModel::getInstance()->isValidateGroupId(nGroupId)) { CImPdu* pPduRes = new CImPdu; bool bRet = CGroupModel::getInstance()->setPush(nUserId, nGroupId, IM_GROUP_SETTING_PUSH, nStatus); msgResp.set_user_id(nUserId); msgResp.set_group_id(nGroupId); msgResp.set_result_code(bRet?0:1); log("userId=%u, groupId=%u, result=%u", nUserId, nGroupId, msgResp.result_code()); msgResp.set_attach_data(msg.attach_data()); pPduRes->SetPBMsg(&msgResp); pPduRes->SetSeqNum(pPdu->GetSeqNum()); pPduRes->SetServiceId(IM::BaseDefine::SID_GROUP); pPduRes->SetCommandId(IM::BaseDefine::CID_GROUP_SHIELD_GROUP_RESPONSE); CProxyConn::AddResponsePdu(conn_uuid, pPduRes); } else { log("Invalid group.userId=%u, groupId=%u", nUserId, nGroupId); } } else { log("parse pb failed"); } }
void CGroupChat::HandleClientGroupCreateRequest(CImPdu* pPdu, CMsgConn* pFromConn) { IM::Group::IMGroupCreateReq msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t req_user_id = pFromConn->GetUserId(); string group_name = msg.group_name(); uint32_t group_type = msg.group_type(); if (group_type == IM::BaseDefine::GROUP_TYPE_NORMAL) { log("HandleClientGroupCreateRequest, create normal group failed, req_id=%u, group_name=%s. ", req_user_id, group_name.c_str()); return; } string group_avatar = msg.group_avatar(); uint32_t user_cnt = msg.member_id_list_size(); log("HandleClientGroupCreateRequest, req_id=%u, group_name=%s, avatar_url=%s, user_cnt=%u ", req_user_id, group_name.c_str(), group_avatar.c_str(), user_cnt); CDBServConn* pDbConn = get_db_serv_conn(); if (pDbConn) { CDbAttachData attach_data(ATTACH_TYPE_HANDLE, pFromConn->GetHandle(), 0); msg.set_user_id(req_user_id); msg.set_attach_data(attach_data.GetBuffer(), attach_data.GetLength()); pPdu->SetPBMsg(&msg); pDbConn->SendPdu(pPdu); } else { log("no DB connection "); IM::Group::IMGroupCreateRsp msg2; msg2.set_user_id(req_user_id); msg2.set_result_code(1); msg2.set_group_name(group_name); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_GROUP); pdu.SetCommandId(CID_GROUP_CREATE_RESPONSE); pdu.SetSeqNum(pPdu->GetSeqNum()); pFromConn->SendPdu(&pdu); } }
void CRouteConn::_HandleUsersStatusRequest(CImPdu* pPdu) { IM::Buddy::IMUsersStatReq msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t request_id = msg.user_id(); uint32_t query_count = msg.user_id_list_size(); log("HandleUserStatusReq, req_id=%u, query_count=%u ", request_id, query_count); IM::Buddy::IMUsersStatRsp msg2; msg2.set_user_id(request_id); msg2.set_attach_data(msg.attach_data()); list<user_stat_t> result_list; user_stat_t status; for(uint32_t i = 0; i < query_count; i++) { IM::BaseDefine::UserStat* user_stat = msg2.add_user_stat_list(); uint32_t user_id = msg.user_id_list(i); user_stat->set_user_id(user_id); CUserInfo* pUser = GetUserInfo(user_id); if (pUser) { user_stat->set_status((::IM::BaseDefine::UserStatType) pUser->GetStatus()) ; } else { user_stat->set_status(USER_STATUS_OFFLINE) ; } } // send back query user status CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_BUDDY_LIST); pdu.SetCommandId(CID_BUDDY_LIST_USERS_STATUS_RESPONSE); pdu.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu); }
uint32_t ClientConn::sendMessage(uint32_t nFromId, uint32_t nToId, IM::BaseDefine::MsgType nType, const string& strMsgData) { CImPdu cPdu; IM::Message::IMMsgData msg; msg.set_from_user_id(nFromId); msg.set_to_session_id(nToId); msg.set_msg_id(0); msg.set_create_time(time(NULL)); msg.set_msg_type(nType); //msg.set_msg_data(strMsgData); //EncryptMsg char * pOutData=NULL; uint32_t nOutLen = 0; int retCode = EncryptMsg( strMsgData.c_str(), strMsgData.length(), &pOutData, nOutLen); if (retCode == 0 && nOutLen > 0 && pOutData != 0) { msg.set_msg_data( pOutData, nOutLen); //delete pOutData; Free(pOutData); pOutData = NULL; } else { log("EncryptMsg error:%s\n", strMsgData.c_str()); msg.set_msg_data( strMsgData); } cPdu.SetPBMsg(&msg); cPdu.SetServiceId(IM::BaseDefine::DFFX_SID_MSG); cPdu.SetCommandId(IM::BaseDefine::DFFX_CID_MSG_DATA); uint32_t nSeqNo = m_pSeqAlloctor->getSeq(ALLOCTOR_PACKET); cPdu.SetSeqNum(nSeqNo); SendPdu(&cPdu); return nSeqNo; }
void hasOfflineFile(CImPdu* pPdu, uint32_t conn_uuid) { IM::File::IMFileHasOfflineReq msg; IM::File::IMFileHasOfflineRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { CImPdu* pPduRes = new CImPdu; uint32_t nUserId = msg.user_id(); CFileModel* pModel = CFileModel::getInstance(); list<IM::BaseDefine::OfflineFileInfo> lsOffline; pModel->getOfflineFile(nUserId, lsOffline); msgResp.set_user_id(nUserId); for (list<IM::BaseDefine::OfflineFileInfo>::iterator it=lsOffline.begin(); it != lsOffline.end(); ++it) { IM::BaseDefine::OfflineFileInfo* pInfo = msgResp.add_offline_file_list(); // *pInfo = *it; pInfo->set_from_user_id(it->from_user_id()); pInfo->set_task_id(it->task_id()); pInfo->set_file_name(it->file_name()); pInfo->set_file_size(it->file_size()); } log("userId=%u, count=%u", nUserId, msgResp.offline_file_list_size()); msgResp.set_attach_data(msg.attach_data()); pPduRes->SetPBMsg(&msgResp); pPduRes->SetSeqNum(pPdu->GetSeqNum()); pPduRes->SetServiceId(IM::BaseDefine::SID_FILE); pPduRes->SetCommandId(IM::BaseDefine::CID_FILE_HAS_OFFLINE_RES); CProxyConn::AddResponsePdu(conn_uuid, pPduRes); } else { log("parse pb failed"); } }
void CGroupChat::HandleGroupInfoResponse(CImPdu* pPdu) { IM::Group::IMGroupInfoListRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); uint32_t group_cnt = msg.group_info_list_size(); CPduAttachData pduAttachData((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); log("HandleGroupInfoResponse, user_id=%u, group_cnt=%u. ", user_id, group_cnt); //此处是查询成员时使用,主要用于群消息从数据库获得msg_id后进行发送,一般此时group_cnt = 1 if (pduAttachData.GetPduLength() > 0 && group_cnt > 0) { IM::BaseDefine::GroupInfo group_info = msg.group_info_list(0); uint32_t group_id = group_info.group_id(); log("GroupInfoRequest is send by server, group_id=%u ", group_id); std::set<uint32_t> group_member_set; for (uint32_t i = 0; i < group_info.group_member_list_size(); i++) { uint32_t member_user_id = group_info.group_member_list(i); group_member_set.insert(member_user_id); } if (group_member_set.find(user_id) == group_member_set.end()) { log("user_id=%u is not in group, group_id=%u. ", user_id, group_id); return; } IM::Message::IMMsgData msg2; CHECK_PB_PARSE_MSG(msg2.ParseFromArray(pduAttachData.GetPdu(), pduAttachData.GetPduLength())); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_MSG); pdu.SetCommandId(CID_MSG_DATA); //Push相关 IM::Server::IMGroupGetShieldReq msg3; msg3.set_group_id(group_id); msg3.set_attach_data(pdu.GetBodyData(), pdu.GetBodyLength()); for (uint32_t i = 0; i < group_info.group_member_list_size(); i++) { uint32_t member_user_id = group_info.group_member_list(i); msg3.add_user_id(member_user_id); CImUser* pToImUser = CImUserManager::GetInstance()->GetImUserById(member_user_id); if (pToImUser) { CMsgConn* pFromConn = NULL; if( member_user_id == user_id ) { uint32_t reqHandle = pduAttachData.GetHandle(); if(reqHandle != 0) pFromConn = CImUserManager::GetInstance()->GetMsgConnByHandle(user_id, reqHandle); } pToImUser->BroadcastData(pdu.GetBuffer(), pdu.GetLength(), pFromConn); } } CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_OTHER); pdu2.SetCommandId(CID_OTHER_GET_SHIELD_REQ); CDBServConn* pDbConn = get_db_serv_conn(); if (pDbConn) { pDbConn->SendPdu(&pdu2); } } else if (pduAttachData.GetPduLength() == 0) { //正常获取群信息的返回 CMsgConn* pConn = CImUserManager::GetInstance()->GetMsgConnByHandle(user_id, pduAttachData.GetHandle()); if (pConn) { msg.clear_attach_data(); pPdu->SetPBMsg(&msg); pConn->SendPdu(pPdu); } } }
void CHttpQuery::_QueryChangeMember(const string& strAppKey, Json::Value &post_json_obj, CHttpConn *pHttpConn) { HTTP::CDBServConn *pConn = HTTP::get_db_serv_conn(); if (!pConn) { log("no connection to RouteServConn "); char* response_buf = PackSendResult(HTTP_ERROR_SERVER_EXCEPTION, HTTP_ERROR_MSG[9].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } if ( post_json_obj["req_user_id"].isNull()) { log("no user id "); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } if ( post_json_obj["group_id"].isNull() ) { log("no group id "); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } if ( post_json_obj["modify_type"].isNull() ) { log("no modify_type "); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } if (post_json_obj["user_id_list"].isNull()) { log("no user list "); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } try { uint32_t user_id = post_json_obj["req_user_id"].asUInt(); uint32_t group_id = post_json_obj["group_id"].asUInt(); uint32_t modify_type = post_json_obj["modify_type"].asUInt(); uint32_t user_cnt = post_json_obj["user_id_list"].size(); log("QueryChangeMember, user_id: %u, group_id: %u, modify type: %u, user_cnt: %u. ", user_id, group_id, modify_type, user_cnt); if (!IM::BaseDefine::GroupModifyType_IsValid(modify_type)) { log("QueryChangeMember, unvalid modify_type"); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); return; } CDbAttachData attach_data(ATTACH_TYPE_HANDLE, pHttpConn->GetConnHandle()); IM::Group::IMGroupChangeMemberReq msg; msg.set_user_id(0); msg.set_change_type((::IM::BaseDefine::GroupModifyType)modify_type); msg.set_group_id(group_id); for (uint32_t i = 0; i < user_cnt; i++) { uint32_t member_id = post_json_obj["user_id_list"][i].asUInt(); msg.add_member_id_list(member_id); } msg.set_attach_data(attach_data.GetBuffer(), attach_data.GetLength()); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(IM::BaseDefine::DFFX_SID_GROUP); pdu.SetCommandId(IM::BaseDefine::DFFX_CID_GROUP_CHANGE_MEMBER_REQUEST); pConn->SendPdu(&pdu); } catch (std::runtime_error msg) { log("parse json data failed."); char* response_buf = PackSendResult(HTTP_ERROR_PARMENT, HTTP_ERROR_MSG[1].c_str()); pHttpConn->Send(response_buf, (uint32_t)strlen(response_buf)); pHttpConn->Close(); } }
void CRouteConn::_HandleUserStatusUpdate(CImPdu* pPdu) { IM::Server::IMUserStatusUpdate msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_status = msg.user_status(); uint32_t user_id = msg.user_id(); uint32_t client_type = msg.client_type(); log("HandleUserStatusUpdate, status=%u, uid=%u, client_type=%u ", user_status, user_id, client_type); _UpdateUserStatus(user_id, user_status, client_type); //用于通知客户端,同一用户在pc端的登录情况 CUserInfo* pUser = GetUserInfo(user_id); if (pUser) { IM::Server::IMServerPCLoginStatusNotify msg2; msg2.set_user_id(user_id); if (user_status == IM::BaseDefine::USER_STATUS_OFFLINE) { msg2.set_login_status(IM_PC_LOGIN_STATUS_OFF); } else { msg2.set_login_status(IM_PC_LOGIN_STATUS_ON); } CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_LOGIN_STATUS_NOTIFY); if (user_status == USER_STATUS_OFFLINE) { //pc端下线且无pc端存在,则给msg_server发送一个通知 if (CHECK_CLIENT_TYPE_PC(client_type) && !pUser->IsPCClientLogin()) { _BroadcastMsg(&pdu); } } else { //只要pc端在线,则不管上线的是pc还是移动端,都通知msg_server if (pUser->IsPCClientLogin()) { _BroadcastMsg(&pdu); } } } //状态更新的是pc client端,则通知给所有其他人 if (CHECK_CLIENT_TYPE_PC(client_type)) { IM::Buddy::IMUserStatNotify msg3; IM::BaseDefine::UserStat* user_stat = msg3.mutable_user_stat(); user_stat->set_user_id(user_id); user_stat->set_status((IM::BaseDefine::UserStatType)user_status); CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_BUDDY_LIST); pdu2.SetCommandId(CID_BUDDY_LIST_STATUS_NOTIFY); //用户存在 if (pUser) { //如果是pc客户端离线,但是仍然存在pc客户端,则不发送离线通知 //此种情况一般是pc客户端多点登录时引起 if (USER_STATUS_OFFLINE == user_status && pUser->IsPCClientLogin()) { return; } else { _BroadcastMsg(&pdu2); } } else//该用户不存在了,则表示是离线状态 { _BroadcastMsg(&pdu2); } } }
/// yunfan add 2014.8.6 void CFileConn::_HandleMsgFileTransferReq(CImPdu* pPdu) { // if realtime transfer // new realtime_task // generate uuid // copy userid_1 userid_2 // time_t = time(null); // return uuid // else new offline_task // generate uuid // copy user_1 // copy file_size // time_t = time(null) // return uuid // create task for: // realtime transfer and offline upload IM::Server::IMFileTransferReq msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t from_id = msg.from_user_id(); uint32_t to_id = msg.to_user_id(); IM::Server::IMFileTransferRsp msg2; msg2.set_result_code(1); msg2.set_from_user_id(from_id); msg2.set_to_user_id(to_id); msg2.set_file_name(msg.file_name()); msg2.set_file_size(msg.file_size()); msg2.set_task_id(""); msg2.set_trans_mode(msg.trans_mode()); msg2.set_attach_data(msg.attach_data()); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_FILE_TRANSFER_RSP); pdu.SetSeqNum(pPdu->GetSeqNum()); char task_id[64] = {0}; int iret = generate_id(task_id); if (0 > iret || NULL == task_id) { SendPdu(&pdu); log("create task id failed"); return; // errno create task id failed 1 } // new task and add to task_map transfer_task_t* task = new transfer_task_t; if (NULL == task) { // log new failed // return error SendPdu(&pdu); Close(); // close connection with msg svr log("create task failed"); return; // create task failed } task->transfer_mode = msg.trans_mode(); task->task_id = task_id; task->from_user_id = from_id; task->to_user_id = to_id; task->file_size = msg.file_size(); task->create_time = time_t(NULL); // read cfg file msg2.set_result_code(0); pdu.SetPBMsg(&msg2); SendPdu(&pdu); task->create_time = time(NULL); pthread_rwlock_wrlock(&g_file_task_map_lock); g_file_task_map.insert(make_pair((char*)task->task_id.c_str(), task)); pthread_rwlock_unlock(&g_file_task_map_lock); log("create task succeed, task id %s, task type %d, from user %d, to user %d", task->task_id.c_str(), task->transfer_mode, task->from_user_id, task->to_user_id); return; }
void getDevicesToken(CImPdu* pPdu, uint32_t conn_uuid) { IM::Server::IMGetDeviceTokenReq msg; IM::Server::IMGetDeviceTokenRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { CacheManager* pCacheManager = CacheManager::getInstance(); CacheConn* pCacheConn = pCacheManager->GetCacheConn("token"); CImPdu* pPduResp = new CImPdu; uint32_t nCnt = msg.user_id_size(); if (pCacheConn) { vector<string> vecTokens; for (uint32_t i=0; i<nCnt; ++i) { string strKey = "device_"+int2string(msg.user_id(i)); vecTokens.push_back(strKey); } map<string, string> mapTokens; bool bRet = pCacheConn->mget(vecTokens, mapTokens); pCacheManager->RelCacheConn(pCacheConn); if(bRet) { for (auto it=mapTokens.begin(); it!=mapTokens.end(); ++it) { string strKey = it->first; size_t nPos = strKey.find("device_"); if( nPos != string::npos) { string strUserId = strKey.substr(nPos + strlen("device_")); uint32_t nUserId = string2int(strUserId); string strValue = it->second; nPos = strValue.find(":"); if(nPos!=string::npos) { string strType = strValue.substr(0, nPos); string strToken = strValue.substr(nPos + 1); IM::BaseDefine::ClientType nClientType = IM::BaseDefine::ClientType(0); if(strType == "ios") { nClientType = IM::BaseDefine::CLIENT_TYPE_IOS; } else if(strType == "android") { nClientType = IM::BaseDefine::CLIENT_TYPE_ANDROID; } if(IM::BaseDefine::ClientType_IsValid(nClientType)) { IM::BaseDefine::UserTokenInfo* pToken = msgResp.add_user_token_info(); pToken->set_user_id(nUserId); pToken->set_token(strToken); pToken->set_user_type(nClientType); uint32_t nTotalCnt = 0; CMessageModel::getInstance()->getUnReadCntAll(nUserId, nTotalCnt); CGroupMessageModel::getInstance()->getUnReadCntAll(nUserId, nTotalCnt); pToken->set_push_count(nTotalCnt); pToken->set_push_type(1); } else { log("invalid clientType.clientType=%u", nClientType); } } else { log("invalid value. value=%s", strValue.c_str()); } } else { log("invalid key.key=%s", strKey.c_str()); } } } else { log("mget failed!"); } } else { log("no cache connection for token"); } log("req devices token.reqCnt=%u, resCnt=%u", nCnt, msgResp.user_token_info_size()); msgResp.set_attach_data(msg.attach_data()); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_OTHER); pPduResp->SetCommandId(IM::BaseDefine::CID_OTHER_GET_DEVICE_TOKEN_RSP); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); } else { log("parse pb failed"); } }
void CDBServConn::_HandleDbRegisterResponse(CImPdu* pPdu) { RUNTIME_TRACE; IM::Server::IMDbRegRes msgDb; CHECK_PB_PARSE_MSG(msgDb.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); string login_name = msgDb.user_name(); CImUser* pImUser = CImUserManager::GetInstance()->GetImUserByLoginName(login_name); if (!pImUser) { log("ImUser for user_name=%s not exist", login_name.c_str()); return; } CDbAttachData attach_data((uchar_t*)msgDb.attach_data().c_str(), msgDb.attach_data().length()); auto pMsgConn = pImUser->GetUnValidateMsgConn(attach_data.GetHandle()); if (!pMsgConn || pMsgConn->IsOpen()) { log("no such conn, user_name=%s", login_name.c_str()); return; } IM::BaseDefine::UserInfo user_info = msgDb.user_info(); uint32_t user_id = user_info.user_id(); pImUser->SetUserId(user_id); pImUser->SetNickName(user_info.user_nick_name()); pImUser->SetValidated(); CImUserManager::GetInstance()->AddImUserById(user_id, pImUser); log("user_name: %s, uid: %d", login_name.c_str(), user_id); pMsgConn->SetUserId(user_id); pMsgConn->SetOpen(); pMsgConn->SendUserStatusUpdate(IM::BaseDefine::USER_STATUS_ONLINE); pImUser->ValidateMsgConn(pMsgConn->GetHandle(), pMsgConn); IM::Login::IMRegisterRes msgRes; msgRes.set_user_name(login_name); msgRes.set_server_time(time(NULL)); msgRes.set_result_code((IM::BaseDefine::ResultType)msgDb.result_code()); msgRes.set_online_status((IM::BaseDefine::UserStatType)pMsgConn->GetOnlineStatus()); msgRes.set_result_string(msgDb.result_string()); IM::BaseDefine::UserInfo* user_info_tmp = msgRes.mutable_user_info(); user_info_tmp->set_user_id(user_info.user_id()); user_info_tmp->set_user_gender(user_info.user_gender()); user_info_tmp->set_user_nick_name(user_info.user_nick_name()); user_info_tmp->set_avatar_url(user_info.avatar_url()); user_info_tmp->set_department_id(user_info.department_id()); user_info_tmp->set_email(user_info.email()); user_info_tmp->set_user_real_name(user_info.user_real_name()); user_info_tmp->set_user_tel(user_info.user_tel()); user_info_tmp->set_user_domain(user_info.user_domain()); user_info_tmp->set_status(user_info.status()); CImPdu pdu; pdu.SetPBMsg(&msgRes); pdu.SetServiceId(SID_LOGIN); pdu.SetCommandId(CID_LOGIN_RES_USERREG); pdu.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu); log("send pdu command id = %d", pdu.GetCommandId()); if (msgDb.result_code()) pMsgConn->Close(); }
void CRouteServConn::_HandleUsersStatusResponse(CImPdu* pPdu) { IM::Buddy::IMUsersStatRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); uint32_t result_count = msg.user_stat_list_size(); log("HandleUsersStatusResp, user_id=%u, query_count=%u ", user_id, result_count); CPduAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); if (attach_data.GetType() == ATTACH_TYPE_HANDLE) { uint32_t handle = attach_data.GetHandle(); auto pConn = CImUserManager::GetInstance()->GetMsgConnByHandle(user_id, handle); if (pConn) { msg.clear_attach_data(); pPdu->SetPBMsg(&msg); pConn->SendPdu(pPdu); } } else if (attach_data.GetType() == ATTACH_TYPE_PDU_FOR_PUSH) { IM::BaseDefine::UserStat user_stat = msg.user_stat_list(0); IM::Server::IMPushToUserReq msg2; CHECK_PB_PARSE_MSG(msg2.ParseFromArray(attach_data.GetPdu(), attach_data.GetPduLength())); IM::BaseDefine::UserTokenInfo* user_token = msg2.mutable_user_token_list(0); //pc client登录,则为勿打扰式推送 if (user_stat.status() == IM::BaseDefine::USER_STATUS_ONLINE) { user_token->set_push_type(IM_PUSH_TYPE_SILENT); log("HandleUsersStatusResponse, user id: %d, push type: normal. ", user_stat.user_id()); } else { user_token->set_push_type(IM_PUSH_TYPE_NORMAL); log("HandleUsersStatusResponse, user id: %d, push type: normal. ", user_stat.user_id()); } CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_PUSH_TO_USER_REQ); auto PushConn = get_push_serv_conn(); if (PushConn) { PushConn->SendPdu(&pdu); } } else if (attach_data.GetType() == ATTACH_TYPE_HANDLE_AND_PDU_FOR_FILE) { IM::BaseDefine::UserStat user_stat = msg.user_stat_list(0); IM::Server::IMFileTransferReq msg3; CHECK_PB_PARSE_MSG(msg3.ParseFromArray(attach_data.GetPdu(), attach_data.GetPduLength())); uint32_t handle = attach_data.GetHandle(); IM::BaseDefine::FileType trans_mode = IM::BaseDefine::FILE_TYPE_OFFLINE; if (user_stat.status() == IM::BaseDefine::USER_STATUS_ONLINE) { trans_mode = IM::BaseDefine::FILE_TYPE_ONLINE; } msg3.set_trans_mode(trans_mode); CImPdu pdu; pdu.SetPBMsg(&msg3); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_FILE_TRANSFER_REQ); pdu.SetSeqNum(pPdu->GetSeqNum()); auto pConn = get_random_file_serv_conn(); if (pConn) { pConn->SendPdu(&pdu); } else { log("no file server "); IM::File::IMFileRsp msg4; msg4.set_result_code(1); msg4.set_from_user_id(msg3.from_user_id()); msg4.set_to_user_id(msg3.to_user_id()); msg4.set_file_name(msg3.file_name()); msg4.set_task_id(""); msg4.set_trans_mode(msg3.trans_mode()); CImPdu pdu2; pdu2.SetPBMsg(&msg4); pdu2.SetServiceId(SID_FILE); pdu2.SetCommandId(CID_FILE_RESPONSE); pdu2.SetSeqNum(pPdu->GetSeqNum()); auto pMsgConn = CImUserManager::GetInstance()->GetMsgConnByHandle(msg3.from_user_id(),handle); if (pMsgConn) { pMsgConn->SendPdu(&pdu2); } } } }
/// yunfan add 2014.8.7 /// offline file upload /// file-svr will send pull-data-req to sender /// then wait for sender's rsp void* _DoUpload(void* lparam) { if (NULL == lparam) { return NULL; } transfer_task_t* t = reinterpret_cast<transfer_task_t*>(lparam); t->create_time = time(NULL); // at begin // send 10 data-pull-req for (uint32_t cnt = 0; cnt < 1; ++cnt) { std::map<uint32_t, upload_package_t*>::iterator iter = t->upload_packages.begin(); if (t->upload_packages.end() != iter) { IM::File::IMFilePullDataReq msg; msg.set_task_id(t->task_id); msg.set_user_id(t->from_user_id); msg.set_trans_mode(::IM::BaseDefine::FILE_TYPE_OFFLINE); msg.set_offset(iter->second->offset); msg.set_data_size(iter->second->size); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); CFileConn* pConn = (CFileConn*)t->GetConn(t->from_user_id); pConn->SendPdu(&pdu); log("Pull Data Req"); } ++iter; } // what if there is no rsp? // still send req? // no! // at last, the user will cancel // next ver, do change while (t->transfered_size != t->upload_packages.size()) { if (t->self_destroy) { log("timeout, exit thread, task %s", t->task_id.c_str()); return NULL; } sleep(1); } t->lock(__LINE__); // write head if (NULL == t->file_head) { t->file_head = new file_header_t; } if (NULL == t->file_head) { log("create file header failed %s", t->task_id.c_str()); // beacuse all data in mem // it has to be released /* UserMap_t::iterator ator = g_file_user_map.find(t->from_user_id); if (g_file_user_map.end() != ator) { CFileConn* pConn = (CFileConn*)ator->second; pConn->Close(); } */ CFileConn* pConn = (CFileConn*)t->GetConn(t->from_user_id); pConn->Close(); t->self_destroy = true; t->unlock(__LINE__); return NULL; } t->file_head->set_create_time(time(NULL)); t->file_head->set_task_id(t->task_id.c_str()); t->file_head->set_from_user_id(t->from_user_id); t->file_head->set_to_user_id(t->to_user_id); t->file_head->set_file_name(""); t->file_head->set_file_size(t->file_size); fwrite(t->file_head, 1, sizeof(file_header_t), t->fp); std::map<uint32_t, upload_package_t*>::iterator itor = t->upload_packages.begin(); for ( ; itor != t->upload_packages.end(); ++itor) { fwrite(itor->second->data, 1, itor->second->size, t->fp); } fflush(t->fp); if (t->fp) { fclose(t->fp); t->fp = NULL; } t->unlock(__LINE__); return NULL; }
void CLoginConn::_HandleMsgServRequest(CImPdu* pPdu) { IM::Login::IMMsgServReq msg; msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength()); log("HandleMsgServReq. "); // no MessageServer available if (g_msg_serv_info.size() == 0) { IM::Login::IMMsgServRsp msg; msg.set_result_code(::IM::BaseDefine::REFUSE_REASON_NO_MSG_SERVER); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_LOGIN); pdu.SetCommandId(CID_LOGIN_RES_MSGSERVER); pdu.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu); Close(); return; } // return a message server with minimum concurrent connection count msg_serv_info_t* pMsgServInfo; uint32_t min_user_cnt = (uint32_t)-1; map<uint32_t, msg_serv_info_t*>::iterator it_min_conn = g_msg_serv_info.end(),it; for (it = g_msg_serv_info.begin() ; it != g_msg_serv_info.end(); it++) { pMsgServInfo = it->second; if ( (pMsgServInfo->cur_conn_cnt < pMsgServInfo->max_conn_cnt) && (pMsgServInfo->cur_conn_cnt < min_user_cnt)) { it_min_conn = it; min_user_cnt = pMsgServInfo->cur_conn_cnt; } } if (it_min_conn == g_msg_serv_info.end()) { log("All TCP MsgServer are full "); IM::Login::IMMsgServRsp msg; msg.set_result_code(::IM::BaseDefine::REFUSE_REASON_MSG_SERVER_FULL); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_LOGIN); pdu.SetCommandId(CID_LOGIN_RES_MSGSERVER); pdu.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu); } else { IM::Login::IMMsgServRsp msg; msg.set_result_code(::IM::BaseDefine::REFUSE_REASON_NONE); msg.set_prior_ip(it_min_conn->second->ip_addr1); msg.set_backip_ip(it_min_conn->second->ip_addr2); msg.set_port(it_min_conn->second->port); CImPdu pdu; pdu.SetPBMsg(&msg); pdu.SetServiceId(SID_LOGIN); pdu.SetCommandId(CID_LOGIN_RES_MSGSERVER); pdu.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu); } Close(); // after send MsgServResponse, active close the connection }
void CFileConn::_HandleClientFilePullFileRsp(CImPdu *pPdu) { if (!_IsAuth()) { return; } IM::File::IMFilePullDataRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); string task_id = msg.task_id(); uint32_t offset = msg.offset(); uint32_t data_size = msg.data().length(); pthread_rwlock_wrlock(&g_file_task_map_lock); TaskMap_t::iterator iter = g_file_task_map.find(task_id.c_str()); if (g_file_task_map.end() == iter) { // invalid task id pthread_rwlock_unlock(&g_file_task_map_lock); return; } transfer_task_t* t = iter->second; pthread_rwlock_unlock(&g_file_task_map_lock); t->lock(__LINE__); t->create_time = time(NULL); if (t->from_user_id != user_id && t->to_user_id != user_id) { // invalid user t->unlock(__LINE__); return; } switch (t->transfer_mode) { case FILE_TYPE_ONLINE: // transfer request to sender { CFileConn* pConn = (CFileConn*)t->GetOpponentConn(user_id); pConn->SendPdu(pPdu); /// send to recver break; } case FILE_TYPE_OFFLINE: /// this is the response to the server pull-data-req { if (t->upload_packages.size() <= 0) { log("FATAL ERROR"); t->unlock(__LINE__); return; } // check if data size ok std::map<uint32_t, upload_package_t*>::iterator itPacks = t->upload_packages.find(offset); if (t->upload_packages.end() != itPacks) { // offset right // check if data size ok if (data_size != itPacks->second->size) { // the rsp's data size is different from req's // refuse it or dynamic adjust // do not adjust now, maybe later uint32_t offset = itPacks->second->offset; uint32_t size = itPacks->second->size; // resend req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(offset); msg2.set_data_size(size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); log("size not match"); t->unlock(__LINE__); return; } // check if data-ptr OK if (NULL == itPacks->second->data) { itPacks->second->data = new char[itPacks->second->size]; if (NULL == itPacks->second->data) { uint32_t offset = itPacks->second->offset; uint32_t size = itPacks->second->size; log("alloc mem failed"); // resend req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(offset); msg2.set_data_size(size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); t->unlock(__LINE__); return; } } // copy data memset(itPacks->second->data, 0, itPacks->second->size); memcpy(itPacks->second->data, msg.data().c_str(), msg.data().length()); ++t->transfered_size; } // find which segment hasn't got data yet bool bFound = false; std::map<uint32_t, upload_package_t*>::iterator itor = t->upload_packages.begin(); for ( ; itor != t->upload_packages.end(); ++itor) { if (NULL == itor->second->data) { bFound = true; break; } } if (!bFound) { // all packages recved _StatesNotify(IM::BaseDefine::CLIENT_FILE_DONE, task_id.c_str(), user_id, t->GetConn(user_id)); Close(); t->unlock(__LINE__); return; } // prepare to send req for this segment uint32_t next_offset = itor->second->offset; uint32_t next_size = itor->second->size; // send pull-data-req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(next_offset); msg2.set_data_size(next_size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); break; } default: break; } t->unlock(__LINE__); return; }
void CFileConn::_HandleClientFilePullFileReq(CImPdu *pPdu) { if (!_IsAuth()) { return; } IM::File::IMFilePullDataReq msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); string task_id = msg.task_id(); uint32_t mode = msg.trans_mode(); uint32_t offset = msg.offset(); uint32_t datasize = msg.data_size(); IM::File::IMFilePullDataRsp msg2; msg2.set_result_code(1); msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_offset(offset); msg2.set_data(""); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_RSP); pdu.SetSeqNum(pPdu->GetSeqNum()); // since the task had been created when the recver logged-in // we can find task in g_file_task_map here pthread_rwlock_wrlock(&g_file_task_map_lock); TaskMap_t::iterator iter = g_file_task_map.find(task_id.c_str()); if (g_file_task_map.end() == iter) { // invalid task id pthread_rwlock_unlock(&g_file_task_map_lock); log("invalid task id %s ", task_id.c_str()); SendPdu(&pdu); return; } transfer_task_t* t = iter->second; pthread_rwlock_unlock(&g_file_task_map_lock); t->lock(__LINE__); t->create_time = time(NULL); if (t->from_user_id != user_id /*for the realtime recver*/ && t->to_user_id != user_id /*for the offline download*/) { // invalid user log("illieage user %d for task %s", user_id, task_id.c_str()); SendPdu(&pdu); t->unlock(__LINE__); return; } switch (mode) { case IM::BaseDefine::FILE_TYPE_ONLINE: // transfer request to sender { CFileConn* pConn = (CFileConn*)t->GetOpponentConn(user_id); pConn->SendPdu(pPdu); break; } case IM::BaseDefine::FILE_TYPE_OFFLINE: // for the offline download { // find file use task id // send header info to user // send data // save path manager not used // save transfered info into task // like FILE* // transfered size // haven't been opened size_t size = 0; if (NULL == t->fp) { char save_path[BUFSIZ] = {0}; snprintf(save_path, BUFSIZ, "%s/%d", g_current_save_path, user_id); // those who can only get files under their user_id-dir int ret = mkdir(save_path, 0755); if ( (ret != 0) && (errno != EEXIST) ) { log("mkdir failed for path: %s", save_path); SendPdu(&pdu); t->unlock(__LINE__); return; } strncat(save_path, "/", BUFSIZ); strncat(save_path, task_id.c_str(), BUFSIZ); // use task_id as file name, in case of same-name file // open at first time t->fp = fopen(save_path, "rb"); // save fp if (!t->fp) { log("can not open file"); SendPdu(&pdu); t->unlock(__LINE__); return; } // read head at open if (NULL == t->file_head) { t->file_head = new file_header_t; if (NULL == t->file_head) { // close to ensure next time will new file-header again log("read file head failed."); fclose(t->fp); SendPdu(&pdu); t->unlock(__LINE__); return; } } size = fread(t->file_head, 1, sizeof(file_header_t), t->fp); // read header if (sizeof(file_header_t) > size) { // close to ensure next time will read again log("read file head failed."); fclose(t->fp); // error to get header SendPdu(&pdu); t->unlock(__LINE__); return; } // the header won't be sent to recver, because the msg svr had already notified it. // if the recver needs to check it, it could be helpful // or sometime later, the recver needs it in some way. } // read data and send based on offset and datasize. char* tmpbuf = new char[datasize]; if (NULL == tmpbuf) { // alloc mem failed log("alloc mem failed."); SendPdu(&pdu); t->unlock(__LINE__); return; } memset(tmpbuf, 0, datasize); // offset file_header_t int iret = fseek(t->fp, sizeof(file_header_t) + offset, SEEK_SET); // read after file_header_t if (0 != iret) { log("seek offset failed."); SendPdu(&pdu); delete[] tmpbuf; t->unlock(__LINE__); return; // offset failed } size = fread(tmpbuf, 1, datasize, t->fp); msg2.set_data(tmpbuf, size); CImPdu pdu2; pdu2.SetPBMsg(&msg2); pdu2.SetServiceId(SID_FILE); pdu2.SetCommandId(CID_FILE_PULL_DATA_RSP); pdu2.SetSeqNum(pPdu->GetSeqNum()); pdu2.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu2); delete[] tmpbuf; t->transfered_size += size; // record transfered size for next time offset if (0 == size) { fclose(t->fp); t->fp = NULL; _StatesNotify(CLIENT_FILE_DONE, task_id.c_str(), user_id, this); Close(); t->self_destroy = true; t->unlock(__LINE__); return; } break; } default: break; } t->unlock(__LINE__); return; }
void CGroupChat::HandleGroupMessage(CImPdu* pPdu) { IM::Message::IMMsgData msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t from_user_id = msg.from_user_id(); uint32_t to_group_id = msg.to_session_id(); string msg_data = msg.msg_data(); uint32_t msg_id = msg.msg_id(); if (msg_id == 0) { log("HandleGroupMsg, write db failed, %u->%u. ", from_user_id, to_group_id); return; } uint8_t msg_type = msg.msg_type(); CDbAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); log("HandleGroupMsg, %u->%u, msg id=%u. ", from_user_id, to_group_id, msg_id); CMsgConn* pFromConn = CImUserManager::GetInstance()->GetMsgConnByHandle(from_user_id, attach_data.GetHandle()); if (pFromConn) { //接收反馈 IM::Message::IMMsgDataAck msg2; msg2.set_user_id(from_user_id); msg2.set_session_id(to_group_id); msg2.set_msg_id(msg_id); msg2.set_session_type(::IM::BaseDefine::SESSION_TYPE_GROUP); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_MSG); pdu.SetCommandId(CID_MSG_DATA_ACK); pdu.SetSeqNum(pPdu->GetSeqNum()); pFromConn->SendPdu(&pdu); } CRouteServConn* pRouteConn = get_route_serv_conn(); if (pRouteConn) { pRouteConn->SendPdu(pPdu); } // 服务器没有群的信息,向DB服务器请求群信息,并带上消息作为附件,返回时在发送该消息给其他群成员 //IM::BaseDefine::GroupVersionInfo group_version_info; CPduAttachData pduAttachData(ATTACH_TYPE_HANDLE_AND_PDU, attach_data.GetHandle(), pPdu->GetBodyLength(), pPdu->GetBodyData()); IM::Group::IMGroupInfoListReq msg3; msg3.set_user_id(from_user_id); IM::BaseDefine::GroupVersionInfo* group_version_info = msg3.add_group_version_list(); group_version_info->set_group_id(to_group_id); group_version_info->set_version(0); msg3.set_attach_data(pduAttachData.GetBuffer(), pduAttachData.GetLength()); CImPdu pdu; pdu.SetPBMsg(&msg3); pdu.SetServiceId(SID_GROUP); pdu.SetCommandId(CID_GROUP_INFO_REQUEST); CDBServConn* pDbConn = get_db_serv_conn(); if(pDbConn) { pDbConn->SendPdu(&pdu); } }
void CDBServConn::_HandleValidateResponse(CImPdu* pPdu) { RUNTIME_TRACE; IM::Server::IMValidateRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); string login_name = msg.user_name(); uint32_t result = msg.result_code(); string result_string = msg.result_string(); CDbAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); log("HandleValidateResp, user_name=%s, result=%d", login_name.c_str(), result); CImUser* pImUser = CImUserManager::GetInstance()->GetImUserByLoginName(login_name); SpCMsgConn pMsgConn = NULL; if (!pImUser) { log("ImUser for user_name=%s not exist", login_name.c_str()); return; } else { pMsgConn = pImUser->GetUnValidateMsgConn(attach_data.GetHandle()); if (!pMsgConn || pMsgConn->IsOpen()) { log("no such conn is validated, user_name=%s", login_name.c_str()); return; } } if (result != 0) { result = IM::BaseDefine::REFUSE_REASON_DB_VALIDATE_FAILED; } if (result == 0) { IM::BaseDefine::UserInfo user_info = msg.user_info(); uint32_t user_id = user_info.user_id(); CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(user_id); if (pUser) { pUser->AddUnValidateMsgConn(pMsgConn); pImUser->DelUnValidateMsgConn(pMsgConn); if (pImUser->IsMsgConnEmpty()) { CImUserManager::GetInstance()->RemoveImUserByLoginName(login_name); delete pImUser; } } else { pUser = pImUser; } pUser->SetUserId(user_id); pUser->SetNickName(user_info.user_nick_name()); pUser->SetValidated(); CImUserManager::GetInstance()->AddImUserById(user_id, pUser); pUser->KickOutSameClientType(pMsgConn->GetClientType(), IM::BaseDefine::KICK_REASON_DUPLICATE_USER, pMsgConn); auto pRouteConn = get_route_serv_conn(); if (pRouteConn) { IM::Server::IMServerKickUser msg2; msg2.set_user_id(user_id); msg2.set_client_type((::IM::BaseDefine::ClientType)pMsgConn->GetClientType()); msg2.set_reason(1); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_SERVER_KICK_USER); pRouteConn->SendPdu(&pdu); } log("user_name: %s, uid: %d", login_name.c_str(), user_id); pMsgConn->SetUserId(user_id); pMsgConn->SetOpen(); pMsgConn->SendUserStatusUpdate(IM::BaseDefine::USER_STATUS_ONLINE); pUser->ValidateMsgConn(pMsgConn->GetHandle(), pMsgConn); IM::Login::IMLoginRes msg3; msg3.set_server_time(time(NULL)); msg3.set_result_code(IM::BaseDefine::REFUSE_REASON_NONE); msg3.set_result_string(result_string); msg3.set_online_status((IM::BaseDefine::UserStatType)pMsgConn->GetOnlineStatus()); IM::BaseDefine::UserInfo* user_info_tmp = msg3.mutable_user_info(); user_info_tmp->set_user_id(user_info.user_id()); user_info_tmp->set_user_gender(user_info.user_gender()); user_info_tmp->set_user_nick_name(user_info.user_nick_name()); user_info_tmp->set_avatar_url(user_info.avatar_url()); user_info_tmp->set_department_id(user_info.department_id()); user_info_tmp->set_email(user_info.email()); user_info_tmp->set_user_real_name(user_info.user_real_name()); user_info_tmp->set_user_tel(user_info.user_tel()); user_info_tmp->set_user_domain(user_info.user_domain()); user_info_tmp->set_status(user_info.status()); CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_LOGIN); pdu2.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu2.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu2); } else { IM::Login::IMLoginRes msg4; msg4.set_server_time(time(NULL)); msg4.set_result_code((IM::BaseDefine::ResultType)result); msg4.set_result_string(result_string); CImPdu pdu3; pdu3.SetPBMsg(&msg4); pdu3.SetServiceId(SID_LOGIN); pdu3.SetCommandId(CID_LOGIN_RES_USERLOGIN); pdu3.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu3); pMsgConn->Close(); } }
void CDBServConn::_HandleMsgData(CImPdu *pPdu) { IM::Message::IMMsgData msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); if (CHECK_MSG_TYPE_GROUP(msg.msg_type())) { s_group_chat->HandleGroupMessage(pPdu); return; } uint32_t from_user_id = msg.from_user_id(); uint32_t to_user_id = msg.to_session_id(); uint32_t msg_id = msg.msg_id(); if (msg_id == 0) { log("HandleMsgData, write db failed, %u->%u.", from_user_id, to_user_id); return; } uint8_t msg_type = msg.msg_type(); CDbAttachData attach_data((uchar_t*)msg.attach_data().c_str(), msg.attach_data().length()); uint32_t handle = attach_data.GetHandle(); log("HandleMsgData, from_user_id=%u, to_user_id=%u, msg_id=%u.", from_user_id, to_user_id, msg_id); SpCMsgConn pMsgConn = CImUserManager::GetInstance()->GetMsgConnByHandle(from_user_id, attach_data.GetHandle()); if (pMsgConn) { IM::Message::IMMsgDataAck msg2; msg2.set_user_id(from_user_id); msg2.set_msg_id(msg_id); msg2.set_session_id(to_user_id); msg2.set_session_type(::IM::BaseDefine::SESSION_TYPE_SINGLE); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_MSG); pdu.SetCommandId(CID_MSG_DATA_ACK); pdu.SetSeqNum(pPdu->GetSeqNum()); pMsgConn->SendPdu(&pdu); } auto pRouteConn = get_route_serv_conn(); if (pRouteConn) { pRouteConn->SendPdu(pPdu); } msg.clear_attach_data(); pPdu->SetPBMsg(&msg); CImUser* pFromImUser = CImUserManager::GetInstance()->GetImUserById(from_user_id); CImUser* pToImUser = CImUserManager::GetInstance()->GetImUserById(to_user_id); pPdu->SetSeqNum(0); if (pFromImUser) { pFromImUser->BroadcastClientMsgData(pPdu, msg_id, pMsgConn, from_user_id); } if (pToImUser) { pToImUser->BroadcastClientMsgData(pPdu, msg_id, NULL, from_user_id); } IM::Server::IMGetDeviceTokenReq msg3; msg3.add_user_id(to_user_id); msg3.set_attach_data(pPdu->GetBodyData(), pPdu->GetBodyLength()); CImPdu pdu2; pdu2.SetPBMsg(&msg3); pdu2.SetServiceId(SID_OTHER); pdu2.SetCommandId(CID_OTHER_GET_DEVICE_TOKEN_REQ); SendPdu(&pdu2); }
void setDevicesToken(CImPdu* pPdu, uint32_t conn_uuid) { IM::Login::IMDeviceTokenReq msg; IM::Login::IMDeviceTokenRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { uint32_t nUserId = msg.user_id(); string strToken = msg.device_token(); CImPdu* pPduResp = new CImPdu; CacheManager* pCacheManager = CacheManager::getInstance(); CacheConn* pCacheConn = pCacheManager->GetCacheConn("token"); if (pCacheConn) { IM::BaseDefine::ClientType nClientType = msg.client_type(); string strValue; if(IM::BaseDefine::CLIENT_TYPE_IOS == nClientType) { strValue = "ios:"+strToken; } else if(IM::BaseDefine::CLIENT_TYPE_ANDROID == nClientType) { strValue = "android:"+strToken; } else { strValue = strToken; } string strOldValue = pCacheConn->get("device_"+int2string(nUserId)); if(!strOldValue.empty()) { size_t nPos = strOldValue.find(":"); if(nPos!=string::npos) { string strOldToken = strOldValue.substr(nPos + 1); string strReply = pCacheConn->get("device_"+strOldToken); if (!strReply.empty()) { string strNewValue(""); pCacheConn->set("device_"+strOldToken, strNewValue); } } } pCacheConn->set("device_"+int2string(nUserId), strValue); string strNewValue = int2string(nUserId); pCacheConn->set("device_"+strToken, strNewValue); log("setDeviceToken. userId=%u, deviceToken=%s", nUserId, strToken.c_str()); pCacheManager->RelCacheConn(pCacheConn); } else { log("no cache connection for token"); } log("setDeviceToken. userId=%u, deviceToken=%s", nUserId, strToken.c_str()); msgResp.set_attach_data(msg.attach_data()); msgResp.set_user_id(nUserId); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_LOGIN); pPduResp->SetCommandId(IM::BaseDefine::CID_LOGIN_RES_DEVICETOKEN); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); } else { log("parse pb failed"); } }
void CDBServConn::_HandleGetDeviceTokenResponse(CImPdu *pPdu) { IM::Server::IMGetDeviceTokenRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); IM::Message::IMMsgData msg2; CHECK_PB_PARSE_MSG(msg2.ParseFromArray(msg.attach_data().c_str(), msg.attach_data().length())); string msg_data = msg2.msg_data(); uint32_t msg_type = msg2.msg_type(); uint32_t from_id = msg2.from_user_id(); uint32_t to_id = msg2.to_session_id(); if (msg_type == IM::BaseDefine::MSG_TYPE_SINGLE_TEXT || msg_type == IM::BaseDefine::MSG_TYPE_GROUP_TEXT) { //msg_data = char* msg_out = NULL; uint32_t msg_out_len = 0; if (pAes->Decrypt(msg_data.c_str(), msg_data.length(), &msg_out, msg_out_len) == 0) { msg_data = string(msg_out, msg_out_len); } else { log("HandleGetDeviceTokenResponse, decrypt msg failed, from_id: %u, to_id: %u, msg_type: %u.", from_id, to_id, msg_type); return; } pAes->Free(msg_out); } build_ios_push_flash(msg_data, msg2.msg_type(), from_id); //{ // "msg_type": 1, // "from_id": "1345232", // "group_type": "12353", //} jsonxx::Object json_obj; json_obj << "msg_type" << (uint32_t)msg2.msg_type(); json_obj << "from_id" << from_id; if (CHECK_MSG_TYPE_GROUP(msg2.msg_type())) { json_obj << "group_id" << to_id; } uint32_t user_token_cnt = msg.user_token_info_size(); log("HandleGetDeviceTokenResponse, user_token_cnt = %u.", user_token_cnt); IM::Server::IMPushToUserReq msg3; for (uint32_t i = 0; i < user_token_cnt; i++) { IM::BaseDefine::UserTokenInfo user_token = msg.user_token_info(i); uint32_t user_id = user_token.user_id(); string device_token = user_token.token(); uint32_t push_cnt = user_token.push_count(); uint32_t client_type = user_token.user_type(); //自己发得消息不给自己发推送 if (from_id == user_id) { continue; } log("HandleGetDeviceTokenResponse, user_id = %u, device_token = %s, push_cnt = %u, client_type = %u.", user_id, device_token.c_str(), push_cnt, client_type); CImUser* pUser = CImUserManager::GetInstance()->GetImUserById(user_id); if (pUser) { msg3.set_flash(msg_data); msg3.set_data(json_obj.json()); IM::BaseDefine::UserTokenInfo* user_token_tmp = msg3.add_user_token_list(); user_token_tmp->set_user_id(user_id); user_token_tmp->set_user_type((IM::BaseDefine::ClientType)client_type); user_token_tmp->set_token(device_token); user_token_tmp->set_push_count(push_cnt); //pc client登录,则为勿打扰式推送 if (pUser->GetPCLoginStatus() == IM_PC_LOGIN_STATUS_ON) { user_token_tmp->set_push_type(IM_PUSH_TYPE_SILENT); log("HandleGetDeviceTokenResponse, user id: %d, push type: silent.", user_id); } else { user_token_tmp->set_push_type(IM_PUSH_TYPE_NORMAL); log("HandleGetDeviceTokenResponse, user id: %d, push type: normal.", user_id); } } else { IM::Server::IMPushToUserReq msg4; msg4.set_flash(msg_data); msg4.set_data(json_obj.json()); IM::BaseDefine::UserTokenInfo* user_token_tmp = msg4.add_user_token_list(); user_token_tmp->set_user_id(user_id); user_token_tmp->set_user_type((IM::BaseDefine::ClientType)client_type); user_token_tmp->set_token(device_token); user_token_tmp->set_push_count(push_cnt); user_token_tmp->set_push_type(IM_PUSH_TYPE_NORMAL); CImPdu pdu; pdu.SetPBMsg(&msg4); pdu.SetServiceId(SID_OTHER); pdu.SetCommandId(CID_OTHER_PUSH_TO_USER_REQ); CPduAttachData attach_data(ATTACH_TYPE_PDU_FOR_PUSH, 0, pdu.GetBodyLength(), pdu.GetBodyData()); IM::Buddy::IMUsersStatReq msg5; msg5.set_user_id(0); msg5.add_user_id_list(user_id); msg5.set_attach_data(attach_data.GetBuffer(), attach_data.GetLength()); CImPdu pdu2; pdu2.SetPBMsg(&msg5); pdu2.SetServiceId(SID_BUDDY_LIST); pdu2.SetCommandId(CID_BUDDY_LIST_USERS_STATUS_REQUEST); auto route_conn = get_route_serv_conn(); if (route_conn) { route_conn->SendPdu(&pdu2); } } } if (msg3.user_token_list_size() > 0) { CImPdu pdu3; pdu3.SetPBMsg(&msg3); pdu3.SetServiceId(SID_OTHER); pdu3.SetCommandId(CID_OTHER_PUSH_TO_USER_REQ); auto PushConn = get_push_serv_conn(); if (PushConn) { PushConn->SendPdu(&pdu3); } } }
void doLogin(CImPdu* pPdu, uint32_t conn_uuid) { CImPdu* pPduResp = new CImPdu; IM::Server::IMValidateReq msg; IM::Server::IMValidateRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { string strDomain = msg.user_name(); string strPass = msg.password(); msgResp.set_user_name(strDomain); msgResp.set_attach_data(msg.attach_data()); do { CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; uint32_t tmNow = time(NULL); //清理超过30分钟的错误时间点记录 /* 清理放在这里还是放在密码错误后添加的时候呢? 放在这里,每次都要遍历,会有一点点性能的损失。 放在后面,可能会造成30分钟之前有10次错的,但是本次是对的就没办法再访问了。 */ auto itTime=lsErrorTime.begin(); for(; itTime!=lsErrorTime.end();++itTime) { if(tmNow - *itTime > 30*60) { break; } } if(itTime != lsErrorTime.end()) { lsErrorTime.erase(itTime, lsErrorTime.end()); } // 判断30分钟内密码错误次数是否大于10 if(lsErrorTime.size() > 10) { itTime = lsErrorTime.begin(); if(tmNow - *itTime <= 30*60) { msgResp.set_result_code(6); msgResp.set_result_string("用户名/密码错误次数太多"); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_OTHER); pPduResp->SetCommandId(IM::BaseDefine::CID_OTHER_VALIDATE_RSP); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); return ; } } } while(false); log("%s request login.", strDomain.c_str()); IM::BaseDefine::UserInfo cUser; if(g_loginStrategy.doLogin(strDomain, strPass, cUser)) { IM::BaseDefine::UserInfo* pUser = msgResp.mutable_user_info(); pUser->set_user_id(cUser.user_id()); pUser->set_user_gender(cUser.user_gender()); pUser->set_department_id(cUser.department_id()); pUser->set_user_nick_name(cUser.user_nick_name()); pUser->set_user_domain(cUser.user_domain()); pUser->set_avatar_url(cUser.avatar_url()); pUser->set_email(cUser.email()); pUser->set_user_tel(cUser.user_tel()); pUser->set_user_real_name(cUser.user_real_name()); pUser->set_status(0); pUser->set_sign_info(cUser.sign_info()); msgResp.set_result_code(0); msgResp.set_result_string("成功"); //如果登陆成功,则清除错误尝试限制 CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; lsErrorTime.clear(); } else { //密码错误,记录一次登陆失败 uint32_t tmCurrent = time(NULL); CAutoLock cAutoLock(&g_cLimitLock); list<uint32_t>& lsErrorTime = g_hmLimits[strDomain]; lsErrorTime.push_front(tmCurrent); log("get result false"); msgResp.set_result_code(1); msgResp.set_result_string("用户名/密码错误"); } } else { msgResp.set_result_code(2); msgResp.set_result_string("服务端内部错误"); } pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_OTHER); pPduResp->SetCommandId(IM::BaseDefine::CID_OTHER_VALIDATE_RSP); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); }
void CFileConn::_HandleClientFileLoginReq(CImPdu* pPdu) { // if can not find uuid // return invalid uuid // if invalid user_id // return invalid user // if ready_to_recv or offline / mobile task // return can_send // return ok IM::File::IMFileLoginReq msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); string task_id = msg.task_id(); IM::BaseDefine::ClientFileRole mode = msg.file_role(); m_user_id = user_id; log("client login, user_id=%u, handle %d", m_user_id, m_handle); // auth done m_bAuth = true; m_conntype = CONN_TYPE_CLIENT; IM::File::IMFileLoginRsp msg2; msg2.set_result_code(1); msg2.set_task_id(task_id); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_LOGIN_RES); pdu.SetSeqNum(pPdu->GetSeqNum()); // create task for offline download if (IM::BaseDefine::CLIENT_OFFLINE_DOWNLOAD == mode) { // create a thread // insert into a queue, multi-threads handle the queue // find file // send file transfer_task_t* t = new transfer_task_t; if (NULL == t) { SendPdu(&pdu); Close(); log("create task failed for task id %s, user %d", task_id.c_str(), m_user_id); return; // create task failed } t->task_id = task_id; t->to_user_id = m_user_id; t->create_time = time(NULL); pthread_rwlock_wrlock(&g_file_task_map_lock); g_file_task_map.insert(std::make_pair(task_id.c_str(), t)); pthread_rwlock_unlock(&g_file_task_map_lock); } // check task pthread_rwlock_wrlock(&g_file_task_map_lock); TaskMap_t::iterator iter = g_file_task_map.find(task_id.c_str()); if (g_file_task_map.end() == iter) { // failed to find task // return invaild task id pthread_rwlock_unlock(&g_file_task_map_lock); SendPdu(&pdu); Close(); // invalid user for task log("check task id failed, user_id = %u, request taks id %s", m_user_id, task_id.c_str()); return; } transfer_task_t* t = iter->second; pthread_rwlock_unlock(&g_file_task_map_lock); // check user if (t->from_user_id != m_user_id && t->to_user_id != m_user_id) { // invalid user // return error SendPdu(&pdu); Close(); log("invalid user %u for task %s", m_user_id, task_id.c_str()); return; } // prepare for offline upload if (CLIENT_OFFLINE_UPLOAD == mode) { int iret = _PreUpload(task_id.c_str()); if (0 > iret) { SendPdu(&pdu); Close(); log("preload faild for task %s, err %d", task_id.c_str(), iret); return; } } if (t->from_user_id == m_user_id) { t->from_conn = this; } if (t->to_user_id == m_user_id) { t->to_conn = this; } // send result msg2.set_result_code(0); CImPdu pdu2; pdu2.SetPBMsg(&msg2); pdu2.SetServiceId(SID_FILE); pdu2.SetCommandId(CID_FILE_LOGIN_RES); pdu2.SetSeqNum(pPdu->GetSeqNum()); SendPdu(&pdu2); // login succeed /// yunfan add 2014.8.12 // 2014.8.14 // record state if (m_user_id == t->from_user_id) { t->ready_to_send = true; } if (m_user_id == t->to_user_id) { t->ready_to_recv = true; } // notify that the peet is ready if ( (m_user_id == t->to_user_id && \ t->ready_to_send) || \ (m_user_id == t->from_user_id && \ t->ready_to_recv)){ // send peer-ready state to recver _StatesNotify(IM::BaseDefine::CLIENT_FILE_PEER_READY, task_id.c_str(), m_user_id, t->GetConn(m_user_id)); log("nofity recver %d task %s can recv", m_user_id, task_id.c_str()); } // create a thread // insert into a queue, multi-threads handle the queue // send to client PULLDATA msg // recv and write file if (IM::BaseDefine::CLIENT_OFFLINE_UPLOAD == mode) { // check thread id pthread_create(&t->worker, NULL, _DoUpload, t); log("create thread for offline upload task %s user %d thread id %d", task_id.c_str(), m_user_id, t->worker); } /// yunfan add end return; }