Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
3f41f383
Commit
3f41f383
authored
Nov 05, 2003
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* sap: big clean up + some buffer overflow fixes (still need some work).
parent
313cc2da
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
388 additions
and
635 deletions
+388
-635
modules/misc/sap.c
modules/misc/sap.c
+388
-635
No files found.
modules/misc/sap.c
View file @
3f41f383
...
...
@@ -2,11 +2,12 @@
* sap.c : SAP interface module
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: sap.c,v 1.
29 2003/11/03 22:36:45 sam
Exp $
* $Id: sap.c,v 1.
30 2003/11/05 23:28:36 fenrir
Exp $
*
* Authors: Arnaud Schauly <gitan@via.ecp.fr>
* Clment Stenac <zorglub@via.ecp.fr>
* Damien Lucas <nitrox@videolan.org>
* Laurent Aimar <fenrir@via.ecp.fr>
*
* 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
...
...
@@ -27,26 +28,19 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
#include <errno.h>
/* ENOMEM */
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/vout.h>
#include <errno.h>
/* ENOMEM */
#include <ctype.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/types.h>
#ifdef WIN32
# include <winsock2.h>
...
...
@@ -82,82 +76,10 @@
#define IPV6_ADDR_1 "FF0"
/* Scope is inserted between them */
#define IPV6_ADDR_2 "::2:7FFE"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
typedef
struct
media_descr_t
media_descr_t
;
typedef
struct
sess_descr_t
sess_descr_t
;
typedef
struct
attr_descr_t
attr_descr_t
;
static
int
Activate
(
vlc_object_t
*
);
static
void
Run
(
intf_thread_t
*
p_intf
);
static
int
Kill
(
intf_thread_t
*
);
static
ssize_t
NetRead
(
intf_thread_t
*
,
int
,
int
,
byte_t
*
,
size_t
);
/* playlist related functions */
static
int
sess_toitem
(
intf_thread_t
*
,
sess_descr_t
*
);
/* sap/sdp related functions */
static
int
parse_sap
(
char
*
);
static
int
packet_handle
(
intf_thread_t
*
,
char
*
,
int
);
static
sess_descr_t
*
parse_sdp
(
intf_thread_t
*
,
char
*
)
;
/* specific sdp fields parsing */
static
void
cfield_parse
(
char
*
,
char
**
);
static
void
mfield_parse
(
char
*
psz_mfield
,
char
**
ppsz_proto
,
char
**
ppsz_port
);
static
void
free_sd
(
sess_descr_t
*
);
/* Detect multicast addresses */
static
int
ismult
(
char
*
);
/* Our custom structure */
struct
intf_sys_t
{
int
i_group
;
};
/* The struct that contains sdp informations */
struct
sess_descr_t
{
char
*
psz_version
;
char
*
psz_origin
;
char
*
psz_sessionname
;
char
*
psz_information
;
char
*
psz_uri
;
char
*
psz_emails
;
char
*
psz_phone
;
char
*
psz_time
;
char
*
psz_repeat
;
char
*
psz_attribute
;
char
*
psz_connection
;
int
i_media
;
int
i_attributes
;
media_descr_t
**
pp_media
;
attr_descr_t
**
pp_attributes
;
};
/* All this informations are not useful yet. */
struct
media_descr_t
{
char
*
psz_medianame
;
char
*
psz_mediaconnection
;
};
struct
attr_descr_t
{
char
*
psz_field
;
char
*
psz_value
;
};
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define SAP_ADDR_TEXT N_("SAP multicast address")
#define SAP_ADDR_LONGTEXT N_("SAP multicast address")
#define SAP_IPV4_TEXT N_("IPv4-SAP listening")
...
...
@@ -167,6 +89,9 @@ struct attr_descr_t
#define SAP_SCOPE_TEXT N_("IPv6 SAP scope")
#define SAP_SCOPE_LONGTEXT N_("Sets the scope for IPv6 announces (default is 8)")
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
vlc_module_begin
();
add_category_hint
(
N_
(
"SAP"
),
NULL
,
VLC_TRUE
);
add_string
(
"sap-addr"
,
NULL
,
NULL
,
...
...
@@ -183,347 +108,236 @@ vlc_module_begin();
set_description
(
_
(
"SAP interface"
)
);
set_capability
(
"interface"
,
0
);
set_callbacks
(
Activate
,
NULL
);
set_callbacks
(
Open
,
Close
);
vlc_module_end
();
/*****************************************************************************
* Activate: initialize and create stuff
*****************************************************************************/
static
int
Activate
(
vlc_object_t
*
p_this
)
{
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
p_intf
->
pf_run
=
Run
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Run: sap thread
*****************************************************************************
* Listens to SAP packets, and sends them to packet_handle
* Local prototypes
*****************************************************************************/
#define MAX_SAP_BUFFER 2000
static
void
Run
(
intf_thread_t
*
p_intf
)
{
char
*
psz_addr
;
char
*
psz_addrv6
;
char
*
psz_network
=
NULL
;
int
fd
=
-
1
;
int
fdv6
=
-
1
;
static
void
Run
(
intf_thread_t
*
p_intf
);
static
int
NetRead
(
intf_thread_t
*
,
int
fd
[
2
],
uint8_t
*
,
int
);
int
sap_ipv4
=
config_GetInt
(
p_intf
,
"sap-ipv4"
)
;
int
sap_ipv6
=
config_GetInt
(
p_intf
,
"sap-ipv6"
)
;
char
*
sap_ipv6_scope
=
config_GetPsz
(
p_intf
,
"sap-ipv6-scope"
)
;
typedef
struct
media_descr_t
media_descr_t
;
typedef
struct
sess_descr_t
sess_descr_t
;
typedef
struct
attr_descr_t
attr_descr_t
;
char
buffer
[
MAX_SAP_BUFFER
+
1
]
;
static
void
sess_toitem
(
intf_thread_t
*
,
sess_descr_t
*
)
;
module_t
*
p_network
;
network_socket_t
socket_desc
;
playlist_t
*
p_playlist
;
playlist_group_t
*
p_group
;
static
sess_descr_t
*
parse_sdp
(
intf_thread_t
*
,
char
*
)
;
static
void
free_sd
(
sess_descr_t
*
);
if
(
sap_ipv4
==
-
1
||
sap_ipv6
==
-
1
||
sap_ipv6_scope
==
NULL
)
{
msg_Warn
(
p_intf
,
"unable to parse module configuration"
);
return
;
}
/* Detect multicast addresses */
static
int
ismult
(
char
*
);
/* The struct that contains sdp informations */
struct
sess_descr_t
{
int
i_version
;
char
*
psz_sessionname
;
char
*
psz_connection
;
p_intf
->
p_sys
=
malloc
(
sizeof
(
intf_sys_t
)
);
if
(
!
p_intf
->
p_sys
)
{
msg_Err
(
p_intf
,
"out of memory"
);
p_intf
->
b_die
=
VLC_TRUE
;
return
;
}
int
i_media
;
media_descr_t
**
pp_media
;
int
i_attributes
;
attr_descr_t
**
pp_attributes
;
};
/* Create our playlist group
*/
p_playlist
=
(
playlist_t
*
)
vlc_object_find
(
p_intf
,
VLC_OBJECT_PLAYLIST
,
FIND_ANYWHERE
)
;
p_group
=
playlist_CreateGroup
(
p_playlist
,
"SAP"
)
;
p_intf
->
p_sys
->
i_group
=
p_group
->
i_id
;
/* All this informations are not useful yet.
*/
struct
media_descr_t
{
char
*
psz_medianame
;
char
*
psz_mediaconnection
;
}
;
vlc_object_release
(
p_playlist
);
struct
attr_descr_t
{
char
*
psz_field
;
char
*
psz_value
;
};
/* Prepare IPv4 Networking */
if
(
sap_ipv4
==
1
)
{
if
(
!
(
psz_addr
=
config_GetPsz
(
p_intf
,
"sap-addr"
)
)
)
{
psz_addr
=
strdup
(
HELLO_GROUP
);
}
struct
intf_sys_t
{
/* IPV4 and IPV6 */
int
fd
[
2
];
/* Prepare the network_socket_t structure */
socket_desc
.
i_type
=
NETWORK_UDP
;
socket_desc
.
psz_bind_addr
=
psz_addr
;
socket_desc
.
i_bind_port
=
HELLO_PORT
;
socket_desc
.
psz_server_addr
=
""
;
socket_desc
.
i_server_port
=
0
;
socket_desc
.
i_ttl
=
0
;
p_intf
->
p_private
=
(
void
*
)
&
socket_desc
;
/* playlist group */
int
i_group
;
};
psz_network
=
"ipv4"
;
/*****************************************************************************
* Open: initialize and create stuff
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
{
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
intf_sys_t
*
p_sys
=
malloc
(
sizeof
(
intf_sys_t
)
);
/* Create, Bind the socket, ... with the appropriate module */
playlist_t
*
p_playlist
;
if
(
!
(
p_network
=
module_Need
(
p_intf
,
"network"
,
psz_network
)
)
)
p_sys
->
fd
[
0
]
=
-
1
;
p_sys
->
fd
[
1
]
=
-
1
;
if
(
config_GetInt
(
p_intf
,
"sap-ipv4"
)
)
{
char
*
psz_address
=
config_GetPsz
(
p_intf
,
"sap-addr"
);
network_socket_t
sock
;
module_t
*
p_network
;
if
(
psz_address
==
NULL
||
*
psz_address
==
'\0'
)
{
msg_Warn
(
p_intf
,
"failed to open a UDP connection"
);
p_intf
->
b_die
=
VLC_TRUE
;
return
;
psz_address
=
strdup
(
HELLO_GROUP
);
}
module_Unneed
(
p_intf
,
p_network
);
fd
=
socket_desc
.
i_handle
;
}
/* Prepare IPv6 Networking */
if
(
sap_ipv6
>
0
)
{
/* Prepare the network_socket_t structure */
sock
.
i_type
=
NETWORK_UDP
;
sock
.
psz_bind_addr
=
psz_address
;
sock
.
i_bind_port
=
HELLO_PORT
;
sock
.
psz_server_addr
=
""
;
sock
.
i_server_port
=
0
;
sock
.
i_ttl
=
0
;
p_intf
->
p_private
=
(
void
*
)
&
sock
;
psz_addrv6
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
38
);
if
(
!
psz_addrv6
)
p_network
=
module_Need
(
p_intf
,
"network"
,
"ipv4"
);
if
(
p_network
)
{
msg_Warn
(
p_intf
,
"out of memory"
);
p_sys
->
fd
[
0
]
=
sock
.
i_handle
;
module_Unneed
(
p_intf
,
p_network
);
}
/* Max size of an IPv6 address */
sprintf
(
psz_addrv6
,
"[%s%c%s]"
,
IPV6_ADDR_1
,
sap_ipv6_scope
[
0
],
IPV6_ADDR_2
);
socket_desc
.
i_type
=
NETWORK_UDP
;
socket_desc
.
psz_bind_addr
=
psz_addrv6
;
socket_desc
.
i_bind_port
=
HELLO_PORT
;
socket_desc
.
psz_server_addr
=
""
;
socket_desc
.
i_server_port
=
0
;
socket_desc
.
i_ttl
=
0
;
p_intf
->
p_private
=
(
void
*
)
&
socket_desc
;
psz_network
=
"ipv6"
;
/* Create, Bind the socket, ... with the appropriate module */
if
(
!
(
p_network
=
module_Need
(
p_intf
,
"network"
,
psz_network
)
)
)
else
{
msg_Warn
(
p_intf
,
"failed to open a UDP connection"
);
p_intf
->
b_die
=
VLC_TRUE
;
return
;
msg_Warn
(
p_intf
,
"failed to open %s:%d"
,
psz_address
,
HELLO_PORT
);
}
module_Unneed
(
p_intf
,
p_network
);
fdv6
=
socket_desc
.
i_handle
;
free
(
psz_address
);
}
/* read SAP packets */
while
(
!
p_intf
->
b_die
)
if
(
config_GetInt
(
p_intf
,
"sap-ipv6"
)
)
{
int
i_read
;
char
psz_address
[
100
];
char
*
psz_scope
=
config_GetPsz
(
p_intf
,
"sap-ipv6-scope"
);
network_socket_t
sock
;
module_t
*
p_network
;
//memset( buffer, 0, MAX_SAP_BUFFER + 1);
if
(
psz_scope
==
NULL
||
*
psz_scope
==
'\0'
)
{
psz_scope
=
strdup
(
"8"
);
}
snprintf
(
psz_address
,
100
,
"[%s%c%s]"
,
IPV6_ADDR_1
,
psz_scope
[
0
],
IPV6_ADDR_2
);
free
(
psz_scope
);
i_read
=
NetRead
(
p_intf
,
fd
,
fdv6
,
buffer
,
MAX_SAP_BUFFER
);
sock
.
i_type
=
NETWORK_UDP
;
sock
.
psz_bind_addr
=
psz_address
;
sock
.
i_bind_port
=
HELLO_PORT
;
sock
.
psz_server_addr
=
""
;
sock
.
i_server_port
=
0
;
sock
.
i_ttl
=
0
;
p_intf
->
p_private
=
(
void
*
)
&
sock
;
if
(
i_read
<
0
)
p_network
=
module_Need
(
p_intf
,
"network"
,
"ipv6"
);
if
(
p_network
)
{
msg_Err
(
p_intf
,
"cannot read from socket"
);
p_sys
->
fd
[
1
]
=
sock
.
i_handle
;
module_Unneed
(
p_intf
,
p_network
);
}
if
(
i_read
==
0
)
else
{
continue
;
msg_Warn
(
p_intf
,
"failed to open %s:%d"
,
psz_address
,
HELLO_PORT
)
;
}
buffer
[
i_read
]
=
'\0'
;
packet_handle
(
p_intf
,
buffer
,
i_read
);
}
/* Closing socket */
if
(
fd
>
0
)
if
(
p_sys
->
fd
[
0
]
<=
0
&&
p_sys
->
fd
[
1
]
<=
0
)
{
if
(
close
(
fd
)
)
{
msg_Warn
(
p_intf
,
"uh-oh, unable to close the socket"
);
}
msg_Warn
(
p_intf
,
"IPV4 and IPV6 failed"
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
if
(
fdv6
>
0
)
/* Create our playlist group */
p_playlist
=
(
playlist_t
*
)
vlc_object_find
(
p_intf
,
VLC_OBJECT_PLAYLIST
,
FIND_ANYWHERE
);
if
(
p_playlist
)
{
if
(
close
(
fdv6
)
)
{
msg_Warn
(
p_intf
,
"uh-oh, unable to close the socket"
);
}
playlist_group_t
*
p_group
=
playlist_CreateGroup
(
p_playlist
,
"SAP"
);
p_sys
->
i_group
=
p_group
->
i_id
;
vlc_object_release
(
p_playlist
);
}
}
/********************************************************************
* Kill
*******************************************************************
* Kills the SAP interface.
********************************************************************/
static
int
Kill
(
intf_thread_t
*
p_intf
)
{
p_intf
->
b_die
=
VLC_TRUE
;
p_intf
->
pf_run
=
Run
;
p_intf
->
p_sys
=
p_sys
;
return
VLC_SUCCESS
;
}
/*******************************************************************
* sess_toitem : changes a sess_descr_t into a hurd of
* playlist_item_t, which are enqueued.
*******************************************************************
* Note : does not support sessions that take place on consecutive
* port or adresses yet.
*******************************************************************/
static
int
sess_toitem
(
intf_thread_t
*
p_intf
,
sess_descr_t
*
p_sd
)
/*****************************************************************************
* Close:
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
{
playlist_item_t
*
p_item
;
char
*
psz_uri
,
*
psz_proto
;
char
*
psz_port
;
char
*
psz_uri_default
;
int
i_multicast
;
int
i_count
,
i
;
vlc_bool_t
b_http
=
VLC_FALSE
;
char
*
psz_http_path
=
NULL
;
playlist_t
*
p_playlist
;
psz_uri_default
=
NULL
;
cfield_parse
(
p_sd
->
psz_connection
,
&
psz_uri_default
);
intf_thread_t
*
p_intf
=
(
intf_thread_t
*
)
p_this
;
intf_sys_t
*
p_sys
=
p_intf
->
p_sys
;
for
(
i_count
=
0
;
i_count
<
p_sd
->
i_media
;
i_count
++
)
if
(
p_sys
->
fd
[
0
]
>
0
)
{
p_item
=
malloc
(
sizeof
(
playlist_item_t
)
);
if
(
p_item
==
NULL
)
{
msg_Err
(
p_intf
,
"out of memory for p_item in sesstoitem()"
);
return
VLC_ENOMEM
;
}
p_item
->
psz_name
=
strdup
(
p_sd
->
psz_sessionname
);
p_item
->
i_type
=
0
;
p_item
->
i_status
=
0
;
p_item
->
b_autodeletion
=
VLC_FALSE
;
p_item
->
psz_uri
=
NULL
;
p_item
->
ppsz_options
=
NULL
;
p_item
->
i_options
=
0
;
close
(
p_sys
->
fd
[
0
]
);
}
if
(
p_sys
->
fd
[
1
]
>
0
)
{
close
(
p_sys
->
fd
[
1
]
);
}
psz_uri
=
NULL
;
free
(
p_sys
);
}
/* Build what we have to put in p_item->psz_uri, with the m and
* c fields */
/*****************************************************************************
* Run: sap thread
*****************************************************************************
* Listens to SAP packets, and sends them to packet_handle
*****************************************************************************/
#define MAX_SAP_BUFFER 2000
if
(
!
p_sd
->
pp_media
[
i_count
]
)
{
return
VLC_EGENERIC
;
}
static
void
Run
(
intf_thread_t
*
p_intf
)
{
intf_sys_t
*
p_sys
=
p_intf
->
p_sys
;
uint8_t
buffer
[
MAX_SAP_BUFFER
+
1
];
mfield_parse
(
p_sd
->
pp_media
[
i_count
]
->
psz_medianame
,
&
psz_proto
,
&
psz_port
);
/* read SAP packets */
while
(
!
p_intf
->
b_die
)
{
int
i_read
=
NetRead
(
p_intf
,
p_sys
->
fd
,
buffer
,
MAX_SAP_BUFFER
);
uint8_t
*
p_sdp
;
if
(
!
psz_proto
||
!
psz_port
)
/* Minimum length is > 6 */
if
(
i_read
<=
6
)
{
return
VLC_EGENERIC
;
if
(
i_read
<
0
)
{
msg_Warn
(
p_intf
,
"Cannot read in the socket"
);
}
continue
;
}
if
(
p_sd
->
pp_media
[
i_count
]
->
psz_mediaconnection
)
{
cfield_parse
(
p_sd
->
pp_media
[
i_count
]
->
psz_mediaconnection
,
&
psz_uri
);
}
else
{
psz_uri
=
psz_uri_default
;
}
buffer
[
i_read
]
=
'\0'
;
if
(
psz_uri
==
NULL
)
{
return
VLC_EGENERIC
;
}
/* Parse the SAP header */
p_sdp
=
&
buffer
[
4
];
p_sdp
+=
(
buffer
[
0
]
&
0x10
)
?
16
:
4
;
p_sdp
+=
buffer
[
1
];
for
(
i
=
0
;
i
<
p_sd
->
i_attributes
;
i
++
)
while
(
p_sdp
<
&
buffer
[
i_read
-
1
]
&&
*
p_sdp
!=
'\0'
&&
p_sdp
[
0
]
!=
'v'
&&
p_sdp
[
1
]
!=
'='
)
{
if
(
!
strcasecmp
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
,
"type"
)
&&
strstr
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
,
"http"
)
)
{
b_http
=
VLC_TRUE
;
}
if
(
!
strcasecmp
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
,
"http-path"
))
{
psz_http_path
=
strdup
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
);
}
p_sdp
++
;
}
/* Filling p_item->psz_uri */
if
(
b_http
==
VLC_FALSE
)
if
(
*
p_sdp
==
'\0'
)
{
i_multicast
=
ismult
(
psz_uri
);
p_item
->
psz_uri
=
malloc
(
strlen
(
psz_proto
)
+
strlen
(
psz_uri
)
+
strlen
(
psz_port
)
+
5
+
i_multicast
);
if
(
p_item
->
psz_uri
==
NULL
)
{
msg_Err
(
p_intf
,
"out of memory"
);
free
(
p_item
);
return
VLC_ENOMEM
;
}
if
(
i_multicast
==
1
)
{
sprintf
(
p_item
->
psz_uri
,
"%s://@%s:%s"
,
psz_proto
,
psz_uri
,
psz_port
);
}
else
{
sprintf
(
p_item
->
psz_uri
,
"%s://%s:%s"
,
psz_proto
,
psz_uri
,
psz_port
);
}
p_sdp
++
;
}
else
if
(
p_sdp
<
&
buffer
[
i_read
]
)
{
if
(
psz_http_path
==
NULL
)
psz_http_path
=
strdup
(
"/"
);
p_item
->
psz_uri
=
malloc
(
strlen
(
psz_proto
)
+
strlen
(
psz_uri
)
+
strlen
(
psz_port
)
+
3
+
strlen
(
psz_http_path
)
);
if
(
p_item
->
psz_uri
==
NULL
)
sess_descr_t
*
p_sd
=
parse_sdp
(
p_intf
,
p_sdp
);
if
(
p_sd
)
{
msg_Err
(
p_intf
,
"out of memory"
);
free
(
p_item
);
return
VLC_ENOMEM
;
sess_toitem
(
p_intf
,
p_sd
);
free_sd
(
p_sd
);
}
sprintf
(
p_item
->
psz_uri
,
"%s://%s:%s%s"
,
psz_proto
,
psz_uri
,
psz_port
,
psz_http_path
);
}
/* Enqueueing p_item in the playlist */
if
(
p_item
)
{
p_item
->
i_group
=
p_intf
->
p_sys
->
i_group
;
p_item
->
b_enabled
=
VLC_TRUE
;
p_item
->
psz_author
=
NULL
;
p_playlist
=
vlc_object_find
(
p_intf
,
VLC_OBJECT_PLAYLIST
,
FIND_ANYWHERE
);
playlist_AddItem
(
p_playlist
,
p_item
,
PLAYLIST_CHECK_INSERT
,
PLAYLIST_END
);
vlc_object_release
(
p_playlist
);
}
if
(
psz_http_path
)
free
(
psz_http_path
);
}
return
VLC_SUCCESS
;
}
/**********************************************************************
...
...
@@ -620,62 +434,132 @@ static void mfield_parse( char *psz_mfield, char **ppsz_proto,
return
;
}
/***********************************************************************
* parse_sap : Takes care of the SAP headers
***********************************************************************
* checks if the packet has the true headers ;
* returns the SAP header lenhth
***********************************************************************/
static
int
parse_sap
(
char
*
p_packet
)
/*******************************************************************
* sess_toitem : changes a sess_descr_t into a hurd of
* playlist_item_t, which are enqueued.
*******************************************************************
* Note : does not support sessions that take place on consecutive
* port or adresses yet.
*******************************************************************/
static
void
sess_toitem
(
intf_thread_t
*
p_intf
,
sess_descr_t
*
p_sd
)
{
// According to RFC 2974
int
i_hlen
=
4
;
// Minimum header length is 4
i_hlen
+=
(
p_packet
[
0
]
&
0x10
)
?
16
:
4
;
// Address type IPv6=16bytes
i_hlen
+=
p_packet
[
1
];
// Authentification length
//Looks for the first '\0' byte after length
for
(;
p_packet
[
i_hlen
]
!=
'\0'
;
i_hlen
++
);
if
(
i_hlen
>
50
)
/* Definitely too long...
Maybe we have a fucked up packet without \0 */
{
/* As a workaround, we search for "v=" */
i_hlen
=
4
;
for
(;
p_packet
[
i_hlen
]
!=
'v'
&&
p_packet
[
i_hlen
+
1
]
!=
'='
;
i_hlen
++
);
return
i_hlen
-
1
;
}
playlist_item_t
*
p_item
;
char
*
psz_uri
,
*
psz_proto
;
char
*
psz_port
;
char
*
psz_uri_default
;
int
i_count
,
i
;
vlc_bool_t
b_http
=
VLC_FALSE
;
char
*
psz_http_path
=
NULL
;
playlist_t
*
p_playlist
;
return
(
i_hlen
)
;
}
psz_uri_default
=
NULL
;
cfield_parse
(
p_sd
->
psz_connection
,
&
psz_uri_default
);
/*************************************************************************
* packet_handle : handle the received packet and enques the
* the understated session
*************************************************************************/
for
(
i_count
=
0
;
i_count
<
p_sd
->
i_media
;
i_count
++
)
{
p_item
=
malloc
(
sizeof
(
playlist_item_t
)
);
p_item
->
psz_name
=
strdup
(
p_sd
->
psz_sessionname
);
p_item
->
psz_uri
=
NULL
;
p_item
->
i_duration
=
-
1
;
p_item
->
ppsz_options
=
NULL
;
p_item
->
i_options
=
0
;
p_item
->
i_type
=
0
;
p_item
->
i_status
=
0
;
p_item
->
b_autodeletion
=
VLC_FALSE
;
p_item
->
b_enabled
=
VLC_TRUE
;
p_item
->
i_group
=
p_intf
->
p_sys
->
i_group
;
p_item
->
psz_author
=
strdup
(
""
);
static
int
packet_handle
(
intf_thread_t
*
p_intf
,
char
*
p_packet
,
int
i_len
)
{
sess_descr_t
*
p_sd
;
int
i_hlen
;
// Header length
psz_uri
=
NULL
;
i_hlen
=
parse_sap
(
p_packet
);
/* Build what we have to put in p_item->psz_uri, with the m and
* c fields */
if
(
(
i_hlen
>
0
)
&&
(
i_hlen
<
i_len
)
)
{
p_sd
=
parse_sdp
(
p_intf
,
p_packet
+
i_hlen
+
1
);
if
(
p_sd
)
if
(
!
p_sd
->
pp_media
[
i_count
]
)
{
sess_toitem
(
p_intf
,
p_sd
);
free_sd
(
p_sd
);
return
VLC_TRUE
;
return
;
}
}
return
VLC_FALSE
;
// Invalid Packet
}
mfield_parse
(
p_sd
->
pp_media
[
i_count
]
->
psz_medianame
,
&
psz_proto
,
&
psz_port
);
if
(
!
psz_proto
||
!
psz_port
)
{
return
;
}
if
(
p_sd
->
pp_media
[
i_count
]
->
psz_mediaconnection
)
{
cfield_parse
(
p_sd
->
pp_media
[
i_count
]
->
psz_mediaconnection
,
&
psz_uri
);
}
else
{
psz_uri
=
psz_uri_default
;
}
if
(
psz_uri
==
NULL
)
{
return
;
}
for
(
i
=
0
;
i
<
p_sd
->
i_attributes
;
i
++
)
{
if
(
!
strcasecmp
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
,
"type"
)
&&
strstr
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
,
"http"
)
)
{
b_http
=
VLC_TRUE
;
}
if
(
!
strcasecmp
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
,
"http-path"
))
{
psz_http_path
=
strdup
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
);
}
}
/* Filling p_item->psz_uri */
if
(
b_http
==
VLC_FALSE
)
{
p_item
->
psz_uri
=
malloc
(
strlen
(
psz_proto
)
+
strlen
(
psz_uri
)
+
strlen
(
psz_port
)
+
7
);
if
(
ismult
(
psz_uri
)
)
{
sprintf
(
p_item
->
psz_uri
,
"%s://@%s:%s"
,
psz_proto
,
psz_uri
,
psz_port
);
}
else
{
sprintf
(
p_item
->
psz_uri
,
"%s://%s:%s"
,
psz_proto
,
psz_uri
,
psz_port
);
}
}
else
{
if
(
psz_http_path
==
NULL
)
{
psz_http_path
=
strdup
(
"/"
);
}
p_item
->
psz_uri
=
malloc
(
strlen
(
psz_proto
)
+
strlen
(
psz_uri
)
+
strlen
(
psz_port
)
+
strlen
(
psz_http_path
)
+
5
);
sprintf
(
p_item
->
psz_uri
,
"%s://%s:%s%s"
,
psz_proto
,
psz_uri
,
psz_port
,
psz_http_path
);
if
(
psz_http_path
)
{
free
(
psz_http_path
);
}
}
/* Enqueueing p_item in the playlist */
p_playlist
=
vlc_object_find
(
p_intf
,
VLC_OBJECT_PLAYLIST
,
FIND_ANYWHERE
);
playlist_AddItem
(
p_playlist
,
p_item
,
PLAYLIST_CHECK_INSERT
,
PLAYLIST_END
);
vlc_object_release
(
p_playlist
);
}
}
/***********************************************************************
* parse_sdp : SDP parsing
...
...
@@ -686,189 +570,110 @@ static int packet_handle( intf_thread_t * p_intf, char *p_packet, int i_len )
static
sess_descr_t
*
parse_sdp
(
intf_thread_t
*
p_intf
,
char
*
p_packet
)
{
sess_descr_t
*
sd
;
char
*
psz_eof
;
unsigned
int
i
;
/* According to RFC 2327, the first bytes should be exactly "v=" */
if
(
p_packet
[
0
]
!=
'v'
||
p_packet
[
1
]
!=
'='
)
{
msg_Warn
(
p_intf
,
"bad SDP packet %.2x%.2x"
,
p_packet
[
0
],
p_packet
[
1
]
);
msg_Warn
(
p_intf
,
"bad SDP packet"
);
return
NULL
;
}
if
(
(
sd
=
malloc
(
sizeof
(
sess_descr_t
)
)
)
==
NULL
)
{
msg_Err
(
p_intf
,
"out of memory for sd in parse_sdp()"
);
return
NULL
;
}
sd
->
pp_media
=
NULL
;
sd
->
pp_attributes
=
NULL
;
sd
->
psz_origin
=
NULL
;
sd
=
malloc
(
sizeof
(
sess_descr_t
)
);
sd
->
psz_sessionname
=
NULL
;
sd
->
psz_information
=
NULL
;
sd
->
psz_uri
=
NULL
;
sd
->
psz_emails
=
NULL
;
sd
->
psz_phone
=
NULL
;
sd
->
psz_time
=
NULL
;
sd
->
psz_repeat
=
NULL
;
sd
->
psz_attribute
=
NULL
;
sd
->
psz_connection
=
NULL
;
sd
->
i_media
=
0
;
sd
->
i_attributes
=
0
;
sd
->
psz_connection
=
NULL
;
sd
->
i_media
=
0
;
sd
->
pp_media
=
NULL
;
sd
->
i_attributes
=
0
;
sd
->
pp_attributes
=
NULL
;
while
(
*
p_packet
!=
'\0'
)
{
#define FIELD_COPY( p ) \
p = strndup( &p_packet[2], i_field_len );
char
*
psz_end
;
int
i_field_len
;
/* Search begin of field */
while
(
*
p_packet
==
'\n'
||
*
p_packet
==
' '
||
*
p_packet
==
'\t'
)
{
p_packet
++
;
}
if
(
*
p_packet
==
'\0'
)
/* search end of line */
if
(
(
psz_end
=
strchr
(
p_packet
,
'\n'
)
)
==
NULL
)
{
psz_end
=
p_packet
+
strlen
(
p_packet
);
}
if
(
psz_end
<=
p_packet
)
{
break
;
}
*
psz_end
++
=
'\0'
;
if
(
(
psz_end
=
strchr
(
p_packet
,
'\n'
)
)
==
NULL
)
if
(
p_packet
[
1
]
!=
'='
)
{
psz_end
=
p_packet
+
strlen
(
p_packet
);
msg_Warn
(
p_intf
,
"packet invalid"
);
free_sd
(
sd
);
return
NULL
;
}
i_field_len
=
psz_end
-
&
p_packet
[
2
];
if
(
p_packet
[
1
]
==
'='
&&
i_field_len
>
0
)
switch
(
p_packet
[
0
]
)
{
switch
(
*
p_packet
)
case
(
'v'
):
sd
->
i_version
=
atoi
(
&
p_packet
[
2
]
);
break
;
case
(
's'
):
sd
->
psz_sessionname
=
strdup
(
&
p_packet
[
2
]
);
break
;
case
(
'o'
):
case
(
'i'
):
case
(
'u'
):
case
(
'e'
):
case
(
'p'
):
case
(
't'
):
case
(
'r'
):
break
;
case
(
'a'
):
{
case
(
'v'
):
FIELD_COPY
(
sd
->
psz_version
);
break
;
case
(
'o'
):
FIELD_COPY
(
sd
->
psz_origin
);
break
;
case
(
's'
):
FIELD_COPY
(
sd
->
psz_sessionname
);
break
;
case
(
'i'
):
FIELD_COPY
(
sd
->
psz_information
);
break
;
case
(
'u'
):
FIELD_COPY
(
sd
->
psz_uri
);
break
;
case
(
'e'
):
FIELD_COPY
(
sd
->
psz_emails
);
break
;
case
(
'p'
):
FIELD_COPY
(
sd
->
psz_phone
);
break
;
case
(
't'
):
FIELD_COPY
(
sd
->
psz_time
);
break
;
case
(
'r'
):
FIELD_COPY
(
sd
->
psz_repeat
);
break
;
case
(
'a'
):
if
(
sd
->
pp_attributes
)
{
sd
->
pp_attributes
=
realloc
(
sd
->
pp_attributes
,
sizeof
(
attr_descr_t
)
*
(
sd
->
i_attributes
+
1
)
);
}
else
{
sd
->
pp_attributes
=
malloc
(
sizeof
(
void
*
)
);
}
if
(
!
sd
->
pp_attributes
)
{
msg_Warn
(
p_intf
,
"out of memory"
);
return
NULL
;
}
sd
->
pp_attributes
[
sd
->
i_attributes
]
=
malloc
(
sizeof
(
attr_descr_t
)
);
if
(
!
sd
->
pp_attributes
[
sd
->
i_attributes
])
{
msg_Warn
(
p_intf
,
"out of memory"
);
return
NULL
;
}
p_packet
+=
2
;
psz_eof
=
strchr
(
p_packet
,
':'
);
if
(
psz_eof
)
*
psz_eof
=
'\0'
;
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_field
=
strdup
(
p_packet
);
if
(
psz_eof
+
1
)
{
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_value
=
strdup
(
++
psz_eof
);
}
else
{
if
(
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_field
)
free
(
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_field
);
break
;
}
for
(
i
=
0
;
i
<
strlen
(
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_value
)
;
i
++
)
{
if
(
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_value
[
i
]
==
'\n'
)
sd
->
pp_attributes
[
sd
->
i_attributes
]
->
psz_value
[
i
]
=
0
;
}
sd
->
i_attributes
++
;
break
;
case
(
'm'
):
if
(
sd
->
pp_media
)
{
sd
->
pp_media
=
realloc
(
sd
->
pp_media
,
sizeof
(
media_descr_t
)
*
(
sd
->
i_media
+
1
)
);
}
else
{
sd
->
pp_media
=
malloc
(
sizeof
(
void
*
)
);
}
if
(
!
sd
->
pp_media
)
{
msg_Warn
(
p_intf
,
"out of memory"
);
return
NULL
;
}
sd
->
pp_media
[
sd
->
i_media
]
=
malloc
(
sizeof
(
media_descr_t
)
);
sd
->
pp_media
[
sd
->
i_media
]
->
psz_medianame
=
NULL
;
sd
->
pp_media
[
sd
->
i_media
]
->
psz_mediaconnection
=
NULL
;
sd
->
pp_media
[
sd
->
i_media
]
->
psz_medianame
=
strndup
(
&
p_packet
[
2
],
i_field_len
);
sd
->
i_media
++
;
break
;
case
(
'c'
):
if
(
sd
->
i_media
<=
0
)
{
FIELD_COPY
(
sd
->
psz_connection
);
}
else
{
FIELD_COPY
(
sd
->
pp_media
[
sd
->
i_media
-
1
]
->
psz_mediaconnection
);
}
break
;
default:
break
;
char
*
psz_eof
=
strchr
(
&
p_packet
[
2
],
':'
);
if
(
psz_eof
&&
psz_eof
[
1
]
!=
'\0'
)
{
attr_descr_t
*
attr
=
malloc
(
sizeof
(
attr_descr_t
)
);
*
psz_eof
++
=
'\0'
;
attr
->
psz_field
=
strdup
(
&
p_packet
[
2
]
);
attr
->
psz_value
=
strdup
(
psz_eof
);
TAB_APPEND
(
sd
->
i_attributes
,
sd
->
pp_attributes
,
attr
);
}
break
;
}
case
(
'm'
):
{
media_descr_t
*
media
=
malloc
(
sizeof
(
media_descr_t
)
);
media
->
psz_medianame
=
strdup
(
&
p_packet
[
2
]
);
media
->
psz_mediaconnection
=
NULL
;
TAB_APPEND
(
sd
->
i_media
,
sd
->
pp_media
,
media
);
break
;
}
case
(
'c'
):
if
(
sd
->
i_media
<=
0
)
{
sd
->
psz_connection
=
strdup
(
&
p_packet
[
2
]
);
}
else
{
sd
->
pp_media
[
sd
->
i_media
-
1
]
->
psz_mediaconnection
=
strdup
(
&
p_packet
[
2
]
);
}
break
;
default:
break
;
}
p_packet
=
psz_end
;
#undef FIELD_COPY
}
return
sd
;
...
...
@@ -879,39 +684,24 @@ static sess_descr_t * parse_sdp( intf_thread_t * p_intf, char *p_packet )
static
void
free_sd
(
sess_descr_t
*
p_sd
)
{
int
i
;
if
(
p_sd
)
{
FREE
(
p_sd
->
psz_origin
);
FREE
(
p_sd
->
psz_sessionname
);
FREE
(
p_sd
->
psz_information
);
FREE
(
p_sd
->
psz_uri
);
FREE
(
p_sd
->
psz_emails
);
FREE
(
p_sd
->
psz_phone
);
FREE
(
p_sd
->
psz_time
);
FREE
(
p_sd
->
psz_repeat
);
FREE
(
p_sd
->
psz_attribute
);
FREE
(
p_sd
->
psz_connection
);
for
(
i
=
0
;
i
<
p_sd
->
i_media
;
i
++
)
{
FREE
(
p_sd
->
pp_media
[
i
]
->
psz_medianame
);
FREE
(
p_sd
->
pp_media
[
i
]
->
psz_mediaconnection
);
}
for
(
i
=
0
;
i
<
p_sd
->
i_attributes
;
i
++
)
{
FREE
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
);
FREE
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
);
}
FREE
(
p_sd
->
pp_attributes
);
FREE
(
p_sd
->
pp_media
);
free
(
p_sd
);
FREE
(
p_sd
->
psz_sessionname
);
FREE
(
p_sd
->
psz_connection
);
for
(
i
=
0
;
i
<
p_sd
->
i_media
;
i
++
)
{
FREE
(
p_sd
->
pp_media
[
i
]
->
psz_medianame
);
FREE
(
p_sd
->
pp_media
[
i
]
->
psz_mediaconnection
);
}
else
for
(
i
=
0
;
i
<
p_sd
->
i_attributes
;
i
++
)
{
;
FREE
(
p_sd
->
pp_attributes
[
i
]
->
psz_field
);
FREE
(
p_sd
->
pp_attributes
[
i
]
->
psz_value
);
}
return
;
FREE
(
p_sd
->
pp_attributes
);
FREE
(
p_sd
->
pp_media
);
free
(
p_sd
);
}
/***********************************************************************
...
...
@@ -928,26 +718,16 @@ static int ismult( char *psz_uri )
/* IPv6 */
if
(
psz_uri
[
0
]
==
'['
)
{
if
(
!
strncasecmp
(
&
psz_uri
[
1
],
"FF0"
,
3
)
&&
!
strncasecmp
(
&
psz_uri
[
2
],
"FF0"
,
3
)
)
{
return
VLC_FALSE
;
}
return
VLC_TRUE
;
}
if
(
*
psz_end
!=
'.'
)
{
return
VLC_FALSE
;
if
(
strncasecmp
(
&
psz_uri
[
1
],
"FF0"
,
3
)
||
strncasecmp
(
&
psz_uri
[
2
],
"FF0"
,
3
))
return
(
VLC_TRUE
);
else
return
(
VLC_FALSE
);
}
if
(
i_value
<
224
)
{
return
VLC_FALSE
;
}
if
(
*
psz_end
!=
'.'
)
{
return
(
VLC_FALSE
);
}
return
VLC_TRUE
;
return
(
i_value
<
224
?
VLC_FALSE
:
VLC_TRUE
)
;
}
...
...
@@ -958,39 +738,27 @@ static int ismult( char *psz_uri )
* Taken from udp.c
******************************************************************************/
static
ssize_t
NetRead
(
intf_thread_t
*
p_intf
,
int
i_handle
,
int
i_handle_v6
,
byte_t
*
p_buffer
,
size_t
i_len
)
int
fd
[
2
],
uint8_t
*
p_buffer
,
int
i_len
)
{
#ifdef UNDER_CE
return
-
1
;
#else
struct
timeval
timeout
;
fd_set
fds
;
int
i_ret
;
int
i_max_handle
;
ssize_t
i_recv
=-
1
;
/* Get the max handle for select */
if
(
i_handle_v6
>
i_handle
)
i_max_handle
=
i_handle_v6
;
else
i_max_handle
=
i_handle
;
int
i_handle_max
=
__MAX
(
fd
[
0
],
fd
[
1
]
);
/* Initialize file descriptor set */
FD_ZERO
(
&
fds
);
if
(
i_handle
>
0
)
FD_SET
(
i_handle
,
&
fds
);
if
(
i_handle_v6
>
0
)
FD_SET
(
i_handle_v6
,
&
fds
);
if
(
fd
[
0
]
>
0
)
FD_SET
(
fd
[
0
],
&
fds
);
if
(
fd
[
1
]
>
0
)
FD_SET
(
fd
[
1
],
&
fds
);
/* We'll wait 0.5 second if nothing happens */
timeout
.
tv_sec
=
0
;
timeout
.
tv_usec
=
500000
;
/* Find if some data is available */
i_ret
=
select
(
i_
max_handle
+
1
,
&
fds
,
NULL
,
NULL
,
&
timeout
);
i_ret
=
select
(
i_
handle_max
+
1
,
&
fds
,
NULL
,
NULL
,
&
timeout
);
if
(
i_ret
==
-
1
&&
errno
!=
EINTR
)
{
...
...
@@ -998,31 +766,16 @@ static ssize_t NetRead( intf_thread_t *p_intf,
}
else
if
(
i_ret
>
0
)
{
/* Get the data */
if
(
i_handle
>
0
)
{
if
(
FD_ISSET
(
i_handle
,
&
fds
))
{
i_recv
=
recv
(
i_handle
,
p_buffer
,
i_len
,
0
);
}
}
if
(
i_handle_v6
>
0
)
if
(
fd
[
0
]
>
0
&&
FD_ISSET
(
fd
[
0
],
&
fds
)
)
{
if
(
FD_ISSET
(
i_handle_v6
,
&
fds
))
{
i_recv
=
recv
(
i_handle_v6
,
p_buffer
,
i_len
,
0
);
}
return
recv
(
fd
[
0
],
p_buffer
,
i_len
,
0
);
}
if
(
i_recv
<
0
)
else
if
(
fd
[
1
]
>
0
&&
FD_ISSET
(
fd
[
1
],
&
fds
)
)
{
msg_Err
(
p_intf
,
"recv failed (%s)"
,
strerror
(
errno
)
);
return
recv
(
fd
[
1
],
p_buffer
,
i_len
,
0
);
}
return
i_recv
;
}
return
0
;
#endif
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment