Commit 25beb37d authored by Rafaël Carré's avatar Rafaël Carré
Browse files

* #6905: simplify SIP code

try to make it more readable/understandable
parent 7c87bca1
......@@ -70,7 +70,6 @@ static const char *const CONFIG_ACCOUNT_TYPE = "Account.type";
static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias";
static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox";
static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable";
static const char *const CONFIG_ACCOUNT_RESOLVE_ONCE = "Account.resolveOnce";
static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.expire";
static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count";
static const char *const ACCOUNT_DTMF_TYPE = "Account.dtmfType";
......
......@@ -248,5 +248,3 @@ void AudioRtpFactory::sendDtmfDigit (int digit)
}
}
......@@ -30,6 +30,7 @@
#include "AudioRtpRecordHandler.h"
#include <fstream>
#include "sip/sipcall.h"
#include "audio/audiolayer.h"
#include "manager.h"
......
......@@ -36,7 +36,7 @@ using std::ptrdiff_t;
#include <ccrtp/rtp.h>
#include <list>
#include "sip/sipcall.h"
class SIPCall;
#include "audio/codecs/audiocodec.h"
#include "audio/samplerateconverter.h"
#include "audio/noisesuppress.h"
......@@ -105,7 +105,7 @@ class AudioRtpRecord
class AudioRtpRecordHandler
{
public:
AudioRtpRecordHandler (SIPCall *ca);
AudioRtpRecordHandler(SIPCall *);
virtual ~AudioRtpRecordHandler();
/**
......
......@@ -87,51 +87,26 @@ Call::getState()
std::string
Call::getStateStr ()
{
CallState state = getState();
ConnectionState connection = getConnectionState ();
CallType type = _type;
std::string state_str;
switch (state) {
switch (getState()) {
case Active:
switch (connection) {
case Ringing:
(type == Incoming) ? state_str = "INCOMING":state_str = "RINGING";
break;
switch (getConnectionState()) {
case Ringing: return isIncoming() ? "INCOMING" : "RINGING";
case Connected:
default:
isRecording() ? state_str = "RECORD" : state_str = "CURRENT";
break;
default: return isRecording() ? "RECORD" : "CURRENT";
}
case Hold:
state_str = "HOLD";
break;
case Busy:
state_str = "BUSY";
break;
case Hold: return "HOLD";
case Busy: return "BUSY";
case Inactive:
switch (connection) {
case Ringing:
(type == Incoming) ? state_str = "INCOMING":state_str = "RINGING";
break;
case Connected:
state_str = "CURRENT";
break;
default:
state_str = "INACTIVE";
break;
switch (getConnectionState()) {
case Ringing: return isIncoming() ? "INCOMING" : "RINGING";
case Connected: return "CURRENT";
default: return "INACTIVE";
}
break;
case Conferencing:
state_str = "CONFERENCING";
break;
case Conferencing: return "CONFERENCING";
case Refused:
case Error:
default:
state_str = "FAILURE";
break;
default: return "FAILURE";
}
return state_str;
}
......@@ -152,36 +127,20 @@ Call::getLocalAudioPort()
bool
Call::setRecording()
{
_debug ("Call: Set recording");
bool recordStatus = Recordable::recAudio.isRecording();
Recordable::recAudio.setRecording();
MainBuffer *mbuffer = Manager::instance().getMainBuffer();
std::string process_id = Recordable::recorder.getRecorderID();
// Start recording
if (!recordStatus) {
_debug ("Call: Call not recording yet, set ringbuffers");
MainBuffer *mbuffer = Manager::instance().getMainBuffer();
std::string process_id = Recordable::recorder.getRecorderID();
mbuffer->bindHalfDuplexOut (process_id, _id);
mbuffer->bindHalfDuplexOut (process_id);
Recordable::recorder.start();
}
// Stop recording
else {
_debug ("Call: Stop recording");
MainBuffer *mbuffer = Manager::instance().getMainBuffer();
std::string process_id = Recordable::recorder.getRecorderID();
} else {
mbuffer->unBindHalfDuplexOut (process_id, _id);
mbuffer->unBindHalfDuplexOut (process_id);
}
Manager::instance().getMainBuffer()->stateInfo();
......
......@@ -170,7 +170,7 @@ class Call: public Recordable
* false otherwise
*/
bool isIncoming() {
return (_type == Incoming) ? true : false;
return _type == Incoming;
}
/**
......
......@@ -33,6 +33,7 @@
#include "global.h"
#include "callmanager.h"
#include "sip/sipcall.h"
#include "sip/sipvoiplink.h"
#include "audio/audiortp/AudioRtpFactory.h"
#include "audio/audiortp/AudioZrtpSession.h"
......@@ -366,26 +367,15 @@ sfl::AudioZrtpSession * CallManager::getAudioZrtpSession (const std::string& cal
SIPCall *call;
try {
call = link->getSIPCall (callID);
call = link->getSIPCall(callID);
}
catch (const VoipLinkException &e) {
throw CallManagerException("Call id " + callID + " is not valid");
}
sfl::AudioRtpFactory * audioRtp = NULL;
audioRtp = call->getAudioRtp();
if (!audioRtp) {
throw CallManagerException("Failed to get AudioRtpFactory");
}
sfl::AudioZrtpSession * zSession = NULL;
zSession = audioRtp->getAudioZrtpSession();
if (!zSession) {
sfl::AudioZrtpSession * zSession = call->getAudioRtp()->getAudioZrtpSession();
if (!zSession)
throw CallManagerException("Failed to get AudioZrtpSession");
}
return zSession;
}
......
......@@ -6,7 +6,6 @@ libsiplink_la_SOURCES = \
Pattern.cpp \
SdesNegotiator.cpp \
sdp.cpp \
sdpmedia.cpp \
sipaccount.cpp \
sipcall.cpp \
sipvoiplink.cpp
......@@ -15,7 +14,6 @@ noinst_HEADERS = \
Pattern.h \
SdesNegotiator.h \
sdp.h \
sdpmedia.h \
sipaccount.h \
sipcall.h \
sipvoiplink.h
......
......@@ -31,24 +31,9 @@
*/
#include "sdp.h"
#include "sdpmedia.h"
#include "global.h"
#include "manager.h"
static const char* const ZRTP_VERSION = "1.10";
static const pj_str_t STR_AUDIO = { (char*) "audio", 5};
static const pj_str_t STR_VIDEO = { (char*) "video", 5};
static const pj_str_t STR_IN = { (char*) "IN", 2 };
static const pj_str_t STR_IP4 = { (char*) "IP4", 3};
static const pj_str_t STR_IP6 = { (char*) "IP6", 3};
static const pj_str_t STR_RTP_AVP = { (char*) "RTP/AVP", 7 };
static const pj_str_t STR_RTP_SAVP = { (char*) "RTP/SAVP", 8 };
static const pj_str_t STR_SDP_NAME = { (char*) "sflphone", 8 };
static const pj_str_t STR_SENDRECV = { (char*) "sendrecv", 8 };
static const pj_str_t STR_RTPMAP = { (char*) "rtpmap", 6 };
static const pj_str_t STR_CRYPTO = { (char*) "crypto", 6 };
static const pj_str_t STR_TELEPHONE_EVENT = { (char*) "telephone-event", 15};
#include <cassert>
Sdp::Sdp (pj_pool_t *pool)
: memPool_(pool)
......@@ -57,8 +42,6 @@ Sdp::Sdp (pj_pool_t *pool)
, remoteSession_(NULL)
, activeLocalSession_(NULL)
, activeRemoteSession_(NULL)
, localAudioMediaCap_()
, sessionAudioMedia_(0)
, localIpAddr_("")
, remoteIpAddr_("")
, localAudioPort_(0)
......@@ -71,154 +54,104 @@ Sdp::Sdp (pj_pool_t *pool)
void Sdp::setActiveLocalSdpSession (const pjmedia_sdp_session *sdp)
{
int nb_media, nb_codecs;
int port;
pjmedia_sdp_media *current;
sdpMedia *media = NULL;
std::string dir;
pjmedia_sdp_attr *attribute = NULL;
pjmedia_sdp_rtpmap *rtpmap;
_debug ("SDP: Set active local SDP session");
activeLocalSession_ = (pjmedia_sdp_session*) sdp;
// retrieve the media information
nb_media = activeLocalSession_->media_count;
for (int i = 0; i < nb_media ; i++) {
// Retrieve the media
current = activeLocalSession_->media[i];
std::string type (current->desc.media.ptr, current->desc.media.slen);
port = current->desc.port;
media = new sdpMedia (type, port);
// Retrieve the payload
nb_codecs = current->desc.fmt_count; // Must be one
for (int j = 0; j < nb_codecs; j++) {
attribute = pjmedia_sdp_media_find_attr(current, &STR_RTPMAP, NULL);
// pj_strtoul(attribute->pt)
if (!attribute)
{
delete media;
return;
}
if (activeLocalSession_->media_count < 1)
return;
pjmedia_sdp_attr_to_rtpmap (memPool_, attribute, &rtpmap);
pjmedia_sdp_media *current = activeLocalSession_->media[0];
sfl::Codec *codec = Manager::instance().audioCodecFactory.getCodec((int) pj_strtoul (&rtpmap->pt));
for (unsigned j = 0; j < current->desc.fmt_count; j++) {
static const pj_str_t STR_RTPMAP = { (char*) "rtpmap", 6 };
pjmedia_sdp_attr *attribute = pjmedia_sdp_media_find_attr(current, &STR_RTPMAP, NULL);
if (!attribute) {
sessionAudioMedia_.clear();
return;
}
if (!codec)
{
delete media;
return;
}
pjmedia_sdp_rtpmap *rtpmap;
pjmedia_sdp_attr_to_rtpmap (memPool_, attribute, &rtpmap);
media->add_codec(codec);
}
sfl::Codec *codec = Manager::instance().audioCodecFactory.getCodec((int) pj_strtoul (&rtpmap->pt));
if (!codec) {
sessionAudioMedia_.clear();
return;
}
sessionAudioMedia_.push_back (media);
}
sessionAudioMedia_.push_back(codec);
}
}
void Sdp::setActiveRemoteSdpSession (const pjmedia_sdp_session *sdp)
{
_debug ("SDP: Set negotiated SDP");
activeRemoteSession_ = (pjmedia_sdp_session*) sdp;
getRemoteSdpTelephoneEventFromOffer(sdp);
if(!sdp) {
_error("Sdp: Error: Remote sdp is NULL while parsing telephone event attribute");
return;
}
for (unsigned i = 0; i < sdp->media_count; i++)
if(pj_stricmp2(&sdp->media[i]->desc.media, "audio") == 0) {
pjmedia_sdp_media *r_media = sdp->media[i];
static const pj_str_t STR_TELEPHONE_EVENT = { (char*) "telephone-event", 15};
pjmedia_sdp_attr *attribute = pjmedia_sdp_attr_find(r_media->attr_count, r_media->attr, &STR_TELEPHONE_EVENT, NULL);
if (attribute != NULL) {
pjmedia_sdp_rtpmap *rtpmap;
pjmedia_sdp_attr_to_rtpmap (memPool_, attribute, &rtpmap);
telephoneEventPayload_ = pj_strtoul (&rtpmap->pt);
}
return;
}
_error("Sdp: Error: Could not found dtmf event from remote sdp");
}
bool Sdp::hasSessionMedia(void) const
std::string Sdp::getCodecName(void) const
{
return not sessionAudioMedia_.empty();
try {
sfl::AudioCodec *codec = getSessionMedia();
return codec ? codec->getMimeSubtype() : "";
} catch(...) {
return "";
}
}
sfl::AudioCodec* Sdp::getSessionMedia (void)
sfl::AudioCodec* Sdp::getSessionMedia (void) const
{
int nbMedia;
int nbCodec;
sfl::Codec *codec = NULL;
std::vector<sdpMedia *> mediaList;
_debug ("SDP: Get session media");
nbMedia = sessionAudioMedia_.size();
if (nbMedia <= 0) {
_error("SDP: Error: No media in session description");
throw SdpException("No media description for this SDP");
}
nbCodec = sessionAudioMedia_[0]->get_media_codec_list().size();
if (nbCodec <= 0) {
_error("SDP: Error: No codec description for this media");
if (sessionAudioMedia_.size() < 1)
throw SdpException("No codec description for this media");
}
codec = sessionAudioMedia_[0]->get_media_codec_list()[0];
return static_cast<sfl::AudioCodec *>(codec);
return static_cast<sfl::AudioCodec *>(sessionAudioMedia_[0]);
}
namespace
{
std::string convertIntToString (int value)
{
std::ostringstream result;
result << value;
return result.str();
}
} // end anonymous namespace
void Sdp::setMediaDescriptorLine (sdpMedia *media, pjmedia_sdp_media** p_med)
pjmedia_sdp_media *Sdp::setMediaDescriptorLine ()
{
pjmedia_sdp_media *med = PJ_POOL_ZALLOC_T (memPool_, pjmedia_sdp_media);
pjmedia_sdp_media* med;
pjmedia_sdp_rtpmap rtpmap;
pjmedia_sdp_attr *attr;
sfl::Codec *codec;
int count, i;
std::string tmp;
med = PJ_POOL_ZALLOC_T (memPool_, pjmedia_sdp_media);
// Get the right media format
pj_strdup (memPool_, &med->desc.media,
(media->get_media_type() == MIME_TYPE_AUDIO) ? &STR_AUDIO : &STR_VIDEO);
med->desc.media = pj_str((char*)"audio");
med->desc.port_count = 1;
med->desc.port = media->get_port();
med->desc.port = localAudioPort_;
// in case of sdes, media are tagged as "RTP/SAVP", RTP/AVP elsewhere
if (srtpCrypto_.empty()) {
pj_strdup (memPool_, &med->desc.transport, &STR_RTP_AVP);
} else {
pj_strdup (memPool_, &med->desc.transport, &STR_RTP_SAVP);
}
med->desc.transport = pj_str(srtpCrypto_.empty() ? (char*)"RTP/AVP" : (char*)"RTP/SAVP");
// Media format ( RTP payload )
count = media->get_media_codec_list().size();
med->desc.fmt_count = count;
med->desc.fmt_count = codec_list_.size();
for (unsigned i=0; i<med->desc.fmt_count; i++) {
sfl::Codec *codec = codec_list_[i];
// add the payload list
std::ostringstream result;
result << (int)codec->getPayloadType ();
for (i=0; i<count; i++) {
codec = media->get_media_codec_list() [i];
tmp = convertIntToString (codec->getPayloadType ());
_debug ("%s", tmp.c_str());
pj_strdup2 (memPool_, &med->desc.fmt[i], tmp.c_str());
pj_strdup2(memPool_, &med->desc.fmt[i], result.str().c_str());
// Add a rtpmap field for each codec
// We could add one only for dynamic payloads because the codecs with static RTP payloads
// are entirely defined in the RFC 3351, but if we want to add other attributes like an asymmetric
// connection, the rtpmap attribute will be useful to specify for which codec it is applicable
pjmedia_sdp_rtpmap rtpmap;
rtpmap.pt = med->desc.fmt[i];
rtpmap.enc_name = pj_str ( (char*) codec->getMimeSubtype().c_str());
......@@ -232,25 +165,20 @@ void Sdp::setMediaDescriptorLine (sdpMedia *media, pjmedia_sdp_media** p_med)
rtpmap.param.ptr = ((char* const)"");
rtpmap.param.slen = 0;
pjmedia_sdp_attr *attr;
pjmedia_sdp_rtpmap_to_attr (memPool_, &rtpmap, &attr);
med->attr[med->attr_count++] = attr;
}
// Add the direction stream
attr = (pjmedia_sdp_attr*) pj_pool_zalloc (memPool_, sizeof (pjmedia_sdp_attr));
med->attr[ med->attr_count++] = pjmedia_sdp_attr_create(memPool_, "sendrecv", NULL);
pj_strdup2 (memPool_, &attr->name, media->get_stream_direction_str().c_str());
med->attr[ med->attr_count++] = attr;
if (!zrtpHelloHash_.empty()) {
if (!zrtpHelloHash_.empty())
addZrtpAttribute (med, zrtpHelloHash_);
}
setTelephoneEventRtpmap(med);
*p_med = med;
return med;
}
void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med)
......@@ -273,299 +201,135 @@ void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med)
void Sdp::setLocalMediaCapabilities (const CodecOrder &selectedCodecs)
{
sdpMedia *audio;
// Clean it first
localAudioMediaCap_.clear();
_debug ("SDP: Fetch local media capabilities. Local extern audio port: %i" , getLocalPublishedAudioPort());
/* Only one audio media used right now */
audio = new sdpMedia (MIME_TYPE_AUDIO);
audio->set_port (getLocalPublishedAudioPort());
if (selectedCodecs.size() == 0)
_warn("No selected codec while building local SDP offer");
else {
for (CodecOrder::const_iterator iter = selectedCodecs.begin(); iter != selectedCodecs.end(); ++iter) {
sfl::Codec *codec = Manager::instance().audioCodecFactory.getCodec(*iter);
if (codec)
audio->add_codec(codec);
else
_warn ("SDP: Couldn't find audio codec");
}
}
localAudioMediaCap_.push_back (audio);
codec_list_.clear();
for (CodecOrder::const_iterator iter = selectedCodecs.begin(); iter != selectedCodecs.end(); ++iter) {
sfl::Codec *codec = Manager::instance().audioCodecFactory.getCodec(*iter);
if (codec)
codec_list_.push_back(codec);
else
_warn ("SDP: Couldn't find audio codec");
}
}
int Sdp::createLocalSession (const CodecOrder &selectedCodecs)
{
char buffer[1000];
setLocalMediaCapabilities (selectedCodecs);
_info ("SDP: Create local session");
localSession_ = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_session);
localSession_->conn = PJ_POOL_ZALLOC_T(memPool_, pjmedia_sdp_conn);
// Build local media capabilities
setLocalMediaCapabilities (selectedCodecs);
/* Initialize the fields of the struct */
localSession_->origin.version = 0;
pj_time_val tv;
pj_gettimeofday (&tv);
// Reference: RFC 4566 [5]
localSession_->origin.user = pj_str (pj_gethostname()->ptr);
// Use Network Time Protocol format timestamp to ensure uniqueness.
localSession_->origin.id = tv.sec + 2208988800UL;
localSession_->origin.net_type = pj_str((char*)"IN");
localSession_->origin.addr_type = pj_str((char*)"IP4");
localSession_->origin.addr = pj_str((char*)localIpAddr_.c_str());
/* Create and initialize basic SDP session */
localSession_ = PJ_POOL_ZALLOC_T (memPool_, pjmedia_sdp_session);
localSession_->conn = PJ_POOL_ZALLOC_T (memPool_, pjmedia_sdp_conn);
localSession_->name = pj_str((char*)"sflphone");
/* Initialize the fields of the struct */
addProtocol();
addOrigin();
addSessionName();
addConnectionInfo();
addTiming();
addAudioMediaDescription();
if (!srtpCrypto_.empty()) {
localSession_->conn->net_type = localSession_->origin.net_type;
localSession_->conn->addr_type = localSession_->origin.addr_type;
localSession_->conn->addr = localSession_->origin.addr;
// RFC 3264: An offer/answer model session description protocol
// As the session is created and destroyed through an external signaling mean (SIP), the line
// should have a value of "0 0".
localSession_->time.start = 0;
localSession_->time.stop = 0;
// For DTMF RTP events
localSession_->media_count = 1;
localSession_->media[0] = setMediaDescriptorLine();
if (!srtpCrypto_.empty())
addSdesAttribute (srtpCrypto_);
}
memset(buffer, 0, 1000);
pjmedia_sdp_print(localSession_, buffer, 1000);
char buffer[1000];
pjmedia_sdp_print(localSession_, buffer, sizeof(buffer));
_debug("SDP: Local SDP Session:\n%s", buffer);
// Validate the sdp session
return pjmedia_sdp_validate (localSession_);
}
int Sdp::createOffer (const CodecOrder &selectedCodecs)
void Sdp::createOffer (const CodecOrder &selectedCodecs)
{
pj_status_t status;
// Build the SDP session descriptor
status = createLocalSession (selectedCodecs);
if (status != PJ_SUCCESS) {
if (createLocalSession (selectedCodecs) != PJ_SUCCESS)
_error ("SDP: Error: Failed to create initial offer");
return status;
}