Skip to content

Commit

Permalink
add support for call information / sip history in active calls
Browse files Browse the repository at this point in the history
  • Loading branch information
rbucek committed Sep 2, 2024
1 parent ca1a494 commit 5a50a72
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 18 deletions.
86 changes: 77 additions & 9 deletions calltable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,21 @@ Call_abstract::addTarPos(u_int64_t pos, int type) {
}
}

string CallStructs::sSipPacketInfo::getJson() {
JsonExport json;
json.add("time", time_us);
json.add("src_ip", src.ip.getString());
json.add("src_port", src.port.getString());
json.add("dst_ip", dst.ip.getString());
json.add("dst_port", dst.port.getString());
json.add("sip", sip_first_line);
json.add("sip_len", sip_length);
json.add("packet_len", packet_length);
json.add("cseq_m", cseq.method);
json.add("cseq_n", cseq.number);
return(json.getJson());
}

CallBranch::CallBranch(Call *call, unsigned branch_id) {
this->call = call;
this->branch_id = branch_id;
Expand Down Expand Up @@ -593,6 +608,12 @@ CallBranch::CallBranch(Call *call, unsigned branch_id) {
updateDstnumFromMessage = false;
}

CallBranch::~CallBranch() {
for(list<sSipPacketInfo*>::iterator iter = SIPpacketInfoList.begin(); iter != SIPpacketInfoList.end(); iter++) {
delete *iter;
}
}

void CallBranch::proxies_undup(set<vmIP> *proxies_undup, list<vmIPport> *proxies, vmIPport *exclude) {
bool need_lock = !proxies;
if(need_lock) proxies_lock();
Expand Down Expand Up @@ -644,6 +665,20 @@ int64_t CallBranch::get_min_response_xxx_time_us(){
return(rslt);
}

string CallBranch::get_sip_packets_info_json() {
string rslt = "[";
unsigned counter = 0;
for(list<sSipPacketInfo*>::iterator iter = SIPpacketInfoList.begin(); iter != SIPpacketInfoList.end(); iter++) {
if(counter) {
rslt += ",";
}
rslt += (*iter)->getJson();
++counter;
}
rslt += "]";
return(rslt);
}

/* constructor */
Call::Call(int call_type, char *call_id, unsigned long call_id_len, vector<string> *call_id_alternative, u_int64_t time_us) :
Call_abstract(call_type, time_us),
Expand Down Expand Up @@ -4740,22 +4775,30 @@ void Call::getValue(eCallField field, RecordArrayField *rfield) {
}

string Call::getJsonHeader() {
string header = "[";
for(unsigned i = 0; i < sizeof(callFields) / sizeof(callFields[0]); i++) {
vector<string> header;
getJsonHeader(&header);
string header_str = "[";
for(unsigned i = 0; i < header.size(); i++) {
if(i) {
header += ",";
header_str += ",";
}
header += '"' + string(callFields[i].fieldName) + '"';
header_str += '"' + header[i] + '"';
}
header_str += "]";
return(header_str);
}

void Call::getJsonHeader(vector<string> *header) {
for(unsigned i = 0; i < sizeof(callFields) / sizeof(callFields[0]); i++) {
header->push_back(callFields[i].fieldName);
}
if(custom_headers_cdr) {
list<string> headers;
custom_headers_cdr->getHeaders(&headers);
for(list<string>::iterator iter = headers.begin(); iter != headers.end(); iter++) {
header += ",\"" + *iter + '"';
header->push_back(*iter);
}
}
header += "]";
return(header);
}

void Call::getRecordData(RecordArray *rec) {
Expand All @@ -4773,9 +4816,17 @@ void Call::getRecordData(RecordArray *rec) {
}

string Call::getJsonData() {
RecordArray rec(sizeof(callFields) / sizeof(callFields[0]));
unsigned custom_headers_size = 0;
unsigned custom_headers_reserve = 0;
if(custom_headers_cdr) {
custom_headers_size = custom_headers_cdr->getSize();
custom_headers_reserve = 5;
}
RecordArray rec(sizeof(callFields) / sizeof(callFields[0]) + custom_headers_size + custom_headers_reserve);
getRecordData(&rec);
string data = rec.getJson();
vector<string> header;
getJsonHeader(&header);
string data = rec.getJson(&header);
rec.free();
return(data);
}
Expand Down Expand Up @@ -14597,6 +14648,23 @@ void Call::srvcc_check_pre(CallBranch *c_branch) {
}
}

string Call::get_rtp_streams_info_json() {
string rslt = "[";
unsigned counter = 0;
for(int i = 0; i < min(ssrc_n, MAX_SSRC_PER_CALL_FIX); i++) {
RTP *rtp = rtp_fix[i];
if(rtp) {
if(counter) {
rslt += ",";
}
rslt += rtp->getJson();
++counter;
}
}
rslt += "]";
return(rslt);
}

void Call::dtls_keys_add(cDtlsLink::sSrtpKeys* keys_item) {
dtls_keys_lock();
bool exists = false;
Expand Down
15 changes: 15 additions & 0 deletions calltable.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,16 @@ class CallStructs {
string SIPresponse;
int SIPresponseNum;
};
struct sSipPacketInfo {
u_int64_t time_us;
vmIPport src;
vmIPport dst;
string sip_first_line;
u_int32_t sip_length;
u_int32_t packet_length;
sCseq cseq;
string getJson();
};
struct sSipcalleRD_IP {
sSipcalleRD_IP() {
for(unsigned i = 0; i < MAX_SIPCALLERDIP; i++) {
Expand Down Expand Up @@ -543,6 +553,7 @@ class CallStructs {
class CallBranch : public CallStructs {
public:
CallBranch(Call *call = NULL, unsigned branch_id = 0);
virtual ~CallBranch();
inline void invite_list_lock() {
__SYNC_LOCK_USLEEP(_invite_list_lock, 50);
}
Expand Down Expand Up @@ -579,6 +590,7 @@ class CallBranch : public CallStructs {
}
int64_t get_min_response_100_time_us();
int64_t get_min_response_xxx_time_us();
string get_sip_packets_info_json();
public:

Call *call;
Expand Down Expand Up @@ -665,6 +677,7 @@ class CallBranch : public CallStructs {
int lastSIPresponseNum;
list<sSipResponse> SIPresponse;
list<sSipHistory> SIPhistory;
list<sSipPacketInfo*> SIPpacketInfoList;
bool new_invite_after_lsr487;
bool cancel_lsr487;

Expand Down Expand Up @@ -2714,6 +2727,7 @@ class Call : public CallStructs, public Call_abstract {

void getValue(eCallField field, RecordArrayField *rfield);
static string getJsonHeader();
static void getJsonHeader(vector<string> *header);
void getRecordData(RecordArray *rec);
string getJsonData();
void setRtpThreadNum();
Expand Down Expand Up @@ -2797,6 +2811,7 @@ class Call : public CallStructs, public Call_abstract {
inline int rtp_size() {
return(ssrc_n);
}
string get_rtp_streams_info_json();

inline bool existsSrtp() {
return(exists_srtp);
Expand Down
61 changes: 61 additions & 0 deletions manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ int Mgmt_getactivesniffers(Mgmt_params *params);
int Mgmt_readaudio(Mgmt_params *params);
int Mgmt_listen(Mgmt_params *params);
int Mgmt_listen_stop(Mgmt_params *params);
int Mgmt_active_call_info(Mgmt_params *params);
int Mgmt_options_qualify_refresh(Mgmt_params *params);
int Mgmt_send_call_info_refresh(Mgmt_params *params);
int Mgmt_fraud_refresh(Mgmt_params *params);
Expand Down Expand Up @@ -551,6 +552,7 @@ int (* MgmtFuncArray[])(Mgmt_params *params) = {
Mgmt_readaudio,
Mgmt_listen,
Mgmt_listen_stop,
Mgmt_active_call_info,
Mgmt_options_qualify_refresh,
Mgmt_send_call_info_refresh,
Mgmt_fraud_refresh,
Expand Down Expand Up @@ -3754,6 +3756,65 @@ int Mgmt_readaudio(Mgmt_params *params) {
return(rslt);
}

int Mgmt_active_call_info(Mgmt_params *params) {
if (params->task == params->mgmt_task_DoInit) {
params->registerCommand("active_call_info", "get ative call packet info");
return(0);
}
if(!calltable) {
return(-1);
}
int rslt = 0;
string error;
extern bool opt_active_call_info;
if(opt_active_call_info) {
long long callreference = 0;
string callreference_str;
bool zip = false;
char params_str[1000];
sscanf(params->buf, "active_call_info %[^\n\r]", params_str);
if(isJsonObject(params_str)) {
JsonItem jsonParams;
jsonParams.parse(params_str);
callreference_str = jsonParams.getValue("callreference");
string zip_str = jsonParams.getValue("zip");
zip = yesno(zip_str.c_str()) || is_true(zip_str.c_str());
} else {
callreference_str = params_str;
}
sscanf(callreference_str.c_str(), "%llu", &callreference);
if(!callreference) {
sscanf(callreference_str.c_str(), "%llx", &callreference);
}
params->zip = zip;
calltable->lock_calls_listMAP();
Call *call = calltable->find_by_reference(callreference, false);
if(call) {
JsonExport json_export;
json_export.addJson("call", call->getJsonData());
string sip_packets = call->branch_main()->get_sip_packets_info_json();
json_export.addJson("sip_packets", sip_packets);
string rtp_streams = call->get_rtp_streams_info_json();
json_export.addJson("rtp_streams", rtp_streams);
string json_rslt = json_export.getJson();
if(params->sendString(&json_rslt) == -1) {
rslt = -1;
}
} else {
error = "call not found";
}
calltable->unlock_calls_listMAP();
} else {
error = "active call info is disabled (option active_call_info)";
}
if(!error.empty()) {
if(params->sendString(&error) == -1) {
rslt = -1;
}
}
return(rslt);
}

int Mgmt_reload(Mgmt_params *params) {
if (params->task == params->mgmt_task_DoInit) {
params->registerCommand("reload", "voipmonitor's reload. The reloaded items: the capture rules for now");
Expand Down
29 changes: 21 additions & 8 deletions record_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,27 @@ void RecordArray::freeRecord() {
delete [] fields;
}

string RecordArray::getJson() {
string json = "[";
for(unsigned i = 0; i < max_fields; i++) {
if(i) {
json += ",";
string RecordArray::getJson(vector<string> *header) {
if(header) {
string json = "{";
for(unsigned i = 0; i < min((unsigned)header->size(), max_fields); i++) {
if(i) {
json += ",";
}
json += "\"" + (*header)[i] + "\":" +
fields[i].getJson();
}
json += "}";
return(json);
} else {
string json = "[";
for(unsigned i = 0; i < max_fields; i++) {
if(i) {
json += ",";
}
json += fields[i].getJson();
}
json += fields[i].getJson();
json += "]";
return(json);
}
json += "]";
return(json);
}
2 changes: 1 addition & 1 deletion record_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ struct RecordArray {
void free();
void freeFields();
void freeRecord();
string getJson();
string getJson(vector<string> *header = NULL);
bool operator == (const RecordArray& other) const {
return(fields[sortBy] == other.fields[sortBy] &&
(sortBy2 == -1 || fields[sortBy2] == other.fields[sortBy2]));
Expand Down
17 changes: 17 additions & 0 deletions rtp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3242,6 +3242,23 @@ bool RTP::channel_is_adaptive(struct ast_channel *channel) {
return(channel && channel->jitter_impl);
}

string RTP::getJson() {
JsonExport json;
json.add("src_ip", saddr.getString());
json.add("src_port", sport.getString());
json.add("dst_ip", daddr.getString());
json.add("dst_port", dport.getString());
json.add("time", first_packet_time_us);
json.add("time_last", last_packet_time_us);
json.add("ssrc", ssrc);
json.add("codec", codec);
json.add("received", stats.received);
json.add("lost", stats.lost);
json.add("jitter_avg", (double)stats.avgjitter);
json.add("jitter_max", (double)stats.maxjitter);
return(json.getJson());
}

#endif // not EXPERIMENTAL_LITE_RTP_MOD

extern "C" {
Expand Down
2 changes: 2 additions & 0 deletions rtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,8 @@ class RTP {
return(channel_is_adaptive(channel_record));
}

string getJson();

private:
/*
* Per-source state information
Expand Down
25 changes: 25 additions & 0 deletions sniff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ extern bool _save_sip_history;
extern bool _save_sip_history_request_types[1000];
extern bool _save_sip_history_all_requests;
extern bool _save_sip_history_all_responses;
extern bool opt_active_call_info;
extern int opt_rtpfromsdp_onlysip;
extern int opt_rtpfromsdp_onlysip_skinny;
extern int opt_t2_boost;
Expand Down Expand Up @@ -6099,6 +6100,30 @@ void process_packet_sip_call(packet_s_process *packetS) {
}
}
}
if(opt_active_call_info) {
char *sip_data = packetS->data_()+ packetS->sipDataOffset;
unsigned sip_data_len = packetS->sipDataLen;
char *endFirstSipLine = NULL;
for(int i = 0; i < 2; i++) {
char *sep = strnchr(sip_data, i == 0 ? '\r' : '\n', sip_data_len);
if(sep && (!endFirstSipLine || sep < endFirstSipLine)) {
endFirstSipLine = sep;
}
}
if(endFirstSipLine) {
Call::sSipPacketInfo *sipPacketInfo = new FILE_LINE(0) Call::sSipPacketInfo;
sipPacketInfo->time_us = packet_time_us;
sipPacketInfo->src.ip = packetS->saddr_();
sipPacketInfo->src.port = packetS->source_();
sipPacketInfo->dst.ip = packetS->daddr_();
sipPacketInfo->dst.port = packetS->dest_();
sipPacketInfo->sip_first_line = string(sip_data, endFirstSipLine - sip_data);
sipPacketInfo->sip_length = packetS->sipDataLen;
sipPacketInfo->packet_length = packetS->header_pt->len;
sipPacketInfo->cseq = packetS->cseq;
c_branch->SIPpacketInfoList.push_back(sipPacketInfo);
}
}

if(call && sipSendSocket && !opt_sip_send_before_packetbuffer) {
// send packet to socket if enabled
Expand Down
Loading

0 comments on commit 5a50a72

Please sign in to comment.