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
00026
00027
00028
00029
00030
00031 #include "avformat.h"
00032 #include "mms.h"
00033 #include "internal.h"
00034 #include "avio_internal.h"
00035 #include "libavutil/intreadwrite.h"
00036 #include "libavcodec/bytestream.h"
00037 #include "network.h"
00038 #include "url.h"
00039
00040 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
00041 #define LOCAL_PORT 1037 // as above.
00042
00043 typedef enum {
00044 CS_PKT_INITIAL = 0x01,
00045 CS_PKT_PROTOCOL_SELECT = 0x02,
00046 CS_PKT_MEDIA_FILE_REQUEST = 0x05,
00047 CS_PKT_START_FROM_PKT_ID = 0x07,
00048 CS_PKT_STREAM_PAUSE = 0x09,
00049 CS_PKT_STREAM_CLOSE = 0x0d,
00050 CS_PKT_MEDIA_HEADER_REQUEST = 0x15,
00051 CS_PKT_TIMING_DATA_REQUEST = 0x18,
00052 CS_PKT_USER_PASSWORD = 0x1a,
00053 CS_PKT_KEEPALIVE = 0x1b,
00054 CS_PKT_STREAM_ID_REQUEST = 0x33,
00055 } MMSCSPacketType;
00056
00058 typedef enum {
00061 SC_PKT_CLIENT_ACCEPTED = 0x01,
00062 SC_PKT_PROTOCOL_ACCEPTED = 0x02,
00063 SC_PKT_PROTOCOL_FAILED = 0x03,
00064 SC_PKT_MEDIA_PKT_FOLLOWS = 0x05,
00065 SC_PKT_MEDIA_FILE_DETAILS = 0x06,
00066 SC_PKT_HEADER_REQUEST_ACCEPTED = 0x11,
00067 SC_PKT_TIMING_TEST_REPLY = 0x15,
00068 SC_PKT_PASSWORD_REQUIRED = 0x1a,
00069 SC_PKT_KEEPALIVE = 0x1b,
00070 SC_PKT_STREAM_STOPPED = 0x1e,
00071 SC_PKT_STREAM_CHANGING = 0x20,
00072 SC_PKT_STREAM_ID_ACCEPTED = 0x21,
00077 SC_PKT_CANCEL = -1,
00078 SC_PKT_NO_DATA = -2,
00083 SC_PKT_ASF_HEADER = 0x010000,
00084 SC_PKT_ASF_MEDIA = 0x010001,
00086 } MMSSCPacketType;
00087
00088 typedef struct {
00089 MMSContext mms;
00090 int outgoing_packet_seq;
00091 char path[256];
00092 char host[128];
00093 int incoming_packet_seq;
00094 int incoming_flags;
00095 int packet_id;
00096 unsigned int header_packet_id;
00097 } MMSTContext;
00098
00100 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
00101 {
00102 MMSContext *mms = &mmst->mms;
00103 mms->write_out_ptr = mms->out_buffer;
00104
00105 bytestream_put_le32(&mms->write_out_ptr, 1);
00106 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
00107 bytestream_put_le32(&mms->write_out_ptr, 0);
00108 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
00109 bytestream_put_le32(&mms->write_out_ptr, 0);
00110 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++);
00111 bytestream_put_le64(&mms->write_out_ptr, 0);
00112 bytestream_put_le32(&mms->write_out_ptr, 0);
00113 bytestream_put_le16(&mms->write_out_ptr, packet_type);
00114 bytestream_put_le16(&mms->write_out_ptr, 3);
00115 }
00116
00118 static void insert_command_prefixes(MMSContext *mms,
00119 uint32_t prefix1, uint32_t prefix2)
00120 {
00121 bytestream_put_le32(&mms->write_out_ptr, prefix1);
00122 bytestream_put_le32(&mms->write_out_ptr, prefix2);
00123 }
00124
00126 static int send_command_packet(MMSTContext *mmst)
00127 {
00128 MMSContext *mms = &mmst->mms;
00129 int len= mms->write_out_ptr - mms->out_buffer;
00130 int exact_length = FFALIGN(len, 8);
00131 int first_length= exact_length - 16;
00132 int len8= first_length/8;
00133 int write_result;
00134
00135
00136 AV_WL32(mms->out_buffer + 8, first_length);
00137 AV_WL32(mms->out_buffer + 16, len8);
00138 AV_WL32(mms->out_buffer + 32, len8-2);
00139 memset(mms->write_out_ptr, 0, exact_length - len);
00140
00141
00142 write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length);
00143 if(write_result != exact_length) {
00144 av_log(NULL, AV_LOG_ERROR,
00145 "Failed to write data of length %d: %d (%s)\n",
00146 exact_length, write_result,
00147 write_result < 0 ? strerror(write_result) :
00148 "The server closed the connection");
00149 return AVERROR(EIO);
00150 }
00151
00152 return 0;
00153 }
00154
00155 static void mms_put_utf16(MMSContext *mms, const uint8_t *src)
00156 {
00157 AVIOContext bic;
00158 int size = mms->write_out_ptr - mms->out_buffer;
00159 int len;
00160 ffio_init_context(&bic, mms->write_out_ptr,
00161 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
00162
00163 len = avio_put_str16le(&bic, src);
00164 mms->write_out_ptr += len;
00165 }
00166
00167 static int send_time_test_data(MMSTContext *mmst)
00168 {
00169 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST);
00170 insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
00171 return send_command_packet(mmst);
00172 }
00173
00174 static int send_protocol_select(MMSTContext *mmst)
00175 {
00176 char data_string[256];
00177 MMSContext *mms = &mmst->mms;
00178
00179 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT);
00180 insert_command_prefixes(mms, 0, 0xffffffff);
00181 bytestream_put_le32(&mms->write_out_ptr, 0);
00182 bytestream_put_le32(&mms->write_out_ptr, 0x00989680);
00183 bytestream_put_le32(&mms->write_out_ptr, 2);
00184 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
00185 (LOCAL_ADDRESS>>24)&0xff,
00186 (LOCAL_ADDRESS>>16)&0xff,
00187 (LOCAL_ADDRESS>>8)&0xff,
00188 LOCAL_ADDRESS&0xff,
00189 "TCP",
00190 LOCAL_PORT);
00191
00192 mms_put_utf16(mms, data_string);
00193 return send_command_packet(mmst);
00194 }
00195
00196 static int send_media_file_request(MMSTContext *mmst)
00197 {
00198 MMSContext *mms = &mmst->mms;
00199 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST);
00200 insert_command_prefixes(mms, 1, 0xffffffff);
00201 bytestream_put_le32(&mms->write_out_ptr, 0);
00202 bytestream_put_le32(&mms->write_out_ptr, 0);
00203 mms_put_utf16(mms, mmst->path + 1);
00204
00205 return send_command_packet(mmst);
00206 }
00207
00208 static void handle_packet_stream_changing_type(MMSTContext *mmst)
00209 {
00210 MMSContext *mms = &mmst->mms;
00211 av_dlog(NULL, "Stream changing!\n");
00212
00213
00214 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
00215 av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id);
00216 }
00217
00218 static int send_keepalive_packet(MMSTContext *mmst)
00219 {
00220
00221 start_command_packet(mmst, CS_PKT_KEEPALIVE);
00222 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
00223 return send_command_packet(mmst);
00224 }
00225
00228 static void pad_media_packet(MMSContext *mms)
00229 {
00230 if(mms->remaining_in_len<mms->asf_packet_len) {
00231 int padding_size = mms->asf_packet_len - mms->remaining_in_len;
00232 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
00233 mms->remaining_in_len += padding_size;
00234 }
00235 }
00236
00238 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
00239 {
00240 int read_result;
00241 MMSSCPacketType packet_type= -1;
00242 MMSContext *mms = &mmst->mms;
00243 for(;;) {
00244 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8);
00245 if (read_result != 8) {
00246 if(read_result < 0) {
00247 av_log(NULL, AV_LOG_ERROR,
00248 "Error reading packet header: %d (%s)\n",
00249 read_result, strerror(read_result));
00250 packet_type = SC_PKT_CANCEL;
00251 } else {
00252 av_log(NULL, AV_LOG_ERROR,
00253 "The server closed the connection\n");
00254 packet_type = SC_PKT_NO_DATA;
00255 }
00256 return packet_type;
00257 }
00258
00259
00260 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
00261 int length_remaining, hr;
00262
00263 mmst->incoming_flags= mms->in_buffer[3];
00264 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
00265 if(read_result != 4) {
00266 av_log(NULL, AV_LOG_ERROR,
00267 "Reading command packet length failed: %d (%s)\n",
00268 read_result,
00269 read_result < 0 ? strerror(read_result) :
00270 "The server closed the connection");
00271 return read_result < 0 ? read_result : AVERROR(EIO);
00272 }
00273
00274 length_remaining= AV_RL32(mms->in_buffer+8) + 4;
00275 av_dlog(NULL, "Length remaining is %d\n", length_remaining);
00276
00277 if (length_remaining < 0
00278 || length_remaining > sizeof(mms->in_buffer) - 12) {
00279 av_log(NULL, AV_LOG_ERROR,
00280 "Incoming packet length %d exceeds bufsize %zu\n",
00281 length_remaining, sizeof(mms->in_buffer) - 12);
00282 return AVERROR_INVALIDDATA;
00283 }
00284 read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12,
00285 length_remaining) ;
00286 if (read_result != length_remaining) {
00287 av_log(NULL, AV_LOG_ERROR,
00288 "Reading pkt data (length=%d) failed: %d (%s)\n",
00289 length_remaining, read_result,
00290 read_result < 0 ? strerror(read_result) :
00291 "The server closed the connection");
00292 return read_result < 0 ? read_result : AVERROR(EIO);
00293 }
00294 packet_type= AV_RL16(mms->in_buffer+36);
00295 if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
00296 av_log(NULL, AV_LOG_ERROR,
00297 "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
00298 return AVERROR(EINVAL);
00299 }
00300 } else {
00301 int length_remaining;
00302 int packet_id_type;
00303 int tmp;
00304
00305
00306
00307 tmp = AV_RL16(mms->in_buffer + 6);
00308 length_remaining = (tmp - 8) & 0xffff;
00309 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
00310 packet_id_type = mms->in_buffer[4];
00311 mmst->incoming_flags = mms->in_buffer[5];
00312
00313 if (length_remaining < 0
00314 || length_remaining > sizeof(mms->in_buffer) - 8) {
00315 av_log(NULL, AV_LOG_ERROR,
00316 "Data length %d is invalid or too large (max=%zu)\n",
00317 length_remaining, sizeof(mms->in_buffer));
00318 return AVERROR_INVALIDDATA;
00319 }
00320 mms->remaining_in_len = length_remaining;
00321 mms->read_in_ptr = mms->in_buffer;
00322 read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
00323 if(read_result != length_remaining) {
00324 av_log(NULL, AV_LOG_ERROR,
00325 "Failed to read packet data of size %d: %d (%s)\n",
00326 length_remaining, read_result,
00327 read_result < 0 ? strerror(read_result) :
00328 "The server closed the connection");
00329 return read_result < 0 ? read_result : AVERROR(EIO);
00330 }
00331
00332
00333 if(packet_id_type == mmst->header_packet_id) {
00334 packet_type = SC_PKT_ASF_HEADER;
00335
00336 if(!mms->header_parsed) {
00337 void *p = av_realloc(mms->asf_header,
00338 mms->asf_header_size + mms->remaining_in_len);
00339 if (!p) {
00340 av_freep(&mms->asf_header);
00341 return AVERROR(ENOMEM);
00342 }
00343 mms->asf_header = p;
00344 memcpy(mms->asf_header + mms->asf_header_size,
00345 mms->read_in_ptr, mms->remaining_in_len);
00346 mms->asf_header_size += mms->remaining_in_len;
00347 }
00348
00349 if (mmst->incoming_flags == 0x04)
00350 continue;
00351 } else if(packet_id_type == mmst->packet_id) {
00352 packet_type = SC_PKT_ASF_MEDIA;
00353 } else {
00354 av_dlog(NULL, "packet id type %d is old.", packet_id_type);
00355 continue;
00356 }
00357 }
00358
00359
00360 if(packet_type == SC_PKT_KEEPALIVE) {
00361 send_keepalive_packet(mmst);
00362 continue;
00363 } else if(packet_type == SC_PKT_STREAM_CHANGING) {
00364 handle_packet_stream_changing_type(mmst);
00365 } else if(packet_type == SC_PKT_ASF_MEDIA) {
00366 pad_media_packet(mms);
00367 }
00368 return packet_type;
00369 }
00370 }
00371
00372 static int mms_safe_send_recv(MMSTContext *mmst,
00373 int (*send_fun)(MMSTContext *mmst),
00374 const MMSSCPacketType expect_type)
00375 {
00376 MMSSCPacketType type;
00377 if(send_fun) {
00378 int ret = send_fun(mmst);
00379 if (ret < 0) {
00380 av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
00381 return ret;
00382 }
00383 }
00384
00385 if ((type = get_tcp_server_response(mmst)) != expect_type) {
00386 av_log(NULL, AV_LOG_ERROR,
00387 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
00388 type, expect_type);
00389 return AVERROR_INVALIDDATA;
00390 } else {
00391 return 0;
00392 }
00393 }
00394
00395 static int send_media_header_request(MMSTContext *mmst)
00396 {
00397 MMSContext *mms = &mmst->mms;
00398 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST);
00399 insert_command_prefixes(mms, 1, 0);
00400 bytestream_put_le32(&mms->write_out_ptr, 0);
00401 bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
00402 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00403 bytestream_put_le32(&mms->write_out_ptr, 0);
00404 bytestream_put_le32(&mms->write_out_ptr, 0);
00405 bytestream_put_le32(&mms->write_out_ptr, 0);
00406
00407
00408 bytestream_put_le32(&mms->write_out_ptr, 0);
00409 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
00410 bytestream_put_le32(&mms->write_out_ptr, 2);
00411 bytestream_put_le32(&mms->write_out_ptr, 0);
00412
00413 return send_command_packet(mmst);
00414 }
00415
00417 static int send_startup_packet(MMSTContext *mmst)
00418 {
00419 char data_string[256];
00420 MMSContext *mms = &mmst->mms;
00421
00422
00423
00424
00425 snprintf(data_string, sizeof(data_string),
00426 "NSPlayer/7.0.0.1956; {%s}; Host: %s",
00427 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
00428
00429 start_command_packet(mmst, CS_PKT_INITIAL);
00430 insert_command_prefixes(mms, 0, 0x0004000b);
00431 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
00432 mms_put_utf16(mms, data_string);
00433 return send_command_packet(mmst);
00434 }
00435
00437 static int send_stream_selection_request(MMSTContext *mmst)
00438 {
00439 int i;
00440 MMSContext *mms = &mmst->mms;
00441
00442 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST);
00443 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num);
00444 for(i= 0; i<mms->stream_num; i++) {
00445 bytestream_put_le16(&mms->write_out_ptr, 0xffff);
00446 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id);
00447 bytestream_put_le16(&mms->write_out_ptr, 0);
00448 }
00449 return send_command_packet(mmst);
00450 }
00451
00452 static int send_close_packet(MMSTContext *mmst)
00453 {
00454 start_command_packet(mmst, CS_PKT_STREAM_CLOSE);
00455 insert_command_prefixes(&mmst->mms, 1, 1);
00456
00457 return send_command_packet(mmst);
00458 }
00459
00461 static int mms_close(URLContext *h)
00462 {
00463 MMSTContext *mmst = (MMSTContext *)h->priv_data;
00464 MMSContext *mms = &mmst->mms;
00465 if(mms->mms_hd) {
00466 send_close_packet(mmst);
00467 ffurl_close(mms->mms_hd);
00468 }
00469
00470
00471 av_free(mms->streams);
00472 av_free(mms->asf_header);
00473 av_freep(&h->priv_data);
00474
00475 return 0;
00476 }
00477
00478 static int send_media_packet_request(MMSTContext *mmst)
00479 {
00480 MMSContext *mms = &mmst->mms;
00481 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID);
00482 insert_command_prefixes(mms, 1, 0x0001FFFF);
00483 bytestream_put_le64(&mms->write_out_ptr, 0);
00484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00485 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
00486 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00487 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00488 bytestream_put_byte(&mms->write_out_ptr, 0xff);
00489 bytestream_put_byte(&mms->write_out_ptr, 0x00);
00490
00491 mmst->packet_id++;
00492 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
00493 return send_command_packet(mmst);
00494 }
00495
00496
00497 static void clear_stream_buffers(MMSContext *mms)
00498 {
00499 mms->remaining_in_len = 0;
00500 mms->read_in_ptr = mms->in_buffer;
00501 }
00502
00503 static int mms_open(URLContext *h, const char *uri, int flags)
00504 {
00505 MMSTContext *mmst;
00506 MMSContext *mms;
00507 int port, err;
00508 char tcpname[256];
00509
00510 h->is_streamed = 1;
00511 mmst = h->priv_data = av_mallocz(sizeof(MMSTContext));
00512 if (!h->priv_data)
00513 return AVERROR(ENOMEM);
00514 mms = &mmst->mms;
00515
00516
00517 av_url_split(NULL, 0, NULL, 0,
00518 mmst->host, sizeof(mmst->host), &port, mmst->path,
00519 sizeof(mmst->path), uri);
00520
00521 if(port<0)
00522 port = 1755;
00523
00524
00525 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
00526 err = ffurl_open(&mms->mms_hd, tcpname, AVIO_RDWR);
00527 if (err)
00528 goto fail;
00529
00530 mmst->packet_id = 3;
00531 mmst->header_packet_id = 2;
00532 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED);
00533 if (err)
00534 goto fail;
00535 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY);
00536 if (err)
00537 goto fail;
00538 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED);
00539 if (err)
00540 goto fail;
00541 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS);
00542 if (err)
00543 goto fail;
00544 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED);
00545 if (err)
00546 goto fail;
00547 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER);
00548 if (err)
00549 goto fail;
00550 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
00551 av_log(NULL, AV_LOG_ERROR,
00552 "The server does not support MMST (try MMSH or RTSP)\n");
00553 err = AVERROR(EINVAL);
00554 goto fail;
00555 }
00556 err = ff_mms_asf_header_parser(mms);
00557 if (err) {
00558 av_dlog(NULL, "asf header parsed failed!\n");
00559 goto fail;
00560 }
00561 mms->header_parsed = 1;
00562
00563 if (!mms->asf_packet_len || !mms->stream_num)
00564 goto fail;
00565
00566 clear_stream_buffers(mms);
00567 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED);
00568 if (err)
00569 goto fail;
00570
00571 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
00572 if (err) {
00573 goto fail;
00574 }
00575 av_dlog(NULL, "Leaving open (success)\n");
00576 return 0;
00577 fail:
00578 mms_close(h);
00579 av_dlog(NULL, "Leaving open (failure: %d)\n", err);
00580 return err;
00581 }
00582
00584 static int mms_read(URLContext *h, uint8_t *buf, int size)
00585 {
00586
00587 MMSTContext *mmst = h->priv_data;
00588 MMSContext *mms = &mmst->mms;
00589 int result = 0;
00590
00591 do {
00592 if(mms->asf_header_read_size < mms->asf_header_size) {
00593
00594 result = ff_mms_read_header(mms, buf, size);
00595 } else if(mms->remaining_in_len) {
00596
00597
00598 result = ff_mms_read_data(mms, buf, size);
00599 } else {
00600
00601 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
00602 if (err == 0) {
00603 if(mms->remaining_in_len>mms->asf_packet_len) {
00604 av_log(NULL, AV_LOG_ERROR,
00605 "Incoming pktlen %d is larger than ASF pktsize %d\n",
00606 mms->remaining_in_len, mms->asf_packet_len);
00607 result= AVERROR(EIO);
00608 } else {
00609
00610 result = ff_mms_read_data(mms, buf, size);
00611 if (result == 0) {
00612 av_dlog(NULL, "read asf media paket size is zero!\n");
00613 break;
00614 }
00615 }
00616 } else {
00617 av_dlog(NULL, "read packet error!\n");
00618 break;
00619 }
00620 }
00621 } while(!result);
00622 return result;
00623 }
00624
00625 URLProtocol ff_mmst_protocol = {
00626 .name = "mmst",
00627 .url_open = mms_open,
00628 .url_read = mms_read,
00629 .url_close = mms_close,
00630 };