Files
openbts-2.8/SIP/SIPMessage.cpp
kurtis.heimerl 3d4ec90bd1 Fixes #734 in public, , as well as rearchitects a number of SIP
control flows. Basically, there was a small bug where I forgot to listen
 for an OK, which caused transactions to stick around too long and fuck
 everything up. That was quickly fixed, but my compulsion required me to
 reorganize the code to avoid such errors in the future. I implemented
 another new feature as well, we now respond with a 480 Temporarily
 Unavailable message (rather than cancel) when canceling an INCOMING call.
 The prior behavior was incorrect.

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3264 19bc5d8c-e614-43d4-8b26-e1612bc8e597
2012-03-05 03:53:57 +00:00

1109 lines
32 KiB
C++

/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ortp/ortp.h>
#include <osipparser2/sdp_message.h>
#include <osipparser2/osip_md5.h>
#include "SIPInterface.h"
#include "SIPUtility.h"
#include "SIPMessage.h"
using namespace std;
using namespace SIP;
#define DEBUG 1
#define MAX_VIA 10
osip_message_t * SIP::sip_register( const char * sip_username, short timeout, short wlocal_port, const char * local_ip, const char * proxy_ip, const char * from_tag, const char * via_branch, const char * call_id, int cseq) {
char local_port[10];
sprintf(local_port,"%i",wlocal_port);
// Message URI
osip_message_t * request;
osip_message_init(&request);
// FIXME -- Should use the "force_update" function.
request->message_property = 2; // buffer is not synchronized with object
request->sip_method = strdup("REGISTER");
osip_message_set_version(request, strdup("SIP/2.0"));
osip_uri_init(&request->req_uri);
osip_uri_set_host(request->req_uri, strdup(proxy_ip));
// VIA
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// VIA BRANCH
osip_via_set_branch(via, strdup(via_branch));
// MAX FORWARDS
osip_message_set_max_forwards(request, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
char * via_str;
osip_via_to_str(via, &via_str);
osip_message_set_via(request, via_str);
// FROM
osip_from_init(&request->from);
osip_from_set_displayname(request->from, strdup(sip_username));
// FROM TAG
osip_from_set_tag(request->from, strdup(from_tag));
osip_uri_init(&request->from->url);
osip_uri_set_host(request->from->url, strdup(proxy_ip));
osip_uri_set_username(request->from->url, strdup(sip_username));
// TO
osip_to_init(&request->to);
osip_to_set_displayname(request->to, strdup(sip_username));
osip_uri_init(&request->to->url);
osip_uri_set_host(request->to->url, strdup(proxy_ip));
osip_uri_set_username(request->to->url, strdup(sip_username));
// CALL ID
osip_call_id_init(&request->call_id);
osip_call_id_set_host(request->call_id, strdup(local_ip));
osip_call_id_set_number(request->call_id, strdup(call_id));
// CSEQ
osip_cseq_init(&request->cseq);
osip_cseq_set_method(request->cseq, strdup("REGISTER"));
char temp_buf[14];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(request->cseq, strdup(temp_buf));
// CONTACT
osip_contact_t * con;
osip_to_init(&con);
// CONTACT URI
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
osip_uri_set_port(con->url, strdup(local_port));
osip_uri_set_username(con->url, strdup(sip_username));
char numbuf[10];
sprintf(numbuf,"%d",timeout);
osip_contact_param_add(con, strdup("expires"), strdup(numbuf) );
// add contact
osip_list_add(&request->contacts, con, -1);
return request;
}
osip_message_t * SIP::sip_message( const char * dialed_number, const char * sip_username, short wlocal_port, const char * local_ip, const char * proxy_ip, const char * from_tag, const char * via_branch, const char * call_id, int cseq, const char* message, const char* content_type) {
char local_port[10];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * request;
osip_message_init(&request);
// FIXME -- Should use the "force_update" function.
request->message_property = 2;
// METHOD
request->sip_method = strdup("MESSAGE");
osip_message_set_version(request, strdup("SIP/2.0"));
// REQ.URI
osip_uri_init(&request->req_uri);
osip_uri_set_host(request->req_uri, strdup(proxy_ip));
osip_uri_set_username(request->req_uri, strdup(dialed_number));
// VIA
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
osip_via_set_branch(via, strdup(via_branch));
// MAX FORWARDS
osip_message_set_max_forwards(request, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// add via
osip_list_add(&request->vias, via, -1);
// FROM
osip_from_init(&request->from);
osip_from_set_displayname(request->from, strdup(sip_username));
osip_uri_init(&request->from->url);
osip_uri_set_host(request->from->url, strdup(proxy_ip));
osip_uri_set_username(request->from->url, strdup(sip_username));
// FROM TAG
osip_from_set_tag(request->from, strdup(from_tag));
// TO
osip_to_init(&request->to);
osip_to_set_displayname(request->to, strdup(dialed_number));
osip_uri_init(&request->to->url);
osip_uri_set_host(request->to->url, strdup(proxy_ip));
osip_uri_set_username(request->to->url, strdup(dialed_number));
// CALL ID
osip_call_id_init(&request->call_id);
osip_call_id_set_host(request->call_id, strdup(local_ip));
osip_call_id_set_number(request->call_id, strdup(call_id));
// CSEQ
osip_cseq_init(&request->cseq);
osip_cseq_set_method(request->cseq, strdup("MESSAGE"));
char temp_buf[21];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(request->cseq, strdup(temp_buf));
// Content-Type
if (content_type)
{
// Explicit value provided
osip_message_set_content_type(request, strdup(content_type));
} else {
// Default to text/plain
osip_message_set_content_type(request, strdup("text/plain"));
}
// Content-Length
sprintf(temp_buf,"%u",strlen(message));
osip_message_set_content_length(request, strdup(temp_buf));
// Payload.
osip_message_set_body(request,message,strlen(message));
return request;
}
osip_message_t * SIP::sip_invite5031(short rtp_port, const char * sip_username, short wlocal_port, const char * local_ip, const char* proxy_ip, const char * from_tag, const char * via_branch, const char * call_id, int cseq, unsigned codec)
{
char local_port[10];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * request;
osip_message_init(&request);
// FIXME -- Should use the "force_update" function.
request->message_property = 2;
request->sip_method = strdup("INVITE");
osip_message_set_version(request, strdup("SIP/2.0"));
osip_uri_init(&request->req_uri);
osip_uri_set_scheme(request->req_uri, strdup("sip"));
osip_uri_set_username(request->req_uri, strdup("sos"));
osip_uri_set_host(request->req_uri, strdup(proxy_ip));
// VIA
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// VIA BRANCH
osip_via_set_branch(via, strdup(via_branch));
// MAX FORWARDS
osip_message_set_max_forwards(request, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// add via
osip_list_add(&request->vias, via, -1);
// FROM
osip_from_init(&request->from);
osip_from_set_displayname(request->from, strdup(sip_username));
// FROM TAG
osip_from_set_tag(request->from, strdup(from_tag));
osip_uri_init(&request->from->url);
osip_uri_set_host(request->from->url, strdup(local_ip));
osip_uri_set_username(request->from->url, strdup(sip_username));
// TO
osip_to_init(&request->to);
osip_to_set_displayname(request->to, strdup(""));
osip_uri_init(&request->to->url);
osip_uri_set_host(request->to->url, strdup(gConfig.getStr("Emergency.Destination.Host").c_str()));
osip_uri_set_username(request->to->url, strdup(gConfig.getStr("Emergency.Destination.User").c_str()));
// If response, we need a to tag.
//osip_uri_param_t * to_tag_param;
//osip_from_get_tag(rsp->to, &to_tag_param);
// CALL ID
osip_call_id_init(&request->call_id);
osip_call_id_set_host(request->call_id, strdup(local_ip));
osip_call_id_set_number(request->call_id, strdup(call_id));
// CSEQ
osip_cseq_init(&request->cseq);
osip_cseq_set_method(request->cseq, strdup("INVITE"));
char temp_buf[14];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(request->cseq, strdup(temp_buf));
// CONTACT
osip_contact_t * con;
osip_to_init(&con);
// CONTACT URI
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
osip_uri_set_port(con->url, strdup(local_port));
osip_uri_set_username(con->url, strdup(sip_username));
osip_contact_param_add(con, strdup("expires"), strdup("3600") );
// add contact
osip_list_add(&request->contacts, con, -1);
sdp_message_t * sdp;
sdp_message_init(&sdp);
sdp_message_v_version_set(sdp, strdup("0"));
sdp_message_o_origin_set(sdp, strdup(sip_username), strdup("0"),
strdup("0"), strdup("IN"), strdup("IP4"), strdup(local_ip));
sdp_message_s_name_set(sdp, strdup("Talk Time"));
sdp_message_t_time_descr_add(sdp, strdup("0"), strdup("0") );
sprintf(temp_buf,"%i",rtp_port);
sdp_message_m_media_add(sdp, strdup("audio"),
strdup(temp_buf), NULL, strdup("RTP/AVP"));
sdp_message_c_connection_add
(sdp, 0, strdup("IN"), strdup("IP4"), strdup(local_ip),NULL, NULL);
// FIXME -- This should also be inside the switch?
sdp_message_m_payload_add(sdp,0,strdup("3"));
switch (codec) {
case RTPuLaw:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("0 PCMU/8000"));
break;
case RTPGSM610:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("3 GSM/8000"));
break;
default: assert(0);
};
/*
* We construct a sdp_message_t, turn it into a string, and then treat it
* like an osip_body_t. This works, and perhaps is how it is supposed to
* be done, but in any case we're going to have to do the extra processing
* to turn it into a string first.
*/
char * sdp_str;
sdp_message_to_str(sdp, &sdp_str);
osip_message_set_body(request, sdp_str, strlen(sdp_str));
osip_free(sdp_str);
osip_message_set_content_type(request, strdup("application/sdp"));
return request;
}
osip_message_t * SIP::sip_invite( const char * dialed_number, short rtp_port, const char * sip_username, short wlocal_port, const char * local_ip, const char * proxy_ip, const char * from_tag, const char * via_branch, const char * call_id, int cseq, unsigned codec) {
char local_port[10];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * request;
osip_message_init(&request);
// FIXME -- Should use the "force_update" function.
request->message_property = 2;
request->sip_method = strdup("INVITE");
osip_message_set_version(request, strdup("SIP/2.0"));
osip_uri_init(&request->req_uri);
osip_uri_set_host(request->req_uri, strdup(proxy_ip));
osip_uri_set_username(request->req_uri, strdup(dialed_number));
// VIA
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// VIA BRANCH
osip_via_set_branch(via, strdup(via_branch));
// MAX FORWARDS
osip_message_set_max_forwards(request, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// add via
osip_list_add(&request->vias, via, -1);
// FROM
osip_from_init(&request->from);
osip_from_set_displayname(request->from, strdup(sip_username));
// FROM TAG
osip_from_set_tag(request->from, strdup(from_tag));
osip_uri_init(&request->from->url);
osip_uri_set_host(request->from->url, strdup(proxy_ip));
osip_uri_set_username(request->from->url, strdup(sip_username));
// TO
osip_to_init(&request->to);
osip_to_set_displayname(request->to, strdup(""));
osip_uri_init(&request->to->url);
osip_uri_set_host(request->to->url, strdup(proxy_ip));
osip_uri_set_username(request->to->url, strdup(dialed_number));
// If response, we need a to tag.
//osip_uri_param_t * to_tag_param;
//osip_from_get_tag(rsp->to, &to_tag_param);
// CALL ID
osip_call_id_init(&request->call_id);
osip_call_id_set_host(request->call_id, strdup(local_ip));
osip_call_id_set_number(request->call_id, strdup(call_id));
// CSEQ
osip_cseq_init(&request->cseq);
osip_cseq_set_method(request->cseq, strdup("INVITE"));
char temp_buf[14];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(request->cseq, strdup(temp_buf));
// CONTACT
osip_contact_t * con;
osip_to_init(&con);
// CONTACT URI
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
osip_uri_set_port(con->url, strdup(local_port));
osip_uri_set_username(con->url, strdup(sip_username));
osip_contact_param_add(con, strdup("expires"), strdup("3600") );
// add contact
osip_list_add(&request->contacts, con, -1);
sdp_message_t * sdp;
sdp_message_init(&sdp);
sdp_message_v_version_set(sdp, strdup("0"));
sdp_message_o_origin_set(sdp, strdup(sip_username), strdup("0"),
strdup("0"), strdup("IN"), strdup("IP4"), strdup(local_ip));
sdp_message_s_name_set(sdp, strdup("Talk Time"));
sdp_message_t_time_descr_add(sdp, strdup("0"), strdup("0") );
sprintf(temp_buf,"%i",rtp_port);
sdp_message_m_media_add(sdp, strdup("audio"),
strdup(temp_buf), NULL, strdup("RTP/AVP"));
sdp_message_c_connection_add
(sdp, 0, strdup("IN"), strdup("IP4"), strdup(local_ip),NULL, NULL);
// FIXME -- This should also be inside the switch?
sdp_message_m_payload_add(sdp,0,strdup("3"));
switch (codec) {
case RTPuLaw:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("0 PCMU/8000"));
break;
case RTPGSM610:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("3 GSM/8000"));
break;
default: assert(0);
};
/*
* We construct a sdp_message_t, turn it into a string, and then treat it
* like an osip_body_t. This works, and perhaps is how it is supposed to
* be done, but in any case we're going to have to do the extra processing
* to turn it into a string first.
*/
char * sdp_str;
sdp_message_to_str(sdp, &sdp_str);
osip_message_set_body(request, sdp_str, strlen(sdp_str));
osip_free(sdp_str);
osip_message_set_content_type(request, strdup("application/sdp"));
return request;
}
// Take the authorization produced by an earlier invite message.
osip_message_t * SIP::sip_ack(const char * req_uri, const char * dialed_number, const char * sip_username, short wlocal_port, const char * local_ip, const char * proxy_ip, const osip_from_t *from_header, const osip_to_t* to_header, const char * via_branch, const osip_call_id_t* call_id_header, int cseq) {
char local_port[20];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * ack;
osip_message_init(&ack);
// FIXME -- Should use the "force_update" function.
ack->message_property = 2;
ack->sip_method = strdup("ACK");
osip_message_set_version(ack, strdup("SIP/2.0"));
osip_uri_init(&ack->req_uri);
// If we are Acking a BYE message then need to
// set the req_uri to the owner address thats taken from the 200 Okay.
if( req_uri == NULL ) {
osip_uri_set_host(ack->req_uri, strdup(proxy_ip));
} else {
osip_uri_set_host(ack->req_uri, strdup(req_uri));
}
osip_uri_set_username(ack->req_uri, strdup(dialed_number));
// Via
osip_via_t *via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// VIA BRANCH
osip_via_set_branch(via, strdup(via_branch));
// MAX FORWARDS
osip_message_set_max_forwards(ack, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// add via
osip_list_add(&ack->vias, via, -1);
osip_from_init(&ack->from);
osip_from_set_displayname(ack->from, strdup(sip_username));
osip_uri_init(&ack->from->url);
osip_uri_set_host(ack->from->url, strdup(proxy_ip));
osip_uri_set_username(ack->from->url, strdup(sip_username));
// from/to headers
osip_from_clone(from_header, &ack->from);
osip_to_clone(to_header, &ack->to);
// call id
osip_call_id_clone(call_id_header, &ack->call_id);
osip_cseq_init(&ack->cseq);
osip_cseq_set_method(ack->cseq, strdup("ACK"));
char temp_buf[14];
sprintf(temp_buf, "%i", cseq);
osip_cseq_set_number(ack->cseq, strdup(temp_buf));
return ack;
}
osip_message_t * SIP::sip_bye(const char * req_uri, const char * dialed_number, const char * sip_username, short wlocal_port, const char * local_ip, const char * proxy_ip, short wproxy_port, const osip_from_t* from_header, const osip_to_t* to_header, const char * via_branch, const osip_call_id_t* call_id_header, int cseq) {
// FIXME -- We really need some NULL-value error checking in here.
char local_port[10];
sprintf(local_port,"%i",wlocal_port);
char proxy_port[10];
sprintf(proxy_port,"%i",wproxy_port);
osip_message_t * bye;
osip_message_init(&bye);
// FIXME -- Should use the "force_update" function.
bye->message_property = 2;
bye->sip_method = strdup("BYE");
osip_message_set_version(bye, strdup("SIP/2.0"));
//char o_addr[30];
//get_owner_ip(okay, o_addr);
osip_uri_init(&bye->req_uri);
osip_uri_set_host(bye->req_uri, strdup(req_uri));
osip_uri_set_username(bye->req_uri, strdup(dialed_number));
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// via branch + max forwards
osip_via_set_branch(via, strdup(via_branch));
osip_message_set_max_forwards(bye, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// add via
osip_list_add(&bye->vias, via, -1);
// from/to header
osip_from_clone(from_header, &bye->from);
osip_to_clone(to_header, &bye->to);
// Call Id Header
osip_call_id_clone(call_id_header, &bye->call_id);
// Cseq Number
osip_cseq_init(&bye->cseq);
osip_cseq_set_method(bye->cseq, strdup("BYE"));
char temp_buf[12];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(bye->cseq, strdup(temp_buf));
// Contact
osip_contact_t * contact;
osip_contact_init(&contact);
osip_contact_set_displayname(contact, strdup(sip_username) );
osip_uri_init(&contact->url);
osip_uri_set_host(contact->url, strdup(local_ip));
osip_uri_set_username(contact->url, strdup(sip_username));
osip_uri_set_port(contact->url, strdup(local_port));
// add contact
osip_list_add(&bye->contacts, contact, -1);
return bye;
}
osip_message_t * SIP::sip_temporarily_unavailable( osip_message_t * invite, const char * host, const char * username, short port)
{
if(invite==NULL){ return NULL;}
osip_message_t * unavail;
osip_message_init(&unavail);
//clone doesn't work -kurtis
// FIXME -- Should use the "force_update" function.
unavail->message_property = 2;
//header stuff first
unavail->status_code = 480;
unavail->reason_phrase = strdup("Temporarily Unavailable");
osip_message_set_version(unavail, strdup("SIP/2.0"));
char local_port[10];
sprintf(local_port, "%i", port);
//uri
osip_uri_init(&unavail->req_uri);
osip_uri_set_host(unavail->req_uri, strdup(host));
osip_uri_set_username(unavail->req_uri, strdup(username));
osip_uri_set_port(unavail->req_uri, strdup(local_port));
//via
osip_via_t * via;
char * via_str;
osip_message_get_via(invite, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(unavail, via_str);
osip_free(via_str);
// MAX FORWARDS
osip_message_set_max_forwards(unavail, strdup(gConfig.getStr("SIP.MaxForwards").c_str()));
// from/to header
osip_from_clone(invite->from, &unavail->from);
osip_to_clone(invite->to, &unavail->to);
//contact
osip_contact_t * cont;
char * cont_str;
osip_message_get_contact(invite, 0, &cont);
osip_contact_to_str(cont, &cont_str);
osip_message_set_contact(unavail, cont_str);
osip_free(cont_str);
// Get Call-ID.
osip_call_id_clone(invite->call_id, &unavail->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(invite);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(unavail, cseq_str);
osip_free(cseq_str);
return unavail;
}
/* Cancel a previously sent invite */
osip_message_t * SIP::sip_cancel( osip_message_t * invite, const char * host, const char * username, short port)
{
if(invite==NULL){ return NULL;}
osip_message_t * cancel;
osip_message_init(&cancel);
//clone doesn't work -kurtis
//osip_message_clone(invite, &cancel);
// FIXME -- Should use the "force_update" function.
cancel->message_property = 2;
//header stuff first
cancel->sip_method = strdup("CANCEL");
osip_message_set_version(cancel, strdup("SIP/2.0"));
char local_port[10];
sprintf(local_port, "%i", port);
//uri
osip_uri_init(&cancel->req_uri);
osip_uri_set_host(cancel->req_uri, strdup(host));
osip_uri_set_username(cancel->req_uri, strdup(username));
osip_uri_set_port(cancel->req_uri, strdup(local_port));
//via
osip_via_t * via;
char * via_str;
osip_message_get_via(invite, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(cancel, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(invite->from, &cancel->from);
osip_to_clone(invite->to, &cancel->to);
//contact
osip_contact_t * cont;
char * cont_str;
osip_message_get_contact(invite, 0, &cont);
osip_contact_to_str(cont, &cont_str);
osip_message_set_contact(cancel, cont_str);
osip_free(cont_str);
// Get Call-ID.
osip_call_id_clone(invite->call_id, &cancel->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(invite);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(cancel, cseq_str);
osip_free(cseq_str);
//update message type
osip_cseq_set_method(cancel->cseq, strdup("CANCEL"));
return cancel;
}
osip_message_t * SIP::sip_okay_sdp( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port, short rtp_port, unsigned audio_codec)
{
// Check for consistency.
if(inv==NULL){ return NULL;}
char local_port[10];
sprintf(local_port, "%i", wlocal_port);
// k used for error conditions on various osip operations.
osip_message_t * okay;
osip_message_init(&okay);
// FIXME -- Should use the "force_update" function.
okay->message_property = 2;
// Set Header stuff.
okay->status_code = 200;
okay->reason_phrase = strdup("OK");
osip_message_set_version(okay, strdup("SIP/2.0"));
osip_uri_init(&okay->req_uri);
// Get Record Route.
// FIXME -- Should use _clone() routines.
osip_record_route_t * rr;
char * rr_str;
osip_message_get_record_route(inv, 0, &rr);
osip_record_route_to_str(rr, &rr_str);
osip_message_set_record_route(okay, rr_str);
osip_free(rr_str);
// SIP Okay needs to repeat the Via tags from the INVITE Message.
osip_via_t * via;
char * via_str;
osip_message_get_via(inv, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(okay, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(inv->from, &okay->from);
osip_to_clone(inv->to, &okay->to);
// CONTACT URI
osip_contact_t * con;
osip_to_init(&con);
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
osip_uri_set_port(con->url, strdup(local_port));
osip_uri_set_username(con->url, strdup(sip_username));
osip_contact_param_add(con, strdup("expires"), strdup("3600") );
// add contact
osip_list_add(&okay->contacts, con, -1);
// Get Call-ID.
osip_call_id_clone(inv->call_id, &okay->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(inv);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(okay, cseq_str);
osip_free(cseq_str);
// Session Description Protocol.
sdp_message_t * sdp;
sdp_message_init(&sdp);
sdp_message_v_version_set(sdp, strdup("0"));
sdp_message_o_origin_set(sdp, strdup(sip_username), strdup("0"),
strdup("0"), strdup("IN"), strdup("IP4"), strdup(local_ip));
sdp_message_s_name_set(sdp, strdup("Talk Time"));
sdp_message_t_time_descr_add(sdp, strdup("0"), strdup("0") );
char temp_buf[10];
sprintf(temp_buf,"%i", rtp_port);
sdp_message_m_media_add(sdp, strdup("audio"),
strdup(temp_buf), NULL, strdup("RTP/AVP"));
sdp_message_c_connection_add
(sdp, 0, strdup("IN"), strdup("IP4"), strdup(local_ip),NULL, NULL);
// FIXME -- This should also be inside the switch?
sdp_message_m_payload_add(sdp,0,strdup("3"));
switch (audio_codec) {
case RTPuLaw:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("0 PCMU/8000"));
break;
case RTPGSM610:
sdp_message_a_attribute_add(sdp,0,strdup("rtpmap"),strdup("3 GSM/8000"));
break;
default: assert(0);
};
char * sdp_str;
sdp_message_to_str(sdp, &sdp_str);
osip_message_set_body(okay, sdp_str, strlen(sdp_str));
osip_free(sdp_str);
osip_message_set_content_type(okay, strdup("application/sdp"));
return okay;
}
osip_message_t * SIP::sip_b_okay( osip_message_t * bye )
{
// Check for consistency.
if(bye==NULL){ return NULL;}
// k used for error conditions on various osip operations.
osip_message_t * okay;
osip_message_init(&okay);
// FIXME -- Should use the "force_update" function.
okay->message_property = 2;
// Set Header stuff.
okay->status_code = 200;
okay->reason_phrase = strdup("OK");
osip_message_set_version(okay, strdup("SIP/2.0"));
osip_uri_init(&okay->req_uri);
// SIP Okay needs to repeat the Via tags from the BYE Message.
osip_via_t * via;
char * via_str;
osip_message_get_via(bye, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(okay, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(bye->from, &okay->from);
osip_to_clone(bye->to, &okay->to);
// Get Call-ID.
osip_call_id_clone(bye->call_id, &okay->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(bye);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(okay, cseq_str);
osip_free(cseq_str);
return okay;
}
osip_message_t * SIP::sip_trying( osip_message_t * invite, const char * sip_username, const char * local_ip )
{
osip_message_t * trying;
osip_message_init(&trying);
// FIXME -- Should use the "force_update" function.
trying->message_property = 2;
// Set Header stuff.
trying->status_code = 100;
trying->reason_phrase = strdup("Trying");
osip_message_set_version(trying, strdup("SIP/2.0"));
osip_uri_init(&invite->req_uri); // FIXME? -- Invite rather than trying?
// Get Record Route.
osip_via_t * via;
char * via_str;
osip_message_get_via(invite, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(trying, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(invite->from, &trying->from);
osip_to_clone(invite->to, &trying->to);
// Get Call-ID.
osip_call_id_clone(invite->call_id, &trying->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(invite);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(trying, cseq_str);
osip_free(cseq_str);
// CONTACT URI
osip_contact_t * con;
osip_to_init(&con);
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
//osip_uri_set_port(con->url, strdup(local_port)); // FIXME ??
osip_uri_set_username(con->url, strdup(sip_username));
// add contact
osip_list_add(&trying->contacts, con, -1);
return trying;
}
osip_message_t * SIP::sip_ringing( osip_message_t * invite, const char * sip_username, const char *local_ip)
{
osip_message_t * ringing;
osip_message_init(&ringing);
// FIXME -- Should use the "force_update" function.
ringing->message_property = 2;
// Set Header stuff.
ringing->status_code = 180;
ringing->reason_phrase = strdup("Ringing");
osip_message_set_version(ringing, strdup("SIP/2.0"));
//osip_uri_init(&invite->req_uri);
// Get Record Route.
osip_via_t * via;
char * via_str;
osip_message_get_via(invite, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(ringing, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(invite->from, &ringing->from);
osip_to_clone(invite->to, &ringing->to);
// Get Call-ID.
osip_call_id_clone(invite->call_id, &ringing->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(invite);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(ringing, cseq_str);
osip_free(cseq_str);
// CONTACT URI
osip_contact_t * con;
osip_to_init(&con);
osip_uri_init(&con->url);
osip_uri_set_host(con->url, strdup(local_ip));
osip_uri_set_username(con->url, strdup(sip_username));
// add contact
osip_list_add(&ringing->contacts, con, -1);
return ringing;
}
osip_message_t * SIP::sip_okay( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port)
{
// Check for consistency.
if(inv==NULL){ return NULL;}
char local_port[20];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * okay;
osip_message_init(&okay);
// FIXME -- Should use the "force_update" function.
okay->message_property = 2;
// FIXME -- Do we really need all of this string conversion?
// Set Header stuff.
okay->status_code = 200;
okay->reason_phrase = strdup("OK");
osip_message_set_version(okay, strdup("SIP/2.0"));
osip_uri_init(&okay->req_uri);
// Get Record Route.
osip_record_route_t * rr;
char * rr_str;
osip_message_get_record_route(inv, 0, &rr);
osip_record_route_to_str(rr, &rr_str);
osip_message_set_record_route(okay, rr_str);
osip_free(rr_str);
// SIP Okay needs to repeat the Via tags from the INVITE Message.
// osip_via_clone(inv->via, &okay->via);
osip_via_t * via;
char * via_str;
osip_message_get_via(inv, 0, &via);
osip_via_to_str(via, &via_str);
osip_message_set_via(okay, via_str);
osip_free(via_str);
// from/to header
osip_from_clone(inv->from, &okay->from);
osip_to_clone(inv->to, &okay->to);
// Get Call-ID.
osip_call_id_clone(inv->call_id, &okay->call_id);
// Get Cseq.
osip_cseq_t * cseq;
char * cseq_str;
cseq = osip_message_get_cseq(inv);
osip_cseq_to_str(cseq ,&cseq_str);
osip_message_set_cseq(okay, cseq_str);
osip_free(cseq_str);
return okay;
}
osip_message_t * SIP::sip_info(unsigned info, const char *dialed_number, short rtp_port, const char * sip_username, short wlocal_port, const char * local_ip, const char * proxy_ip, const char * from_tag, const char * via_branch, const osip_call_id_t *call_id_header, int cseq) {
char local_port[10];
sprintf(local_port, "%i", wlocal_port);
osip_message_t * request;
osip_message_init(&request);
// FIXME -- Should use the "force_update" function.
request->message_property = 2;
request->sip_method = strdup("INFO");
osip_message_set_version(request, strdup("SIP/2.0"));
osip_uri_init(&request->req_uri);
osip_uri_set_host(request->req_uri, strdup(proxy_ip));
osip_uri_set_username(request->req_uri, strdup(dialed_number));
// VIA
osip_via_t * via;
osip_via_init(&via);
via_set_version(via, strdup("2.0"));
via_set_protocol(via, strdup("UDP"));
via_set_host(via, strdup(local_ip));
via_set_port(via, strdup(local_port));
// VIA BRANCH
osip_via_set_branch(via, strdup(via_branch));
// add via
osip_list_add(&request->vias, via, -1);
// FROM
osip_from_init(&request->from);
osip_from_set_displayname(request->from, strdup(sip_username));
// FROM TAG
osip_from_set_tag(request->from, strdup(from_tag));
osip_uri_init(&request->from->url);
osip_uri_set_host(request->from->url, strdup(proxy_ip));
osip_uri_set_username(request->from->url, strdup(sip_username));
// TO
osip_to_init(&request->to);
osip_to_set_displayname(request->to, strdup(""));
osip_uri_init(&request->to->url);
osip_uri_set_host(request->to->url, strdup(proxy_ip));
osip_uri_set_username(request->to->url, strdup(dialed_number));
// CALL ID
osip_call_id_clone(call_id_header, &request->call_id);
// CSEQ
osip_cseq_init(&request->cseq);
osip_cseq_set_method(request->cseq, strdup("INFO"));
char temp_buf[21];
sprintf(temp_buf,"%i",cseq);
osip_cseq_set_number(request->cseq, strdup(temp_buf));
osip_message_set_content_type(request, strdup("application/dtmf-relay"));
char message[31];
// FIXME -- This duration should probably come from a config file.
switch (info) {
case 11:
snprintf(message,sizeof(message),"Signal=*\nDuration=200");
break;
case 12:
snprintf(message,sizeof(message),"Signal=#\nDuration=200");
break;
default:
snprintf(message,sizeof(message),"Signal=%i\nDuration=200",info);
}
sprintf(temp_buf,"%lu",strlen(message));
osip_message_set_content_length(request, strdup(temp_buf));
// Payload.
osip_message_set_body(request,message,strlen(message));
return request;
}
// vim: ts=4 sw=4