~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to src/stream_output/sap.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 * sap.c : SAP announce handler
3
3
 *****************************************************************************
4
 
 * Copyright (C) 2002-2005 the VideoLAN team
5
 
 * $Id: 64a4554ab03174e2e56b6816111d3882604ca8a4 $
 
4
 * Copyright (C) 2002-2007 the VideoLAN team
 
5
 * $Id: 11bcbc41b8bd6cab255cac188610f7470a293237 $
6
6
 *
7
7
 * Authors: Clément Stenac <zorglub@videolan.org>
8
8
 *          Rémi Denis-Courmont <rem # videolan.org>
25
25
/*****************************************************************************
26
26
 * Preamble
27
27
 *****************************************************************************/
 
28
 
 
29
#ifdef HAVE_CONFIG_H
 
30
# include "config.h"
 
31
#endif
 
32
 
 
33
#include <vlc_common.h>
 
34
 
28
35
#include <stdlib.h>                                                /* free() */
29
36
#include <stdio.h>                                              /* sprintf() */
30
 
#include <string.h>                                            /* strerror() */
 
37
#include <string.h>
31
38
#include <ctype.h>                                  /* tolower(), isxdigit() */
32
 
 
33
 
#include <vlc/vlc.h>
34
 
#include <vlc/sout.h>
35
 
 
36
 
#include "network.h"
37
 
#include "charset.h"
 
39
#include <assert.h>
 
40
 
 
41
#include <vlc_sout.h>
 
42
#include <vlc_network.h>
 
43
#include <vlc_charset.h>
 
44
 
 
45
#include "stream_output.h"
 
46
#include "libvlc.h"
38
47
 
39
48
/* SAP is always on that port */
40
49
#define SAP_PORT 9875
56
65
struct sap_address_t
57
66
{
58
67
    char *psz_address;
59
 
    char psz_machine[NI_MAXNUMERICHOST];
 
68
    struct sockaddr_storage orig;
 
69
    socklen_t origlen;
60
70
    int i_rfd; /* Read socket */
61
71
    int i_wfd; /* Write socket */
62
72
 
63
73
    /* Used for flow control */
64
74
    mtime_t t1;
65
 
    vlc_bool_t b_enabled;
66
 
    vlc_bool_t b_ready;
 
75
    bool b_enabled;
 
76
    bool b_ready;
67
77
    int i_interval;
68
78
    int i_buff;
69
79
    int i_limit;
70
80
};
71
81
 
 
82
/* A SAP session descriptor, enqueued in the SAP handler queue */
 
83
struct sap_session_t {
 
84
    uint8_t       *psz_data;
 
85
    unsigned      i_length;
 
86
    sap_address_t *p_address;
 
87
    session_descriptor_t *p_sd;
 
88
 
 
89
    /* Last and next send */
 
90
    mtime_t        i_last;
 
91
    mtime_t        i_next;
 
92
};
 
93
 
72
94
/*****************************************************************************
73
95
 * Local prototypes
74
96
 *****************************************************************************/
75
 
static void RunThread( vlc_object_t *p_this);
76
 
static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address );
77
 
static char *SDPGenerate( sap_handler_t *p_sap,
78
 
                          const session_descriptor_t *p_session,
79
 
                          const sap_address_t *p_addr, vlc_bool_t b_ssm );
 
97
static void * RunThread( vlc_object_t *p_this);
 
98
static int ComputeRate( sap_address_t *p_address );
80
99
 
81
100
static int announce_SendSAPAnnounce( sap_handler_t *p_sap,
82
101
                                     sap_session_t *p_session );
88
107
static int announce_SAPAnnounceDel( sap_handler_t *p_sap,
89
108
                             session_descriptor_t *p_session );
90
109
 
91
 
#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
 
110
static void announce_SAPHandlerDestructor( vlc_object_t *p_this );
92
111
 
93
112
 
94
113
/**
101
120
{
102
121
    sap_handler_t *p_sap;
103
122
 
104
 
    p_sap = vlc_object_create( p_announce, sizeof( sap_handler_t ) );
105
 
 
 
123
    p_sap = vlc_custom_create( VLC_OBJECT(p_announce), sizeof( sap_handler_t ),
 
124
                               VLC_OBJECT_ANNOUNCE, "sap announcer" );
106
125
    if( !p_sap )
107
 
    {
108
 
        msg_Err( p_announce, "out of memory" );
109
126
        return NULL;
110
 
    }
111
 
 
112
 
    vlc_mutex_init( p_sap, &p_sap->object_lock );
113
127
 
114
128
    p_sap->pf_add = announce_SAPAnnounceAdd;
115
129
    p_sap->pf_del = announce_SAPAnnounceDel;
121
135
    p_sap->b_control = config_GetInt( p_sap, "sap-flow-control");
122
136
 
123
137
    if( vlc_thread_create( p_sap, "sap handler", RunThread,
124
 
                       VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
 
138
                       VLC_THREAD_PRIORITY_LOW, false ) )
125
139
    {
126
140
        msg_Dbg( p_announce, "unable to spawn SAP handler thread");
127
 
        free( p_sap );
 
141
        vlc_object_release( p_sap );
128
142
        return NULL;
129
 
    };
 
143
    }
 
144
 
 
145
    vlc_object_set_destructor( p_sap, announce_SAPHandlerDestructor );
 
146
 
130
147
    msg_Dbg( p_announce, "thread created, %i sessions", p_sap->i_sessions);
 
148
 
131
149
    return p_sap;
132
150
}
133
151
 
134
 
/**
135
 
 *  Destroy the SAP handler
136
 
 *  \param p_this the SAP Handler to destroy
137
 
 *  \return nothing
138
 
 */
139
 
void announce_SAPHandlerDestroy( sap_handler_t *p_sap )
 
152
static void announce_SAPHandlerDestructor( vlc_object_t * p_this )
140
153
{
 
154
    sap_handler_t *p_sap = (sap_handler_t *)p_this;
141
155
    int i;
142
156
 
143
 
    vlc_mutex_destroy( &p_sap->object_lock );
144
 
 
145
157
    /* Free the remaining sessions */
146
158
    for( i = 0 ; i< p_sap->i_sessions ; i++)
147
159
    {
148
160
        sap_session_t *p_session = p_sap->pp_sessions[i];
149
 
        FREE( p_session->psz_sdp );
150
 
        FREE( p_session->psz_data );
 
161
        FREENULL( p_session->psz_data );
151
162
        REMOVE_ELEM( p_sap->pp_sessions, p_sap->i_sessions , i );
152
 
        FREE( p_session );
 
163
        FREENULL( p_session );
153
164
    }
154
165
 
155
166
    /* Free the remaining addresses */
156
167
    for( i = 0 ; i< p_sap->i_addresses ; i++)
157
168
    {
158
169
        sap_address_t *p_address = p_sap->pp_addresses[i];
159
 
        FREE( p_address->psz_address );
 
170
        FREENULL( p_address->psz_address );
160
171
        if( p_address->i_rfd > -1 )
161
172
        {
162
173
            net_Close( p_address->i_rfd );
166
177
            net_Close( p_address->i_wfd );
167
178
        }
168
179
        REMOVE_ELEM( p_sap->pp_addresses, p_sap->i_addresses, i );
169
 
        FREE( p_address );
 
180
        FREENULL( p_address );
170
181
    }
171
 
 
172
 
    /* Free the structure */
173
 
    vlc_object_destroy( p_sap );
174
182
}
175
183
 
176
184
/**
178
186
 * \param p_this the SAP Handler object
179
187
 * \return nothing
180
188
 */
181
 
static void RunThread( vlc_object_t *p_this)
 
189
static void * RunThread( vlc_object_t *p_this)
182
190
{
183
191
    sap_handler_t *p_sap = (sap_handler_t*)p_this;
184
192
    sap_session_t *p_session;
187
195
    {
188
196
        int i;
189
197
 
 
198
        msleep( SAP_IDLE );
 
199
 
190
200
        /* If needed, get the rate info */
191
 
        if( p_sap->b_control == VLC_TRUE )
 
201
        if( p_sap->b_control == true )
192
202
        {
193
203
            for( i = 0 ; i< p_sap->i_addresses ; i++)
194
204
            {
195
 
                if( p_sap->pp_addresses[i]->b_enabled == VLC_TRUE )
 
205
                if( p_sap->pp_addresses[i]->b_enabled == true )
196
206
                {
197
 
                    CalculateRate( p_sap, p_sap->pp_addresses[i] );
 
207
                    ComputeRate( p_sap->pp_addresses[i] );
198
208
                }
199
209
            }
200
210
        }
201
211
 
202
212
        /* Find the session to announce */
203
 
        vlc_mutex_lock( &p_sap->object_lock );
 
213
        vlc_object_lock( p_sap );
204
214
        if( p_sap->i_sessions > p_sap->i_current_session + 1)
205
215
        {
206
216
            p_sap->i_current_session++;
211
221
        }
212
222
        else
213
223
        {
214
 
            vlc_mutex_unlock( &p_sap->object_lock );
215
 
            msleep( SAP_IDLE );
 
224
            vlc_object_unlock( p_sap );
216
225
            continue;
217
226
        }
218
227
        p_session = p_sap->pp_sessions[p_sap->i_current_session];
219
 
        vlc_mutex_unlock( &p_sap->object_lock );
220
228
 
221
229
        /* And announce it */
222
 
        if( p_session->p_address->b_enabled == VLC_TRUE &&
223
 
            p_session->p_address->b_ready == VLC_TRUE )
 
230
        if( p_session->p_address->b_enabled == true &&
 
231
            p_session->p_address->b_ready == true )
224
232
        {
225
233
            announce_SendSAPAnnounce( p_sap, p_session );
226
234
        }
227
 
 
228
 
        msleep( SAP_IDLE );
 
235
        vlc_object_unlock( p_sap );
229
236
    }
 
237
    return NULL;
230
238
}
231
239
 
232
240
/* Add a SAP announce */
233
241
static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
234
242
                             session_descriptor_t *p_session )
235
243
{
236
 
    int i_header_size, i;
237
 
    char *psz_head, psz_addr[NI_MAXNUMERICHOST];
238
 
    vlc_bool_t b_ipv6 = VLC_FALSE, b_ssm = VLC_FALSE;
 
244
    int i;
 
245
    char psz_addr[NI_MAXNUMERICHOST];
 
246
    bool b_ipv6 = false, b_ssm = false;
239
247
    sap_session_t *p_sap_session;
240
248
    mtime_t i_hash;
241
 
    struct addrinfo hints, *res;
242
249
    struct sockaddr_storage addr;
243
 
 
244
 
    vlc_mutex_lock( &p_sap->object_lock );
245
 
 
246
 
    if( p_session->psz_uri == NULL )
 
250
    socklen_t addrlen;
 
251
 
 
252
    vlc_object_lock( p_sap );
 
253
    addrlen = p_session->addrlen;
 
254
    if ((addrlen == 0) || (addrlen > sizeof (addr)))
247
255
    {
248
 
        vlc_mutex_unlock( &p_sap->object_lock );
249
 
        msg_Err( p_sap, "*FIXME* unexpected NULL URI for SAP announce" );
250
 
        msg_Err( p_sap, "This should not happen. VLC needs fixing." );
 
256
        vlc_object_unlock( p_sap );
 
257
        msg_Err( p_sap, "No/invalid address specified for SAP announce" );
251
258
        return VLC_EGENERIC;
252
259
    }
253
260
 
254
261
    /* Determine SAP multicast address automatically */
255
 
    memset( &hints, 0, sizeof( hints ) );
256
 
    hints.ai_socktype = SOCK_DGRAM;
257
 
    hints.ai_flags = AI_NUMERICHOST;
258
 
 
259
 
    i = vlc_getaddrinfo( (vlc_object_t *)p_sap, p_session->psz_uri, 0,
260
 
                         &hints, &res );
261
 
    if( i )
262
 
    {
263
 
        vlc_mutex_unlock( &p_sap->object_lock );
264
 
        msg_Err( p_sap, "Invalid URI for SAP announce: %s: %s",
265
 
                 p_session->psz_uri, vlc_gai_strerror( i ) );
266
 
        return VLC_EGENERIC;
267
 
    }
268
 
 
269
 
    if( (unsigned)res->ai_addrlen > sizeof( addr ) )
270
 
    {
271
 
        vlc_mutex_unlock( &p_sap->object_lock );
272
 
        vlc_freeaddrinfo( res );
273
 
        msg_Err( p_sap, "Unsupported address family of size %d > %u",
274
 
                 res->ai_addrlen, (unsigned) sizeof( addr ) );
275
 
        return VLC_EGENERIC;
276
 
    }
277
 
 
278
 
    memcpy( &addr, res->ai_addr, res->ai_addrlen );
279
 
 
280
 
    switch( addr.ss_family )
 
262
    memcpy (&addr, &p_session->addr, addrlen);
 
263
 
 
264
    switch( p_session->addr.ss_family )
281
265
    {
282
266
#if defined (HAVE_INET_PTON) || defined (WIN32)
283
267
        case AF_INET6:
299
283
                /* Unicast IPv6 - assume global scope */
300
284
                memcpy( a6->s6_addr, "\xff\x0e", 2 );
301
285
 
302
 
            b_ipv6 = VLC_TRUE;
 
286
            b_ipv6 = true;
303
287
            break;
304
288
        }
305
289
#endif
335
319
            if( ipv4 == 0 )
336
320
            {
337
321
                msg_Err( p_sap, "Out-of-scope multicast address "
338
 
                        "not supported by SAP: %s", p_session->psz_uri );
339
 
                vlc_mutex_unlock( &p_sap->object_lock );
340
 
                vlc_freeaddrinfo( res );
 
322
                         "not supported by SAP" );
 
323
                vlc_object_unlock( p_sap );
341
324
                return VLC_EGENERIC;
342
325
            }
343
326
 
346
329
        }
347
330
 
348
331
        default:
349
 
            vlc_mutex_unlock( &p_sap->object_lock );
350
 
            vlc_freeaddrinfo( res );
 
332
            vlc_object_unlock( p_sap );
351
333
            msg_Err( p_sap, "Address family %d not supported by SAP",
352
334
                     addr.ss_family );
353
335
            return VLC_EGENERIC;
354
336
    }
355
337
 
356
 
    i = vlc_getnameinfo( (struct sockaddr *)&addr, res->ai_addrlen,
 
338
    i = vlc_getnameinfo( (struct sockaddr *)&addr, addrlen,
357
339
                         psz_addr, sizeof( psz_addr ), NULL, NI_NUMERICHOST );
358
 
    vlc_freeaddrinfo( res );
359
340
 
360
341
    if( i )
361
342
    {
362
 
        vlc_mutex_unlock( &p_sap->object_lock );
 
343
        vlc_object_unlock( p_sap );
363
344
        msg_Err( p_sap, "%s", vlc_gai_strerror( i ) );
364
345
        return VLC_EGENERIC;
365
346
    }
368
349
 
369
350
    /* XXX: Check for dupes */
370
351
    p_sap_session = (sap_session_t*)malloc(sizeof(sap_session_t));
 
352
    p_sap_session->p_sd = p_session;
371
353
    p_sap_session->p_address = NULL;
372
354
 
373
355
    /* Add the address to the buffer */
386
368
                                    malloc( sizeof(sap_address_t) );
387
369
        if( !p_address )
388
370
        {
389
 
            msg_Err( p_sap, "out of memory" );
 
371
            vlc_object_unlock( p_sap );
390
372
            return VLC_ENOMEM;
391
373
        }
392
374
        p_address->psz_address = strdup( psz_addr );
393
 
        p_address->i_wfd = net_ConnectUDP( p_sap, psz_addr, SAP_PORT, 255 );
 
375
        p_address->i_wfd = net_ConnectUDP( VLC_OBJECT(p_sap), psz_addr, SAP_PORT, 255 );
394
376
        if( p_address->i_wfd != -1 )
395
377
        {
396
 
            char *ptr;
397
 
 
398
 
            net_StopRecv( p_address->i_wfd );
399
 
            net_GetSockAddress( p_address->i_wfd, p_address->psz_machine,
400
 
                                NULL );
401
 
 
402
 
            /* removes scope if present */
403
 
            ptr = strchr( p_address->psz_machine, '%' );
404
 
            if( ptr != NULL )
405
 
                *ptr = '\0';
 
378
            shutdown( p_address->i_wfd, SHUT_RD );
 
379
            p_address->origlen = sizeof (p_address->orig);
 
380
            getsockname (p_address->i_wfd, (struct sockaddr *)&p_address->orig,
 
381
                         &p_address->origlen);
406
382
        }
407
383
 
408
 
        if( p_sap->b_control == VLC_TRUE )
 
384
        if( p_sap->b_control == true )
409
385
        {
410
 
            p_address->i_rfd = net_OpenUDP( p_sap, psz_addr, SAP_PORT, "", 0 );
 
386
            p_address->i_rfd = net_ListenUDP1( (vlc_object_t*)p_sap, psz_addr, SAP_PORT );
411
387
            if( p_address->i_rfd != -1 )
412
 
                net_StopSend( p_address->i_rfd );
 
388
                shutdown( p_address->i_rfd, SHUT_WR );
413
389
            p_address->i_buff = 0;
414
 
            p_address->b_enabled = VLC_TRUE;
415
 
            p_address->b_ready = VLC_FALSE;
 
390
            p_address->b_enabled = true;
 
391
            p_address->b_ready = false;
416
392
            p_address->i_limit = 10000; /* 10000 bps */
417
393
            p_address->t1 = 0;
418
394
        }
419
395
        else
420
396
        {
421
 
            p_address->b_enabled = VLC_TRUE;
422
 
            p_address->b_ready = VLC_TRUE;
 
397
            p_address->b_enabled = true;
 
398
            p_address->b_ready = true;
423
399
            p_address->i_interval = config_GetInt( p_sap,"sap-interval");
424
400
            p_address->i_rfd = -1;
425
401
        }
428
404
                                        && p_sap->b_control ) )
429
405
        {
430
406
            msg_Warn( p_sap, "disabling address" );
431
 
            p_address->b_enabled = VLC_FALSE;
 
407
            p_address->b_enabled = false;
432
408
        }
433
409
 
434
410
        INSERT_ELEM( p_sap->pp_addresses,
438
414
        p_sap_session->p_address = p_address;
439
415
    }
440
416
 
 
417
    memcpy (&p_session->orig, &p_sap_session->p_address->orig,
 
418
             p_session->origlen = p_sap_session->p_address->origlen);
 
419
 
 
420
    size_t headsize = 20;
 
421
    switch (p_session->orig.ss_family)
 
422
    {
 
423
#ifdef AF_INET6
 
424
        case AF_INET6:
 
425
            headsize += 16;
 
426
            break;
 
427
#endif
 
428
        case AF_INET:
 
429
            headsize += 4;
 
430
            break;
 
431
        default:
 
432
            msg_Err( p_sap, "Address family %d not supported by SAP",
 
433
                     addr.ss_family );
 
434
            vlc_object_unlock( p_sap );
 
435
            return VLC_EGENERIC;
 
436
    }
 
437
 
 
438
    /* If needed, build the SDP */
 
439
    assert( p_session->psz_sdp != NULL );
 
440
 
 
441
    p_sap_session->i_last = 0;
 
442
    p_sap_session->i_length = headsize + strlen (p_session->psz_sdp);
 
443
    p_sap_session->psz_data = malloc (p_sap_session->i_length + 1);
 
444
    if (p_sap_session->psz_data == NULL)
 
445
    {
 
446
        free (p_session->psz_sdp);
 
447
        vlc_object_unlock( p_sap );
 
448
        return VLC_ENOMEM;
 
449
    }
441
450
 
442
451
    /* Build the SAP Headers */
443
 
    i_header_size = ( b_ipv6 ? 16 : 4 ) + 20;
444
 
    psz_head = (char *) malloc( i_header_size * sizeof( char ) );
445
 
    if( psz_head == NULL )
446
 
    {
447
 
        msg_Err( p_sap, "out of memory" );
448
 
        return VLC_ENOMEM;
449
 
    }
 
452
    uint8_t *psz_head = p_sap_session->psz_data;
450
453
 
451
454
    /* SAPv1, not encrypted, not compressed */
452
 
    psz_head[0] = b_ipv6 ? 0x30 : 0x20;
 
455
    psz_head[0] = 0x20;
453
456
    psz_head[1] = 0x00; /* No authentification length */
454
457
 
455
458
    i_hash = mdate();
456
 
    psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */
457
 
    psz_head[3] = (i_hash & 0xFF);        /* Msg id hash 2 */
 
459
    psz_head[2] = i_hash >> 8; /* Msg id hash */
 
460
    psz_head[3] = i_hash;      /* Msg id hash 2 */
458
461
 
459
 
#if defined (HAVE_INET_PTON) || defined (WIN32)
460
 
    if( b_ipv6 )
 
462
    headsize = 4;
 
463
    switch (p_session->orig.ss_family)
461
464
    {
462
 
        inet_pton( AF_INET6, /* can't fail */
463
 
                   p_sap_session->p_address->psz_machine,
464
 
                   psz_head + 4 );
465
 
    }
466
 
    else
 
465
#ifdef AF_INET6
 
466
        case AF_INET6:
 
467
        {
 
468
            struct in6_addr *a6 =
 
469
                &((struct sockaddr_in6 *)&p_session->orig)->sin6_addr;
 
470
            memcpy (psz_head + headsize, a6, 16);
 
471
            psz_head[0] |= 0x10; /* IPv6 flag */
 
472
            headsize += 16;
 
473
            break;
 
474
        }
467
475
#endif
468
 
    {
469
 
        inet_pton( AF_INET, /* can't fail */
470
 
                   p_sap_session->p_address->psz_machine,
471
 
                   psz_head + 4 );
472
 
    }
473
 
 
474
 
    memcpy( psz_head + (b_ipv6 ? 20 : 8), "application/sdp", 15 );
475
 
 
476
 
    /* If needed, build the SDP */
477
 
    if( p_session->psz_sdp == NULL )
478
 
    {
479
 
        p_session->psz_sdp = SDPGenerate( p_sap, p_session,
480
 
                                          p_sap_session->p_address, b_ssm );
481
 
        if( p_session->psz_sdp == NULL )
 
476
        case AF_INET:
482
477
        {
483
 
            vlc_mutex_unlock( &p_sap->object_lock );
484
 
            return VLC_ENOMEM;
 
478
            uint32_t ipv4 =
 
479
                (((struct sockaddr_in *)&p_session->orig)->sin_addr.s_addr);
 
480
            memcpy (psz_head + headsize, &ipv4, 4);
 
481
            headsize += 4;
 
482
            break;
485
483
        }
 
484
 
486
485
    }
487
486
 
488
 
    p_sap_session->psz_sdp = strdup( p_session->psz_sdp );
489
 
    p_sap_session->i_last = 0;
490
 
 
491
 
    psz_head[ i_header_size-1 ] = '\0';
492
 
    p_sap_session->i_length = i_header_size + strlen( p_sap_session->psz_sdp);
493
 
 
494
 
    p_sap_session->psz_data = (uint8_t *)malloc( sizeof(char)*
495
 
                                                 p_sap_session->i_length );
 
487
    memcpy (psz_head + headsize, "application/sdp", 16);
 
488
    headsize += 16;
496
489
 
497
490
    /* Build the final message */
498
 
    memcpy( p_sap_session->psz_data, psz_head, i_header_size );
499
 
    memcpy( p_sap_session->psz_data+i_header_size, p_sap_session->psz_sdp,
500
 
            strlen( p_sap_session->psz_sdp) );
501
 
 
502
 
    free( psz_head );
 
491
    strcpy( (char *)psz_head + headsize, p_session->psz_sdp);
503
492
 
504
493
    /* Enqueue the announce */
505
494
    INSERT_ELEM( p_sap->pp_sessions,
509
498
    msg_Dbg( p_sap,"%i addresses, %i sessions",
510
499
                   p_sap->i_addresses,p_sap->i_sessions);
511
500
 
512
 
    /* Remember the SAP session for later deletion */
513
 
    p_session->p_sap = p_sap_session;
514
 
 
515
 
    vlc_mutex_unlock( &p_sap->object_lock );
 
501
    vlc_object_unlock( p_sap );
516
502
 
517
503
    return VLC_SUCCESS;
518
504
}
522
508
                             session_descriptor_t *p_session )
523
509
{
524
510
    int i;
525
 
    vlc_mutex_lock( &p_sap->object_lock );
 
511
    vlc_object_lock( p_sap );
526
512
 
527
 
    msg_Dbg( p_sap,"removing SAP announce %p",p_session->p_sap);
 
513
    msg_Dbg( p_sap, "removing session %p from SAP", p_session);
528
514
 
529
515
    /* Dequeue the announce */
530
516
    for( i = 0; i< p_sap->i_sessions; i++)
531
517
    {
532
 
        if( p_session->p_sap == p_sap->pp_sessions[i] )
 
518
        if( p_session == p_sap->pp_sessions[i]->p_sd )
533
519
        {
 
520
            free( p_session->psz_sdp );
 
521
            sap_session_t *p_mysession = p_sap->pp_sessions[i];
534
522
            REMOVE_ELEM( p_sap->pp_sessions,
535
523
                         p_sap->i_sessions,
536
524
                         i );
537
525
 
538
 
            FREE( p_session->p_sap->psz_sdp );
539
 
            FREE( p_session->p_sap->psz_data );
540
 
            free( p_session->p_sap );
 
526
            free( p_mysession->psz_data );
 
527
            free( p_mysession );
541
528
            break;
542
529
        }
543
530
    }
548
535
 
549
536
    msg_Dbg( p_sap,"%i announcements remaining", p_sap->i_sessions );
550
537
 
551
 
    vlc_mutex_unlock( &p_sap->object_lock );
 
538
    vlc_object_unlock( p_sap );
552
539
 
553
540
    return VLC_SUCCESS;
554
541
}
584
571
        p_session->i_next = p_session->i_last
585
572
                            + p_session->p_address->i_interval*1000000;
586
573
    }
587
 
    else
588
 
    {
589
 
        return VLC_SUCCESS;
590
 
    }
591
574
    return VLC_SUCCESS;
592
575
}
593
576
 
594
 
static char *SDPGenerate( sap_handler_t *p_sap,
595
 
                          const session_descriptor_t *p_session,
596
 
                          const sap_address_t *p_addr, vlc_bool_t b_ssm )
597
 
{
598
 
    int64_t i_sdp_id = mdate();
599
 
    int     i_sdp_version = 1 + p_sap->i_sessions + (rand()&0xfff);
600
 
    char *psz_group, *psz_name, psz_uribuf[NI_MAXNUMERICHOST], *psz_uri,
601
 
         *psz_sdp;
602
 
    char ipv;
603
 
    char *sfilter = NULL;
604
 
    int res;
605
 
 
606
 
    psz_group = p_session->psz_group;
607
 
    psz_name = p_session->psz_name;
608
 
 
609
 
    /* FIXME: really check that psz_uri is a real IP address
610
 
     * FIXME: make a common function to obtain a canonical IP address */
611
 
    ipv = ( strchr( p_session->psz_uri, ':' )  != NULL) ? '6' : '4';
612
 
    if( *p_session->psz_uri == '[' )
613
 
    {
614
 
        char *ptr;
615
 
 
616
 
        strlcpy( psz_uribuf, p_session->psz_uri + 1, sizeof( psz_uribuf ) );
617
 
        ptr = strchr( psz_uribuf, '%' );
618
 
        if( ptr != NULL)
619
 
            *ptr = '\0';
620
 
        ptr = strchr( psz_uribuf, ']' );
621
 
        if( ptr != NULL)
622
 
            *ptr = '\0';
623
 
        psz_uri = psz_uribuf;
624
 
    }
625
 
    else
626
 
        psz_uri = p_session->psz_uri;
627
 
 
628
 
    if (b_ssm)
629
 
    {
630
 
        if (asprintf (&sfilter, "a=source-filter: incl IN IP%c * %s\r\n",
631
 
                      ipv, p_addr->psz_machine) == -1)
632
 
            return NULL;
633
 
    }
634
 
 
635
 
    /* see the lists in modules/stream_out/rtp.c for compliance stuff */
636
 
    res = asprintf (&psz_sdp,
637
 
                        "v=0\r\n"
638
 
                        "o=- "I64Fd" %d IN IP%c %s\r\n"
639
 
                        "s=%s\r\n"
640
 
                        "c=IN IP%c %s%s\r\n"
641
 
                        "t=0 0\r\n"
642
 
                        "a=tool:"PACKAGE_STRING"\r\n"
643
 
                        "a=recvonly\r\n"
644
 
                        "a=type:broadcast\r\n"
645
 
                        "%s"
646
 
                        "%s%s%s"
647
 
                        "m=video %d %s %d\r\n",
648
 
                        i_sdp_id, i_sdp_version,
649
 
                        ipv, p_addr->psz_machine,
650
 
                        psz_name, ipv, psz_uri,
651
 
                        (ipv == 4) ? "/255" : "",
652
 
                        (sfilter != NULL) ? sfilter : "",
653
 
                        psz_group ? "a=x-plgroup:" : "",
654
 
                        psz_group ? psz_group : "", psz_group ? "\r\n" : "",
655
 
                        p_session->i_port,
656
 
                        p_session->b_rtp ? "RTP/AVP" : "udp",
657
 
                        p_session->i_payload);
658
 
    if (sfilter != NULL)
659
 
        free (sfilter);
660
 
 
661
 
    if (res == -1)
662
 
        return NULL;
663
 
 
664
 
    msg_Dbg( p_sap, "Generated SDP (%i bytes):\n%s", strlen(psz_sdp),
665
 
             psz_sdp );
666
 
    return psz_sdp;
667
 
}
668
 
 
669
 
static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address )
670
 
{
671
 
    int i_read;
 
577
static int ComputeRate( sap_address_t *p_address )
 
578
{
672
579
    uint8_t buffer[SAP_MAX_BUFFER];
673
 
    int i_tot = 0;
 
580
    ssize_t i_tot = 0;
674
581
    mtime_t i_temp;
675
582
    int i_rate;
676
583
 
679
586
        p_address->t1 = mdate();
680
587
        return VLC_SUCCESS;
681
588
    }
682
 
    do
 
589
    for (;;)
683
590
    {
684
591
        /* Might be too slow if we have huge data */
685
 
        i_read = net_ReadNonBlock( p_sap, p_address->i_rfd, NULL, buffer,
686
 
                                   SAP_MAX_BUFFER, 0 );
 
592
        ssize_t i_read = recv( p_address->i_rfd, buffer, SAP_MAX_BUFFER, 0 );
 
593
        if (i_read == -1)
 
594
            break;
687
595
        i_tot += i_read;
688
 
    } while( i_read > 0 && i_tot < SAP_MAX_BUFFER );
 
596
    }
689
597
 
690
598
    i_temp = mdate();
691
599
 
714
622
             p_address->psz_address,SAP_PORT, i_rate, p_address->i_interval );
715
623
#endif
716
624
 
717
 
    p_address->b_ready = VLC_TRUE;
 
625
    p_address->b_ready = true;
718
626
 
719
627
    p_address->t1 = i_temp;
720
628
    p_address->i_buff = 0;