Temporary commit - SDP modification

This commit is contained in:
Emmanuel Milou
2009-02-14 12:36:47 -05:00
parent 1aa6939e16
commit 777f7a4d8c
7 changed files with 557 additions and 397 deletions

View File

@ -29,6 +29,7 @@ sflphoned_SOURCES = \
call.cpp \
account.cpp \
sipcall.cpp \
sdp.cpp \
$(IAXSOURCES)
sflphoned_CXXFLAGS = \
@ -67,7 +68,8 @@ noinst_HEADERS = \
accountcreator.h \
sipvoiplink.h \
call.h \
sipcall.h
sipcall.h \
sdp.h
libsflphone_la_LIBADD = \
$(src)/libs/stund/libstun.la \

335
src/sdp.cpp Normal file
View File

@ -0,0 +1,335 @@
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
*
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "sdp.h"
#include "global.h"
#define _SENDRECV 0
#define _SENDONLY 1
#define _RECVONLY 2
Sdp::Sdp( pj_pool_t *pool ) : _localSDP(NULL)
, _negociator(NULL)
, _codecMap()
, _ipAddr("")
{
_pool = pool;
}
Sdp::~Sdp() {}
bool
Sdp::SIPCallInvite(pjsip_rx_data *rdata)
{
pj_status_t status;
// We retrieve the remote sdp offer in the rdata struct to begin the negociation
pjmedia_sdp_session* remote_sdp = getRemoteSDPFromRequest(rdata);
if (remote_sdp == 0) {
return false;
}
// Have to do some stuff here with the SDP
_localSDP = PJ_POOL_ZALLOC_T(_pool, pjmedia_sdp_session);
_localSDP->conn = PJ_POOL_ZALLOC_T(_pool, pjmedia_sdp_conn);
_localSDP->origin.version = 0;
sdpAddOrigin();
_localSDP->name = pj_str((char*)"sflphone");
sdpAddConnectionInfo();
_localSDP->time.start = _localSDP->time.stop = 0;
sdpAddMediaDescription();
status = pjmedia_sdp_validate( _localSDP );
if (status != PJ_SUCCESS) {
_debug("Can not generate valid local sdp\n");
return false;
}
_debug("Before create negociator!\n");
status = pjmedia_sdp_neg_create_w_remote_offer(_pool, _localSDP, remote_sdp, &_negociator);
if (status != PJ_SUCCESS) {
_debug("Can not create negociator\n");
return false;
}
_debug("After create negociator!\n");
pjmedia_sdp_media* remote_med = getRemoteMedia(remote_sdp);
if (remote_med == 0) {
_debug("SIP Failure: unable to get remote media\n");
return false;
}
_debug("Before set audio!\n");
if (!setRemoteAudioFromSDP(remote_sdp, remote_med)) {
_debug("SIP Failure: unable to set IP address and port from SDP\n");
return false;
}
_debug("Before set codec!\n");
if (!setAudioCodecFromSDP(remote_med)) {
_debug("SIP Failure: unable to set audio codecs from the remote SDP\n");
return false;
}
return true;
}
bool
Sdp::SIPCallAnsweredWithoutHold(pjsip_rx_data *rdata)
{
pjmedia_sdp_session* remote_sdp = getRemoteSDPFromRequest(rdata);
if (remote_sdp == NULL) {
_debug("SIP Failure: no remote sdp\n");
return false;
}
pjmedia_sdp_media* remote_med = getRemoteMedia(remote_sdp);
if (remote_med==NULL) {
return false;
}
_debug("Before set audio!\n");
if (!setRemoteAudioFromSDP(remote_sdp, remote_med)) {
_debug("SIP Failure: unable to set IP address and port from SDP\n");
return false;
}
_debug("Before set codec!\n");
if (!setAudioCodecFromSDP(remote_med)) {
_debug("SIP Failure: unable to set audio codecs from the remote SDP\n");
return false;
}
return true;
}
pjmedia_sdp_session*
Sdp::getRemoteSDPFromRequest(pjsip_rx_data *rdata)
{
pjmedia_sdp_session *sdp;
pjsip_msg *msg;
pjsip_msg_body *body;
msg = rdata->msg_info.msg;
body = msg->body;
pjmedia_sdp_parse( rdata->tp_info.pool, (char*)body->data, body->len, &sdp );
return sdp;
}
bool
Sdp::setRemoteAudioFromSDP(pjmedia_sdp_session* remote_sdp, pjmedia_sdp_media *remote_med)
{
std::string remoteIP(remote_sdp->conn->addr.ptr, remote_sdp->conn->addr.slen);
_debug(" Remote Audio IP: %s\n", remoteIP.data());
//setRemoteIP(remoteIP);
int remotePort = remote_med->desc.port;
_debug(" Remote Audio Port: %d\n", remotePort);
//setRemoteAudioPort(remotePort);
return true;
}
bool
Sdp::setAudioCodecFromSDP(pjmedia_sdp_media* remote_med)
{
// Remote Payload
int payLoad = -1;
int codecCount = remote_med->desc.fmt_count;
for(int i = 0; i < codecCount; i++) {
payLoad = atoi(remote_med->desc.fmt[i].ptr);
if (_codecMap.isActive((AudioCodecType)payLoad))
break;
payLoad = -1;
}
if(payLoad != -1) {
_debug(" Payload: %d\n", payLoad);
setAudioCodec((AudioCodecType)payLoad);
} else
return false;
return true;
}
void Sdp::sdpAddOrigin( void )
{
pj_time_val tv;
pj_gettimeofday(&tv);
_localSDP->origin.user = pj_str(pj_gethostname()->ptr);
// Use Network Time Protocol format timestamp to ensure uniqueness.
_localSDP->origin.id = tv.sec + 2208988800UL;
// The type of network ( IN for INternet )
_localSDP->origin.net_type = pj_str((char*)"IN"); //STR_IN;
// The type of address
_localSDP->origin.addr_type = pj_str((char*)"IP4"); //STR_IP4;
// The address of the machine from which the session was created
_localSDP->origin.addr = pj_str( (char*)_ipAddr.c_str() );
}
void Sdp::sdpAddConnectionInfo( void )
{
_localSDP->conn->net_type = _localSDP->origin.net_type;
_localSDP->conn->addr_type = _localSDP->origin.addr_type;
_localSDP->conn->addr = _localSDP->origin.addr;
}
void Sdp::sdpAddMediaDescription()
{
pjmedia_sdp_media* med;
pjmedia_sdp_attr *attr;
pjmedia_sdp_rtpmap rtpMap;
//int nbMedia, i;
med = PJ_POOL_ZALLOC_T(_pool, pjmedia_sdp_media);
//nbMedia = getSDPMediaList().size();
_localSDP->media_count = 1;
med->desc.media = pj_str((char*)"audio");
med->desc.port_count = 1;
med->desc.port = getLocalExternAudioPort();
med->desc.transport = pj_str((char*)"RTP/AVP");
CodecOrder::iterator itr;
itr = _codecMap.getActiveCodecs().begin();
int count = _codecMap.getActiveCodecs().size();
med->desc.fmt_count = count;
int i = 0;
while(itr != _codecMap.getActiveCodecs().end()) {
std::ostringstream format;
format << *itr;
pj_strdup2(_pool, &med->desc.fmt[i], format.str().data());
rtpMap.pt = med->desc.fmt[i];
rtpMap.enc_name = pj_str((char *)_codecMap.getCodecName(*itr).data());
rtpMap.clock_rate = _codecMap.getSampleRate(*itr);
if(_codecMap.getChannel(*itr) > 1) {
std::ostringstream channel;
channel << _codecMap.getChannel(*itr);
rtpMap.param = pj_str((char *)channel.str().data());
} else
rtpMap.param.slen = 0;
pjmedia_sdp_rtpmap_to_attr( _pool, &rtpMap, &attr );
med->attr[i] = attr;
i++;
itr++;
}
//FIXME! Add the direction stream
attr = (pjmedia_sdp_attr*)pj_pool_zalloc( _pool, sizeof(pjmedia_sdp_attr) );
pj_strdup2( _pool, &attr->name, "sendrecv");
med->attr[ i++] = attr;
med->attr_count = i;
_localSDP->media[0] = med;
/*for( i=0; i<nbMedia; i++ ){
getMediaDescriptorLine( getSDPMediaList()[i], pool, &med );
this->_local_offer->media[i] = med;
} */
}
pjmedia_sdp_media* Sdp::getRemoteMedia(pjmedia_sdp_session *remote_sdp)
{
int count, i;
count = remote_sdp->media_count;
for(i = 0; i < count; ++i) {
if(pj_stricmp2(&remote_sdp->media[i]->desc.media, "audio") == 0)
return remote_sdp->media[i];
}
return NULL;
}
bool Sdp::startNegociation()
{
pj_status_t status;
_debug("Before negotiate!\n");
status = pjmedia_sdp_neg_negotiate(_pool, _negociator, 0);
return (status == PJ_SUCCESS);
}
bool Sdp::createInitialOffer()
{
pj_status_t status;
// Have to do some stuff here with the SDP
_localSDP = PJ_POOL_ZALLOC_T(_pool, pjmedia_sdp_session);
_localSDP->conn = PJ_POOL_ZALLOC_T(_pool, pjmedia_sdp_conn);
_localSDP->origin.version = 0;
sdpAddOrigin();
_localSDP->name = pj_str((char*)"sflphone");
sdpAddConnectionInfo();
_localSDP->time.start = _localSDP->time.stop = 0;
sdpAddMediaDescription();
_debug("Before validate SDP!\n");
status = pjmedia_sdp_validate( _localSDP );
if (status != PJ_SUCCESS) {
_debug("Can not generate valid local sdp %d\n", status);
return false;
}
_debug("Before create negociator!\n");
// Create the SDP negociator instance with local offer
status = pjmedia_sdp_neg_create_w_local_offer( _pool, _localSDP, &_negociator);
//state = pjmedia_sdp_neg_get_state( _negociator );
PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 );
return true;
}
int Sdp::receiving_initial_offer( pjmedia_sdp_session* remote )
{
// Create the SDP negociator instance by calling
// 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;
// Create the SDP negociator instance by calling
// pjmedia_sdp_neg_create_w_remote_offer with the remote offer, and by providing the local offer ( optional )
// Build the local offer to respond
createInitialOffer();
status = pjmedia_sdp_neg_create_w_remote_offer( _pool,
getLocalSDPSession(), remote, &_negociator );
state = pjmedia_sdp_neg_get_state( _negociator );
PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 );
return PJ_SUCCESS;
}

169
src/sdp.h Normal file
View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2009 Savoir-Faire Linux inc.
*
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _SDP_H
#define _SDP_H
#include <pjmedia/sdp.h>
#include <pjmedia/sdp_neg.h>
#include <pjsip/sip_transport.h>
#include <pjlib.h>
#include <pj/pool.h>
#include <pj/assert.h>
#include "audio/codecDescriptor.h"
class Sdp {
public:
Sdp(pj_pool_t *pool);
~Sdp();
/**
* Setup incoming call, and verify for errors, before ringing the user.
* @param pjsip_rx_data *rdata
* @param pj_pool_t *pool
* @return bool True on success
* false otherwise
*/
bool SIPCallInvite(pjsip_rx_data *rdata);
bool SIPCallAnsweredWithoutHold(pjsip_rx_data *rdata);
/**
* Get the local SDP
* @param void
* @return _localSDP pjmedia_sdp_session
*/
pjmedia_sdp_session* getLocalSDPSession( void ) { return _localSDP; }
/**
* Begin negociation of media information between caller and callee
* @param pj_pool_t *pool
* @return bool True if ok
*/
bool startNegociation();
/**
* Create the localSDP, media negociation and codec information
* @param pj_pool_t *pool
* @return void
*/
bool createInitialOffer();
/**
* Set internal codec Map: initialization only, not protected
* @param map The codec map
*/
void setCodecMap(const CodecDescriptor& map) { _codecMap = map; }
/**
* Save IP Address
* @param ip std::string
* @return void
*/
void setIp(std::string ip) {_ipAddr = ip;}
/**
* Get internal codec Map: initialization only, not protected
* @return CodecDescriptor The codec map
*/
CodecDescriptor& getCodecMap();
void setLocalExternAudioPort(int port){ _localPort = port; }
int getLocalExternAudioPort (void){ return _localPort; }
int receiving_initial_offer( pjmedia_sdp_session* remote );
private:
/**
* Set the audio codec used. [not protected]
* @param audioCodec The payload of the codec
*/
void setAudioCodec(AudioCodecType audioCodec) { _audioCodec = audioCodec; }
/** Codec pointer */
AudioCodecType _audioCodec;
/** IP address */
std::string _ipAddr;
int _localPort;
/**
* Get a valid remote media
* @param remote_sdp pjmedia_sdp_session*
* @return pjmedia_sdp_media*. A valid sdp_media_t or 0
*/
pjmedia_sdp_media* getRemoteMedia(pjmedia_sdp_session *remote_sdp);
pjmedia_sdp_session * getRemoteSDPFromRequest (pjsip_rx_data *rdata);
/**
* Set Audio Port and Audio IP from Remote SDP Info
* @param remote_med Remote Media info
* @param remote_sdp Remote SDP pointer
* @return bool True if everything is set correctly
*/
bool setRemoteAudioFromSDP(pjmedia_sdp_session* remote_sdp, pjmedia_sdp_media* remote_med);
/**
* Set Audio Codec with the remote choice
* @param remote_med Remote Media info
* @return bool True if everything is set correctly
*/
bool setAudioCodecFromSDP(pjmedia_sdp_media* remote_med);
/** Local SDP */
pjmedia_sdp_session *_localSDP;
pjmedia_sdp_session *_negociated_offer;
/** negociator */
pjmedia_sdp_neg *_negociator;
// The pool to allocate memory
pj_pool_t *_pool;
/** Codec Map */
CodecDescriptor _codecMap;
/**
* Set origin information for local SDP
*/
void sdpAddOrigin( void );
/**
* Set connection information for local SDP
*/
void sdpAddConnectionInfo( void );
/**
* Set media information including codec for localSDP
* @param pj_pool_t* pool
* @return void
*/
void sdpAddMediaDescription();
};
#endif

View File

@ -23,17 +23,11 @@
#include "sipcall.h"
#include "global.h" // for _debug
#define _SENDRECV 0
#define _SENDONLY 1
#define _RECVONLY 2
SIPCall::SIPCall(const CallID& id, Call::CallType type) : Call(id, type)
, _cid(0)
, _did(0)
, _tid(0)
, _localSDP(NULL)
, _negociator(NULL)
, _ipAddr("")
, _xferSub(NULL)
, _invSession(NULL)
{
@ -43,281 +37,9 @@ SIPCall::SIPCall(const CallID& id, Call::CallType type) : Call(id, type)
SIPCall::~SIPCall()
{
_debug("SIPCALL::Destructor for this clss is called \n");
delete _local_sdp; _local_sdp = 0;
_debug("SIPCALL::Destructor for this clss is called \n");
}
bool
SIPCall::SIPCallInvite(pjsip_rx_data *rdata, pj_pool_t *pool)
{
pj_status_t status;
// We retrieve the remote sdp offer in the rdata struct to begin the negociation
pjmedia_sdp_session* remote_sdp = getRemoteSDPFromRequest(rdata);
if (remote_sdp == 0) {
return false;
}
// Have to do some stuff here with the SDP
_localSDP = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);
_localSDP->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
_localSDP->origin.version = 0;
sdpAddOrigin();
_localSDP->name = pj_str((char*)"sflphone");
sdpAddConnectionInfo();
_localSDP->time.start = _localSDP->time.stop = 0;
sdpAddMediaDescription(pool);
status = pjmedia_sdp_validate( _localSDP );
if (status != PJ_SUCCESS) {
_debug("Can not generate valid local sdp\n");
return false;
}
_debug("Before create negociator!\n");
status = pjmedia_sdp_neg_create_w_remote_offer(pool, _localSDP, remote_sdp, &_negociator);
if (status != PJ_SUCCESS) {
_debug("Can not create negociator\n");
return false;
}
_debug("After create negociator!\n");
pjmedia_sdp_media* remote_med = getRemoteMedia(remote_sdp);
if (remote_med == 0) {
_debug("SIP Failure: unable to get remote media\n");
return false;
}
_debug("Before set audio!\n");
if (!setRemoteAudioFromSDP(remote_sdp, remote_med)) {
_debug("SIP Failure: unable to set IP address and port from SDP\n");
return false;
}
_debug("Before set codec!\n");
if (!setAudioCodecFromSDP(remote_med)) {
_debug("SIP Failure: unable to set audio codecs from the remote SDP\n");
return false;
}
return true;
}
bool
SIPCall::SIPCallAnsweredWithoutHold(pjsip_rx_data *rdata)
{
pjmedia_sdp_session* remote_sdp = getRemoteSDPFromRequest(rdata);
if (remote_sdp == NULL) {
_debug("SIP Failure: no remote sdp\n");
return false;
}
pjmedia_sdp_media* remote_med = getRemoteMedia(remote_sdp);
if (remote_med==NULL) {
return false;
}
_debug("Before set audio!\n");
if (!setRemoteAudioFromSDP(remote_sdp, remote_med)) {
_debug("SIP Failure: unable to set IP address and port from SDP\n");
return false;
}
_debug("Before set codec!\n");
if (!setAudioCodecFromSDP(remote_med)) {
_debug("SIP Failure: unable to set audio codecs from the remote SDP\n");
return false;
}
return true;
}
pjmedia_sdp_session*
SIPCall::getRemoteSDPFromRequest(pjsip_rx_data *rdata)
{
pjmedia_sdp_session *sdp;
pjsip_msg *msg;
pjsip_msg_body *body;
msg = rdata->msg_info.msg;
body = msg->body;
pjmedia_sdp_parse( rdata->tp_info.pool, (char*)body->data, body->len, &sdp );
return sdp;
}
bool
SIPCall::setRemoteAudioFromSDP(pjmedia_sdp_session* remote_sdp, pjmedia_sdp_media *remote_med)
{
std::string remoteIP(remote_sdp->conn->addr.ptr, remote_sdp->conn->addr.slen);
_debug(" Remote Audio IP: %s\n", remoteIP.data());
setRemoteIP(remoteIP);
int remotePort = remote_med->desc.port;
_debug(" Remote Audio Port: %d\n", remotePort);
setRemoteAudioPort(remotePort);
return true;
}
bool
SIPCall::setAudioCodecFromSDP(pjmedia_sdp_media* remote_med)
{
// Remote Payload
int payLoad = -1;
int codecCount = remote_med->desc.fmt_count;
for(int i = 0; i < codecCount; i++) {
payLoad = atoi(remote_med->desc.fmt[i].ptr);
if (_codecMap.isActive((AudioCodecType)payLoad))
break;
payLoad = -1;
}
if(payLoad != -1) {
_debug(" Payload: %d\n", payLoad);
setAudioCodec((AudioCodecType)payLoad);
} else
return false;
return true;
}
void SIPCall::sdpAddOrigin( void )
{
pj_time_val tv;
pj_gettimeofday(&tv);
_localSDP->origin.user = pj_str(pj_gethostname()->ptr);
// Use Network Time Protocol format timestamp to ensure uniqueness.
_localSDP->origin.id = tv.sec + 2208988800UL;
// The type of network ( IN for INternet )
_localSDP->origin.net_type = pj_str((char*)"IN"); //STR_IN;
// The type of address
_localSDP->origin.addr_type = pj_str((char*)"IP4"); //STR_IP4;
// The address of the machine from which the session was created
_localSDP->origin.addr = pj_str( (char*)_ipAddr.c_str() );
}
void SIPCall::sdpAddConnectionInfo( void )
{
_localSDP->conn->net_type = _localSDP->origin.net_type;
_localSDP->conn->addr_type = _localSDP->origin.addr_type;
_localSDP->conn->addr = _localSDP->origin.addr;
}
void SIPCall::sdpAddMediaDescription(pj_pool_t* pool)
{
pjmedia_sdp_media* med;
pjmedia_sdp_attr *attr;
pjmedia_sdp_rtpmap rtpMap;
//int nbMedia, i;
med = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
//nbMedia = getSDPMediaList().size();
_localSDP->media_count = 1;
med->desc.media = pj_str((char*)"audio");
med->desc.port_count = 1;
med->desc.port = getLocalExternAudioPort();
med->desc.transport = pj_str((char*)"RTP/AVP");
CodecOrder::iterator itr;
itr = _codecMap.getActiveCodecs().begin();
int count = _codecMap.getActiveCodecs().size();
med->desc.fmt_count = count;
int i = 0;
while(itr != _codecMap.getActiveCodecs().end()) {
std::ostringstream format;
format << *itr;
pj_strdup2(pool, &med->desc.fmt[i], format.str().data());
rtpMap.pt = med->desc.fmt[i];
rtpMap.enc_name = pj_str((char *)_codecMap.getCodecName(*itr).data());
rtpMap.clock_rate = _codecMap.getSampleRate(*itr);
if(_codecMap.getChannel(*itr) > 1) {
std::ostringstream channel;
channel << _codecMap.getChannel(*itr);
rtpMap.param = pj_str((char *)channel.str().data());
} else
rtpMap.param.slen = 0;
pjmedia_sdp_rtpmap_to_attr( pool, &rtpMap, &attr );
med->attr[i] = attr;
i++;
itr++;
}
//FIXME! Add the direction stream
attr = (pjmedia_sdp_attr*)pj_pool_zalloc( pool, sizeof(pjmedia_sdp_attr) );
pj_strdup2( pool, &attr->name, "sendrecv");
med->attr[ i++] = attr;
med->attr_count = i;
_localSDP->media[0] = med;
/*for( i=0; i<nbMedia; i++ ){
getMediaDescriptorLine( getSDPMediaList()[i], pool, &med );
this->_local_offer->media[i] = med;
} */
}
pjmedia_sdp_media* SIPCall::getRemoteMedia(pjmedia_sdp_session *remote_sdp)
{
int count, i;
count = remote_sdp->media_count;
for(i = 0; i < count; ++i) {
if(pj_stricmp2(&remote_sdp->media[i]->desc.media, "audio") == 0)
return remote_sdp->media[i];
}
return NULL;
}
bool SIPCall::startNegociation(pj_pool_t *pool)
{
pj_status_t status;
_debug("Before negotiate!\n");
status = pjmedia_sdp_neg_negotiate(pool, _negociator, 0);
return (status == PJ_SUCCESS);
}
bool SIPCall::createInitialOffer(pj_pool_t *pool)
{
pj_status_t status;
// Have to do some stuff here with the SDP
_localSDP = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);
_localSDP->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
_localSDP->origin.version = 0;
sdpAddOrigin();
_localSDP->name = pj_str((char*)"sflphone");
sdpAddConnectionInfo();
_localSDP->time.start = _localSDP->time.stop = 0;
sdpAddMediaDescription(pool);
_debug("Before validate SDP!\n");
status = pjmedia_sdp_validate( _localSDP );
if (status != PJ_SUCCESS) {
_debug("Can not generate valid local sdp %d\n", status);
return false;
}
_debug("Before create negociator!\n");
// Create the SDP negociator instance with local offer
status = pjmedia_sdp_neg_create_w_local_offer( pool, _localSDP, &_negociator);
//state = pjmedia_sdp_neg_get_state( _negociator );
PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 );
return true;
}

View File

@ -23,7 +23,6 @@
#include "call.h"
#include "sipvoiplink.h"
#include "audio/codecDescriptor.h"
class AudioCodec;
@ -78,51 +77,13 @@ class SIPCall : public Call
*/
int getTid() { return _tid; }
/**
* Transaction identifier
* @param tid SIP transaction id
*/
void setTid(int tid) { _tid = tid; }
/**
* Setup incoming call, and verify for errors, before ringing the user.
* @param pjsip_rx_data *rdata
* @param pj_pool_t *pool
* @return bool True on success
* false otherwise
*/
bool SIPCallInvite(pjsip_rx_data *rdata, pj_pool_t *pool);
bool SIPCallAnsweredWithoutHold(pjsip_rx_data *rdata);
/**
* Save IP Address
* @param ip std::string
* @return void
*/
void setIp(std::string ip) {_ipAddr = ip;}
/**
* Get the local SDP
* @param void
* @return _localSDP pjmedia_sdp_session
*/
pjmedia_sdp_session* getLocalSDPSession( void ) { return _localSDP; }
/**
* Begin negociation of media information between caller and callee
* @param pj_pool_t *pool
* @return bool True if ok
*/
bool startNegociation(pj_pool_t *pool);
/**
* Create the localSDP, media negociation and codec information
* @param pj_pool_t *pool
* @return void
*/
bool createInitialOffer(pj_pool_t *pool);
void setXferSub(pjsip_evsub* sub) {_xferSub = sub;}
pjsip_evsub *getXferSub() {return _xferSub;}
@ -131,74 +92,16 @@ class SIPCall : public Call
private:
int _cid;
int _did;
int _tid;
// Copy Constructor
SIPCall(const SIPCall& rh);
// Assignment Operator
SIPCall& operator=( const SIPCall& rh);
/**
* Get a valid remote SDP or return a 400 bad request response if invalid
* @param
* @return
*/
pjmedia_sdp_session* getRemoteSDPFromRequest(pjsip_rx_data *rdata);
/**
* Get a valid remote media
* @param remote_sdp pjmedia_sdp_session*
* @return pjmedia_sdp_media*. A valid sdp_media_t or 0
*/
pjmedia_sdp_media* getRemoteMedia(pjmedia_sdp_session *remote_sdp);
/**
* Set Audio Port and Audio IP from Remote SDP Info
* @param remote_med Remote Media info
* @param remote_sdp Remote SDP pointer
* @return bool True if everything is set correctly
*/
bool setRemoteAudioFromSDP(pjmedia_sdp_session* remote_sdp, pjmedia_sdp_media* remote_med);
/**
* Set Audio Codec with the remote choice
* @param remote_med Remote Media info
* @return bool True if everything is set correctly
*/
bool setAudioCodecFromSDP(pjmedia_sdp_media* remote_med);
/** SIP call id */
int _cid;
/** SIP domain id */
int _did;
/** SIP transaction id */
int _tid;
/** Local SDP */
pjmedia_sdp_session *_localSDP;
/** negociator */
pjmedia_sdp_neg *_negociator;
/**
* Set origin information for local SDP
*/
void sdpAddOrigin( void );
/**
* Set connection information for local SDP
*/
void sdpAddConnectionInfo( void );
/**
* Set media information including codec for localSDP
* @param pj_pool_t* pool
* @return void
*/
void sdpAddMediaDescription(pj_pool_t* pool);
/** IP address */
std::string _ipAddr;
pjsip_evsub *_xferSub;
pjsip_inv_session *_invSession;

View File

@ -27,6 +27,8 @@
/**************** EXTERN VARIABLES AND FUNCTIONS (callbacks) **************************/
int getModId();
/*
* The global pool factory
*/
@ -53,7 +55,6 @@ pjsip_module _mod_ua;
pj_thread_t *thread;
pj_thread_desc desc;
/**
* Get the number of voicemail waiting in a SIP message
*/
@ -107,6 +108,8 @@ void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
*/
void call_on_tsx_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
void on_rx_offer( pjsip_inv_session *inv, const pjmedia_sdp_session *offer );
/*
* Registration callback
*/
@ -205,6 +208,7 @@ SIPVoIPLink::terminate()
delete _evThread; _evThread = NULL;
}
/* Clean shutdown of pjsip library */
if( initDone() )
{
@ -453,7 +457,7 @@ SIPVoIPLink::answer(const CallID& id)
}
// User answered the incoming call, tell peer this news
if (call->startNegociation(_pool)) {
if (call->startNegociation()) {
// Create and send a 200(OK) response
_debug("UserAgent: Negociation success!\n");
status = pjsip_inv_answer(call->getInvSession(), PJSIP_SC_OK, NULL, NULL, &tdata);
@ -904,14 +908,14 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject UNUSED)
PJ_ASSERT_RETURN(status == PJ_SUCCESS, false);
setCallAudioLocal(call, getLocalIPAddress(), useStun(), getStunServer());
call->setIp(getLocalIP());
_local_sdp->setIp(getLocalIP());
// Building the local SDP offer
call->createInitialOffer(_pool);
_local_sdp->createInitialOffer();
// Create the invite session for this call
pjsip_inv_session *inv;
status = pjsip_inv_create_uac(dialog, call->getLocalSDPSession(), 0, &inv);
status = pjsip_inv_create_uac(dialog, _local_sdp->getLocalSDPSession(), 0, &inv);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, false);
// Set auth information
@ -980,6 +984,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
call->setLocalIp(localIP);
call->setLocalAudioPort(callLocalAudioPort);
call->setLocalExternAudioPort(callLocalExternAudioPort);
_local_sdp->setLocalExternAudioPort(callLocalExternAudioPort);
return true;
}
@ -1056,7 +1061,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
if (call->getConnectionState() != Call::Connected) {
//call->SIPCallAnswered(event);
call->SIPCallAnsweredWithoutHold(rdata);
_local_sdp->SIPCallAnsweredWithoutHold(rdata);
call->setConnectionState(Call::Connected);
call->setState(Call::Active);
@ -1241,6 +1246,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
inv_cb.on_new_session = &call_on_forked;
inv_cb.on_media_update = &call_on_media_update;
inv_cb.on_tsx_state_changed = &call_on_tsx_changed;
inv_cb.on_rx_offer = &on_rx_offer;
// Initialize session invite module
status = pjsip_inv_usage_init(_endpt, &inv_cb);
@ -1258,6 +1264,10 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
// Register "application/sdp" in ACCEPT header
pjsip_endpt_add_capability(_endpt, &_mod_ua, PJSIP_H_ACCEPT, NULL, 1, &accepted);
/* Create the SDP object */
_local_sdp = new Sdp (_pool);
_debug("UserAgent: pjsip version %s for %s initialized\n", pj_get_version(), PJ_OS_NAME);
// Create the secondary thread to poll sip events
@ -1434,7 +1444,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
/* Done. */
}
int SIPVoIPLink::getModId(){
int getModId(){
return _mod_ua.id;
}
@ -1481,6 +1491,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
PJ_UNUSED_ARG(inv);
SIPCall *call = reinterpret_cast<SIPCall*> (inv->mod_data[_mod_ua.id]);
if(!call)
return;
@ -1568,6 +1579,8 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
rdata = e->body.tsx_state.src.rdata;
if (tsx->role == PJSIP_ROLE_UAC) {
switch (tsx->state) {
case PJSIP_TSX_STATE_TERMINATED:
if (tsx->status_code == 200 &&
@ -1665,6 +1678,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
}
break;
default:
_debug("default: %i\n", tsx->status_code);
break;
} // end of switch
}
@ -1833,9 +1847,9 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
// Set the codec map, IP, peer number and so on... for the SIPCall object
setCallAudioLocal(call, link->getLocalIPAddress(), link->useStun(), link->getStunServer());
call->setCodecMap(Manager::instance().getCodecDescriptorMap());
_local_sdp->setCodecMap(Manager::instance().getCodecDescriptorMap());
call->setConnectionState(Call::Progressing);
call->setIp(link->getLocalIPAddress());
_local_sdp->setIp(link->getLocalIPAddress());
call->setPeerNumber(peerNumber);
/* Call the SIPCallInvite function to generate the local sdp,
@ -1845,7 +1859,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
* remote IP and port number
* possilbe audio codec will be used in this call
*/
if (call->SIPCallInvite(rdata, _pool)) {
if (_local_sdp->SIPCallInvite(rdata)) {
// Notify UI there is an incoming call
if (Manager::instance().incomingCall(call, account_id)) {
@ -1876,7 +1890,7 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
// Specify media capability during invite session creation
pjsip_inv_session *inv;
status = pjsip_inv_create_uas(dialog, rdata, call->getLocalSDPSession(), 0, &inv);
status = pjsip_inv_create_uas(dialog, rdata, _local_sdp->getLocalSDPSession(), 0, &inv);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
// Associate the call in the invite session
@ -2287,3 +2301,20 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
_debug("UserAgent: Xfer server subscription terminated\n");
}
}
void on_rx_offer( pjsip_inv_session *inv, const pjmedia_sdp_session *offer ){
PJ_UNUSED_ARG( inv );
SIPCall *call;
pj_status_t status;
call = (SIPCall*)inv->mod_data[getModId()];
if (!call)
return;
_local_sdp->receiving_initial_offer( (pjmedia_sdp_session*)offer);
status=pjsip_inv_set_sdp_answer( call->getInvSession(), _local_sdp->getLocalSDPSession() );
}

View File

@ -33,7 +33,6 @@
#include <pjnath/stun_config.h>
///////////////////////////////
class EventThread;
class SIPCall;
class AudioRtp;
@ -42,7 +41,7 @@ class AudioRtp;
#define RANDOM_SIP_PORT rand() % 64000 + 1024
// To set the verbosity. From 0 (min) to 6 (max)
#define PJ_LOG_LEVEL 1
#define PJ_LOG_LEVEL 6
/**
* @file sipvoiplink.h
@ -309,7 +308,6 @@ class SIPVoIPLink : public VoIPLink
static SIPVoIPLink* _instance;
void busy_sleep(unsigned msec);
int getModId();
/**
* Initialize the PJSIP library