blob: 105aee5c01ebc21b6b577e71e10b6e375b84ab53 [file] [log] [blame]
#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;
}