/* Main parsing functions */
static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp );
- static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read );
+ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *p_buffer, size_t i_read );
static sdp_t * ParseSDP( vlc_object_t *p_sd, char* psz_sdp );
static sap_announce_t *CreateAnnounce( services_discovery_t *, uint16_t, sdp_t * );
static int RemoveAnnounce( services_discovery_t *p_sd, sap_announce_t *p_announce );
static char *GetAttribute( sdp_t *p_sdp, const char *psz_search );
static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 );
static int InitSocket( services_discovery_t *p_sd, const char *psz_address, int i_port );
-#ifdef HAVE_ZLIB_H
- static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len );
-#endif
+ static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len );
static void FreeSDP( sdp_t *p_sdp );
/*****************************************************************************
**************************************************************/
/* i_read is at least > 6 */
-static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read )
+static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
+ size_t len )
{
- int i_version, i_address_type, i_hash, i;
- char *psz_sdp, *psz_foo, *psz_initial_sdp;
- uint8_t *p_decompressed_buffer = NULL;
+ int i;
+ const char *psz_sdp;
+ const uint8_t *end = buf + len;
sdp_t *p_sdp;
- vlc_bool_t b_compressed;
- vlc_bool_t b_need_delete = VLC_FALSE;
- /* First, check the sap announce is correct */
- i_version = p_buffer[0] >> 5;
- if( i_version != 1 )
- {
- msg_Dbg( p_sd, "strange sap version %d found", i_version );
- }
+ assert (buf[len] == '\0');
- i_address_type = p_buffer[0] & 0x10;
+ if (len < 4)
+ return VLC_EGENERIC;
- if( (p_buffer[0] & 0x08) != 0 )
- {
- msg_Dbg( p_sd, "reserved bit incorrectly set" );
+ uint8_t flags = buf[0];
+
+ /* First, check the sap announce is correct */
+ if ((flags >> 5) != 1)
return VLC_EGENERIC;
- }
- if( (p_buffer[0] & 0x04) != 0 )
- {
- msg_Dbg( p_sd, "session deletion packet" );
- b_need_delete = VLC_TRUE;
- }
+ vlc_bool_t b_ipv6 = (flags & 0x10) != 0;
+ vlc_bool_t b_need_delete = (flags & 0x04) != 0;
- if( p_buffer[0] & 0x02 )
+ if (flags & 0x02)
{
msg_Dbg( p_sd, "encrypted packet, unsupported" );
return VLC_EGENERIC;
}
- b_compressed = p_buffer[0] & 0x01;
+ vlc_bool_t b_compressed = (flags & 0x01) != 0;
- i_hash = ( p_buffer[2] << 8 ) + p_buffer[3];
+ uint16_t i_hash = U16_AT (buf + 2);
if( p_sd->p_sys->b_strict && i_hash == 0 )
{
return VLC_EGENERIC;
}
- psz_sdp = (char *)p_buffer + 4;
- psz_initial_sdp = psz_sdp;
+ // Skips source address and auth data
+ buf += 4 + (b_ipv6 ? 16 : 4) + buf[1];
+ if (buf > end)
+ return VLC_EGENERIC;
- if( i_address_type == 0 ) /* ipv4 source address */
- {
- psz_sdp += 4;
- if( i_read <= 9 )
- {
- msg_Warn( p_sd, "too short SAP packet" );
- return VLC_EGENERIC;
- }
- }
- else /* ipv6 source address */
+ uint8_t *decomp = NULL;
+ if (b_compressed)
{
- psz_sdp += 16;
- if( i_read <= 21 )
+ int newsize = Decompress (buf, &decomp, end - buf);
+ if (newsize < 0)
{
- msg_Warn( p_sd, "too short SAP packet" );
+ msg_Warn( p_sd, "decompression of sap packet failed" );
return VLC_EGENERIC;
}
- }
- if( b_compressed )
- {
-#ifdef HAVE_ZLIB_H
- int i_decompressed_size;
+ decomp = realloc (decomp, newsize + 1);
+ decomp[newsize++] = '\0';
- i_decompressed_size = Decompress( (uint8_t *)psz_sdp,
- &p_decompressed_buffer, i_read - ( psz_sdp - (char *)p_buffer ) );
- if( i_decompressed_size > 0 )
- {
- psz_sdp = (char *)p_decompressed_buffer;
- realloc( p_decompressed_buffer, i_decompressed_size++ );
- psz_sdp[i_decompressed_size] = '\0';
- }
- else
- {
- msg_Warn( p_sd, "decompression of sap packet failed" );
- return VLC_EGENERIC;
- }
-#else
- msg_Warn( p_sd, "ignoring compressed sap packet" );
- return VLC_EGENERIC;
-#endif
+ psz_sdp = (const char *)decomp;
+ len = newsize;
}
-
- /* Add the size of authentification info */
- if( i_read < p_buffer[1] + (psz_sdp - psz_initial_sdp ) )
+ else
{
- msg_Warn( p_sd, "too short SAP packet\n");
- return VLC_EGENERIC;
+ psz_sdp = (const char *)buf;
+ len = end - buf;
}
- psz_sdp += p_buffer[1];
- psz_foo = psz_sdp;
+
+ assert (buf[len] == '\0');
+
+ msg_Dbg( p_sd, "SDP:\n%s", psz_sdp );
/* Skip payload type */
- /* Handle announces without \0 between SAP and SDP */
- while( *psz_sdp != '\0' && ( psz_sdp[0] != 'v' && psz_sdp[1] != '=' ) )
+ /* SAPv1 has implicit "application/sdp" payload type: first line is v=0 */
+ if (strncmp (psz_sdp, "v=0", 3))
{
- if( psz_sdp - psz_initial_sdp >= i_read - 5 )
+ size_t clen = strlen (psz_sdp) + 1;
+
+ if (strcmp (psz_sdp, "application/sdp"))
{
- msg_Warn( p_sd, "empty SDP ?");
+ msg_Dbg (p_sd, "unsupported content type: %s", psz_sdp);
+ return VLC_EGENERIC;
}
- psz_sdp++;
- }
- if( *psz_sdp == '\0' )
- {
- psz_sdp++;
- }
- if( ( psz_sdp != psz_foo ) && strcasecmp( psz_foo, "application/sdp" ) )
- {
- msg_Dbg( p_sd, "unhandled content type: %s", psz_foo );
- }
- if( ( psz_sdp - (char *)p_buffer ) >= i_read )
- {
- msg_Warn( p_sd, "package without content" );
- return VLC_EGENERIC;
+ // skips content type
+ if (len <= clen)
+ return VLC_EGENERIC;
+
+ len -= clen;
+ psz_sdp += clen;
}
/* Parse SDP info */
CreateAnnounce( p_sd, i_hash, p_sdp );
- FREENULL( p_decompressed_buffer );
+ FREENULL (decomp);
return VLC_SUCCESS;
}
return VLC_EGENERIC;
}
-#ifdef HAVE_ZLIB_H
-static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len )
+static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len )
{
+#ifdef HAVE_ZLIB_H
int i_result, i_dstsize, n;
unsigned char *psz_dst;
z_stream d_stream;
i_result = inflateInit(&d_stream);
if( i_result != Z_OK )
- {
- printf( "inflateInit() failed. Result: %d\n", i_result );
return( -1 );
- }
+
d_stream.next_in = (Bytef *)psz_src;
d_stream.avail_in = i_len;
n = 0;
i_result = inflate(&d_stream, Z_NO_FLUSH);
if( ( i_result != Z_OK ) && ( i_result != Z_STREAM_END ) )
- {
- printf( "Zlib decompression failed. Result: %d\n", i_result );
return( -1 );
- }
}
while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) &&
( i_result != Z_STREAM_END ) );
*_dst = (unsigned char *)realloc( psz_dst, i_dstsize );
return i_dstsize;
-}
+#else
+ (void)psz_src;
+ (void)_dst;
+ (void)i_len;
+ return -1;
#endif
+}
static void FreeSDP( sdp_t *p_sdp )