00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <string.h>
00027
00028 #include <vlc/vlc.h>
00029
00030 #include "rtsp.h"
00031 #include "real.h"
00032 #include "real_sdpplin.h"
00033
00034 const unsigned char xor_table[] = {
00035 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
00036 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
00037 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
00038 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
00039 0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 };
00040
00041 #define BE_32(x) GetDWBE(x)
00042 #define LE_32(x) GetDWLE(x)
00043 #define BE_16(x) GetWBE(x)
00044 #define LE_16(x) GetWLE(x)
00045 #define BE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWBE(&in);} while(0)
00046 #define LE_32C(x,y) do {uint32_t in=y; *(uint32_t *)(x)=GetDWLE(&in);} while(0)
00047 #define MAX(x,y) ((x>y) ? x : y)
00048
00049
00050 static void hash(char *field, char *param)
00051 {
00052 uint32_t a, b, c, d;
00053
00054
00055 a = LE_32(field);
00056 b = LE_32(field+4);
00057 c = LE_32(field+8);
00058 d = LE_32(field+12);
00059
00060 lprintf("hash input: %x %x %x %x\n", a, b, c, d);
00061 lprintf("hash parameter:\n");
00062
00063 a = ((b & c) | (~b & d)) + LE_32((param+0x00)) + a - 0x28955B88;
00064 a = ((a << 0x07) | (a >> 0x19)) + b;
00065 d = ((a & b) | (~a & c)) + LE_32((param+0x04)) + d - 0x173848AA;
00066 d = ((d << 0x0c) | (d >> 0x14)) + a;
00067 c = ((d & a) | (~d & b)) + LE_32((param+0x08)) + c + 0x242070DB;
00068 c = ((c << 0x11) | (c >> 0x0f)) + d;
00069 b = ((c & d) | (~c & a)) + LE_32((param+0x0c)) + b - 0x3E423112;
00070 b = ((b << 0x16) | (b >> 0x0a)) + c;
00071 a = ((b & c) | (~b & d)) + LE_32((param+0x10)) + a - 0x0A83F051;
00072 a = ((a << 0x07) | (a >> 0x19)) + b;
00073 d = ((a & b) | (~a & c)) + LE_32((param+0x14)) + d + 0x4787C62A;
00074 d = ((d << 0x0c) | (d >> 0x14)) + a;
00075 c = ((d & a) | (~d & b)) + LE_32((param+0x18)) + c - 0x57CFB9ED;
00076 c = ((c << 0x11) | (c >> 0x0f)) + d;
00077 b = ((c & d) | (~c & a)) + LE_32((param+0x1c)) + b - 0x02B96AFF;
00078 b = ((b << 0x16) | (b >> 0x0a)) + c;
00079 a = ((b & c) | (~b & d)) + LE_32((param+0x20)) + a + 0x698098D8;
00080 a = ((a << 0x07) | (a >> 0x19)) + b;
00081 d = ((a & b) | (~a & c)) + LE_32((param+0x24)) + d - 0x74BB0851;
00082 d = ((d << 0x0c) | (d >> 0x14)) + a;
00083 c = ((d & a) | (~d & b)) + LE_32((param+0x28)) + c - 0x0000A44F;
00084 c = ((c << 0x11) | (c >> 0x0f)) + d;
00085 b = ((c & d) | (~c & a)) + LE_32((param+0x2C)) + b - 0x76A32842;
00086 b = ((b << 0x16) | (b >> 0x0a)) + c;
00087 a = ((b & c) | (~b & d)) + LE_32((param+0x30)) + a + 0x6B901122;
00088 a = ((a << 0x07) | (a >> 0x19)) + b;
00089 d = ((a & b) | (~a & c)) + LE_32((param+0x34)) + d - 0x02678E6D;
00090 d = ((d << 0x0c) | (d >> 0x14)) + a;
00091 c = ((d & a) | (~d & b)) + LE_32((param+0x38)) + c - 0x5986BC72;
00092 c = ((c << 0x11) | (c >> 0x0f)) + d;
00093 b = ((c & d) | (~c & a)) + LE_32((param+0x3c)) + b + 0x49B40821;
00094 b = ((b << 0x16) | (b >> 0x0a)) + c;
00095
00096 a = ((b & d) | (~d & c)) + LE_32((param+0x04)) + a - 0x09E1DA9E;
00097 a = ((a << 0x05) | (a >> 0x1b)) + b;
00098 d = ((a & c) | (~c & b)) + LE_32((param+0x18)) + d - 0x3FBF4CC0;
00099 d = ((d << 0x09) | (d >> 0x17)) + a;
00100 c = ((d & b) | (~b & a)) + LE_32((param+0x2c)) + c + 0x265E5A51;
00101 c = ((c << 0x0e) | (c >> 0x12)) + d;
00102 b = ((c & a) | (~a & d)) + LE_32((param+0x00)) + b - 0x16493856;
00103 b = ((b << 0x14) | (b >> 0x0c)) + c;
00104 a = ((b & d) | (~d & c)) + LE_32((param+0x14)) + a - 0x29D0EFA3;
00105 a = ((a << 0x05) | (a >> 0x1b)) + b;
00106 d = ((a & c) | (~c & b)) + LE_32((param+0x28)) + d + 0x02441453;
00107 d = ((d << 0x09) | (d >> 0x17)) + a;
00108 c = ((d & b) | (~b & a)) + LE_32((param+0x3c)) + c - 0x275E197F;
00109 c = ((c << 0x0e) | (c >> 0x12)) + d;
00110 b = ((c & a) | (~a & d)) + LE_32((param+0x10)) + b - 0x182C0438;
00111 b = ((b << 0x14) | (b >> 0x0c)) + c;
00112 a = ((b & d) | (~d & c)) + LE_32((param+0x24)) + a + 0x21E1CDE6;
00113 a = ((a << 0x05) | (a >> 0x1b)) + b;
00114 d = ((a & c) | (~c & b)) + LE_32((param+0x38)) + d - 0x3CC8F82A;
00115 d = ((d << 0x09) | (d >> 0x17)) + a;
00116 c = ((d & b) | (~b & a)) + LE_32((param+0x0c)) + c - 0x0B2AF279;
00117 c = ((c << 0x0e) | (c >> 0x12)) + d;
00118 b = ((c & a) | (~a & d)) + LE_32((param+0x20)) + b + 0x455A14ED;
00119 b = ((b << 0x14) | (b >> 0x0c)) + c;
00120 a = ((b & d) | (~d & c)) + LE_32((param+0x34)) + a - 0x561C16FB;
00121 a = ((a << 0x05) | (a >> 0x1b)) + b;
00122 d = ((a & c) | (~c & b)) + LE_32((param+0x08)) + d - 0x03105C08;
00123 d = ((d << 0x09) | (d >> 0x17)) + a;
00124 c = ((d & b) | (~b & a)) + LE_32((param+0x1c)) + c + 0x676F02D9;
00125 c = ((c << 0x0e) | (c >> 0x12)) + d;
00126 b = ((c & a) | (~a & d)) + LE_32((param+0x30)) + b - 0x72D5B376;
00127 b = ((b << 0x14) | (b >> 0x0c)) + c;
00128
00129 a = (b ^ c ^ d) + LE_32((param+0x14)) + a - 0x0005C6BE;
00130 a = ((a << 0x04) | (a >> 0x1c)) + b;
00131 d = (a ^ b ^ c) + LE_32((param+0x20)) + d - 0x788E097F;
00132 d = ((d << 0x0b) | (d >> 0x15)) + a;
00133 c = (d ^ a ^ b) + LE_32((param+0x2c)) + c + 0x6D9D6122;
00134 c = ((c << 0x10) | (c >> 0x10)) + d;
00135 b = (c ^ d ^ a) + LE_32((param+0x38)) + b - 0x021AC7F4;
00136 b = ((b << 0x17) | (b >> 0x09)) + c;
00137 a = (b ^ c ^ d) + LE_32((param+0x04)) + a - 0x5B4115BC;
00138 a = ((a << 0x04) | (a >> 0x1c)) + b;
00139 d = (a ^ b ^ c) + LE_32((param+0x10)) + d + 0x4BDECFA9;
00140 d = ((d << 0x0b) | (d >> 0x15)) + a;
00141 c = (d ^ a ^ b) + LE_32((param+0x1c)) + c - 0x0944B4A0;
00142 c = ((c << 0x10) | (c >> 0x10)) + d;
00143 b = (c ^ d ^ a) + LE_32((param+0x28)) + b - 0x41404390;
00144 b = ((b << 0x17) | (b >> 0x09)) + c;
00145 a = (b ^ c ^ d) + LE_32((param+0x34)) + a + 0x289B7EC6;
00146 a = ((a << 0x04) | (a >> 0x1c)) + b;
00147 d = (a ^ b ^ c) + LE_32((param+0x00)) + d - 0x155ED806;
00148 d = ((d << 0x0b) | (d >> 0x15)) + a;
00149 c = (d ^ a ^ b) + LE_32((param+0x0c)) + c - 0x2B10CF7B;
00150 c = ((c << 0x10) | (c >> 0x10)) + d;
00151 b = (c ^ d ^ a) + LE_32((param+0x18)) + b + 0x04881D05;
00152 b = ((b << 0x17) | (b >> 0x09)) + c;
00153 a = (b ^ c ^ d) + LE_32((param+0x24)) + a - 0x262B2FC7;
00154 a = ((a << 0x04) | (a >> 0x1c)) + b;
00155 d = (a ^ b ^ c) + LE_32((param+0x30)) + d - 0x1924661B;
00156 d = ((d << 0x0b) | (d >> 0x15)) + a;
00157 c = (d ^ a ^ b) + LE_32((param+0x3c)) + c + 0x1fa27cf8;
00158 c = ((c << 0x10) | (c >> 0x10)) + d;
00159 b = (c ^ d ^ a) + LE_32((param+0x08)) + b - 0x3B53A99B;
00160 b = ((b << 0x17) | (b >> 0x09)) + c;
00161
00162 a = ((~d | b) ^ c) + LE_32((param+0x00)) + a - 0x0BD6DDBC;
00163 a = ((a << 0x06) | (a >> 0x1a)) + b;
00164 d = ((~c | a) ^ b) + LE_32((param+0x1c)) + d + 0x432AFF97;
00165 d = ((d << 0x0a) | (d >> 0x16)) + a;
00166 c = ((~b | d) ^ a) + LE_32((param+0x38)) + c - 0x546BDC59;
00167 c = ((c << 0x0f) | (c >> 0x11)) + d;
00168 b = ((~a | c) ^ d) + LE_32((param+0x14)) + b - 0x036C5FC7;
00169 b = ((b << 0x15) | (b >> 0x0b)) + c;
00170 a = ((~d | b) ^ c) + LE_32((param+0x30)) + a + 0x655B59C3;
00171 a = ((a << 0x06) | (a >> 0x1a)) + b;
00172 d = ((~c | a) ^ b) + LE_32((param+0x0C)) + d - 0x70F3336E;
00173 d = ((d << 0x0a) | (d >> 0x16)) + a;
00174 c = ((~b | d) ^ a) + LE_32((param+0x28)) + c - 0x00100B83;
00175 c = ((c << 0x0f) | (c >> 0x11)) + d;
00176 b = ((~a | c) ^ d) + LE_32((param+0x04)) + b - 0x7A7BA22F;
00177 b = ((b << 0x15) | (b >> 0x0b)) + c;
00178 a = ((~d | b) ^ c) + LE_32((param+0x20)) + a + 0x6FA87E4F;
00179 a = ((a << 0x06) | (a >> 0x1a)) + b;
00180 d = ((~c | a) ^ b) + LE_32((param+0x3c)) + d - 0x01D31920;
00181 d = ((d << 0x0a) | (d >> 0x16)) + a;
00182 c = ((~b | d) ^ a) + LE_32((param+0x18)) + c - 0x5CFEBCEC;
00183 c = ((c << 0x0f) | (c >> 0x11)) + d;
00184 b = ((~a | c) ^ d) + LE_32((param+0x34)) + b + 0x4E0811A1;
00185 b = ((b << 0x15) | (b >> 0x0b)) + c;
00186 a = ((~d | b) ^ c) + LE_32((param+0x10)) + a - 0x08AC817E;
00187 a = ((a << 0x06) | (a >> 0x1a)) + b;
00188 d = ((~c | a) ^ b) + LE_32((param+0x2c)) + d - 0x42C50DCB;
00189 d = ((d << 0x0a) | (d >> 0x16)) + a;
00190 c = ((~b | d) ^ a) + LE_32((param+0x08)) + c + 0x2AD7D2BB;
00191 c = ((c << 0x0f) | (c >> 0x11)) + d;
00192 b = ((~a | c) ^ d) + LE_32((param+0x24)) + b - 0x14792C6F;
00193 b = ((b << 0x15) | (b >> 0x0b)) + c;
00194
00195 lprintf("hash output: %x %x %x %x\n", a, b, c, d);
00196
00197 a += LE_32(field);
00198 b += LE_32(field+4);
00199 c += LE_32(field+8);
00200 d += LE_32(field+12);
00201
00202 LE_32C(field, a);
00203 LE_32C(field+4, b);
00204 LE_32C(field+8, c);
00205 LE_32C(field+12, d);
00206 }
00207
00208 static void call_hash (char *key, char *challenge, int len) {
00209
00210 uint8_t *ptr1, *ptr2;
00211 uint32_t a, b, c, d, tmp;
00212
00213 ptr1=(key+16);
00214 ptr2=(key+20);
00215
00216 a = LE_32(ptr1);
00217 b = (a >> 3) & 0x3f;
00218 a += len * 8;
00219 LE_32C(ptr1, a);
00220
00221 if (a < (uint32_t)(len << 3))
00222 {
00223 lprintf("not verified: (len << 3) > a true\n");
00224 ptr2 += 4;
00225 }
00226
00227 tmp = LE_32(ptr2) + (len >> 0x1d);
00228 LE_32C(ptr2, tmp);
00229 a = 64 - b;
00230 c = 0;
00231 if (a <= (uint32_t)len)
00232 {
00233 memcpy(key+b+24, challenge, a);
00234 hash(key, key+24);
00235 c = a;
00236 d = c + 0x3f;
00237
00238 while ( d < (uint32_t)len ) {
00239 lprintf("not verified: while ( d < len )\n");
00240 hash(key, challenge+d-0x3f);
00241 d += 64;
00242 c += 64;
00243 }
00244 b = 0;
00245 }
00246
00247 memcpy(key+b+24, challenge+c, len-c);
00248 }
00249
00250 static void calc_response (char *result, char *field) {
00251 char buf1[128];
00252 char buf2[128];
00253 int i;
00254
00255 memset (buf1, 0, 64);
00256 *buf1 = 128;
00257
00258 memcpy (buf2, field+16, 8);
00259 i = ( LE_32((buf2)) >> 3 ) & 0x3f;
00260
00261 if (i < 56)
00262 {
00263 i = 56 - i;
00264 } else
00265 {
00266 lprintf("not verified: ! (i < 56)\n");
00267 i = 120 - i;
00268 }
00269
00270 call_hash (field, buf1, i);
00271 call_hash (field, buf2, 8);
00272 memcpy (result, field, 16);
00273 }
00274
00275 static void calc_response_string (char *result, char *challenge) {
00276 char field[128];
00277 char zres[20];
00278 int i;
00279
00280
00281 BE_32C (field, 0x01234567);
00282 BE_32C ((field+4), 0x89ABCDEF);
00283 BE_32C ((field+8), 0xFEDCBA98);
00284 BE_32C ((field+12), 0x76543210);
00285 BE_32C ((field+16), 0x00000000);
00286 BE_32C ((field+20), 0x00000000);
00287
00288
00289 call_hash(field, challenge, 64);
00290 calc_response(zres,field);
00291
00292
00293 for (i=0; i<16; i++ ) {
00294 char a, b;
00295
00296 a = (zres[i] >> 4) & 15;
00297 b = zres[i] & 15;
00298
00299 result[i*2] = ((a<10) ? (a+48) : (a+87)) & 255;
00300 result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255;
00301 }
00302 }
00303
00304 void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
00305
00306 int ch_len, table_len, resp_len;
00307 int i;
00308 char *ptr;
00309 char buf[128];
00310
00311
00312 memset(response, 0, 64);
00313 memset(chksum, 0, 34);
00314
00315
00316 memset(buf, 0, 128);
00317 ptr=buf;
00318 BE_32C(ptr, 0xa1e9149d);
00319 ptr+=4;
00320 BE_32C(ptr, 0x0e6b3b59);
00321 ptr+=4;
00322
00323
00324 if (challenge != NULL)
00325 {
00326 ch_len = strlen (challenge);
00327
00328 if (ch_len == 40)
00329 {
00330 challenge[32]=0;
00331 ch_len=32;
00332 }
00333 if ( ch_len > 56 ) ch_len=56;
00334
00335
00336 memcpy(ptr, challenge, ch_len);
00337 }
00338
00339 if (xor_table != NULL)
00340 {
00341 table_len = strlen(xor_table);
00342
00343 if (table_len > 56) table_len=56;
00344
00345
00346 for (i=0; i<table_len; i++)
00347 ptr[i] = ptr[i] ^ xor_table[i];
00348 }
00349
00350 calc_response_string (response, buf);
00351
00352
00353 resp_len = strlen (response);
00354 strcpy (&response[resp_len], "01d0a8e3");
00355
00356
00357 for (i=0; i<resp_len/4; i++)
00358 chksum[i] = response[i*4];
00359 }
00360
00361
00362
00363
00364
00365
00366 static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out) {
00367
00368 int numrules, codec, size;
00369 int i;
00370
00371
00372 if ((mlti_chunk[0] != 'M')
00373 ||(mlti_chunk[1] != 'L')
00374 ||(mlti_chunk[2] != 'T')
00375 ||(mlti_chunk[3] != 'I'))
00376 {
00377 lprintf("MLTI tag not detected, copying data\n");
00378 memcpy(*out, mlti_chunk, mlti_size);
00379 return mlti_size;
00380 }
00381
00382 mlti_chunk+=4;
00383
00384
00385 numrules=BE_16(mlti_chunk);
00386 if (selection >= numrules) return 0;
00387
00388
00389
00390 mlti_chunk+=(selection+1)*2;
00391
00392
00393 codec=BE_16(mlti_chunk);
00394
00395
00396 mlti_chunk+=(numrules-selection)*2;
00397
00398
00399 numrules=BE_16(mlti_chunk);
00400
00401 if (codec >= numrules) {
00402 lprintf("codec index >= number of codecs. %i %i\n", codec, numrules);
00403 return 0;
00404 }
00405
00406 mlti_chunk+=2;
00407
00408
00409 for (i=0; i<codec; i++) {
00410 size=BE_32(mlti_chunk);
00411 mlti_chunk+=size+4;
00412 }
00413 size=BE_32(mlti_chunk);
00414
00415 memcpy(*out, mlti_chunk+4, size);
00416 return size;
00417 }
00418
00419
00420
00421
00422
00423 rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
00424
00425 sdpplin_t *desc = NULL;
00426 rmff_header_t *header = NULL;
00427 char *buf = NULL;
00428 int len, i;
00429 int max_bit_rate=0;
00430 int avg_bit_rate=0;
00431 int max_packet_size=0;
00432 int avg_packet_size=0;
00433 int duration=0;
00434
00435 if( !data ) return NULL;
00436
00437 desc=sdpplin_parse(data);
00438 if( !desc ) return NULL;
00439
00440 buf= (char *)malloc(sizeof(char)*2048);
00441 if( !buf ) goto error;
00442
00443 header = (rmff_header_t*)malloc(sizeof(rmff_header_t));
00444 if( !header ) goto error;
00445
00446 memset(header, 0, sizeof(rmff_header_t));
00447 header->fileheader=rmff_new_fileheader(4+desc->stream_count);
00448 header->cont=rmff_new_cont(
00449 desc->title,
00450 desc->author,
00451 desc->copyright,
00452 desc->abstract);
00453
00454 header->data=rmff_new_dataheader(0,0);
00455 if( !header->data ) goto error;
00456
00457 header->streams = (rmff_mdpr_t**) malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
00458 if( !header->streams ) goto error;
00459
00460 memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
00461 lprintf("number of streams: %u\n", desc->stream_count);
00462
00463 for (i=0; i<desc->stream_count; i++) {
00464
00465 int j=0;
00466 int n;
00467 char b[64];
00468 int rulematches[16];
00469
00470 lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
00471
00472 n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
00473 for (j=0; j<n; j++) {
00474 lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
00475 sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
00476 strcat(*stream_rules, b);
00477 }
00478
00479 if (!desc->stream[i]->mlti_data) {
00480 len = 0;
00481 if( buf ) free( buf );
00482 buf = NULL;
00483 } else
00484 len=select_mlti_data(desc->stream[i]->mlti_data,
00485 desc->stream[i]->mlti_data_size, rulematches[0], &buf);
00486
00487 header->streams[i]=rmff_new_mdpr(
00488 desc->stream[i]->stream_id,
00489 desc->stream[i]->max_bit_rate,
00490 desc->stream[i]->avg_bit_rate,
00491 desc->stream[i]->max_packet_size,
00492 desc->stream[i]->avg_packet_size,
00493 desc->stream[i]->start_time,
00494 desc->stream[i]->preroll,
00495 desc->stream[i]->duration,
00496 desc->stream[i]->stream_name,
00497 desc->stream[i]->mime_type,
00498 len,
00499 buf);
00500 if( !header->streams[i] ) goto error;
00501
00502 duration=MAX(duration,desc->stream[i]->duration);
00503 max_bit_rate+=desc->stream[i]->max_bit_rate;
00504 avg_bit_rate+=desc->stream[i]->avg_bit_rate;
00505 max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
00506 if (avg_packet_size)
00507 avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
00508 else
00509 avg_packet_size=desc->stream[i]->avg_packet_size;
00510 }
00511
00512 if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
00513 (*stream_rules)[strlen(*stream_rules)-1]=0;
00514
00515 header->prop=rmff_new_prop(
00516 max_bit_rate,
00517 avg_bit_rate,
00518 max_packet_size,
00519 avg_packet_size,
00520 0,
00521 duration,
00522 0,
00523 0,
00524 0,
00525 desc->stream_count,
00526 desc->flags);
00527 if( !header->prop ) goto error;
00528
00529 rmff_fix_header(header);
00530
00531 if( desc ) sdpplin_free( desc );
00532 if( buf ) free(buf);
00533 return header;
00534
00535 error:
00536 if( desc ) sdpplin_free( desc );
00537 if( header ) rmff_free_header( header );
00538 if( buf ) free( buf );
00539 return NULL;
00540 }
00541
00542 int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) {
00543
00544 int n=1;
00545 uint8_t header[8];
00546 int size;
00547 int flags1;
00548 int unknown1;
00549 uint32_t ts;
00550
00551 n=rtsp_read_data(rtsp_session, header, 8);
00552 if (n<8) return 0;
00553 if (header[0] != 0x24) {
00554 lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
00555 return 0;
00556 }
00557 size=(header[1]<<16)+(header[2]<<8)+(header[3]);
00558 flags1=header[4];
00559 if ((flags1!=0x40)&&(flags1!=0x42)) {
00560 lprintf("got flags1: 0x%02x\n",flags1);
00561 if (header[6]==0x06) {
00562 lprintf("got end of stream packet\n");
00563 return 0;
00564 }
00565 header[0]=header[5];
00566 header[1]=header[6];
00567 header[2]=header[7];
00568 n=rtsp_read_data(rtsp_session, header+3, 5);
00569 if (n<5) return 0;
00570 lprintf("ignoring bytes:\n");
00571 n=rtsp_read_data(rtsp_session, header+4, 4);
00572 if (n<4) return 0;
00573 flags1=header[4];
00574 size-=9;
00575 }
00576 unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
00577 n=rtsp_read_data(rtsp_session, header, 6);
00578 if (n<6) return 0;
00579 ts=BE_32(header);
00580
00581 #if 0
00582 lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
00583 ts, size, flags1, unknown1, header[4], header[5]);
00584 #endif
00585
00586 size+=2;
00587 ph->object_version=0;
00588 ph->length=size;
00589 ph->stream_number=(flags1>>1)&1;
00590 ph->timestamp=ts;
00591 ph->reserved=0;
00592 ph->flags=0;
00593 return size;
00594 }
00595
00596 int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph,
00597 unsigned char **buffer) {
00598
00599 int n;
00600 rmff_dump_pheader(ph, *buffer);
00601 n=rtsp_read_data(rtsp_session, *buffer + 12, ph->length - 12);
00602 return (n <= 0) ? 0 : n+12;
00603 }
00604
00606 #define MAX_DESC_BUF (20 * 1024 * 1024)
00607 rmff_header_t *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth) {
00608
00609 char *description=NULL;
00610 char *session_id=NULL;
00611 rmff_header_t *h;
00612 char *challenge1 = NULL;
00613 char challenge2[64];
00614 char checksum[34];
00615 char *subscribe=NULL;
00616 char *buf=(char*)malloc(sizeof(char)*256);
00617 char *mrl=rtsp_get_mrl(rtsp_session);
00618 unsigned int size;
00619 int status;
00620
00621
00622 challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
00623 lprintf("Challenge1: %s\n", challenge1);
00624
00625
00626 rtsp_schedule_field(rtsp_session, "Accept: application/sdp");
00627 sprintf(buf, "Bandwidth: %u", bandwidth);
00628 rtsp_schedule_field(rtsp_session, buf);
00629 rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000");
00630 rtsp_schedule_field(rtsp_session, "RegionData: 0");
00631 rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
00632 rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
00633 rtsp_schedule_field(rtsp_session, "Language: en-US");
00634 rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
00635
00636 status=rtsp_request_describe(rtsp_session,NULL);
00637 if ( status<200 || status>299 ) {
00638 char *alert=rtsp_search_answers(rtsp_session,"Alert");
00639 if (alert) {
00640 lprintf("real: got message from server:\n%s\n", alert);
00641 }
00642 printf( "bou\n");
00643 rtsp_send_ok(rtsp_session);
00644 if( challenge1 ) free(challenge1);
00645 if( alert ) free(alert);
00646 if( buf ) free(buf);
00647 return NULL;
00648 }
00649
00650
00651 size=0;
00652 if (!rtsp_search_answers(rtsp_session,"Content-length"))
00653 lprintf("real: got no Content-length!\n");
00654 else
00655 size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
00656
00657 if (size > MAX_DESC_BUF) {
00658 printf("real: Content-length for description too big (> %uMB)!\n",
00659 MAX_DESC_BUF/(1024*1024) );
00660 goto error;
00661 }
00662
00663 if (!rtsp_search_answers(rtsp_session,"ETag"))
00664 lprintf("real: got no ETag!\n");
00665 else
00666 session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
00667
00668 lprintf("Stream description size: %i\n", size);
00669
00670 description = (char*)malloc(sizeof(char)*(size+1));
00671 if( !description )
00672 goto error;
00673 if( rtsp_read_data(rtsp_session, description, size) <= 0)
00674 goto error;
00675 description[size]=0;
00676 fprintf(stderr,description);
00677
00678
00679 subscribe = (char *) malloc(sizeof(char)*256);
00680 if( !subscribe )
00681 goto error;
00682
00683 strcpy(subscribe, "Subscribe: ");
00684 h=real_parse_sdp(description, &subscribe, bandwidth);
00685 if (!h)
00686 goto error;
00687
00688 rmff_fix_header(h);
00689
00690 #if 0
00691 fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n",
00692 h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);
00693 #endif
00694
00695
00696 real_calc_response_and_checksum (challenge2, checksum, challenge1);
00697 buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32);
00698 sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
00699 rtsp_schedule_field(rtsp_session, buf);
00700 buf = realloc(buf, strlen(session_id) + 32);
00701 sprintf(buf, "If-Match: %s", session_id);
00702 rtsp_schedule_field(rtsp_session, buf);
00703 rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
00704 buf = realloc(buf, strlen(mrl) + 32);
00705 sprintf(buf, "%s/streamid=0", mrl);
00706 rtsp_request_setup(rtsp_session,buf);
00707
00708 if (h->prop->num_streams > 1) {
00709 rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
00710 buf = realloc(buf, strlen(session_id) + 32);
00711 sprintf(buf, "If-Match: %s", session_id);
00712 rtsp_schedule_field(rtsp_session, buf);
00713 buf = realloc(buf, strlen(mrl) + 32);
00714 sprintf(buf, "%s/streamid=1", mrl);
00715 rtsp_request_setup(rtsp_session,buf);
00716 }
00717
00718 rtsp_schedule_field(rtsp_session, subscribe);
00719 rtsp_request_setparameter(rtsp_session,NULL);
00720
00721
00722 rtsp_schedule_field(rtsp_session, "Range: npt=0-");
00723 rtsp_request_play(rtsp_session,NULL);
00724
00725 if( challenge1 ) free( challenge1 );
00726 if( session_id ) free( session_id );
00727 if( description ) free(description);
00728 if( subscribe ) free(subscribe);
00729 if( buf ) free(buf);
00730 return h;
00731
00732 error:
00733 if( h ) rmff_free_header( h );
00734 if( challenge1 ) free( challenge1 );
00735 if( session_id ) free( session_id );
00736 if( description ) free(description);
00737 if( subscribe ) free(subscribe);
00738 if( buf ) free(buf);
00739 return NULL;
00740 }