netutils.c 17.8 KB
Newer Older
1
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
2
 * netutils.c: various network functions
3
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
4
 * Copyright (C) 1999, 2000, 2001 VideoLAN
5
 * $Id: netutils.c,v 1.48 2001/11/21 22:33:03 jlj Exp $
6
 *
7
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
Benoit Steiner's avatar
   
Benoit Steiner committed
8
 *          Benoit Steiner <benny@via.ecp.fr>
Henri Fallon's avatar
   
Henri Fallon committed
9
 *          Henri Fallon <henri@videolan.org>
Xavier Marchesini's avatar
Xavier Marchesini committed
10
 *          Xavier Marchesini <xav@via.ecp.fr>
11
12
13
14
15
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
Sam Hocevar's avatar
   
Sam Hocevar committed
16
 *
17
18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
21
 *
22
23
24
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
26

27
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
28
 * Preamble
29
 *****************************************************************************/
30
31
#include "defs.h"

32
33
#include <stdlib.h>                             /* free(), realloc(), atoi() */
#include <errno.h>                                                /* errno() */
Sam Hocevar's avatar
   
Sam Hocevar committed
34
#include <string.h>                                              /* memset() */
Sam Hocevar's avatar
   
Sam Hocevar committed
35

Sam Hocevar's avatar
   
Sam Hocevar committed
36
37
38
39
#ifdef STRNCASECMP_IN_STRINGS_H
#   include <strings.h>
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
40
#ifdef HAVE_UNISTD_H
Sam Hocevar's avatar
   
Sam Hocevar committed
41
#   include <unistd.h>                                      /* gethostname() */
Sam Hocevar's avatar
   
Sam Hocevar committed
42
#elif defined( _MSC_VER ) && defined( _WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
43
#   include <io.h>
Sam Hocevar's avatar
   
Sam Hocevar committed
44
45
46
#endif

#if !defined( _MSC_VER )
Henri Fallon's avatar
   
Henri Fallon committed
47
#include <sys/time.h>                                        /* gettimeofday */
Sam Hocevar's avatar
   
Sam Hocevar committed
48
#endif
49

Sam Hocevar's avatar
   
Sam Hocevar committed
50
51
52
53
54
55
56
57
58
#ifdef WIN32
#   include <winsock2.h>
#elif !defined( SYS_BEOS ) && !defined( SYS_NTO )
#   include <netdb.h>                                         /* hostent ... */
#   include <sys/socket.h>                           /* BSD: struct sockaddr */
#   include <netinet/in.h>                            /* BSD: struct in_addr */
#   ifdef HAVE_ARPA_INET_H
#       include <arpa/inet.h>                    /* inet_ntoa(), inet_aton() */
#   endif
59
60
#endif

Henri Fallon's avatar
   
Henri Fallon committed
61
62
63
64
#ifdef SYS_LINUX
#include <sys/ioctl.h>                                            /* ioctl() */
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
65
#if defined( WIN32 )                    /* tools to get the MAC adress from  */
Sam Hocevar's avatar
   
Sam Hocevar committed
66
#include <windows.h>                    /* the interface under Windows       */
Xavier Marchesini's avatar
Xavier Marchesini committed
67
68
69
#include <stdio.h>
#endif

Sam Hocevar's avatar
   
Sam Hocevar committed
70
#ifdef HAVE_NET_IF_H
71
72
#include <net/if.h>                            /* interface (arch-dependent) */
#endif
Henri Fallon's avatar
   
Henri Fallon committed
73

Benoit Steiner's avatar
   
Benoit Steiner committed
74
#ifdef HAVE_SYS_SOCKIO_H
Benoit Steiner's avatar
Benoit Steiner committed
75
#include <sys/sockio.h>
Benoit Steiner's avatar
   
Benoit Steiner committed
76
#endif
Michel Kaempf's avatar
Michel Kaempf committed
77
78
79
80

#include "config.h"
#include "common.h"
#include "mtime.h"
Henri Fallon's avatar
   
Henri Fallon committed
81
#include "threads.h"
Henri Fallon's avatar
   
Henri Fallon committed
82
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
83
84

#include "intf_msg.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
85
#include "intf_playlist.h"
Michel Kaempf's avatar
Michel Kaempf committed
86

Sam Hocevar's avatar
   
Sam Hocevar committed
87
#include "netutils.h"
Henri Fallon's avatar
   
Henri Fallon committed
88

89
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
90
91
92
93
94
95
96
97
98
 * input_channel_t: channel library data
 *****************************************************************************
 * Store global channel library data.
 * The part of the code concerning the channel changing process is unstable
 * as it depends on the VideoLAN channel server, which isn't frozen for
 * the time being.
 *****************************************************************************/
typedef struct input_channel_s
{
Sam Hocevar's avatar
   
Sam Hocevar committed
99
    int         i_channel;                         /* current channel number */
Henri Fallon's avatar
   
Henri Fallon committed
100
101
102
    mtime_t     last_change;                             /* last change date */
} input_channel_t;

Xavier Marchesini's avatar
Xavier Marchesini committed
103
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
104
105
 * Local prototypes
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
106
static int GetMacAddress   ( int i_fd, char *psz_mac );
Sam Hocevar's avatar
   
Sam Hocevar committed
107
108
#ifdef WIN32
static int GetAdapterInfo  ( int i_adapter, char *psz_string );
Xavier Marchesini's avatar
Xavier Marchesini committed
109
110
#endif

Henri Fallon's avatar
   
Henri Fallon committed
111
112
/*****************************************************************************
 * network_BuildLocalAddr : fill a sockaddr_in structure for local binding
113
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
114
int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port,
Henri Fallon's avatar
   
Henri Fallon committed
115
                            char * psz_broadcast )
Michel Kaempf's avatar
Michel Kaempf committed
116
{
Tony Castley's avatar
Tony Castley committed
117
#if defined( SYS_BEOS )
118
    intf_ErrMsg( "error: networking is not yet supported under BeOS" );
Tony Castley's avatar
Tony Castley committed
119
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
120
121

#else
Henri Fallon's avatar
   
Henri Fallon committed
122
123
    /* Reset struct */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
124
    p_socket->sin_family = AF_INET;                                /* family */
Henri Fallon's avatar
   
Henri Fallon committed
125
    p_socket->sin_port = htons( i_port );
Henri Fallon's avatar
   
Henri Fallon committed
126
    if( psz_broadcast == NULL )
Henri Fallon's avatar
   
Henri Fallon committed
127
    {
128
        p_socket->sin_addr.s_addr = INADDR_ANY;
Henri Fallon's avatar
   
Henri Fallon committed
129
130
    }
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
131
    {
132
        struct hostent    * p_hostent;
Henri Fallon's avatar
   
Henri Fallon committed
133

134
135
        /* Try to convert address directly from in_addr - this will work if
         * psz_broadcast is dotted decimal. */
Henri Fallon's avatar
   
Henri Fallon committed
136
#ifdef HAVE_ARPA_INET_H
137
        if( !inet_aton( psz_broadcast, &p_socket->sin_addr) )
138
#else
139
        if( (p_socket->sin_addr.s_addr = inet_addr( psz_broadcast )) == -1 )
140
#endif
Michel Kaempf's avatar
Michel Kaempf committed
141
        {
142
143
144
145
146
147
148
149
150
151
            /* We have a fqdn, try to find its address */
            if ( (p_hostent = gethostbyname( psz_broadcast )) == NULL )
            {
                intf_ErrMsg( "BuildLocalAddr: unknown host %s", psz_broadcast );
                return( -1 );
            }

            /* Copy the first address of the host in the socket address */
            memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
                     p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
152
153
        }
    }
154
    return( 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
155
#endif
Michel Kaempf's avatar
Michel Kaempf committed
156
157
}

158
/*****************************************************************************
Henri Fallon's avatar
   
Henri Fallon committed
159
 * network_BuildRemoteAddr : fill a sockaddr_in structure for remote host
160
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
161
int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server )
Michel Kaempf's avatar
Michel Kaempf committed
162
{
Tony Castley's avatar
Tony Castley committed
163
#if defined( SYS_BEOS )
164
    intf_ErrMsg( "error: networking is not yet supported under BeOS" );
Tony Castley's avatar
Tony Castley committed
165
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
166
167
168

#else
    struct hostent            * p_hostent;
Tony Castley's avatar
Tony Castley committed
169

Henri Fallon's avatar
   
Henri Fallon committed
170
171
    /* Reset structure */
    memset( p_socket, 0, sizeof( struct sockaddr_in ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
172
173
    p_socket->sin_family = AF_INET;                                /* family */
    p_socket->sin_port = htons( 0 );               /* This is for remote end */
Sam Hocevar's avatar
   
Sam Hocevar committed
174

Henri Fallon's avatar
   
Henri Fallon committed
175
176
     /* Try to convert address directly from in_addr - this will work if
      * psz_in_addr is dotted decimal. */
Michel Kaempf's avatar
Michel Kaempf committed
177

Henri Fallon's avatar
   
Henri Fallon committed
178
179
#ifdef HAVE_ARPA_INET_H
    if( !inet_aton( psz_server, &p_socket->sin_addr) )
Benoit Steiner's avatar
Benoit Steiner committed
180
#else
Henri Fallon's avatar
   
Henri Fallon committed
181
    if( (p_socket->sin_addr.s_addr = inet_addr( psz_server )) == -1 )
182
#endif
Michel Kaempf's avatar
Michel Kaempf committed
183
    {
Henri Fallon's avatar
   
Henri Fallon committed
184
185
        /* We have a fqdn, try to find its address */
        if ( (p_hostent = gethostbyname(psz_server)) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
186
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
187
            intf_ErrMsg( "BuildRemoteAddr: unknown host %s",
Henri Fallon's avatar
   
Henri Fallon committed
188
189
                         psz_server );
            return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
190
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
191

Henri Fallon's avatar
   
Henri Fallon committed
192
        /* Copy the first address of the host in the socket address */
Sam Hocevar's avatar
   
Sam Hocevar committed
193
        memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0],
Henri Fallon's avatar
   
Henri Fallon committed
194
                 p_hostent->h_length );
Michel Kaempf's avatar
Michel Kaempf committed
195
    }
Henri Fallon's avatar
   
Henri Fallon committed
196
    return( 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
197
#endif
Michel Kaempf's avatar
Michel Kaempf committed
198
}
Sam Hocevar's avatar
   
Sam Hocevar committed
199

Henri Fallon's avatar
   
Henri Fallon committed
200
201
202
203
/*****************************************************************************
 * network_ChannelCreate: initialize global channel method data
 *****************************************************************************
 * Initialize channel input method global data. This function should be called
Sam Hocevar's avatar
   
Sam Hocevar committed
204
 * once before any input thread is created or any call to other
Henri Fallon's avatar
   
Henri Fallon committed
205
206
207
208
 * input_Channel*() function is attempted.
 *****************************************************************************/
int network_ChannelCreate( void )
{
Sam Hocevar's avatar
   
Sam Hocevar committed
209
#if defined( SYS_LINUX ) || defined( WIN32 )
Sam Hocevar's avatar
   
Sam Hocevar committed
210

Henri Fallon's avatar
   
Henri Fallon committed
211
212
213
214
    /* Allocate structure */
    p_main->p_channel = malloc( sizeof( input_channel_t ) );
    if( p_main->p_channel == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
215
        intf_ErrMsg( "network error: could not create channel bank" );
Henri Fallon's avatar
   
Henri Fallon committed
216
217
218
219
        return( -1 );
    }

    /* Initialize structure */
Sam Hocevar's avatar
   
Sam Hocevar committed
220
    p_main->p_channel->i_channel   = 0;
Henri Fallon's avatar
   
Henri Fallon committed
221
222
    p_main->p_channel->last_change = 0;

Sam Hocevar's avatar
   
Sam Hocevar committed
223
    intf_WarnMsg( 2, "network: channels initialized" );
Henri Fallon's avatar
   
Henri Fallon committed
224
    return( 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
225

Henri Fallon's avatar
   
Henri Fallon committed
226
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
227
    intf_ErrMsg( "network error : channels not supported on this platform" );
Sam Hocevar's avatar
   
Sam Hocevar committed
228
    return( 1 );
Sam Hocevar's avatar
   
Sam Hocevar committed
229
230

#endif
Henri Fallon's avatar
   
Henri Fallon committed
231
232
233
234
235
}

/*****************************************************************************
 * network_ChannelJoin: join a channel
 *****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
236
237
238
239
 * This function will try to join a channel. If the relevant interface is
 * already on the good channel, nothing will be done. Else, and if possible
 * (if the interface is not locked), the channel server will be contacted
 * and a change will be requested. The function will block until the change
Sam Hocevar's avatar
   
Sam Hocevar committed
240
 * is effective. Note that once a channel is no more used, its interface
Henri Fallon's avatar
   
Henri Fallon committed
241
242
243
 * should be unlocked using input_ChannelLeave().
 * Non 0 will be returned in case of error.
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
244
int network_ChannelJoin( int i_channel )
Henri Fallon's avatar
   
Henri Fallon committed
245
{
Sam Hocevar's avatar
   
Sam Hocevar committed
246
247
248
#if defined( SYS_LINUX ) || defined( WIN32 )

#define VLCS_VERSION 12
Sam Hocevar's avatar
   
Sam Hocevar committed
249
#define MESSAGE_LENGTH 256
Sam Hocevar's avatar
   
Sam Hocevar committed
250
251
252
253
254
255
256
257
258

    char psz_mess[ MESSAGE_LENGTH ];
    char psz_mac[ 40 ];
    int i_fd, i_dummy, i_port;
    char *psz_vlcs;
    struct sockaddr_in sa_server;
    struct sockaddr_in sa_client;
    struct timeval delay;
    fd_set fds;
Sam Hocevar's avatar
   
Sam Hocevar committed
259

260
261
    if( !main_GetIntVariable( INPUT_NETWORK_CHANNEL_VAR,
                              INPUT_NETWORK_CHANNEL_DEFAULT  ) )
Henri Fallon's avatar
   
Henri Fallon committed
262
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
263
264
        intf_ErrMsg( "network: channels disabled, to enable them, use the"
                     "--channels option" );
Sam Hocevar's avatar
   
Sam Hocevar committed
265
        return -1;
Henri Fallon's avatar
   
Henri Fallon committed
266
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
267

Henri Fallon's avatar
   
Henri Fallon committed
268
269
270
    /* If last change is too recent, wait a while */
    if( mdate() - p_main->p_channel->last_change < INPUT_CHANNEL_CHANGE_DELAY )
    {
271
        intf_WarnMsg( 2, "network: waiting before changing channel" );
Sam Hocevar's avatar
   
Sam Hocevar committed
272
        /* XXX Isn't this completely brain-damaged ??? -- Sam */
Henri Fallon's avatar
   
Henri Fallon committed
273
274
        mwait( p_main->p_channel->last_change + INPUT_CHANNEL_CHANGE_DELAY );
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
275

Sam Hocevar's avatar
   
Sam Hocevar committed
276
277
    /* Initializing the socket */
    i_fd = socket( AF_INET, SOCK_DGRAM, 0 );
Sam Hocevar's avatar
   
Sam Hocevar committed
278
279
280
281
282
283
    if( i_fd < 0 )
    {
        intf_ErrMsg( "network error: unable to create vlcs socket (%s)",
                     strerror( errno ) );
        return -1;
    }
Henri Fallon's avatar
   
Henri Fallon committed
284

Sam Hocevar's avatar
   
Sam Hocevar committed
285
286
287
288
289
290
291
292
293
294
    i_dummy = 1;
    if( setsockopt( i_fd, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &i_dummy, sizeof( i_dummy ) ) == -1 )
    {
        intf_ErrMsg( "network error: can't SO_REUSEADDR vlcs socket (%s)",
                     strerror(errno));
        close( i_fd );
        return -1;
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
295
296
297
298
299
    /* Getting information about the channel server */
    psz_vlcs = main_GetPszVariable( INPUT_CHANNEL_SERVER_VAR,
                                    INPUT_CHANNEL_SERVER_DEFAULT );
    i_port = main_GetIntVariable( INPUT_CHANNEL_PORT_VAR,
                                  INPUT_CHANNEL_PORT_DEFAULT );
Henri Fallon's avatar
   
Henri Fallon committed
300

Sam Hocevar's avatar
   
Sam Hocevar committed
301
302
    intf_WarnMsg( 5, "network: socket %i, vlcs '%s', port %d",
                     i_fd, psz_vlcs, i_port );
303

Sam Hocevar's avatar
   
Sam Hocevar committed
304
    memset( &sa_client, 0x00, sizeof(struct sockaddr_in) );
Sam Hocevar's avatar
   
Sam Hocevar committed
305
    memset( &sa_server, 0x00, sizeof(struct sockaddr_in) );
Sam Hocevar's avatar
   
Sam Hocevar committed
306
307
308
309
310
    sa_client.sin_family      = AF_INET;
    sa_server.sin_family      = AF_INET;
    sa_client.sin_port        = htons( 4312 );
    sa_server.sin_port        = htons( i_port );
    sa_client.sin_addr.s_addr = INADDR_ANY;
Sam Hocevar's avatar
   
Sam Hocevar committed
311
#ifdef HAVE_ARPA_INET_H
Sam Hocevar's avatar
   
Sam Hocevar committed
312
    inet_aton( psz_vlcs, &sa_server.sin_addr );
Sam Hocevar's avatar
   
Sam Hocevar committed
313
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
314
    sa_server.sin_addr.s_addr = inet_addr( psz_vlcs );
Sam Hocevar's avatar
   
Sam Hocevar committed
315
#endif
Marc Ariberti's avatar
Marc Ariberti committed
316

Sam Hocevar's avatar
   
Sam Hocevar committed
317
    /* Bind the socket */
Sam Hocevar's avatar
   
Sam Hocevar committed
318
    if( bind( i_fd, (struct sockaddr*)(&sa_client), sizeof(sa_client) ) )
Sam Hocevar's avatar
   
Sam Hocevar committed
319
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
320
321
322
        intf_ErrMsg( "network: unable to bind vlcs socket (%s)",
                     strerror( errno ) );
        close( i_fd );
Sam Hocevar's avatar
   
Sam Hocevar committed
323
324
325
326
327
        return -1;
    }

    /* Look for the interface MAC address */
    if( GetMacAddress( i_fd, psz_mac ) )
Henri Fallon's avatar
   
Henri Fallon committed
328
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
329
        intf_ErrMsg( "network error: failed getting MAC address" );
Sam Hocevar's avatar
   
Sam Hocevar committed
330
        close( i_fd );
Sam Hocevar's avatar
   
Sam Hocevar committed
331
        return -1;
Marc Ariberti's avatar
Marc Ariberti committed
332
    }
Henri Fallon's avatar
   
Henri Fallon committed
333

Sam Hocevar's avatar
   
Sam Hocevar committed
334
    intf_WarnMsg( 6, "network: MAC address is %s", psz_mac );
Henri Fallon's avatar
   
Henri Fallon committed
335

Sam Hocevar's avatar
   
Sam Hocevar committed
336
337
    /* Build the message */
    sprintf( psz_mess, "%d %u %lu %s \n", i_channel, VLCS_VERSION,
338
                       (unsigned long)(mdate() / (u64)1000000),
Sam Hocevar's avatar
   
Sam Hocevar committed
339
                       psz_mac );
Sam Hocevar's avatar
   
Sam Hocevar committed
340

Sam Hocevar's avatar
   
Sam Hocevar committed
341
342
343
    /* Send the message */
    sendto( i_fd, psz_mess, MESSAGE_LENGTH, 0,
            (struct sockaddr *)(&sa_server), sizeof(struct sockaddr) );
Henri Fallon's avatar
   
Henri Fallon committed
344

Sam Hocevar's avatar
   
Sam Hocevar committed
345
    intf_WarnMsg( 2, "network: attempting to join channel %d", i_channel );
Henri Fallon's avatar
   
Henri Fallon committed
346

Sam Hocevar's avatar
   
Sam Hocevar committed
347
348
349
    /* We have changed channels ! (or at least, we tried) */
    p_main->p_channel->last_change = mdate();
    p_main->p_channel->i_channel = i_channel;
Sam Hocevar's avatar
   
Sam Hocevar committed
350

Sam Hocevar's avatar
   
Sam Hocevar committed
351
352
353
    /* Wait 5 sec for an answer from the server */
    delay.tv_sec = 5;
    delay.tv_usec = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
354
    FD_ZERO( &fds );
Sam Hocevar's avatar
   
Sam Hocevar committed
355
    FD_SET( i_fd, &fds );
Sam Hocevar's avatar
   
Sam Hocevar committed
356

Sam Hocevar's avatar
   
Sam Hocevar committed
357
    switch( select( i_fd + 1, &fds, NULL, NULL, &delay ) )
Henri Fallon's avatar
   
Henri Fallon committed
358
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
359
360
361
362
363
364
365
366
367
368
369
370
        case 0:
            intf_ErrMsg( "network error: no answer from vlcs" );
            close( i_fd );
            return -1;
            break;

        case -1:
            intf_ErrMsg( "network error: error while listening to vlcs" );
            close( i_fd );
            return -1;
            break;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
371

Sam Hocevar's avatar
   
Sam Hocevar committed
372
373
374
375
    i_dummy = sizeof( struct sockaddr );
    recvfrom( i_fd, psz_mess, MESSAGE_LENGTH, 0,
              (struct sockaddr *)(&sa_client), &i_dummy);
    psz_mess[ MESSAGE_LENGTH - 1 ] = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
376

Sam Hocevar's avatar
   
Sam Hocevar committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    if( !strncasecmp( psz_mess, "E: ", 3 ) )
    {
        intf_ErrMsg( "network error: vlcs said '%s'", psz_mess + 3 );
        close( i_fd );
        return -1;
    }
    else if( !strncasecmp( psz_mess, "I: ", 3 ) )
    {
        intf_WarnMsg( 2, "network info: vlcs said '%s'", psz_mess + 3 );
    }
    else /* We got something to play ! FIXME: not very nice */
    {
#   define p_item \
        (&p_main->p_playlist->p_item[ p_main->p_playlist->i_index + 1])
        vlc_mutex_lock( &p_main->p_playlist->change_lock );
392
393
394
395
396
397
398
399
400
        if( p_item )
        {
            free( p_item->psz_name );
            p_item->psz_name = strdup( psz_mess );
        }
        else
        {
            intf_PlaylistAdd( p_main->p_playlist, 0, psz_mess );
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
401
        vlc_mutex_unlock( &p_main->p_playlist->change_lock );
Henri Fallon's avatar
   
Henri Fallon committed
402
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
403

Sam Hocevar's avatar
   
Sam Hocevar committed
404
405
    /* Close the socket and return nicely */
    close( i_fd );
Henri Fallon's avatar
   
Henri Fallon committed
406

Sam Hocevar's avatar
   
Sam Hocevar committed
407
    return 0;
Marc Ariberti's avatar
Marc Ariberti committed
408

Sam Hocevar's avatar
   
Sam Hocevar committed
409
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
410
    intf_ErrMsg( "network error: channels not supported on this platform" );
Sam Hocevar's avatar
   
Sam Hocevar committed
411
    return -1; 
Sam Hocevar's avatar
   
Sam Hocevar committed
412
413

#endif
Henri Fallon's avatar
   
Henri Fallon committed
414
}
Sam Hocevar's avatar
   
Sam Hocevar committed
415

Sam Hocevar's avatar
   
Sam Hocevar committed
416
417
418
419
420
/* Following functions are local */

/*****************************************************************************
 * GetMacAddress: extract the MAC Address
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
421
static int GetMacAddress( int i_fd, char *psz_mac )
Sam Hocevar's avatar
   
Sam Hocevar committed
422
423
424
425
426
427
428
429
430
{
#if defined( SYS_LINUX )
    struct ifreq interface;
    int i_ret;

    /*
     * Looking for information about the eth0 interface
     */
    interface.ifr_addr.sa_family = AF_INET;
431
432
    strcpy( interface.ifr_name, 
            main_GetPszVariable( INPUT_IFACE_VAR, INPUT_IFACE_DEFAULT ) );
Sam Hocevar's avatar
   
Sam Hocevar committed
433

Sam Hocevar's avatar
   
Sam Hocevar committed
434
    i_ret = ioctl( i_fd, SIOCGIFHWADDR, &interface );
Sam Hocevar's avatar
   
Sam Hocevar committed
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

    if( i_ret )
    {
        intf_ErrMsg( "network error: ioctl SIOCGIFHWADDR failed" );
        return( i_ret );
    }

    sprintf( psz_mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
                      interface.ifr_hwaddr.sa_data[0] & 0xff,
                      interface.ifr_hwaddr.sa_data[1] & 0xff,
                      interface.ifr_hwaddr.sa_data[2] & 0xff,
                      interface.ifr_hwaddr.sa_data[3] & 0xff,
                      interface.ifr_hwaddr.sa_data[4] & 0xff,
                      interface.ifr_hwaddr.sa_data[5] & 0xff );

    return( 0 );

#elif defined( WIN32 )
    int i, i_ret = -1;

    /* Get adapter list - support for more than one adapter */
    LANA_ENUM AdapterList;
    NCB       Ncb;

    intf_WarnMsg( 2, "network: looking for MAC address" );

    memset( &Ncb, 0, sizeof( NCB ) );
    Ncb.ncb_command = NCBENUM;
    Ncb.ncb_buffer = (unsigned char *)&AdapterList;
    Ncb.ncb_length = sizeof( AdapterList );
    Netbios( &Ncb );

    /* Get all of the local ethernet addresses */
    for ( i = 0; i < AdapterList.length ; ++i )
    {
        if ( GetAdapterInfo ( AdapterList.lana[ i ], psz_mac ) == 0 )
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
472
            i_ret = 0;
Sam Hocevar's avatar
   
Sam Hocevar committed
473
474
475
476
477
        }
    }

    return( i_ret );

Sam Hocevar's avatar
   
Sam Hocevar committed
478
#else
Sam Hocevar's avatar
   
Sam Hocevar committed
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
    return( -1);

#endif
}

#ifdef WIN32
/*****************************************************************************
 * GetAdapterInfo : gets some informations about the interface using NETBIOS
 *****************************************************************************/
static int GetAdapterInfo( int i_adapter, char *psz_string )
{
    struct ASTAT
    {
        ADAPTER_STATUS adapt;
        NAME_BUFFER    psz_name[30];
    } Adapter;

    /* Reset the LAN adapter so that we can begin querying it */
    NCB Ncb;
    memset( &Ncb, 0, sizeof ( Ncb ) );
    Ncb.ncb_command  = NCBRESET;
    Ncb.ncb_lana_num = i_adapter;

    if( Netbios( &Ncb ) != NRC_GOODRET )
    {
        intf_ErrMsg( "network error: reset returned %i", Ncb.ncb_retcode );
        return -1;
    }

    /* Prepare to get the adapter status block */
    memset( &Ncb, 0, sizeof( Ncb ) ) ;     /* Initialization */
    Ncb.ncb_command = NCBASTAT;
    Ncb.ncb_lana_num = i_adapter;

    strcpy( (char *)Ncb.ncb_callname, "*" );

    memset( &Adapter, 0, sizeof ( Adapter ) );
    Ncb.ncb_buffer = ( unsigned char * ) &Adapter;
    Ncb.ncb_length = sizeof ( Adapter );

    /* Get the adapter's info and, if this works, return it in standard,
     * colon-delimited form. */
    if ( Netbios( &Ncb ) == 0 )
    {
        sprintf ( psz_string, "%02X:%02X:%02X:%02X:%02X:%02X",
                (int) ( Adapter.adapt.adapter_address[0] ),
                (int) ( Adapter.adapt.adapter_address[1] ),
                (int) ( Adapter.adapt.adapter_address[2] ),
                (int) ( Adapter.adapt.adapter_address[3] ),
                (int) ( Adapter.adapt.adapter_address[4] ),
                (int) ( Adapter.adapt.adapter_address[5] ) );

Sam Hocevar's avatar
   
Sam Hocevar committed
531
        intf_WarnMsg( 2, "network: found MAC address %s", psz_string );
Sam Hocevar's avatar
   
Sam Hocevar committed
532
533
534
535
536
537
538
539
540
541
542

        return 0;
    }
    else
    {
        intf_ErrMsg( "network error: ASTAT returned %i", Ncb.ncb_retcode );
        return -1;
    }
}
#endif /* WIN32 */