Include all possible payload types into 200 OK and actually accept any of them

in the RTP stream. It is possible to disable this new behaviour using
single_codec_in_ok parameter in the sems.conf.

Developed by:	Sippy Software, Inc.
Sponsored by:	Digifonica Canada Limited


git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@279 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Maxim Sobolev 19 years ago
parent 4e6f4a917b
commit 3b527c2353

@ -28,6 +28,7 @@
#include "AmAudio.h"
#include "AmPlugIn.h"
#include "AmUtils.h"
#include "AmSdp.h"
#include "amci/codecs.h"
#include "log.h"
@ -38,19 +39,89 @@
#include <typeinfo>
AmAudioRtpFormat::AmAudioRtpFormat(int payload, string format_parameters)
: AmAudioFormat(), payload(payload), amci_pl(0)
struct CodecContainer
{
sdp_format_parameters = format_parameters;
codec = getCodec();
amci_payload_t* pl = getPayloadP();
if(pl && codec){
channels = pl->channels;
rate = pl->sample_rate;
} else {
ERROR("Could not find payload <%i>\n",payload);
}
amci_codec_t *codec;
int frame_size;
int frame_length;
int frame_encoded_size;
long h_codec;
};
AmAudioRtpFormat::AmAudioRtpFormat(const vector<SdpPayload *>& payloads)
: AmAudioFormat(), m_payloads(payloads), m_currentPayload(-1)
{
for (vector<SdpPayload *>::iterator it = m_payloads.begin();
it != m_payloads.end(); ++it)
{
m_sdpPayloadByPayload[(*it)->payload_type] = *it;
}
setCurrentPayload(m_payloads[0]->payload_type);
}
void AmAudioRtpFormat::setCurrentPayload(int payload)
{
if (m_currentPayload != payload)
{
map<int, SdpPayload *>::iterator p = m_sdpPayloadByPayload.find(payload);
if (p == m_sdpPayloadByPayload.end())
{
ERROR("Could not find payload <%i>\n", payload);
return;
}
map<int, amci_payload_t *>::iterator pp = m_payloadPByPayload.find(payload);
if (pp == m_payloadPByPayload.end())
{
m_currentPayloadP = AmPlugIn::instance()->payload(p->second->int_pt);
if (m_currentPayloadP == NULL)
{
ERROR("Could not find payload <%i>\n", payload);
return;
}
m_payloadPByPayload[payload] = m_currentPayloadP;
}
else
m_currentPayloadP = pp->second;
m_currentPayload = payload;
sdp_format_parameters = p->second->sdp_format_parameters;
map<int, CodecContainer *>::iterator c = m_codecContainerByPayload.find(payload);
if (c == m_codecContainerByPayload.end())
{
codec = NULL;
getCodec();
if (codec)
{
CodecContainer *cc = new CodecContainer();
cc->codec = codec;
cc->frame_size = frame_size;
cc->frame_length = frame_length;
cc->frame_encoded_size = frame_encoded_size;
cc->h_codec = h_codec;
m_codecContainerByPayload[payload] = cc;
}
}
else
{
codec = c->second->codec;
frame_size = c->second->frame_size;
frame_length = c->second->frame_length;
frame_encoded_size = c->second->frame_encoded_size;
h_codec = c->second->h_codec;
}
if (m_currentPayloadP && codec) {
channels = m_currentPayloadP->channels;
rate = m_currentPayloadP->sample_rate;
} else {
ERROR("Could not find payload <%i>\n", payload);
}
}
}
AmAudioRtpFormat::~AmAudioRtpFormat()
{
for (map<int, CodecContainer *>::iterator it = m_codecContainerByPayload.begin(); it != m_codecContainerByPayload.end(); ++it)
delete it->second;
}
AmAudioFormat::AmAudioFormat()
@ -677,22 +748,12 @@ int AmAudioFileFormat::getCodecId()
}
amci_payload_t* AmAudioRtpFormat::getPayloadP()
{
if(!amci_pl)
amci_pl = AmPlugIn::instance()->payload(payload);
return amci_pl;
}
int AmAudioRtpFormat::getCodecId()
{
amci_payload_t* pl = getPayloadP();
if(!pl){
ERROR("AmAudioRtpFormat::getCodecId: could not find payload %i\n",payload);
if(!m_currentPayloadP){
ERROR("AmAudioRtpFormat::getCodecId: could not find payload %i\n", m_currentPayload);
return -1;
}
else
return pl->codec_id;
return m_currentPayloadP->codec_id;
}

@ -38,10 +38,15 @@
using std::auto_ptr;
#include <string>
using std::string;
#include <map>
using std::map;
#define PCM16_B2S(b) ((b) >> 1)
#define PCM16_S2B(s) ((s) << 1)
class SdpPayload;
class CodecContainer;
/** \brief Audio Event */
class AmAudioEvent: public AmEvent
{
@ -206,14 +211,15 @@ public:
/** \brief RTP audio format */
class AmAudioRtpFormat: public AmAudioFormat
{
/** ==-1 if not yet initialized. */
int payload;
/** == 0 if not yet initialized. */
amci_payload_t* amci_pl;
vector<SdpPayload *> m_payloads;
int m_currentPayload;
amci_payload_t *m_currentPayloadP;
map<int, SdpPayload *> m_sdpPayloadByPayload;
map<int, amci_payload_t *> m_payloadPByPayload;
map<int, CodecContainer *> m_codecContainerByPayload;
protected:
int getCodecId();
amci_payload_t* getPayloadP();
public:
/**
@ -221,10 +227,10 @@ public:
* All the information are taken from the
* payload description in the originating plug-in.
*/
AmAudioRtpFormat(int payload, string format_parameters);
AmAudioRtpFormat(const vector<SdpPayload *>& payloads);
~AmAudioRtpFormat();
/** @return Payload ID. */
int getPayload() { return payload; }
void setCurrentPayload(int payload);
};
/**

@ -55,6 +55,7 @@ int AmConfig::MediaProcessorThreads = NUM_MEDIA_PROCESSORS;
int AmConfig::LocalSIPPort = 5060;
string AmConfig::LocalSIPIP = "";
string AmConfig::Signature = "";
bool AmConfig::SingleCodecInOK = false;
AmSessionTimerConfig AmConfig::defaultSessionTimerConfig;
@ -237,6 +238,10 @@ int AmConfig::readConfiguration()
return -1;
}
}
// single codec in 200 OK
if(cfg.hasParameter("single_codec_in_ok")){
SingleCodecInOK = (cfg.getParameter("single_codec_in_ok") == "yes");
}
return defaultSessionTimerConfig.readFromConfig(cfg);
}

@ -85,6 +85,8 @@ struct AmConfig
static int LocalSIPPort;
/** Server/User-Agent header (optional) */
static string Signature;
/** If 200 OK reply should be limited to preferred codec only */
static bool SingleCodecInOK;
/** Init function. Resolves SMTP server address. */
static int init();

@ -77,10 +77,14 @@ int AmRtpAudio::receive(unsigned int audio_buffer_ts)
unsigned int rtp_ts;
while(true) {
int payload;
size = AmRtpStream::receive((unsigned char*)samples,
(unsigned int)AUDIO_BUFFER_SIZE, rtp_ts);
(unsigned int)AUDIO_BUFFER_SIZE, rtp_ts,
payload);
if(size <= 0)
break;
setCurrentPayload(payload);
if(send_only){
playout_buffer->clearLastTs();
@ -122,12 +126,16 @@ int AmRtpAudio::write(unsigned int user_ts, unsigned int size)
return send(user_ts,(unsigned char*)samples,size);
}
void AmRtpAudio::init(const SdpPayload* sdp_payload)
void AmRtpAudio::init(const vector<SdpPayload*>& sdp_payloads)
{
DBG("AmRtpAudio::init(...)\n");
AmRtpStream::init(sdp_payload);
fmt.reset(new AmAudioRtpFormat(int_payload, format_parameters));
AmRtpStream::init(sdp_payloads);
fmt.reset(new AmAudioRtpFormat(sdp_payloads));
}
void AmRtpAudio::setCurrentPayload(int payload)
{
((AmAudioRtpFormat *) fmt.get())->setCurrentPayload(payload);
amci_codec_t* codec = fmt->getCodec();
use_default_plc = !(codec && codec->plc);
}

@ -70,6 +70,8 @@ public:
bool checkInterval(unsigned int ts);
bool sendIntReached();
void setCurrentPayload(int payload);
int receive(unsigned int audio_buffer_ts);
void setSendOnly(bool so){
@ -84,7 +86,7 @@ public:
unsigned int nb_samples);
// AmRtpStream interface
void init(const SdpPayload* sdp_payload);
void init(const vector<SdpPayload*>& sdp_payloads);
void setPlayoutType(PlayoutType type);

@ -193,7 +193,7 @@ int AmRtpStream::send( unsigned int ts, unsigned char* buffer, unsigned int size
// @param audio_buffer_ts [in] current ts at the audio_buffer
int AmRtpStream::receive( unsigned char* buffer, unsigned int size,
unsigned int& ts)
unsigned int& ts, int &out_payload)
{
AmRtpPacket rp;
int err = nextPacket(rp);
@ -247,9 +247,11 @@ int AmRtpStream::receive( unsigned char* buffer, unsigned int size,
return RTP_DTMF;
}
/*
if (payload != rp.payload){
return RTP_UNKNOWN_PL;
}
*/
assert(rp.getData());
if(rp.getDataSize() > size){
@ -258,6 +260,7 @@ int AmRtpStream::receive( unsigned char* buffer, unsigned int size,
}
memcpy(buffer,rp.getData(),rp.getDataSize());
ts = rp.timestamp;
out_payload = rp.payload;
return rp.getDataSize();
}
@ -361,15 +364,12 @@ void AmRtpStream::setRAddr(const string& addr, unsigned short port)
#endif
}
void AmRtpStream::init(const SdpPayload* sdp_payload)
void AmRtpStream::init(const vector<SdpPayload*>& sdp_payloads)
{
SdpPayload *sdp_payload = sdp_payloads[0];
payload = sdp_payload->payload_type;
int_payload = sdp_payload->int_pt;
last_payload = payload;
if(!sdp_payload->sdp_format_parameters.empty())
format_parameters = sdp_payload->sdp_format_parameters;
else
format_parameters = "";
resume();
}

@ -98,8 +98,6 @@ protected:
*/
int last_payload;
string format_parameters;
string r_host;
unsigned short r_port;
#ifdef SUPPORT_IPV6
@ -153,7 +151,7 @@ public:
int receive( unsigned char* buffer, unsigned int size,
unsigned int& ts);
unsigned int& ts, int& payload);
/** Allocates resources for future use of RTP. */
AmRtpStream(AmSession* _s=0);
@ -211,7 +209,7 @@ public:
* @warning It should be called only if the stream has been completly initialized,
* @warning and only once per session. Use resume() then.
*/
virtual void init(const SdpPayload* sdp_payload);
virtual void init(const vector<SdpPayload*>& sdp_payloads);
/**
* Stops RTP stream.

@ -185,7 +185,7 @@ int AmSdp::parse()
int AmSdp::genResponse(const string& localip, int localport,
string& out_buf)
string& out_buf, bool single_codec)
{
string l_ip = "IP4 " + localip;
@ -218,6 +218,7 @@ int AmSdp::genResponse(const string& localip, int localport,
options += "a=fmtp:" + int2str((*it)->payload_type) + " "
+ (*it)->sdp_format_parameters + "\r\n";
}
if (single_codec) break;
}
if (hasTelephoneEvent())
@ -286,10 +287,11 @@ int AmSdp::genRequest(const string& localip,int localport, string& out_buf)
return 0;
}
SdpPayload* AmSdp::getCompatiblePayload(int media_type, string& addr, int& port)
const vector<SdpPayload *>& AmSdp::getCompatiblePayloads(int media_type, string& addr, int& port)
{
vector<SdpMedia>::iterator m_it;
SdpPayload* payload=0;
SdpPayload *payload;
sup_pl.clear();
AmPlugIn* pi = AmPlugIn::instance();
@ -313,7 +315,7 @@ SdpPayload* AmSdp::getCompatiblePayload(int media_type, string& addr, int& port)
payload->int_pt = a_pl->payload_id;
payload->encoding_name = a_pl->name;
payload->clock_rate = a_pl->sample_rate;
goto end;
sup_pl.push_back(payload);
}
else {
// Try dynamic payloads
@ -331,37 +333,30 @@ SdpPayload* AmSdp::getCompatiblePayload(int media_type, string& addr, int& port)
payload = &(*it);
payload->int_pt = int_pt;
goto end;
sup_pl.push_back(payload);
}
}
}
}
end:
sup_pl.clear();
if(payload){
DBG("payload found: %i/%s/%i\n",
payload->int_pt,payload->encoding_name.c_str(),payload->clock_rate);
if(m_it->conn.address.empty()){
DBG("using global address: %s\n",conn.address.c_str());
addr = conn.address;
}
else {
DBG("using media specific address: %s\n",m_it->conn.address.c_str());
addr = m_it->conn.address;
if (sup_pl.size() > 0)
{
if (m_it->conn.address.empty())
{
DBG("using global address: %s\n",conn.address.c_str());
addr = conn.address;
}
else {
DBG("using media specific address: %s\n",m_it->conn.address.c_str());
addr = m_it->conn.address;
}
if(m_it->dir == SdpMedia::DirActive)
remote_active = true;
port = (int)m_it->port;
}
if(m_it->dir == SdpMedia::DirActive)
remote_active = true;
sup_pl.push_back(payload);
port = (int)m_it->port;
break;
}
return payload;
return sup_pl;
}
bool AmSdp::hasTelephoneEvent()

@ -171,7 +171,7 @@ public:
* @return !=0 if error encountered.
*/
int genResponse(const string& localip, int localport,
string& out_buf);
string& out_buf, bool single_codec = false);
/**
* Generate an SDP offer.
@ -181,9 +181,9 @@ public:
/**
* Get a compatible payload from SDP offer/response.
* @return NULL if error encountered.
* @return empty vector if error encountered.
*/
SdpPayload* getCompatiblePayload(int media_type, string& addr, int& port);
const vector<SdpPayload*>& getCompatiblePayloads(int media_type, string& addr, int& port);
/**
* Test if remote UA supports 'telefone_event'.

@ -125,7 +125,7 @@ AmSession::AmSession()
dlg(this),
detached(true),
sess_stopped(false),rtp_str(this),negotiate_onreply(false),
input(0), output(0), payload(0),
input(0), output(0),
m_dtmfDetector(this), m_dtmfEventQueue(&m_dtmfDetector),
m_dtmfDetectionEnabled(true)
{
@ -207,9 +207,9 @@ void AmSession::setLocalTag(const string& tag)
dlg.local_tag = tag;
}
const SdpPayload* AmSession::getPayload()
const vector<SdpPayload*>& AmSession::getPayloads()
{
return &payload;
return m_payloads;
}
int AmSession::getRPort()
@ -232,11 +232,12 @@ void AmSession::negotiate(const string& sdp_body,
if(sdp.media.empty())
throw AmSession::Exception(400,"no media line found in SDP message");
SdpPayload* tmp_pl = sdp.getCompatiblePayload(MT_AUDIO,r_host,r_port);
m_payloads = sdp.getCompatiblePayloads(MT_AUDIO, r_host, r_port);
if(!tmp_pl)
if (m_payloads.size() == 0)
throw AmSession::Exception(606,"could not find compatible payload");
/*
if(payload.int_pt == -1){
payload = *tmp_pl;
@ -246,6 +247,7 @@ void AmSession::negotiate(const string& sdp_body,
DBG("old payload: %i; new payload: %i\n",payload.int_pt,tmp_pl->int_pt);
throw AmSession::Exception(400,"do not accept payload changes");
}
*/
const SdpPayload *telephone_event_payload = sdp.telephoneEventPayload();
if(telephone_event_payload)
@ -277,7 +279,7 @@ void AmSession::negotiate(const string& sdp_body,
unlockAudio();
if(sdp_reply)
sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),*sdp_reply);
sdp.genResponse(AmConfig::LocalIP,rtp_str.getLocalPort(),*sdp_reply, AmConfig::SingleCodecInOK);
}
void AmSession::run()
@ -620,7 +622,7 @@ int AmSession::acceptAudio(const string& body,
// enable RTP stream
lockAudio();
rtp_str.init(&payload);
rtp_str.init(m_payloads);
unlockAudio();
DBG("Sending Rtp data to %s/%i\n",

@ -108,7 +108,7 @@ class AmSession : public AmThread,
AmAudio* input;
AmAudio* output;
SdpPayload payload;
vector<SdpPayload *> m_payloads;
bool negotiate_onreply;
AmDtmfDetector m_dtmfDetector;
@ -248,7 +248,7 @@ public:
void setLocalTag(const string& tag);
/** Gets the current RTP payload */
const SdpPayload* getPayload();
const vector<SdpPayload*>& getPayloads();
/** Gets the port number of the remote part of the session */
int getRPort();

@ -143,3 +143,11 @@ media_processor_threads=1
#
#
# signature="SEMS media server 1.0"
# optional parameter: single_codec_in_ok={yes|no}
#
# - use single codec in 200 OK response
#
# default=no
#
# single_codec_in_ok=no

Loading…
Cancel
Save