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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/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
 
}