sip_msg_t * sip_load_message(const char *header, const char *payload) { sip_msg_t *msg; sip_call_t *call; char *callid; // Get the Call-ID of this message if (!(callid = sip_get_callid(payload))) { return NULL; } // Create a new message from this data if (!(msg = sip_msg_create(header, payload))) { return NULL; } // Find the call for this msg if (!(call = call_find_by_callid(callid))) { // Create the call if not found if (!(call = sip_call_create(callid))) { //@todo sip_msg_destroy(); return NULL; } } // Set message callid msg_set_attribute(msg, SIP_ATTR_CALLID, callid); // Add the message to the found/created call call_add_message(call, msg); // Return the loaded message return msg; }
/* * Validate some of the common headers */ boolean_t sip_check_common_headers(sip_conn_object_t conn_obj, _sip_msg_t *sip_msg) { int err; if (sip_get_to_uri_str((sip_msg_t)sip_msg, &err) == NULL) goto error; if (sip_get_from_uri_str((sip_msg_t)sip_msg, &err) == NULL) goto error; if (sip_get_callseq_num((sip_msg_t)sip_msg, &err) < 0) goto error; if (sip_get_callid((sip_msg_t)sip_msg, &err) == NULL) goto error; return (B_FALSE); error: sip_send_resp(conn_obj, sip_msg, SIP_BAD_REQUEST); return (B_TRUE); }
sip_msg_t * sip_check_packet(packet_t *packet) { sip_msg_t *msg; sip_call_t *call; char callid[1024], xcallid[1024]; address_t src, dst; u_char payload[MAX_SIP_PAYLOAD]; bool newcall = false; // Max SIP payload allowed if (packet->payload_len > MAX_SIP_PAYLOAD) return NULL; // Get Addresses from packet src = packet->src; dst = packet->dst; // Initialize local variables memset(callid, 0, sizeof(callid)); memset(xcallid, 0, sizeof(xcallid)); // Get payload from packet(s) memset(payload, 0, MAX_SIP_PAYLOAD); memcpy(payload, packet_payload(packet), packet_payloadlen(packet)); // Get the Call-ID of this message if (!sip_get_callid((const char*) payload, callid)) return NULL; // Create a new message from this data if (!(msg = msg_create((const char*) payload))) return NULL; // Get Method and request for the following checks // There is no need to parse all payload at this point // If no response or request code is found, this is not a SIP message if (!sip_get_msg_reqresp(msg, payload)) { // Deallocate message memory msg_destroy(msg); return NULL; } // Find the call for this msg if (!(call = sip_find_by_callid(callid))) { // Check if payload matches expression if (!sip_check_match_expression((const char*) payload)) goto skip_message; // User requested only INVITE starting dialogs if (calls.only_calls && msg->reqresp != SIP_METHOD_INVITE) goto skip_message; // Only create a new call if the first msg // is a request message in the following gorup if (calls.ignore_incomplete && msg->reqresp > SIP_METHOD_MESSAGE) goto skip_message; // Get the Call-ID of this message sip_get_xcallid((const char*) payload, xcallid); // Rotate call list if limit has been reached if (calls.limit == sip_calls_count()) sip_calls_rotate(); // Create the call if not found if (!(call = call_create(callid, xcallid))) goto skip_message; // Add this Call-Id to hash table htable_insert(calls.callids, call->callid, call); // Set call index call->index = ++calls.last_index; // Mark this as a new call newcall = true; } // At this point we know we're handling an interesting SIP Packet msg->packet = packet; // Always parse first call message if (call_msg_count(call) == 0) { // Parse SIP payload sip_parse_msg_payload(msg, payload); // If this call has X-Call-Id, append it to the parent call if (strlen(call->xcallid)) { call_add_xcall(sip_find_by_callid(call->xcallid), call); } } // Add the message to the call call_add_message(call, msg); if (call_is_invite(call)) { // Parse media data sip_parse_msg_media(msg, payload); // Update Call State call_update_state(call, msg); // Check if this call should be in active call list if (call_is_active(call)) { if (sip_call_is_active(call)) { vector_append(calls.active, call); } } else { if (sip_call_is_active(call)) { vector_remove(calls.active, call); } } } if (newcall) { // Append this call to the call list vector_append(calls.list, call); } // Mark the list as changed calls.changed = true; // Return the loaded message return msg; skip_message: // Deallocate message memory msg_destroy(msg); return NULL; }