const char * msg_get_attribute(sip_msg_t *msg, int id, char *value) { sdp_media_t *media; char *ar; switch (id) { case SIP_ATTR_SRC: sprintf(value, "%s:%u", msg->packet->ip_src, msg->packet->sport); break; case SIP_ATTR_DST: sprintf(value, "%s:%u", msg->packet->ip_dst, msg->packet->dport); break; case SIP_ATTR_METHOD: if (sip_method_str(msg->reqresp)) { sprintf(value, "%s", sip_method_str(msg->reqresp)); } else { sip_get_response_str(msg, value); } break; case SIP_ATTR_SIPFROM: sprintf(value, "%s", msg->sip_from); break; case SIP_ATTR_SIPTO: sprintf(value, "%s", msg->sip_to); break; case SIP_ATTR_SIPFROMUSER: sprintf(value, "%s", msg->sip_from); if ((ar = strchr(value, '@'))) *ar = '\0'; break; case SIP_ATTR_SIPTOUSER: sprintf(value, "%s", msg->sip_to); if ((ar = strchr(value, '@'))) *ar = '\0'; break; case SIP_ATTR_DATE: timeval_to_date(msg_get_time(msg), value); break; case SIP_ATTR_TIME: timeval_to_time(msg_get_time(msg), value); break; case SIP_ATTR_SDP_ADDRESS: if ((media = vector_first(msg->medias))) sprintf(value, "%s", media_get_address(media)); break; case SIP_ATTR_SDP_PORT: if ((media = vector_first(msg->medias))) sprintf(value, "%d", media_get_port(media)); break; default: fprintf(stderr, "Unhandled attribute %s (%d)\n", sip_attr_get_name(id), id); abort(); break; } return strlen(value) ? value : NULL; }
int msg_is_older(sip_msg_t *one, sip_msg_t *two) { // Yes, you are older than nothing if (!two) return 1; // Otherwise return timeval_is_older(msg_get_time(one), msg_get_time(two)); }
const char * call_get_attribute(sip_call_t *call, enum sip_attr_id id, char *value) { sip_msg_t *first, *last; if (!call) return NULL; switch (id) { case SIP_ATTR_CALLINDEX: sprintf(value, "%d", call->index); break; case SIP_ATTR_CALLID: sprintf(value, "%s", call->callid); break; case SIP_ATTR_XCALLID: sprintf(value, "%s", call->xcallid); break; case SIP_ATTR_MSGCNT: sprintf(value, "%d", vector_count(call->msgs)); break; case SIP_ATTR_CALLSTATE: sprintf(value, "%s", call_state_to_str(call->state)); break; case SIP_ATTR_TRANSPORT: first = vector_first(call->msgs); sprintf(value, "%s", sip_transport_str(first->packet->type)); break; case SIP_ATTR_CONVDUR: timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(call->cend_msg), value); break; case SIP_ATTR_TOTALDUR: first = vector_first(call->msgs); last = vector_last(call->msgs); timeval_to_duration(msg_get_time(first), msg_get_time(last), value); break; default: return msg_get_attribute(vector_first(call->msgs), id, value); break; } return strlen(value) ? value : NULL; }
void call_update_state(sip_call_t *call, sip_msg_t *msg) { const char *callstate; char dur[20]; int reqresp; sip_msg_t *first; if (!call_is_invite(call)) return; // Get the first message in the call first = vector_first(call->msgs); // Get current message Method / Response Code reqresp = msg->reqresp; // If this message is actually a call, get its current state if ((callstate = call_get_attribute(call, SIP_ATTR_CALLSTATE))) { if (!strcmp(callstate, SIP_CALLSTATE_CALLSETUP)) { if (reqresp == 200) { // Alice and Bob are talking call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_INCALL); // Store the timestap where call has started call->active = 1; call->cstart_msg = msg; } else if (reqresp == SIP_METHOD_CANCEL) { // Alice is not in the mood call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CANCELLED); // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); call->active = 0; } else if (reqresp > 400) { // Bob is not in the mood call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_REJECTED); // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); call->active = 0; } } else if (!strcmp(callstate, SIP_CALLSTATE_INCALL)) { if (reqresp == SIP_METHOD_BYE) { // Thanks for all the fish! call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_COMPLETED); // Store Conversation duration call_set_attribute(call, SIP_ATTR_CONVDUR, timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(msg), dur)); call->active = 0; } } else if (reqresp == SIP_METHOD_INVITE && strcmp(callstate, SIP_CALLSTATE_INCALL)) { // Call is being setup (after proper authentication) call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP); call->active = 1; } else { // Store total call duration call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur)); } } else { // This is actually a call if (reqresp == SIP_METHOD_INVITE) { call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP); call->active = 1; } } }