X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Frtsp%2Freal.c;h=da499ec2d35320b8c0155e09abc1ec50e07c6cb7;hb=9630c00c6b310e1a824f0bce00de89f0f777484f;hp=580c8cab143fddd95f9551847ac7ca59d2787547;hpb=775fa8a1c8fc2041908e01ea7f12bc0bb0c22f6f;p=vlc diff --git a/modules/access/rtsp/real.c b/modules/access/rtsp/real.c index 580c8cab14..da499ec2d3 100644 --- a/modules/access/rtsp/real.c +++ b/modules/access/rtsp/real.c @@ -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 * Adapted from xine which itself adapted it from joschkas real tools. @@ -20,10 +20,12 @@ * * 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 -#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include @@ -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; ifileheader=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; +}