Beispiel #1
0
void
call_update_state(sip_call_t *call, sip_msg_t *msg)
{
    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 (call->state) {
        if (call->state == SIP_CALLSTATE_CALLSETUP) {
            if (reqresp == SIP_METHOD_ACK && call->invitecseq == msg->cseq) {
                // Alice and Bob are talking
                call->state = SIP_CALLSTATE_INCALL;
                call->cstart_msg = msg;
            } else if (reqresp == SIP_METHOD_CANCEL) {
                // Alice is not in the mood
                call->state = SIP_CALLSTATE_CANCELLED;
            } else if (reqresp > 400 && call->invitecseq == msg->cseq) {
                // Bob is not in the mood
                call->state = SIP_CALLSTATE_REJECTED;
            }
        } else if (call->state == SIP_CALLSTATE_INCALL) {
            if (reqresp == SIP_METHOD_BYE) {
                // Thanks for all the fish!
                call->state = SIP_CALLSTATE_COMPLETED;
                call->cend_msg = msg;
            }
        } else if (reqresp == SIP_METHOD_INVITE && call->state !=  SIP_CALLSTATE_INCALL) {
            // Call is being setup (after proper authentication)
            call->invitecseq = msg->cseq;
            call->state = SIP_CALLSTATE_CALLSETUP;
        }
    } else {
        // This is actually a call
        if (reqresp == SIP_METHOD_INVITE) {
            call->invitecseq = msg->cseq;
            call->state = SIP_CALLSTATE_CALLSETUP;
        }
    }
}
Beispiel #2
0
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;

}
Beispiel #3
0
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;
        }
    }
}