]> git.sesse.net Git - vlc/blobdiff - modules/access/rtsp/real.c
Another time "Remove useless test before a free".
[vlc] / modules / access / rtsp / real.c
index 580c8cab143fddd95f9551847ac7ca59d2787547..da499ec2d35320b8c0155e09abc1ec50e07c6cb7 100644 (file)
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright (C) 2002-2004 the xine project
  * Copyright (C) 2005 VideoLAN
- * $Id: file.c 10310 2005-03-11 22:36:40Z anil $
+ * $Id$
  *
  * Authors: Gildas Bazin <gbazin@videolan.org>
  *          Adapted from xine which itself adapted it from joschkas real tools.
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
-#include <stdio.h>
-#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include <vlc/vlc.h>
 
@@ -47,17 +49,16 @@ const unsigned char xor_table[] = {
 #define MAX(x,y) ((x>y) ? x : y)
 
 
-static void hash(char *field, char *param) {
-
+static void hash(char *field, char *param)
+{
   uint32_t a, b, c, d;
 
   /* fill variables */
   a = LE_32(field);
   b = LE_32(field+4);
   c = LE_32(field+8);
   d = LE_32(field+12);
-  
+
   lprintf("hash input: %x %x %x %x\n", a, b, c, d);
   lprintf("hash parameter:\n");
 
@@ -93,7 +94,7 @@ static void hash(char *field, char *param) {
   c = ((c << 0x11) | (c >> 0x0f)) + d;
   b = ((c & d) | (~c & a)) + LE_32((param+0x3c)) + b + 0x49B40821;
   b = ((b << 0x16) | (b >> 0x0a)) + c;
-  
+
   a = ((b & d) | (~d & c)) + LE_32((param+0x04)) + a - 0x09E1DA9E;
   a = ((a << 0x05) | (a >> 0x1b)) + b;
   d = ((a & c) | (~c & b)) + LE_32((param+0x18)) + d - 0x3FBF4CC0;
@@ -126,7 +127,7 @@ static void hash(char *field, char *param) {
   c = ((c << 0x0e) | (c >> 0x12)) + d;
   b = ((c & a) | (~a & d)) + LE_32((param+0x30)) + b - 0x72D5B376;
   b = ((b << 0x14) | (b >> 0x0c)) + c;
-  
+
   a = (b ^ c ^ d) + LE_32((param+0x14)) + a - 0x0005C6BE;
   a = ((a << 0x04) | (a >> 0x1c)) + b;
   d = (a ^ b ^ c) + LE_32((param+0x20)) + d - 0x788E097F;
@@ -159,42 +160,42 @@ static void hash(char *field, char *param) {
   c = ((c << 0x10) | (c >> 0x10)) + d;
   b = (c ^ d ^ a) + LE_32((param+0x08)) + b - 0x3B53A99B;
   b = ((b << 0x17) | (b >> 0x09)) + c;
-  
+
   a = ((~d | b) ^ c)  + LE_32((param+0x00)) + a - 0x0BD6DDBC;
-  a = ((a << 0x06) | (a >> 0x1a)) + b; 
+  a = ((a << 0x06) | (a >> 0x1a)) + b;
   d = ((~c | a) ^ b)  + LE_32((param+0x1c)) + d + 0x432AFF97;
-  d = ((d << 0x0a) | (d >> 0x16)) + a; 
+  d = ((d << 0x0a) | (d >> 0x16)) + a;
   c = ((~b | d) ^ a)  + LE_32((param+0x38)) + c - 0x546BDC59;
-  c = ((c << 0x0f) | (c >> 0x11)) + d; 
+  c = ((c << 0x0f) | (c >> 0x11)) + d;
   b = ((~a | c) ^ d)  + LE_32((param+0x14)) + b - 0x036C5FC7;
-  b = ((b << 0x15) | (b >> 0x0b)) + c; 
+  b = ((b << 0x15) | (b >> 0x0b)) + c;
   a = ((~d | b) ^ c)  + LE_32((param+0x30)) + a + 0x655B59C3;
-  a = ((a << 0x06) | (a >> 0x1a)) + b; 
+  a = ((a << 0x06) | (a >> 0x1a)) + b;
   d = ((~c | a) ^ b)  + LE_32((param+0x0C)) + d - 0x70F3336E;
-  d = ((d << 0x0a) | (d >> 0x16)) + a; 
+  d = ((d << 0x0a) | (d >> 0x16)) + a;
   c = ((~b | d) ^ a)  + LE_32((param+0x28)) + c - 0x00100B83;
-  c = ((c << 0x0f) | (c >> 0x11)) + d; 
+  c = ((c << 0x0f) | (c >> 0x11)) + d;
   b = ((~a | c) ^ d)  + LE_32((param+0x04)) + b - 0x7A7BA22F;
-  b = ((b << 0x15) | (b >> 0x0b)) + c; 
+  b = ((b << 0x15) | (b >> 0x0b)) + c;
   a = ((~d | b) ^ c)  + LE_32((param+0x20)) + a + 0x6FA87E4F;
-  a = ((a << 0x06) | (a >> 0x1a)) + b; 
+  a = ((a << 0x06) | (a >> 0x1a)) + b;
   d = ((~c | a) ^ b)  + LE_32((param+0x3c)) + d - 0x01D31920;
-  d = ((d << 0x0a) | (d >> 0x16)) + a; 
+  d = ((d << 0x0a) | (d >> 0x16)) + a;
   c = ((~b | d) ^ a)  + LE_32((param+0x18)) + c - 0x5CFEBCEC;
-  c = ((c << 0x0f) | (c >> 0x11)) + d; 
+  c = ((c << 0x0f) | (c >> 0x11)) + d;
   b = ((~a | c) ^ d)  + LE_32((param+0x34)) + b + 0x4E0811A1;
-  b = ((b << 0x15) | (b >> 0x0b)) + c; 
+  b = ((b << 0x15) | (b >> 0x0b)) + c;
   a = ((~d | b) ^ c)  + LE_32((param+0x10)) + a - 0x08AC817E;
-  a = ((a << 0x06) | (a >> 0x1a)) + b; 
+  a = ((a << 0x06) | (a >> 0x1a)) + b;
   d = ((~c | a) ^ b)  + LE_32((param+0x2c)) + d - 0x42C50DCB;
-  d = ((d << 0x0a) | (d >> 0x16)) + a; 
+  d = ((d << 0x0a) | (d >> 0x16)) + a;
   c = ((~b | d) ^ a)  + LE_32((param+0x08)) + c + 0x2AD7D2BB;
-  c = ((c << 0x0f) | (c >> 0x11)) + d; 
+  c = ((c << 0x0f) | (c >> 0x11)) + d;
   b = ((~a | c) ^ d)  + LE_32((param+0x24)) + b - 0x14792C6F;
-  b = ((b << 0x15) | (b >> 0x0b)) + c; 
+  b = ((b << 0x15) | (b >> 0x0b)) + c;
 
   lprintf("hash output: %x %x %x %x\n", a, b, c, d);
-  
+
   a += LE_32(field);
   b += LE_32(field+4);
   c += LE_32(field+8);
@@ -210,16 +211,16 @@ static void call_hash (char *key, char *challenge, int len) {
 
   uint8_t *ptr1, *ptr2;
   uint32_t a, b, c, d, tmp;
-  
-  ptr1=(key+16);
-  ptr2=(key+20);
-  
+
+  ptr1=(uint8_t*)(key+16);
+  ptr2=(uint8_t*)(key+20);
+
   a = LE_32(ptr1);
   b = (a >> 3) & 0x3f;
   a += len * 8;
   LE_32C(ptr1, a);
-  
-  if (a < (len << 3))
+
+  if (a < (uint32_t)(len << 3))
   {
     lprintf("not verified: (len << 3) > a true\n");
     ptr2 += 4;
@@ -228,16 +229,15 @@ static void call_hash (char *key, char *challenge, int len) {
   tmp = LE_32(ptr2) + (len >> 0x1d);
   LE_32C(ptr2, tmp);
   a = 64 - b;
-  c = 0;  
-  if (a <= len)
+  c = 0;
+  if (a <= (uint32_t)len)
   {
-
     memcpy(key+b+24, challenge, a);
     hash(key, key+24);
     c = a;
     d = c + 0x3f;
-    
-    while ( d < len ) {
+
+    while ( d < (uint32_t)len ) {
       lprintf("not verified:  while ( d < len )\n");
       hash(key, challenge+d-0x3f);
       d += 64;
@@ -245,44 +245,40 @@ static void call_hash (char *key, char *challenge, int len) {
     }
     b = 0;
   }
-  
+
   memcpy(key+b+24, challenge+c, len-c);
 }
 
 static void calc_response (char *result, char *field) {
-
   char buf1[128];
   char buf2[128];
   int i;
 
   memset (buf1, 0, 64);
   *buf1 = 128;
-  
+
   memcpy (buf2, field+16, 8);
-  
   i = ( LE_32((buf2)) >> 3 ) & 0x3f;
-  if (i < 56) {
+
+  if (i < 56)
+  {
     i = 56 - i;
-  } else {
+  } else
+  {
     lprintf("not verified: ! (i < 56)\n");
     i = 120 - i;
   }
 
   call_hash (field, buf1, i);
   call_hash (field, buf2, 8);
-
   memcpy (result, field, 16);
-
 }
 
-
 static void calc_response_string (char *result, char *challenge) {
   char field[128];
   char zres[20];
   int  i;
-      
+
   /* initialize our field */
   BE_32C (field,      0x01234567);
   BE_32C ((field+4),  0x89ABCDEF);
@@ -294,11 +290,11 @@ static void calc_response_string (char *result, char *challenge) {
   /* calculate response */
   call_hash(field, challenge, 64);
   calc_response(zres,field);
+
   /* convert zres to ascii string */
   for (i=0; i<16; i++ ) {
     char a, b;
-    
+
     a = (zres[i] >> 4) & 15;
     b = zres[i] & 15;
 
@@ -337,14 +333,14 @@ void real_calc_response_and_checksum (char *response, char *chksum, char *challe
       ch_len=32;
     }
     if ( ch_len > 56 ) ch_len=56;
-    
+
     /* copy challenge to buf */
     memcpy(ptr, challenge, ch_len);
   }
-  
+
   if (xor_table != NULL)
   {
-    table_len = strlen(xor_table);
+    table_len = strlen((char *)xor_table);
 
     if (table_len > 56) table_len=56;
 
@@ -369,14 +365,12 @@ void real_calc_response_and_checksum (char *response, char *chksum, char *challe
  * takes a MLTI-Chunk and a rule number got from match_asm_rule,
  * returns a pointer to selected data and number of bytes in that.
  */
-
 static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
 
   int numrules, codec, size;
   int i;
-  
-  /* MLTI chunk should begin with MLTI */
 
+  /* MLTI chunk should begin with MLTI */
   if ((mlti_chunk[0] != 'M')
       ||(mlti_chunk[1] != 'L')
       ||(mlti_chunk[2] != 'T')
@@ -412,13 +406,12 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection
   }
 
   mlti_chunk+=2;
+
   /* now seek to selected codec */
   for (i=0; i<codec; i++) {
     size=BE_32(mlti_chunk);
     mlti_chunk+=size+4;
   }
-  
   size=BE_32(mlti_chunk);
 
   memcpy(*out, mlti_chunk+4, size);
@@ -431,35 +424,41 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection
 
 rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
 
-  sdpplin_t *desc;
-  rmff_header_t *header;
-  char *buf;
+  sdpplin_t *desc = NULL;
+  rmff_header_t *header = NULL;
+  char *buf = NULL;
   int len, i;
   int max_bit_rate=0;
   int avg_bit_rate=0;
   int max_packet_size=0;
   int avg_packet_size=0;
   int duration=0;
-  
 
-  if (!data) return NULL;
+  if( !data ) return NULL;
 
   desc=sdpplin_parse(data);
+  if( !desc ) return NULL;
 
-  if (!desc) return NULL;
+  buf= (char *)malloc(sizeof(char)*2048);
+  if( !buf ) goto error;
 
-  buf=malloc(2048);
-  header = malloc(sizeof(rmff_header_t));
-  memset(header, 0, sizeof(rmff_header_t));
+  header = (rmff_header_t*)malloc(sizeof(rmff_header_t));
+  if( !header ) goto error;
 
+  memset(header, 0, sizeof(rmff_header_t));
   header->fileheader=rmff_new_fileheader(4+desc->stream_count);
   header->cont=rmff_new_cont(
       desc->title,
       desc->author,
       desc->copyright,
       desc->abstract);
+
   header->data=rmff_new_dataheader(0,0);
-  header->streams = malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
+  if( !header->data ) goto error;
+
+  header->streams = (rmff_mdpr_t**) malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
+  if( !header->streams ) goto error;
+
   memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
   lprintf("number of streams: %u\n", desc->stream_count);
 
@@ -480,14 +479,15 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt
     }
 
     if (!desc->stream[i]->mlti_data) {
-     len = 0;
-     buf = NULL;
-    }
-    else
-      len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf);
-    
+      len = 0;
+      free( buf );
+      buf = NULL;
+    } else
+      len=select_mlti_data(desc->stream[i]->mlti_data,
+        desc->stream[i]->mlti_data_size, rulematches[0], &buf);
+
     header->streams[i]=rmff_new_mdpr(
-       desc->stream[i]->stream_id,
+      desc->stream[i]->stream_id,
         desc->stream[i]->max_bit_rate,
         desc->stream[i]->avg_bit_rate,
         desc->stream[i]->max_packet_size,
@@ -497,8 +497,9 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt
         desc->stream[i]->duration,
         desc->stream[i]->stream_name,
         desc->stream[i]->mime_type,
-       len,
-       buf);
+        len,
+        buf);
+    if( !header->streams[i] ) goto error;
 
     duration=MAX(duration,desc->stream[i]->duration);
     max_bit_rate+=desc->stream[i]->max_bit_rate;
@@ -509,9 +510,9 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt
     else
       avg_packet_size=desc->stream[i]->avg_packet_size;
   }
-  
+
   if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
-    (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
+      (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
 
   header->prop=rmff_new_prop(
       max_bit_rate,
@@ -525,18 +526,25 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt
       0,
       desc->stream_count,
       desc->flags);
+  if( !header->prop ) goto error;
 
   rmff_fix_header(header);
-  free(buf);
 
+  if( desc ) sdpplin_free( desc );
+  free( buf );
   return header;
+
+error:
+  if( desc ) sdpplin_free( desc );
+  if( header ) rmff_free_header( header );
+  free( buf );
+  return NULL;
 }
 
-int real_get_rdt_chunk(rtsp_client_t *rtsp_session, unsigned char **buffer) {
+int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) {
 
   int n=1;
   uint8_t header[8];
-  rmff_pheader_t ph;
   int size;
   int flags1;
   int unknown1;
@@ -544,20 +552,17 @@ int real_get_rdt_chunk(rtsp_client_t *rtsp_session, unsigned char **buffer) {
 
   n=rtsp_read_data(rtsp_session, header, 8);
   if (n<8) return 0;
-  if (header[0] != 0x24)
-  {
+  if (header[0] != 0x24) {
     lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
     return 0;
   }
   size=(header[1]<<16)+(header[2]<<8)+(header[3]);
   flags1=header[4];
-  if ((flags1!=0x40)&&(flags1!=0x42))
-  {
+  if ((flags1!=0x40)&&(flags1!=0x42)) {
     lprintf("got flags1: 0x%02x\n",flags1);
-    if (header[6]==0x06)
-    {
-    lprintf("got end of stream packet\n");
-    return 0;
+    if (header[6]==0x06) {
+      lprintf("got end of stream packet\n");
+      return 0;
     }
     header[0]=header[5];
     header[1]=header[6];
@@ -576,23 +581,26 @@ int real_get_rdt_chunk(rtsp_client_t *rtsp_session, unsigned char **buffer) {
   ts=BE_32(header);
 
 #if 0
-  lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n", 
+  lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
           ts, size, flags1, unknown1, header[4], header[5]);
 #endif
 
   size+=2;
-  
-  ph.object_version=0;
-  ph.length=size;
-  ph.stream_number=(flags1>>1)&1;
-  ph.timestamp=ts;
-  ph.reserved=0;
-  ph.flags=0;      /* TODO: determine keyframe flag and insert here? */
-  //xine_buffer_ensure_size(*buffer, 12+size);
-  rmff_dump_pheader(&ph, *buffer);
-  size-=12;
-  n=rtsp_read_data(rtsp_session, (*buffer)+12, size);
-  
+  ph->object_version=0;
+  ph->length=size;
+  ph->stream_number=(flags1>>1)&1;
+  ph->timestamp=ts;
+  ph->reserved=0;
+  ph->flags=0;      /* TODO: determine keyframe flag and insert here? */
+  return size;
+}
+
+int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph,
+                       unsigned char **buffer) {
+
+  int n;
+  rmff_dump_pheader(ph, (char*)*buffer);
+  n=rtsp_read_data(rtsp_session, (uint8_t*)(*buffer + 12), ph->length - 12);
   return (n <= 0) ? 0 : n+12;
 }
 
@@ -602,20 +610,20 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
 
   char *description=NULL;
   char *session_id=NULL;
-  rmff_header_t *h;
-  char *challenge1;
+  rmff_header_t *h=NULL;
+  char *challenge1 = NULL;
   char challenge2[64];
   char checksum[34];
-  char *subscribe;
-  char *buf=malloc(256);
+  char *subscribe=NULL;
+  char *buf=(char*)malloc(sizeof(char)*256);
   char *mrl=rtsp_get_mrl(rtsp_session);
   unsigned int size;
   int status;
-  
+
   /* get challenge */
   challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
   lprintf("Challenge1: %s\n", challenge1);
-  
+
   /* request stream description */
   rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
   sprintf(buf, "Bandwidth: %u", bandwidth);
@@ -626,17 +634,18 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
   rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
   rtsp_schedule_field(rtsp_session, "Language: en-US");
   rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
-  status=rtsp_request_describe(rtsp_session,NULL);
 
-  if ( status<200 || status>299 )
-  {
+  status=rtsp_request_describe(rtsp_session,NULL);
+  if ( status<200 || status>299 ) {
     char *alert=rtsp_search_answers(rtsp_session,"Alert");
     if (alert) {
-      lprintf("real: got message from server:\n%s\n", alert);
+        lprintf("real: got message from server:\n%s\n", alert);
     }
     printf( "bou\n");
-    rtsp_send_ok(rtsp_session);
-    free(buf);
+    rtsp_send_ok( rtsp_session );
+    free( challenge1 );
+    free( alert );
+    free( buf );
     return NULL;
   }
 
@@ -649,43 +658,42 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
 
   if (size > MAX_DESC_BUF) {
     printf("real: Content-length for description too big (> %uMB)!\n",
-           MAX_DESC_BUF/(1024*1024) );
-    free(buf);
-    return NULL;
+        MAX_DESC_BUF/(1024*1024) );
+    goto error;
   }
 
   if (!rtsp_search_answers(rtsp_session,"ETag"))
     lprintf("real: got no ETag!\n");
   else
     session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
-    
-  lprintf("Stream description size: %i\n", size);
 
-  description = malloc(sizeof(char)*(size+1));
+  lprintf("Stream description size: %i\n", size);
 
-  if( rtsp_read_data(rtsp_session, description, size) <= 0) {
-    free(buf);
-    return NULL;
-  }
+  description = (char*)malloc(sizeof(char)*(size+1));
+  if( !description )
+    goto error;
+  if( rtsp_read_data(rtsp_session, (uint8_t*)description, size) <= 0)
+    goto error;
   description[size]=0;
+  //fprintf(stderr, "%s", description);
 
-  fprintf(stderr,description);
   /* parse sdp (sdpplin) and create a header and a subscribe string */
-  subscribe=malloc(256);
+  subscribe = (char *) malloc(sizeof(char)*256);
+  if( !subscribe )
+    goto error;
+
   strcpy(subscribe, "Subscribe: ");
   h=real_parse_sdp(description, &subscribe, bandwidth);
-  if (!h) {
-    free(subscribe);
-    free(buf);
-    return NULL;
-  }
+  if (!h)
+    goto error;
+
   rmff_fix_header(h);
 
 #if 0
   fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
-         h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
+      h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
 #endif
-  
+
   /* setup our streams */
   real_calc_response_and_checksum (challenge2, checksum, challenge1);
   buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32);
@@ -704,7 +712,6 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
     buf = realloc(buf, strlen(session_id) + 32);
     sprintf(buf, "If-Match: %s", session_id);
     rtsp_schedule_field(rtsp_session, buf);
-
     buf = realloc(buf, strlen(mrl) + 32);
     sprintf(buf, "%s/streamid=1", mrl);
     rtsp_request_setup(rtsp_session,buf);
@@ -717,8 +724,19 @@ rmff_header_t  *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandw
   rtsp_schedule_field(rtsp_session, "Range: npt=0-");
   rtsp_request_play(rtsp_session,NULL);
 
-  free(subscribe);
-  free(buf);
+  free( challenge1 );
+  free( session_id );
+  free( description );
+  free( subscribe );
+  free( buf );
   return h;
-}
 
+error:
+  if( h ) rmff_free_header( h );
+  free( challenge1 );
+  free( session_id );
+  free( description );
+  free( subscribe );
+  free( buf );
+  return NULL;
+}