~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjmedia/src/pjmedia/session.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* 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
/* $Id: session.c 3841 2011-10-24 09:28:13Z ming $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjmedia/session.h>
 
21
#include <pjmedia/errno.h>
 
22
#include <pj/log.h>
 
23
#include <pj/os.h> 
 
24
#include <pj/pool.h>
 
25
#include <pj/string.h>
 
26
#include <pj/assert.h>
 
27
#include <pj/ctype.h>
 
28
#include <pj/rand.h>
 
29
 
 
30
 
 
31
struct pjmedia_session
 
32
{
 
33
    pj_pool_t              *pool;
 
34
    pjmedia_endpt          *endpt;
 
35
    unsigned                stream_cnt;
 
36
    pjmedia_stream_info     stream_info[PJMEDIA_MAX_SDP_MEDIA];
 
37
    pjmedia_stream         *stream[PJMEDIA_MAX_SDP_MEDIA];
 
38
    void                   *user_data;
 
39
};
 
40
 
 
41
#define THIS_FILE               "session.c"
 
42
 
 
43
#ifndef PJMEDIA_SESSION_SIZE
 
44
#   define PJMEDIA_SESSION_SIZE (10*1024)
 
45
#endif
 
46
 
 
47
#ifndef PJMEDIA_SESSION_INC
 
48
#   define PJMEDIA_SESSION_INC  1024
 
49
#endif
 
50
 
 
51
 
 
52
static const pj_str_t ID_AUDIO = { "audio", 5};
 
53
static const pj_str_t ID_VIDEO = { "video", 5};
 
54
static const pj_str_t ID_APPLICATION = { "application", 11};
 
55
static const pj_str_t ID_IN = { "IN", 2 };
 
56
static const pj_str_t ID_IP4 = { "IP4", 3};
 
57
static const pj_str_t ID_IP6 = { "IP6", 3};
 
58
static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
 
59
static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
 
60
//static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };
 
61
static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
 
62
static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 };
 
63
 
 
64
static const pj_str_t STR_INACTIVE = { "inactive", 8 };
 
65
static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
 
66
static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
 
67
static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
 
68
 
 
69
/*
 
70
 * Initialize session info from SDP session descriptors.
 
71
 */
 
72
PJ_DEF(pj_status_t) pjmedia_session_info_from_sdp( pj_pool_t *pool,
 
73
                               pjmedia_endpt *endpt,
 
74
                               unsigned max_streams,
 
75
                               pjmedia_session_info *si,
 
76
                               const pjmedia_sdp_session *local,
 
77
                               const pjmedia_sdp_session *remote)
 
78
{
 
79
    unsigned i;
 
80
 
 
81
    PJ_ASSERT_RETURN(pool && endpt && si && local && remote, PJ_EINVAL);
 
82
 
 
83
    si->stream_cnt = max_streams;
 
84
    if (si->stream_cnt > local->media_count)
 
85
        si->stream_cnt = local->media_count;
 
86
 
 
87
    for (i=0; i<si->stream_cnt; ++i) {
 
88
        pj_status_t status;
 
89
 
 
90
        status = pjmedia_stream_info_from_sdp( &si->stream_info[i], pool,
 
91
                                               endpt, 
 
92
                                               local, remote, i);
 
93
        if (status != PJ_SUCCESS)
 
94
            return status;
 
95
    }
 
96
 
 
97
    return PJ_SUCCESS;
 
98
}
 
99
 
 
100
 
 
101
/**
 
102
 * Create new session.
 
103
 */
 
104
PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 
 
105
                                            const pjmedia_session_info *si,
 
106
                                            pjmedia_transport *transports[],
 
107
                                            void *user_data,
 
108
                                            pjmedia_session **p_session )
 
109
{
 
110
    pj_pool_t *pool;
 
111
    pjmedia_session *session;
 
112
    int i; /* Must be signed */
 
113
    pj_status_t status;
 
114
 
 
115
    /* Verify arguments. */
 
116
    PJ_ASSERT_RETURN(endpt && si && p_session, PJ_EINVAL);
 
117
 
 
118
    /* Create pool for the session. */
 
119
    pool = pjmedia_endpt_create_pool( endpt, "session", 
 
120
                                      PJMEDIA_SESSION_SIZE, 
 
121
                                      PJMEDIA_SESSION_INC);
 
122
    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
 
123
 
 
124
    session = PJ_POOL_ZALLOC_T(pool, pjmedia_session);
 
125
    session->pool = pool;
 
126
    session->endpt = endpt;
 
127
    session->stream_cnt = si->stream_cnt;
 
128
    session->user_data = user_data;
 
129
 
 
130
    /* Copy stream info (this simple memcpy may break sometime) */
 
131
    pj_memcpy(session->stream_info, si->stream_info,
 
132
              si->stream_cnt * sizeof(pjmedia_stream_info));
 
133
 
 
134
    /*
 
135
     * Now create and start the stream!
 
136
     */
 
137
    for (i=0; i<(int)si->stream_cnt; ++i) {
 
138
 
 
139
        /* Create the stream */
 
140
        status = pjmedia_stream_create(endpt, session->pool,
 
141
                                       &session->stream_info[i],
 
142
                                       (transports?transports[i]:NULL),
 
143
                                       session,
 
144
                                       &session->stream[i]);
 
145
        if (status == PJ_SUCCESS)
 
146
            status = pjmedia_stream_start(session->stream[i]);
 
147
 
 
148
        if (status != PJ_SUCCESS) {
 
149
 
 
150
            for ( --i; i>=0; ++i) {
 
151
                pjmedia_stream_destroy(session->stream[i]);
 
152
            }
 
153
 
 
154
            pj_pool_release(session->pool);
 
155
            return status;
 
156
        }
 
157
    }
 
158
 
 
159
 
 
160
    /* Done. */
 
161
 
 
162
    *p_session = session;
 
163
    return PJ_SUCCESS;
 
164
}
 
165
 
 
166
 
 
167
/*
 
168
 * Get session info.
 
169
 */
 
170
PJ_DEF(pj_status_t) pjmedia_session_get_info( pjmedia_session *session,
 
171
                                              pjmedia_session_info *info )
 
172
{
 
173
    PJ_ASSERT_RETURN(session && info, PJ_EINVAL);
 
174
 
 
175
    info->stream_cnt = session->stream_cnt;
 
176
    pj_memcpy(info->stream_info, session->stream_info,
 
177
              session->stream_cnt * sizeof(pjmedia_stream_info));
 
178
 
 
179
    return PJ_SUCCESS;
 
180
}
 
181
 
 
182
/*
 
183
 * Get user data.
 
184
 */
 
185
PJ_DEF(void*) pjmedia_session_get_user_data( pjmedia_session *session)
 
186
{
 
187
    return (session? session->user_data : NULL);
 
188
}
 
189
 
 
190
/**
 
191
 * Destroy media session.
 
192
 */
 
193
PJ_DEF(pj_status_t) pjmedia_session_destroy (pjmedia_session *session)
 
194
{
 
195
    unsigned i;
 
196
 
 
197
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
198
 
 
199
    for (i=0; i<session->stream_cnt; ++i) {
 
200
        
 
201
        pjmedia_stream_destroy(session->stream[i]);
 
202
 
 
203
    }
 
204
 
 
205
    pj_pool_release (session->pool);
 
206
 
 
207
    return PJ_SUCCESS;
 
208
}
 
209
 
 
210
 
 
211
/**
 
212
 * Activate all stream in media session.
 
213
 *
 
214
 */
 
215
PJ_DEF(pj_status_t) pjmedia_session_resume(pjmedia_session *session,
 
216
                                           pjmedia_dir dir)
 
217
{
 
218
    unsigned i;
 
219
 
 
220
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
221
 
 
222
    for (i=0; i<session->stream_cnt; ++i) {
 
223
        pjmedia_session_resume_stream(session, i, dir);
 
224
    }
 
225
 
 
226
    return PJ_SUCCESS;
 
227
}
 
228
 
 
229
 
 
230
/**
 
231
 * Suspend receipt and transmission of all stream in media session.
 
232
 *
 
233
 */
 
234
PJ_DEF(pj_status_t) pjmedia_session_pause(pjmedia_session *session,
 
235
                                          pjmedia_dir dir)
 
236
{
 
237
    unsigned i;
 
238
 
 
239
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
240
 
 
241
    for (i=0; i<session->stream_cnt; ++i) {
 
242
        pjmedia_session_pause_stream(session, i, dir);
 
243
    }
 
244
 
 
245
    return PJ_SUCCESS;
 
246
}
 
247
 
 
248
 
 
249
/**
 
250
 * Suspend receipt and transmission of individual stream in media session.
 
251
 */
 
252
PJ_DEF(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session,
 
253
                                                  unsigned index,
 
254
                                                  pjmedia_dir dir)
 
255
{
 
256
    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
 
257
 
 
258
    return pjmedia_stream_pause(session->stream[index], dir);
 
259
}
 
260
 
 
261
 
 
262
/**
 
263
 * Activate individual stream in media session.
 
264
 *
 
265
 */
 
266
PJ_DEF(pj_status_t) pjmedia_session_resume_stream( pjmedia_session *session,
 
267
                                                   unsigned index,
 
268
                                                   pjmedia_dir dir)
 
269
{
 
270
    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
 
271
 
 
272
    return pjmedia_stream_resume(session->stream[index], dir);
 
273
}
 
274
 
 
275
/**
 
276
 * Send RTCP SDES for the session.
 
277
 */
 
278
PJ_DEF(pj_status_t) 
 
279
pjmedia_session_send_rtcp_sdes( const pjmedia_session *session )
 
280
{
 
281
    unsigned i;
 
282
 
 
283
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
284
 
 
285
    for (i=0; i<session->stream_cnt; ++i) {
 
286
        pjmedia_stream_send_rtcp_sdes(session->stream[i]);
 
287
    }
 
288
 
 
289
    return PJ_SUCCESS;
 
290
}
 
291
 
 
292
/**
 
293
 * Send RTCP BYE for the session.
 
294
 */
 
295
PJ_DEF(pj_status_t) 
 
296
pjmedia_session_send_rtcp_bye( const pjmedia_session *session )
 
297
{
 
298
    unsigned i;
 
299
 
 
300
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
301
 
 
302
    for (i=0; i<session->stream_cnt; ++i) {
 
303
        pjmedia_stream_send_rtcp_bye(session->stream[i]);
 
304
    }
 
305
 
 
306
    return PJ_SUCCESS;
 
307
}
 
308
 
 
309
/**
 
310
 * Enumerate media stream in the session.
 
311
 */
 
312
PJ_DEF(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session,
 
313
                                                 unsigned *count, 
 
314
                                                 pjmedia_stream_info info[])
 
315
{
 
316
    unsigned i;
 
317
 
 
318
    PJ_ASSERT_RETURN(session && count && *count && info, PJ_EINVAL);
 
319
 
 
320
    if (*count > session->stream_cnt)
 
321
        *count = session->stream_cnt;
 
322
 
 
323
    for (i=0; i<*count; ++i) {
 
324
        pj_memcpy(&info[i], &session->stream_info[i], 
 
325
                  sizeof(pjmedia_stream_info));
 
326
    }
 
327
 
 
328
    return PJ_SUCCESS;
 
329
}
 
330
 
 
331
 
 
332
/*
 
333
 * Get the port interface.
 
334
 */
 
335
PJ_DEF(pj_status_t) pjmedia_session_get_port(  pjmedia_session *session,
 
336
                                               unsigned index,
 
337
                                               pjmedia_port **p_port)
 
338
{
 
339
    return pjmedia_stream_get_port( session->stream[index], p_port);
 
340
}
 
341
 
 
342
/*
 
343
 * Get statistics
 
344
 */
 
345
PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( pjmedia_session *session,
 
346
                                                     unsigned index,
 
347
                                                     pjmedia_rtcp_stat *stat)
 
348
{
 
349
    PJ_ASSERT_RETURN(session && stat && index < session->stream_cnt, 
 
350
                     PJ_EINVAL);
 
351
 
 
352
    return pjmedia_stream_get_stat(session->stream[index], stat);
 
353
}
 
354
 
 
355
 
 
356
/**
 
357
 * Reset session statistics.
 
358
 */
 
359
PJ_DEF(pj_status_t) pjmedia_session_reset_stream_stat( pjmedia_session *session,
 
360
                                                       unsigned index)
 
361
{
 
362
    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
 
363
 
 
364
    return pjmedia_stream_reset_stat(session->stream[index]);
 
365
}
 
366
 
 
367
 
 
368
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
 
369
/*
 
370
 * Get extended statistics
 
371
 */
 
372
PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat_xr(
 
373
                                             pjmedia_session *session,
 
374
                                             unsigned index,
 
375
                                             pjmedia_rtcp_xr_stat *stat_xr)
 
376
{
 
377
    PJ_ASSERT_RETURN(session && stat_xr && index < session->stream_cnt, 
 
378
                     PJ_EINVAL);
 
379
 
 
380
    return pjmedia_stream_get_stat_xr(session->stream[index], stat_xr);
 
381
}
 
382
#endif
 
383
 
 
384
PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat_jbuf(
 
385
                                            pjmedia_session *session,
 
386
                                            unsigned index,
 
387
                                            pjmedia_jb_state *state)
 
388
{
 
389
    PJ_ASSERT_RETURN(session && state && index < session->stream_cnt, 
 
390
                     PJ_EINVAL);
 
391
 
 
392
    return pjmedia_stream_get_stat_jbuf(session->stream[index], state);
 
393
}
 
394
 
 
395
/*
 
396
 * Dial DTMF digit to the stream, using RFC 2833 mechanism.
 
397
 */
 
398
PJ_DEF(pj_status_t) pjmedia_session_dial_dtmf( pjmedia_session *session,
 
399
                                               unsigned index,
 
400
                                               const pj_str_t *ascii_digits )
 
401
{
 
402
    PJ_ASSERT_RETURN(session && ascii_digits, PJ_EINVAL);
 
403
    return pjmedia_stream_dial_dtmf(session->stream[index], ascii_digits);
 
404
}
 
405
 
 
406
/*
 
407
 * Check if the specified stream has received DTMF digits.
 
408
 */
 
409
PJ_DEF(pj_status_t) pjmedia_session_check_dtmf( pjmedia_session *session,
 
410
                                                unsigned index )
 
411
{
 
412
    PJ_ASSERT_RETURN(session, PJ_EINVAL);
 
413
    return pjmedia_stream_check_dtmf(session->stream[index]);
 
414
}
 
415
 
 
416
 
 
417
/*
 
418
 * Retrieve DTMF digits from the specified stream.
 
419
 */
 
420
PJ_DEF(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session,
 
421
                                              unsigned index,
 
422
                                              char *ascii_digits,
 
423
                                              unsigned *size )
 
424
{
 
425
    PJ_ASSERT_RETURN(session && ascii_digits && size, PJ_EINVAL);
 
426
    return pjmedia_stream_get_dtmf(session->stream[index], ascii_digits,
 
427
                                   size);
 
428
}
 
429
 
 
430
/*
 
431
 * Install DTMF callback.
 
432
 */
 
433
PJ_DEF(pj_status_t) pjmedia_session_set_dtmf_callback(pjmedia_session *session,
 
434
                                  unsigned index,
 
435
                                  void (*cb)(pjmedia_stream*, 
 
436
                                             void *user_data, 
 
437
                                             int digit), 
 
438
                                  void *user_data)
 
439
{
 
440
    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
 
441
    return pjmedia_stream_set_dtmf_callback(session->stream[index], cb,
 
442
                                            user_data);
 
443
}
 
444