diff --git a/src/sip.c b/src/sip.c index 5fd41ca..dde3fd1 100644 --- a/src/sip.c +++ b/src/sip.c @@ -172,6 +172,7 @@ sip_init(int limit, int only_calls, int no_incomplete) regcomp(&calls.reg_valid, "^([A-Z]+ [a-zA-Z]+:|SIP/2.0 [0-9]{3})", match_flags & ~REG_NEWLINE); regcomp(&calls.reg_cl, "^(Content-Length|l):[ ]*([0-9]+)\r$", match_flags); regcomp(&calls.reg_body, "\r\n\r\n(.*)", match_flags & ~REG_NEWLINE); + regcomp(&calls.reg_reason, "Reason:[ ]*[^\r]*;text=\"([^\r]+)\"", match_flags); } @@ -196,6 +197,7 @@ sip_deinit() regfree(&calls.reg_valid); regfree(&calls.reg_cl); regfree(&calls.reg_body); + regfree(&calls.reg_reason); } @@ -378,6 +380,8 @@ sip_check_packet(packet_t *packet) sip_parse_msg_media(msg, payload); // Update Call State call_update_state(call, msg); + // Parse extra fields + sip_parse_extra_headers(msg, payload); // Check if this call should be in active call list if (call_is_active(call)) { if (sip_call_is_active(call)) { @@ -676,6 +680,17 @@ sip_parse_msg_media(sip_msg_t *msg, const u_char *payload) #undef ADD_STREAM } +void +sip_parse_extra_headers(sip_msg_t *msg, const u_char *payload) +{ + regmatch_t pmatch[4]; + + // Reason + if (regexec(&calls.reg_reason, (const char *)payload, 2, pmatch, 0) == 0) { + msg->call->reasontxt = sng_malloc((int)pmatch[1].rm_eo - pmatch[1].rm_so + 1); + strncpy(msg->call->reasontxt, (const char *)payload + pmatch[1].rm_so, (int)pmatch[1].rm_eo - pmatch[1].rm_so); + } +} void sip_calls_clear() diff --git a/src/sip.h b/src/sip.h index 641ff94..58f2d83 100644 --- a/src/sip.h +++ b/src/sip.h @@ -157,6 +157,7 @@ struct sip_call_list { regex_t reg_valid; regex_t reg_cl; regex_t reg_body; + regex_t reg_reason; }; /** @@ -309,6 +310,18 @@ sip_find_by_index(int index); sip_call_t * sip_find_by_callid(const char *callid); + +/** + * @brief Parse extra fields only for dialogs strarting with invite + * + * @note This function assumes the msg is already part of a call + * + * @param msg SIP message structure + * @param payload SIP message payload + */ +void +sip_parse_extra_headers(sip_msg_t *msg, const u_char *payload); + /** * @brief Remove al calls * diff --git a/src/sip_attr.c b/src/sip_attr.c index 2c8ccd5..96e51dc 100644 --- a/src/sip_attr.c +++ b/src/sip_attr.c @@ -52,7 +52,8 @@ static sip_attr_hdr_t attrs[SIP_ATTR_COUNT] = { { SIP_ATTR_MSGCNT, "msgcnt", "Msgs", "Message Count", 5 }, { SIP_ATTR_CALLSTATE, "state", NULL, "Call State", 10, sip_attr_color_state }, { SIP_ATTR_CONVDUR, "convdur", "ConvDur", "Conversation Duration", 7 }, - { SIP_ATTR_TOTALDUR, "totaldur", "TotalDur", "Total Duration", 8 } + { SIP_ATTR_TOTALDUR, "totaldur", "TotalDur", "Total Duration", 8 }, + { SIP_ATTR_REASON_TXT, "reason", "Reason Text", "Reason Text", 25 }, }; sip_attr_hdr_t * diff --git a/src/sip_attr.h b/src/sip_attr.h index a4559c7..3d246a8 100644 --- a/src/sip_attr.h +++ b/src/sip_attr.h @@ -81,6 +81,8 @@ enum sip_attr_id { SIP_ATTR_CONVDUR, //! Total call duration SIP_ATTR_TOTALDUR, + //! Text from SIP Reason header + SIP_ATTR_REASON_TXT, //! SIP Attribute count SIP_ATTR_COUNT }; diff --git a/src/sip_call.c b/src/sip_call.c index 6b29c25..7aba5f1 100644 --- a/src/sip_call.c +++ b/src/sip_call.c @@ -83,6 +83,7 @@ call_destroy(sip_call_t *call) // Deallocate call memory sng_free(call->callid); sng_free(call->xcallid); + sng_free(call->reasontxt); sng_free(call); } @@ -277,6 +278,10 @@ call_get_attribute(sip_call_t *call, enum sip_attr_id id, char *value) last = vector_last(call->msgs); timeval_to_duration(msg_get_time(first), msg_get_time(last), value); break; + case SIP_ATTR_REASON_TXT: + if (call->reasontxt) + sprintf(value, "%s", call->reasontxt); + break; default: return msg_get_attribute(vector_first(call->msgs), id, value); break; diff --git a/src/sip_call.h b/src/sip_call.h index ac48c55..cbbc01c 100644 --- a/src/sip_call.h +++ b/src/sip_call.h @@ -72,6 +72,8 @@ struct sip_call { bool changed; //! Locked flag. Calls locked are never deleted bool locked; + //! Las reason text value for this call + char *reasontxt; //! List of calls with with this call as X-Call-Id vector_t *xcalls; //! Cseq from invite startint the call