Skip to content
Snippets Groups Projects
Commit ae818746 authored by pierre-luc's avatar pierre-luc
Browse files

[#1810] Now checking SDP answer after 200 OK. Still need to implement full

event interruption: hangup() is executed but we must also inform the UI.
parent c92f34c1
No related branches found
No related tags found
No related merge requests found
......@@ -180,7 +180,6 @@ int Sdp::receiving_initial_offer (pjmedia_sdp_session* remote)
// pjmedia_sdp_neg_create_w_remote_offer with the remote offer, and by providing the local offer ( optional )
pj_status_t status;
pjmedia_sdp_neg_state state;
_debug ("Receiving initial offer\n");
......@@ -200,13 +199,61 @@ int Sdp::receiving_initial_offer (pjmedia_sdp_session* remote)
status = pjmedia_sdp_neg_create_w_remote_offer (_pool,
get_local_sdp_session(), remote, &_negociator);
state = pjmedia_sdp_neg_get_state (_negociator);
PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
return PJ_SUCCESS;
}
pj_status_t Sdp::check_incoming_sdp(pjsip_inv_session *inv, pjsip_rx_data *rdata)
{
static const pj_str_t str_application = { "application", 11 };
static const pj_str_t str_sdp = { "sdp", 3 };
pj_status_t status;
pjsip_msg * message;
pjmedia_sdp_session * remote_sdp;
message = rdata->msg_info.msg;
if (message->body == NULL) {
_debug("Empty message body\n");
return -1;
}
if (pj_stricmp(&message->body->content_type.type, &str_application) || pj_stricmp(&message->body->content_type.subtype, &str_sdp)) {
_debug("Incoming Message does not contain SDP\n");
return PJMEDIA_SDP_EINSDP;
}
// Parse the SDP body.
status = pjmedia_sdp_parse(rdata->tp_info.pool, (char*)message->body->data, message->body->len, &remote_sdp);
if (status == PJ_SUCCESS) {
status = pjmedia_sdp_validate(remote_sdp);
}
if (status != PJ_SUCCESS) {
_debug("SDP cannot be validated\n");
return PJMEDIA_SDP_EINSDP;
}
if (pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) {
// This is an answer
_debug("Got SDP answer %s\n", pjsip_rx_data_get_info(rdata));
status = pjmedia_sdp_neg_set_remote_answer(inv->pool, inv->neg, remote_sdp);
if (status != PJ_SUCCESS) {
_debug("An error occured while processing remote answer %s\n", pjsip_rx_data_get_info(rdata));
return PJMEDIA_SDP_EINSDP;
}
// Prefer our codecs to remote when possible
pjmedia_sdp_neg_set_prefer_remote_codec_order(inv->neg, 0);
status = pjmedia_sdp_neg_negotiate(inv->pool, inv->neg, 0);
_debug("Negotiation returned with status %d PJ_SUCCESS being %d\n", status, PJ_SUCCESS);
}
return status;
}
void Sdp::sdp_add_protocol (void)
{
this->_local_offer->origin.version = 0;
......@@ -298,7 +345,7 @@ void Sdp::clean_session_media()
_session_media.clear();
}
void Sdp::set_negociated_offer (const pjmedia_sdp_session *sdp)
void Sdp::set_negotiated_sdp (const pjmedia_sdp_session *sdp)
{
int nb_media, nb_codecs;
......
......@@ -25,6 +25,8 @@
#include <pjmedia/sdp_neg.h>
#include <pjsip/sip_transport.h>
#include <pjlib.h>
#include <pjsip_ua.h>
#include <pjmedia/errno.h>
#include <pj/pool.h>
#include <pj/assert.h>
......@@ -97,6 +99,17 @@ class Sdp {
*/
int receiving_initial_offer( pjmedia_sdp_session* remote );
/*
* On receiving a message, check if it contains SDP and negotiate. Should be used for
* SDP answer and offer but currently is only used for answer.
* SDP negociator instance with the remote offer.
*
* @param inv The the invitation
* @param rdata The remote data
*/
pj_status_t check_incoming_sdp(pjsip_inv_session *inv, pjsip_rx_data *rdata);
/*
* Remove all media in the session media vector.
*/
......@@ -138,7 +151,7 @@ class Sdp {
*
* @param sdp the negociated offer
*/
void set_negociated_offer( const pjmedia_sdp_session *sdp );
void set_negotiated_sdp ( const pjmedia_sdp_session *sdp );
/*
* Attribute the specified port to every medias provided
......
......@@ -503,7 +503,6 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
SIPCall* call = new SIPCall (id, Call::Outgoing, _pool);
if (call) {
account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (Manager::instance().getAccountFromCall (id)));
......@@ -520,7 +519,6 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
setCallAudioLocal (call, getLocalIPAddress(), useStun(), getStunServer());
try {
_debug ("CREATE NEW RTP SESSION FROM NEWOUTGOINGCALL\n");
_audiortp->createNewSession (call);
......@@ -528,9 +526,6 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
_debug ("Failed to create rtp thread from newOutGoingCall\n");
}
call->initRecFileName();
_debug ("Try to make a call to: %s with call ID: %s\n", toUrl.data(), id.data());
......@@ -560,8 +555,6 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
bool
SIPVoIPLink::answer (const CallID& id)
{
int i;
SIPCall *call;
pj_status_t status;
pjsip_tx_data *tdata;
......@@ -1415,7 +1408,6 @@ bool get_dns_server_addresses (std::vector<std::string> *servers)
nameservers.push_back (inet_ntoa (address));
}
//nameservers.push_back ("192.168.50.3");
*servers = nameservers;
return true;
......@@ -1427,8 +1419,6 @@ pj_status_t SIPVoIPLink::enable_dns_srv_resolver (pjsip_endpoint *endpt, pj_dns_
pj_status_t status;
pj_dns_resolver *resv;
std::vector <std::string> dns_servers;
pj_uint16_t port = 5353;
pjsip_resolver_t *res;
int scount, i;
// Create the DNS resolver instance
......@@ -1706,13 +1696,10 @@ int SIPVoIPLink::createUDPServer (void)
pj_sockaddr_in bound_addr;
pjsip_host_port a_name;
char tmpIP[32];
pj_sock_t sock;
// Init bound address to ANY
pj_memset (&bound_addr, 0, sizeof (bound_addr));
bound_addr.sin_addr.s_addr = pj_htonl (PJ_INADDR_ANY);
bound_addr.sin_port = pj_htons ( (pj_uint16_t) _localPort);
bound_addr.sin_family = PJ_AF_INET;
......@@ -1875,22 +1862,17 @@ void SIPVoIPLink::handle_reinvite (SIPCall *call)
}
}
/*******************************/
/* CALLBACKS IMPLEMENTATION */
/*******************************/
// This callback is called when the invite session state has changed
void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
{
_debug ("--------------------- call_on_state_changed --------------------- %i\n", inv->state);
SIPCall *call;
AccountID accId;
SIPVoIPLink *link;
pjsip_rx_data *rdata;
pj_status_t status;
/* Retrieve the call information */
call = reinterpret_cast<SIPCall*> (inv->mod_data[_mod_ua.id]);
......@@ -1900,7 +1882,7 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
//Retrieve the body message
rdata = e->body.tsx_state.src.rdata;
/* If this is an outgoing INVITE that was created because of
* REFER/transfer, send NOTIFY to transferer.
*/
......@@ -1961,84 +1943,104 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
}
}
}
} else {
return;
}
// The call is ringing - We need to handle this case only on outgoing call
if (inv->state == PJSIP_INV_STATE_EARLY && e->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) {
call->setConnectionState (Call::Ringing);
Manager::instance().peerRingingCall (call->getCallId());
}
// After 2xx is sent/received.
else if (inv->state == PJSIP_INV_STATE_CONNECTING) {
status = call->getLocalSDP()->check_incoming_sdp (inv, rdata);
if (status != PJ_SUCCESS) {
_debug("Failed to check_incoming_sdp in call_on_state_changed\n");
return;
}
}
// After we sent or received a ACK - The connection is established
else if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
// The call is ringing - We need to handle this case only on outgoing call
if (inv->state == PJSIP_INV_STATE_EARLY && e->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) {
call->setConnectionState (Call::Ringing);
Manager::instance().peerRingingCall (call->getCallId());
/* If the call is a direct IP-to-IP call */
if (call->getCallConfiguration () == Call::IPtoIP) {
link = SIPVoIPLink::instance ("");
} else {
accId = Manager::instance().getAccountFromCall (call->getCallId());
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId));
}
// We receive a ACK - The connection is established
else if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
if (link)
link->SIPCallAnswered (call, rdata);
}
else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
_debug ("------------------- Call disconnected ---------------------\n");
_debug ("State: %i, Disconnection cause: %i\n", inv->state, inv->cause);
/* If the call is a direct IP-to-IP call */
if (call->getCallConfiguration () == Call::IPtoIP) {
link = SIPVoIPLink::instance ("");
} else {
switch (inv->cause) {
/* The call terminates normally - BYE / CANCEL */
case PJSIP_SC_OK:
case PJSIP_SC_DECLINE:
case PJSIP_SC_REQUEST_TERMINATED:
accId = Manager::instance().getAccountFromCall (call->getCallId());
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId));
}
if (link)
link->SIPCallAnswered (call, rdata);
}
else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
int count = 0;
_debug ("------------------- Call disconnected ---------------------\n");
_debug ("State: %i, Disconnection cause: %i\n", inv->state, inv->cause);
switch (inv->cause) {
/* The call terminates normally - BYE / CANCEL */
case PJSIP_SC_OK:
case PJSIP_SC_DECLINE:
case PJSIP_SC_REQUEST_TERMINATED:
accId = Manager::instance().getAccountFromCall (call->getCallId());
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId));
if (link) {
link->SIPCallClosed (call);
}
break;
if (link) {
link->SIPCallClosed (call);
}
/* The call connection failed */
break;
/* The call connection failed */
case PJSIP_SC_NOT_FOUND: /* peer not found */
case PJSIP_SC_REQUEST_TIMEOUT: /* request timeout */
case PJSIP_SC_NOT_ACCEPTABLE_HERE: /* no compatible codecs */
case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE:
case PJSIP_SC_UNSUPPORTED_MEDIA_TYPE:
case PJSIP_SC_UNAUTHORIZED:
case PJSIP_SC_REQUEST_PENDING:
accId = Manager::instance().getAccountFromCall (call->getCallId());
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId));
case PJSIP_SC_NOT_FOUND: /* peer not found */
if (link) {
link->SIPCallServerFailure (call);
}
case PJSIP_SC_REQUEST_TIMEOUT: /* request timeout */
break;
default:
_debug ("sipvoiplink.cpp - line %d : Unhandled call state. This is probably a bug.\n", __LINE__);
break;
}
}
}
case PJSIP_SC_NOT_ACCEPTABLE_HERE: /* no compatible codecs */
int terminate_call_bad_sdp_answer(SIPCall * call, SIPVoIPLink * link)
{
pj_status_t status;
pjsip_tx_data *tdata = NULL;
status = pjsip_inv_end_session(call->getInvSession(), 488, NULL, &tdata);
case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE:
if (status != PJ_SUCCESS)
return false;
case PJSIP_SC_UNSUPPORTED_MEDIA_TYPE:
if (tdata == NULL)
return true;
case PJSIP_SC_UNAUTHORIZED:
status = pjsip_inv_send_msg (call->getInvSession(), tdata);
case PJSIP_SC_REQUEST_PENDING:
accId = Manager::instance().getAccountFromCall (call->getCallId());
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (accId));
if (status != PJ_SUCCESS)
return false;
if (link) {
link->SIPCallServerFailure (call);
}
call->getInvSession()->mod_data[getModId() ] = NULL;
break;
link->terminateOneCall (call->getCallId());
default:
_debug ("sipvoiplink.cpp - line %d : Unhandled call state. This is probably a bug.\n", __LINE__);
break;
}
}
}
link->removeCall (call->getCallId());
}
// This callback is called after SDP offer/answer session has completed.
void call_on_media_update (pjsip_inv_session *inv, pj_status_t status)
{
_debug ("--------------------- call_on_media_update --------------------- \n");
......@@ -2048,38 +2050,42 @@ void call_on_media_update (pjsip_inv_session *inv, pj_status_t status)
SIPVoIPLink * link = NULL;
SIPCall * call;
if (status != PJ_SUCCESS) {
_debug ("Error while negociating the offer\n");
return;
}
// Get the new sdp, result of the negociation
pjmedia_sdp_neg_get_active_local (inv->neg, &local_sdp);
pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
call = reinterpret_cast<SIPCall *> (inv->mod_data[getModId() ]);
if (!call) {
_debug ("Call declined by peer, SDP negociation stopped\n");
return;
}
// Clean the resulting sdp offer to create a new one (in case of a reinvite)
call->getLocalSDP()->clean_session_media();
// Set the fresh negociated one
call->getLocalSDP()->set_negociated_offer (local_sdp);
// Set remote ip / port
call->getLocalSDP()->set_media_transport_info_from_remote_sdp (remote_sdp);
link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink(AccountNULL));
if(link == NULL) {
_debug ("Failed to get sip link\n");
return;
}
if (status != PJ_SUCCESS) {
_debug ("Error while negotiating the offer\n");
//terminate_call_bad_sdp_answer(call, link);
link->hangup(call->getCallId());
return;
}
// Get the new sdp, result of the negotiation
pjmedia_sdp_neg_get_active_local (inv->neg, &local_sdp);
pjmedia_sdp_neg_get_active_remote (inv->neg, &remote_sdp);
// Clean the resulting sdp offer to create a new one (in case of a reinvite)
call->getLocalSDP()->clean_session_media();
// Set the fresh negotiated one, no matter if that was an offer or answer.
// The local sdp is updated in case of an answer, even if the remote sdp
// is kept internally.
call->getLocalSDP()->set_negotiated_sdp (local_sdp);
// Set remote ip / port
call->getLocalSDP()->set_media_transport_info_from_remote_sdp (remote_sdp);
try {
call->setAudioStart (true);
link->getAudioRtp()->start();
......@@ -2107,11 +2113,8 @@ void call_on_tsx_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_
void regc_cb (struct pjsip_regc_cbparam *param)
{
//AccountID *id = static_cast<AccountID *> (param->token);
SIPAccount *account;
//_debug("UserAgent: Account ID is %s, Register result: %d, Status: %d\n", id->data(), param->status, param->code);
account = static_cast<SIPAccount *> (param->token);
if (!account)
......@@ -2167,11 +2170,10 @@ void regc_cb (struct pjsip_regc_cbparam *param)
}
// Optional function to be called to process incoming request message.
pj_bool_t
mod_on_rx_request (pjsip_rx_data *rdata)
{
pj_status_t status;
pj_str_t reason;
unsigned options = 0;
......@@ -2325,7 +2327,6 @@ mod_on_rx_request (pjsip_rx_data *rdata)
get_remote_sdp_from_offer (rdata, &r_sdp);
// _debug("r_sdp = %s\n", r_sdp);
status = call->getLocalSDP()->receiving_initial_offer (r_sdp);
if (status!=PJ_SUCCESS) {
......@@ -2334,7 +2335,6 @@ mod_on_rx_request (pjsip_rx_data *rdata)
return false;
}
call->setConnectionState (Call::Progressing);
call->setPeerNumber (peerNumber);
......@@ -2364,7 +2364,6 @@ mod_on_rx_request (pjsip_rx_data *rdata)
return true;
}
// Specify media capability during invite session creation
status = pjsip_inv_create_uas (dialog, rdata, call->getLocalSDP()->get_local_sdp_session(), 0, &inv);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment