From 15c3df5122f4dd743374345bc5c8d7ca381f9f25 Mon Sep 17 00:00:00 2001 From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Date: Mon, 2 Mar 2009 17:43:33 -0500 Subject: [PATCH] Build the SDP session with the right codecs --- src/sdp.cpp | 360 +++++++++++++++++++++++++------------------- src/sdp.h | 4 + src/sipvoiplink.cpp | 8 + 3 files changed, 216 insertions(+), 156 deletions(-) diff --git a/src/sdp.cpp b/src/sdp.cpp index 208dfa836c..c9bdc1468c 100644 --- a/src/sdp.cpp +++ b/src/sdp.cpp @@ -26,103 +26,107 @@ #define _RECVONLY 2 Sdp::Sdp( pj_pool_t *pool ) : _localSDP(NULL) - , _negociator(NULL) - , _codecMap() - , _ipAddr("") + , _negociator(NULL) + , _codecMap() + , _ipAddr("") { _pool = pool; } Sdp::~Sdp() {} -bool + 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; + 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) { + _debug ("Failed to retrieve the remote sdp offer in the rdata struct to begin the negociation\n"); + 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(); + + // DEBUG + toString (); + + 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 + 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* 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* + pjmedia_sdp_session* Sdp::getRemoteSDPFromRequest(pjsip_rx_data *rdata) { pjmedia_sdp_session *sdp; @@ -137,40 +141,40 @@ Sdp::getRemoteSDPFromRequest(pjsip_rx_data *rdata) return sdp; } -bool + 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; + 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 + 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; + // 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 ) @@ -201,6 +205,8 @@ void Sdp::sdpAddConnectionInfo( void ) void Sdp::sdpAddMediaDescription() { + + pjmedia_sdp_media* med; pjmedia_sdp_attr *attr; pjmedia_sdp_rtpmap rtpMap; @@ -209,25 +215,27 @@ void Sdp::sdpAddMediaDescription() 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(); + _debug ("Add media description %i\n", count); med->desc.fmt_count = count; - + int i = 0; while(itr != _codecMap.getActiveCodecs().end()) { + _debug ("First media description\n"); 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); @@ -237,13 +245,13 @@ void Sdp::sdpAddMediaDescription() 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"); @@ -252,22 +260,22 @@ void Sdp::sdpAddMediaDescription() _localSDP->media[0] = med; /*for( i=0; i<nbMedia; i++ ){ - getMediaDescriptorLine( getSDPMediaList()[i], pool, &med ); - this->_local_offer->media[i] = med; - } */ - + 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; } @@ -276,63 +284,103 @@ 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::createLocalOffer (void) { + 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; + } + + +} 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; - + + pj_status_t status; + + createLocalOffer (); + + _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(); + createLocalOffer(); status = pjmedia_sdp_neg_create_w_remote_offer( _pool, - getLocalSDPSession(), remote, &_negociator ); + getLocalSDPSession(), remote, &_negociator ); state = pjmedia_sdp_neg_get_state( _negociator ); PJ_ASSERT_RETURN( status == PJ_SUCCESS, 1 ); return PJ_SUCCESS; + +} + +void Sdp::toString (void) { + + std::ostringstream sdp; + + sdp << "origin= " << _localSDP->origin.user.ptr << "\n"; + sdp << "origin.id= " << _localSDP->origin.id << "\n"; + sdp << "origin.version= " << _localSDP->origin.version<< "\n"; + sdp << "origin.net_type= " << _localSDP->origin.net_type.ptr<< "\n"; + sdp << "origin.addr_type= " << _localSDP->origin.addr_type.ptr<< "\n"; + + sdp << "name=" << _localSDP->name.ptr<< "\n"; + + sdp << "conn.net_type=" << _localSDP->conn->net_type.ptr<< "\n"; + sdp << "conn.addr_type=" << _localSDP->conn->addr_type.ptr<< "\n"; + sdp << "conn.addr=" << _localSDP->conn->addr.ptr<< "\n"; + + sdp << "start=" <<_localSDP->time.start<< "\n"; + sdp << "stop=" <<_localSDP->time.stop<< "\n"; + + sdp << "attr_count=" << _localSDP->attr_count << "\n"; + sdp << "media_count=" << _localSDP->media_count << "\n"; + sdp << "m=" << _localSDP->media[0]->desc.media.ptr << "\n"; + sdp << "port=" << _localSDP->media[0]->desc.port << "\n"; + sdp << "transport=" << _localSDP->media[0]->desc.transport.ptr << "\n"; + sdp << "fmt_count=" << _localSDP->media[0]->desc.fmt_count << "\n"; + sdp << "fmt=" << _localSDP->media[0]->desc.fmt[0].ptr << "\n"; + _debug ("LOCAL SDP: \n%s\n", sdp.str().c_str()); + } diff --git a/src/sdp.h b/src/sdp.h index 2ef266249e..33ab231aca 100644 --- a/src/sdp.h +++ b/src/sdp.h @@ -70,6 +70,8 @@ class Sdp { */ bool createInitialOffer(); + bool createLocalOffer (); + /** * Set internal codec Map: initialization only, not protected * @param map The codec map @@ -95,6 +97,8 @@ class Sdp { int receiving_initial_offer( pjmedia_sdp_session* remote ); + void toString (void); + private: /** * Set the audio codec used. [not protected] diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp index 59633b0e32..e44bae1337 100644 --- a/src/sipvoiplink.cpp +++ b/src/sipvoiplink.cpp @@ -25,6 +25,8 @@ #include "sipaccount.h" #include "audio/audiortp.h" +#define CAN_REINVITE 1 + /**************** EXTERN VARIABLES AND FUNCTIONS (callbacks) **************************/ int getModId(); @@ -430,6 +432,7 @@ SIPVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl) _debug("Try to make a call to: %s with call ID: %s\n", toUrl.data(), id.data()); // we have to add the codec before using it in SIPOutgoingInvite... call->setCodecMap(Manager::instance().getCodecDescriptorMap()); + call->getLocalSDP()->setCodecMap(Manager::instance().getCodecDescriptorMap()); if ( SIPOutgoingInvite(call) ) { call->setConnectionState(Call::Progressing); call->setState(Call::Active); @@ -929,6 +932,8 @@ SIPVoIPLink::SIPStartCall(SIPCall* call, const std::string& subject UNUSED) // Building the local SDP offer call->getLocalSDP()->createInitialOffer(); + call->getLocalSDP()->toString (); + // Create the invite session for this call pjsip_inv_session *inv; status = pjsip_inv_create_uac(dialog, call->getLocalSDP()->getLocalSDPSession(), 0, &inv); @@ -2322,6 +2327,9 @@ void SIPVoIPLink::setStunServer( const std::string &server ) PJ_UNUSED_ARG( inv ); #ifdef CAN_REINVITE + + _debug ("reinvite SIP\n"); + SIPCall *call; pj_status_t status; -- GitLab