| #include <iostream> |
| #include <memory> |
| #include <string> |
| #include <sstream> |
| #include <time.h> |
| #include <grpcpp/grpcpp.h> |
| |
| #include "mmeGrpc.grpc.pb.h" |
| |
| #include <controlBlock.h> |
| #include <contextManager/dataBlocks.h> |
| #include <contextManager/subsDataGroupManager.h> |
| #include <procedureStats.h> |
| |
| using grpc::Server; |
| using grpc::ServerBuilder; |
| using grpc::ServerContext; |
| using grpc::ServerReader; |
| using grpc::ServerReaderWriter; |
| using grpc::ServerWriter; |
| using grpc::Status; |
| using mmeGrpc::UeContextReqBuf; |
| using mmeGrpc::UeContextRespBuf; |
| using mmeGrpc::UeContextRespBuf_SessionContextRespBuf; |
| using mmeGrpc::MmeGrpcCli; |
| using mmeGrpc::Empty; |
| using mmeGrpc::ProcedureStatsRespBuf; |
| using mmeGrpc::EventInfoRespBuf; |
| using mmeGrpc::EventInfoRespBuf_EventInfoBuf; |
| |
| using namespace mme; |
| |
| const string UEStates[4]={ "NoState", "EpsAttached", "Detached", "Idle" }; |
| // Logic and data behind the server's behavior. |
| class MmeGrpcCliServiceImpl final : public MmeGrpcCli::Service { |
| Status GetUeContextInfo(SM::ControlBlock* controlBlk_p, UeContextRespBuf* reply) { |
| //time_t my_time = time(NULL); |
| // SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| if (controlBlk_p) |
| { |
| UEContext* uecontext_p=dynamic_cast<UEContext*>(controlBlk_p->getPermDataBlock()); |
| if (uecontext_p != NULL) |
| { |
| //cout << "MY TIME " << ctime(&my_time); |
| |
| // Display IMSI |
| stringstream ss; |
| ss << uecontext_p->getImsi(); |
| reply->set_imsi(ss.str()); |
| |
| // MSISDN |
| ss.str(""); |
| ss << uecontext_p->getMsisdn(); |
| string ms(ss.str()); |
| ms.resize(10); |
| ms.shrink_to_fit(); |
| reply->set_msisdn(ms); |
| |
| // TAI |
| ss.str(""); |
| const TAI& tai = uecontext_p->getTai().tai_m; |
| ss << "MCC : "; |
| ss << (unsigned char)((tai.plmn_id.idx[0] & 0x0f) + 0x30); |
| ss << (unsigned char)((tai.plmn_id.idx[0] >> 4) + 0x30); |
| ss << (unsigned char)((tai.plmn_id.idx[1] & 0x0f) + 0x30); |
| ss << " MNC : "; |
| ss << (unsigned char)((tai.plmn_id.idx[2] & 0x0f) + 0x30); |
| ss << (unsigned char)((tai.plmn_id.idx[2] >> 4) + 0x30); |
| ss << " TAC : " << tai.tac ; |
| reply->set_tai(ss.str()); |
| |
| // Cell Identity |
| ss.str(""); |
| const CGI& cgi = uecontext_p->getUtranCgi().cgi_m; |
| ss << "0x" << std::hex << cgi.cell_id; |
| reply->set_eutran_cgi(ss.str()); |
| |
| reply->set_context_id(uecontext_p->getContextID()); |
| |
| reply->set_enb_ue_s1ap_id(uecontext_p->getS1apEnbUeId()); |
| |
| MmContext* mmCtxt = uecontext_p->getMmContext(); |
| UE_State_e uestate = mmCtxt->getMmState(); |
| |
| reply->set_ue_state(UEStates[uestate]); |
| |
| SessionContext* sessioncontext_p = uecontext_p->getSessionContext(); |
| if (sessioncontext_p != NULL) |
| { |
| UeContextRespBuf_SessionContextRespBuf* session_ctxt = reply->add_sessioncontext(); |
| if (session_ctxt) |
| { |
| // APN |
| const apn_name& apn = sessioncontext_p->getAccessPtName().apnname_m; |
| string apnStr((const char*)(apn.val), apn.len); |
| session_ctxt->set_apn(apnStr); |
| |
| // PDN address |
| const PAA& PdnAddr = sessioncontext_p->getPdnAddr().paa_m; |
| char ipStr[INET_ADDRSTRLEN]; |
| inet_ntop(AF_INET, &(PdnAddr.ip_type.ipv4), ipStr, INET_ADDRSTRLEN); |
| session_ctxt->set_pdn_address(ipStr); |
| |
| // Bearer ID |
| session_ctxt->set_bearer_id(5); |
| |
| // S11 SGW GTP-C TEID |
| const fteid& s11SgwCTeid = sessioncontext_p->getS11SgwCtrlFteid().fteid_m; |
| |
| ss.str(""); |
| memset(ipStr, 0, INET_ADDRSTRLEN); |
| uint32_t ip = ntohl(s11SgwCTeid.ip.ipv4.s_addr); |
| |
| inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| ss << "IP " << ipStr << " TEID " << s11SgwCTeid.header.teid_gre; |
| session_ctxt->set_s11_sgw_gtpc_teid(ss.str()); |
| |
| // S5S8 PGW GTP-C TEID |
| const fteid& s5s8PgwCTeid = sessioncontext_p->getS5S8PgwCtrlFteid().fteid_m; |
| |
| ss.str(""); |
| memset(ipStr, 0, INET_ADDRSTRLEN); |
| ip = ntohl(s5s8PgwCTeid.ip.ipv4.s_addr); |
| |
| inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| ss << "IP " << ipStr << " TEID " << s5s8PgwCTeid.header.teid_gre; |
| session_ctxt->set_s5_pgw_gtpc_teid(ss.str()); |
| |
| BearerContext* bearerCtxt = sessioncontext_p->getBearerContext(); |
| // S1U ENB TEID |
| const fteid& s1uEnbTeid = bearerCtxt->getS1uEnbUserFteid().fteid_m; |
| |
| ss.str(""); |
| memset(ipStr, 0, INET_ADDRSTRLEN); |
| ip = ntohl(s1uEnbTeid.ip.ipv4.s_addr); |
| |
| inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| ss << "IP " << ipStr << " TEID " << s1uEnbTeid.header.teid_gre; |
| session_ctxt->set_s1u_enb_teid(ss.str()); |
| |
| // S1U SGW TEID |
| const fteid& s1uSgwTeid = bearerCtxt->getS1uSgwUserFteid().fteid_m; |
| ss.str(""); |
| memset(ipStr, 0, INET_ADDRSTRLEN); |
| ip = ntohl(s1uSgwTeid.ip.ipv4.s_addr); |
| |
| inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| ss << "IP " << ipStr << " TEID " << s1uSgwTeid.header.teid_gre; |
| session_ctxt->set_s1u_sgw_teid(ss.str()); |
| |
| // S5-U PGW TEID |
| const fteid& s5uPgwTeid = bearerCtxt->getS5S8PgwUserFteid().fteid_m; |
| ss.str(""); |
| memset(ipStr, 0, INET_ADDRSTRLEN); |
| ip = ntohl(s5uPgwTeid.ip.ipv4.s_addr); |
| |
| inet_ntop(AF_INET, &(ip), ipStr, INET_ADDRSTRLEN); |
| ss << "IP " << ipStr << " TEID " << s5uPgwTeid.header.teid_gre; |
| session_ctxt->set_s5u_pgw_teid(ss.str()); |
| |
| } |
| } |
| } |
| } |
| return Status::OK; |
| |
| } |
| |
| Status GetUeContext(ServerContext* context, const UeContextReqBuf* request, |
| UeContextRespBuf* reply) override |
| { |
| SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| GetUeContextInfo(controlBlk_p, reply); |
| |
| return Status::OK; |
| } |
| |
| Status ShowAllMobileContexts(ServerContext* context, const Empty* request, |
| ServerWriter<UeContextRespBuf>* writer) override |
| { |
| for (uint32_t i = 1; i <= 8000; i++) |
| { |
| SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock(i); |
| if (controlBlk_p != NULL && controlBlk_p->getPermDataBlock() != NULL) |
| { |
| UeContextRespBuf reply; |
| GetUeContextInfo(controlBlk_p, &reply); |
| writer->Write(reply); |
| } |
| } |
| return Status::OK; |
| } |
| |
| Status GetDebugUeContext(ServerContext* context, const UeContextReqBuf* request, |
| EventInfoRespBuf* reply) override { |
| SM::ControlBlock* controlBlk_p = mme::SubsDataGroupManager::Instance()->findControlBlock((uint32_t)request->id()); |
| if( controlBlk_p ) |
| { |
| UEContext* uecontext_p=dynamic_cast<UEContext*>(controlBlk_p->getPermDataBlock()); |
| if( uecontext_p ) |
| { |
| MmContext* mmCtxt = uecontext_p->getMmContext(); |
| UE_State_e uestate = mmCtxt->getMmState(); |
| reply->set_ue_state(UEStates[static_cast<int>(uestate)]); |
| } |
| deque<SM::debugEventInfo> evtQ = controlBlk_p->getDebugInfoQueue(); |
| for(auto it=evtQ.begin();it!=evtQ.end();it++) |
| { |
| EventInfoRespBuf_EventInfoBuf* EvtInfo = reply->add_eventinfo(); |
| string strEvent = Events[it->event]; |
| EvtInfo->set_event(strEvent); |
| string strState = States[it->state]; |
| EvtInfo->set_state(strState); |
| EvtInfo->set_time(ctime(&(it->evt_time))); |
| } |
| } |
| return Status::OK; |
| } |
| |
| Status GetProcStats(ServerContext* context,const Empty* request, |
| ProcedureStatsRespBuf* reply) override { |
| /*time_t my_time = time(NULL); |
| my_time = time(NULL); |
| cout << "Req recieved at server" << ctime(&my_time);*/ |
| reply->set_num_of_air_sent(ProcedureStats::num_of_air_sent); |
| reply->set_num_of_ulr_sent(ProcedureStats::num_of_ulr_sent); |
| reply->set_num_of_processed_aia(ProcedureStats::num_of_processed_aia); |
| reply->set_num_of_processed_ula(ProcedureStats::num_of_processed_ula); |
| reply->set_num_of_auth_req_to_ue_sent(ProcedureStats::num_of_auth_req_to_ue_sent); |
| reply->set_num_of_processed_auth_response(ProcedureStats::num_of_processed_auth_response); |
| reply->set_num_of_sec_mode_cmd_to_ue_sent(ProcedureStats::num_of_sec_mode_cmd_to_ue_sent); |
| reply->set_num_of_processed_sec_mode_resp(ProcedureStats::num_of_processed_sec_mode_resp); |
| reply->set_num_of_esm_info_req_to_ue_sent(ProcedureStats::num_of_esm_info_req_to_ue_sent); |
| reply->set_num_of_handled_esm_info_resp(ProcedureStats::num_of_handled_esm_info_resp); |
| reply->set_num_of_cs_req_to_sgw_sent(ProcedureStats::num_of_cs_req_to_sgw_sent); |
| reply->set_num_of_processed_cs_resp(ProcedureStats::num_of_processed_cs_resp); |
| reply->set_num_of_init_ctxt_req_to_ue_sent(ProcedureStats::num_of_init_ctxt_req_to_ue_sent); |
| reply->set_num_of_processed_init_ctxt_resp(ProcedureStats::num_of_processed_init_ctxt_resp); |
| reply->set_num_of_mb_req_to_sgw_sent(ProcedureStats::num_of_mb_req_to_sgw_sent); |
| reply->set_num_of_processed_attach_cmp_from_ue(ProcedureStats::num_of_processed_attach_cmp_from_ue); |
| reply->set_num_of_processed_mb_resp(ProcedureStats::num_of_processed_mb_resp); |
| reply->set_num_of_attach_done(ProcedureStats::num_of_attach_done); |
| reply->set_num_of_del_session_req_sent(ProcedureStats::num_of_del_session_req_sent); |
| reply->set_num_of_purge_req_sent(ProcedureStats::num_of_purge_req_sent); |
| reply->set_num_of_processed_del_session_resp(ProcedureStats::num_of_processed_del_session_resp); |
| reply->set_num_of_processed_pur_resp(ProcedureStats::num_of_processed_pur_resp); |
| reply->set_num_of_detach_accept_to_ue_sent(ProcedureStats::num_of_detach_accept_to_ue_sent); |
| reply->set_num_of_processed_detach_accept(ProcedureStats::num_of_processed_detach_accept); |
| reply->set_num_of_ue_ctxt_release(ProcedureStats::num_of_ue_ctxt_release); |
| reply->set_num_of_processed_ctxt_rel_resp(ProcedureStats::num_of_processed_ctxt_rel_resp); |
| reply->set_num_of_subscribers_attached(ProcedureStats::num_of_subscribers_attached); |
| reply->set_num_of_rel_access_bearer_req_sent(ProcedureStats::num_of_rel_access_bearer_req_sent); |
| reply->set_num_of_rel_access_bearer_resp_received(ProcedureStats::num_of_rel_access_bearer_resp_received); |
| reply->set_num_of_s1_rel_req_received(ProcedureStats::num_of_s1_rel_req_received); |
| reply->set_num_of_s1_rel_cmd_sent(ProcedureStats::num_of_s1_rel_cmd_sent); |
| reply->set_num_of_s1_rel_comp_received(ProcedureStats::num_of_s1_rel_comp_received); |
| reply->set_num_of_clr_received(ProcedureStats::num_of_clr_received); |
| reply->set_num_of_cla_sent(ProcedureStats::num_of_cla_sent); |
| reply->set_num_of_detach_req_to_ue_sent(ProcedureStats::num_of_detach_req_to_ue_sent); |
| reply->set_num_of_detach_accept_from_ue(ProcedureStats::num_of_detach_accept_from_ue); |
| reply->set_total_num_of_subscribers(ProcedureStats::total_num_of_subscribers); |
| reply->set_num_of_subscribers_detached(ProcedureStats::num_of_subscribers_detached); |
| reply->set_num_of_tau_response_to_ue_sent(ProcedureStats::num_of_tau_response_to_ue_sent); |
| |
| //reply->set_num_of_ddn_received(ProcedureStats::num_of_ddn_received); |
| return Status::OK; |
| } |
| |
| }; |
| |
| void * RunServer(void* data) { |
| std::string server_address("0.0.0.0:50051"); |
| MmeGrpcCliServiceImpl service; |
| |
| ServerBuilder builder; |
| // Listen on the given address without any authentication mechanism. |
| builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); |
| // Register "service" as the instance through which we'll communicate with |
| // clients. In this case it corresponds to an *synchronous* service. |
| builder.RegisterService(&service); |
| // Finally assemble the server. |
| std::unique_ptr<Server> server(builder.BuildAndStart()); |
| std::cout << "Server listening on " << server_address << std::endl; |
| |
| // Wait for the server to shutdown. Note that some other thread must be |
| // responsible for shutting down the server for this call to ever return. |
| server->Wait(); |
| |
| return NULL; |
| } |