~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/src/sip/sdp.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
 
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
3
 *
4
4
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5
5
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
39
39
#include "manager.h"
40
40
 
41
41
#include <algorithm>
 
42
#include "sipaccount.h"
 
43
 
42
44
 
43
45
#ifdef SFL_VIDEO
44
46
#include "video/libav_utils.h"
60
62
    , video_codec_list_()
61
63
    , sessionAudioMedia_()
62
64
    , sessionVideoMedia_()
63
 
    , localIpAddr_()
 
65
    , publishedIpAddr_()
64
66
    , remoteIpAddr_()
65
67
    , localAudioDataPort_(0)
66
68
    , localAudioControlPort_(0)
73
75
    , telephoneEventPayload_(101) // same as asterisk
74
76
{}
75
77
 
 
78
Sdp::~Sdp()
 
79
{
 
80
    SIPAccount::releasePort(localAudioDataPort_);
 
81
#ifdef SFL_VIDEO
 
82
    SIPAccount::releasePort(localVideoDataPort_);
 
83
#endif
 
84
}
 
85
 
76
86
namespace {
77
87
    bool hasPayload(const std::vector<sfl::AudioCodec*> &codecs, int pt)
78
88
    {
79
 
        for (std::vector<sfl::AudioCodec*>::const_iterator i = codecs.begin(); i != codecs.end(); ++i)
80
 
            if (*i and (*i)->getPayloadType() == pt)
 
89
        for (const auto &i : codecs)
 
90
            if (i and i->getPayloadType() == pt)
81
91
                return true;
82
92
        return false;
83
93
    }
110
120
 
111
121
            if (!pj_stricmp2(&current->desc.media, "audio")) {
112
122
                const unsigned long pt = pj_strtoul(&current->desc.fmt[fmt]);
113
 
                if (not hasPayload(sessionAudioMedia_, pt)) {
 
123
                if (pt != telephoneEventPayload_ and not hasPayload(sessionAudioMedia_, pt)) {
114
124
                    sfl::AudioCodec *codec = Manager::instance().audioCodecFactory.getCodec(pt);
115
125
                    if (codec)
116
126
                        sessionAudioMedia_.push_back(codec);
194
204
    return result;
195
205
}
196
206
 
197
 
void Sdp::getSessionAudioMedia(std::vector<sfl::AudioCodec*> &codecs) const
 
207
std::vector<sfl::AudioCodec*>
 
208
Sdp::getSessionAudioMedia() const
198
209
{
199
 
    codecs = sessionAudioMedia_;
 
210
    return sessionAudioMedia_;
200
211
}
201
212
 
202
213
 
214
225
    int dynamic_payload = 96;
215
226
 
216
227
    med->desc.fmt_count = audio ? audio_codec_list_.size() : video_codec_list_.size();
 
228
 
217
229
    for (unsigned i = 0; i < med->desc.fmt_count; ++i) {
218
230
        unsigned clock_rate;
219
231
        string enc_name;
220
232
        int payload;
 
233
        const char *channels = "";
221
234
 
222
235
        if (audio) {
223
236
            sfl::AudioCodec *codec = audio_codec_list_[i];
224
237
            payload = codec->getPayloadType();
225
238
            enc_name = codec->getMimeSubtype();
226
 
            clock_rate = codec->getClockRate();
 
239
            clock_rate = codec->getSDPClockRate();
 
240
            channels = codec->getSDPChannels();
227
241
            // G722 require G722/8000 media description even if it is 16000 codec
228
242
            if (codec->getPayloadType () == 9)
229
243
                clock_rate = 8000;
247
261
        rtpmap.pt = med->desc.fmt[i];
248
262
        rtpmap.enc_name = pj_str((char*) enc_name.c_str());
249
263
        rtpmap.clock_rate = clock_rate;
250
 
        rtpmap.param.ptr = ((char* const)"");
251
 
        rtpmap.param.slen = 0;
 
264
        rtpmap.param.ptr = (char *) channels;
 
265
        rtpmap.param.slen = strlen(channels); // don't include NULL terminator
252
266
 
253
267
        pjmedia_sdp_attr *attr;
254
268
        pjmedia_sdp_rtpmap_to_attr(memPool_, &rtpmap, &attr);
255
269
 
256
270
        med->attr[med->attr_count++] = attr;
 
271
 
257
272
#ifdef SFL_VIDEO
258
273
        if (enc_name == "H264") {
259
274
            std::ostringstream os;
286
301
void Sdp::addRTCPAttribute(pjmedia_sdp_media *med)
287
302
{
288
303
    std::ostringstream os;
289
 
    os << localIpAddr_ << ":" << localAudioControlPort_;
 
304
    os << publishedIpAddr_ << ":" << localAudioControlPort_;
290
305
    const std::string str(os.str());
291
306
    pj_str_t input_str = pj_str((char*) str.c_str());
292
307
    pj_sockaddr outputAddr;
301
316
}
302
317
 
303
318
void
 
319
Sdp::setPublishedIP(const std::string &ip_addr)
 
320
{
 
321
    publishedIpAddr_ = ip_addr;
 
322
    if (localSession_) {
 
323
        localSession_->origin.addr = pj_str((char*) publishedIpAddr_.c_str());
 
324
        localSession_->conn->addr = localSession_->origin.addr;
 
325
        if (pjmedia_sdp_validate(localSession_) != PJ_SUCCESS)
 
326
            ERROR("Could not validate SDP");
 
327
    }
 
328
}
 
329
 
 
330
void
304
331
Sdp::updatePorts(const std::vector<pj_sockaddr_in> &sockets)
305
332
{
306
333
    localAudioDataPort_     = pj_ntohs(sockets[0].sin_port);
307
334
    localAudioControlPort_  = pj_ntohs(sockets[1].sin_port);
308
335
    localVideoDataPort_     = pj_ntohs(sockets[2].sin_port);
309
336
    localVideoControlPort_  = pj_ntohs(sockets[3].sin_port);
 
337
 
 
338
    if (localSession_) {
 
339
        if (localSession_->media[0]) {
 
340
            localSession_->media[0]->desc.port = localAudioDataPort_;
 
341
            // update RTCP attribute
 
342
            if (pjmedia_sdp_media_remove_all_attr(localSession_->media[0], "rtcp"))
 
343
                addRTCPAttribute(localSession_->media[0]);
 
344
        }
 
345
        if (localSession_->media[1])
 
346
            localSession_->media[1]->desc.port = localVideoDataPort_;
 
347
 
 
348
        if (not pjmedia_sdp_validate(localSession_))
 
349
            ERROR("Could not validate SDP");
 
350
    }
310
351
}
311
352
 
312
353
 
313
354
void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med)
314
355
{
 
356
    std::ostringstream s;
 
357
    s << telephoneEventPayload_;
 
358
    ++med->desc.fmt_count;
 
359
    pj_strdup2(memPool_, &med->desc.fmt[med->desc.fmt_count - 1], s.str().c_str());
 
360
 
315
361
    pjmedia_sdp_attr *attr_rtpmap = static_cast<pjmedia_sdp_attr *>(pj_pool_zalloc(memPool_, sizeof(pjmedia_sdp_attr)));
316
362
    attr_rtpmap->name = pj_str((char *) "rtpmap");
317
363
    attr_rtpmap->value = pj_str((char *) "101 telephone-event/8000");
344
390
        WARN("No selected codec while building local SDP offer");
345
391
 
346
392
    audio_codec_list_.clear();
347
 
    for (vector<int>::const_iterator i = selectedCodecs.begin(); i != selectedCodecs.end(); ++i) {
348
 
        sfl::AudioCodec *codec = Manager::instance().audioCodecFactory.getCodec(*i);
 
393
    for (const auto &i : selectedCodecs) {
 
394
        sfl::AudioCodec *codec = Manager::instance().audioCodecFactory.getCodec(i);
349
395
 
350
396
        if (codec)
351
397
            audio_codec_list_.push_back(codec);
382
428
    localSession_->origin.id = tv.sec + 2208988800UL;
383
429
    localSession_->origin.net_type = pj_str((char*) "IN");
384
430
    localSession_->origin.addr_type = pj_str((char*) "IP4");
385
 
    localSession_->origin.addr = pj_str((char*) localIpAddr_.c_str());
 
431
    localSession_->origin.addr = pj_str((char*) publishedIpAddr_.c_str());
386
432
 
387
433
    localSession_->name = pj_str((char*) PACKAGE);
388
434
 
449
495
 
450
496
    remoteSession_ = pjmedia_sdp_session_clone(memPool_, remote);
451
497
 
452
 
    pjmedia_sdp_neg_create_w_remote_offer(memPool_, localSession_,
453
 
                                          remoteSession_, &negotiator_);
 
498
    if (pjmedia_sdp_neg_create_w_remote_offer(memPool_, localSession_,
 
499
            remoteSession_, &negotiator_) != PJ_SUCCESS)
 
500
        ERROR("Failed to initialize negotiator");
454
501
}
455
502
 
456
503
void Sdp::startNegotiation()
499
546
    int size = pjmedia_sdp_print(sess, buffer, sizeof buffer);
500
547
    string sdp(buffer, size);
501
548
    const vector<string> tokens(split(sdp, '\n'));
502
 
    for (vector<string>::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
503
 
        if ((*iter).find(keyword) != string::npos)
504
 
            return *iter;
 
549
    for (const auto &item : tokens)
 
550
        if (item.find(keyword) != string::npos)
 
551
            return item;
505
552
    return "";
506
553
}
507
554
 
613
660
 
614
661
void Sdp::addSdesAttribute(const vector<std::string>& crypto)
615
662
{
616
 
    for (vector<std::string>::const_iterator iter = crypto.begin();
617
 
            iter != crypto.end(); ++iter) {
618
 
        pj_str_t val = { (char*)(*iter).c_str(), static_cast<pj_ssize_t>((*iter).size()) };
 
663
    for (const auto &item : crypto) {
 
664
        pj_str_t val = { (char*) item.c_str(), static_cast<pj_ssize_t>(item.size()) };
619
665
        pjmedia_sdp_attr *attr = pjmedia_sdp_attr_create(memPool_, "crypto", &val);
620
666
 
621
667
        for (unsigned i = 0; i < localSession_->media_count; i++)
759
805
        }
760
806
        return true;
761
807
    }
 
808
#else
 
809
    (void) args;
762
810
#endif
763
811
    return false;
764
812
}