1 /*
2 * MMS protocol over TCP
3 * Copyright (c) 2006,2007 Ryan Martell
4 * Copyright (c) 2007 Björn Axelsson
5 * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /* References
25 * MMS protocol specification:
26 * [1]http://msdn.microsoft.com/en-us/library/cc234711(PROT.10).aspx
27 * ASF specification. Revision 01.20.03.
28 * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx
29 */
30
39
40 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
41 #define LOCAL_PORT 1037 // as above.
42 /** Client to server packet types. */
56
57 /** Server to client packet types. */
59 /** Control packets. */
60 /*@{*/
73 /*@}*/
74
75 /** Pseudo packets. */
76 /*@{*/
79 /*@}*/
80
81 /** Data packets. */
82 /*@{*/
85 /*@}*/
87
91 char path[256];
///< Path of the resource being asked for.
92 char host[128];
///< Host of the resources.
95 int packet_id;
///< Identifier for packets in the current stream.
98
99 /** Create MMST command packet header */
101 {
104
105 bytestream_put_le32(&mms->
write_out_ptr, 1);
// start sequence
107 bytestream_put_le32(&mms->
write_out_ptr, 0);
// Length starts from after the protocol type bytes
114 bytestream_put_le16(&mms->
write_out_ptr, 3);
// direction to server
115 }
116
117 /** Add prefixes to MMST command packet. */
119 uint32_t prefix1, uint32_t prefix2)
120 {
121 bytestream_put_le32(&mms->
write_out_ptr, prefix1);
// first prefix
122 bytestream_put_le32(&mms->
write_out_ptr, prefix2);
// second prefix
123 }
124
125 /** Send a prepared MMST command packet. */
127 {
131 int first_length= exact_length - 16;
132 int len8= first_length/8;
133 int write_result;
134
135 // update packet length fields.
140
141 // write it out.
143 if(write_result != exact_length) {
145 "Failed to write data of length %d: %d (%s)\n",
146 exact_length, write_result,
147 write_result < 0 ? strerror(
AVUNERROR(write_result)) :
148 "The server closed the connection");
150 }
151
152 return 0;
153 }
154
156 {
162
167 return 0;
168 }
169
171 {
175 }
176
178 {
180 char data_string[256];
182
185 bytestream_put_le32(&mms->
write_out_ptr, 0);
// maxFunnelBytes
186 bytestream_put_le32(&mms->
write_out_ptr, 0x00989680);
// maxbitRate
188 snprintf(data_string,
sizeof(data_string),
"\\\\%d.%d.%d.%d\\%s\\%d",
193 "TCP", // or UDP
195
199 }
200
202 {
211
213 }
214
216 {
219
220 // 40 is the packet header size, 7 is the prefix size.
223 }
224
226 {
227 // respond to a keepalive with a keepalive...
231 }
232
233 /** Pad media packets smaller than max_packet_size and/or adjust read position
234 * after a seek. */
236 {
241 }
242 }
243
244 /** Read incoming MMST media, header or command packet. */
246 {
247 int read_result;
250 for(;;) {
252 if (read_result != 8) {
253 if(read_result < 0) {
255 "Error reading packet header: %d (%s)\n",
256 read_result, strerror(
AVUNERROR(read_result)));
258 } else {
260 "The server closed the connection\n");
262 }
263 return packet_type;
264 }
265
266 // handle command packet.
268 int length_remaining, hr;
269
272 if(read_result != 4) {
274 "Reading command packet length failed: %d (%s)\n",
275 read_result,
276 read_result < 0 ? strerror(
AVUNERROR(read_result)) :
277 "The server closed the connection");
278 return read_result < 0 ? read_result :
AVERROR(EIO);
279 }
280
283 // read the rest of the packet.
284 if (length_remaining < 0
285 || length_remaining >
sizeof(mms->
in_buffer) - 12) {
288 length_remaining,
sizeof(mms->
in_buffer) - 12);
290 }
292 length_remaining) ;
293 if (read_result != length_remaining) {
295 "Reading pkt data (length=%d) failed: %d (%s)\n",
296 length_remaining, read_result,
297 read_result < 0 ? strerror(
AVUNERROR(read_result)) :
298 "The server closed the connection");
299 return read_result < 0 ? read_result :
AVERROR(EIO);
300 }
304 "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
306 }
307 } else {
308 int length_remaining;
309 int packet_id_type;
311
312 // note we cache the first 8 bytes,
313 // then fill up the buffer with the others
315 length_remaining = (
tmp - 8) & 0xffff;
319
320 if (length_remaining < 0
321 || length_remaining >
sizeof(mms->
in_buffer) - 8) {
323 "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER ")\n",
324 length_remaining,
sizeof(mms->
in_buffer));
326 }
330 if(read_result != length_remaining) {
332 "Failed to read packet data of size %d: %d (%s)\n",
333 length_remaining, read_result,
334 read_result < 0 ? strerror(
AVUNERROR(read_result)) :
335 "The server closed the connection");
336 return read_result < 0 ? read_result :
AVERROR(EIO);
337 }
338
339 // if we successfully read everything.
341 int err;
343 // Store the asf header
349 return err;
350 }
354 }
355 // 0x04 means asf header is sent in multiple packets.
357 continue;
358 }
else if(packet_id_type == mmst->
packet_id) {
360 } else {
362 continue;
363 }
364 }
365
366 // preprocess some packet type
369 continue;
374 }
375 return packet_type;
376 }
377 }
378
382 {
384 if(send_fun) {
385 int ret = send_fun(mmst);
389 }
390 }
391
394 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
397 } else {
398 return 0;
399 }
400 }
401
403 {
413
414 // the media preroll value in milliseconds?
419
421 }
422
423 /** Send the initial handshake. */
425 {
426 char data_string[256];
429 // SubscriberName is defined in MS specification linked below.
430 // The GUID value can be any valid value.
431 // http://download.microsoft.com/
432 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
433 snprintf(data_string,
sizeof(data_string),
434 "NSPlayer/7.0.0.1956; {%s}; Host: %s",
435 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->
host);
436
443 }
444
445 /** Send MMST stream selection command based on the AVStream->discard values. */
447 {
450 // send the streams we want back...
457 }
459 }
460
462 {
465
467 }
468
469 /** Close the MMSH/MMST connection */
471 {
474 if(mms->mms_hd) {
477 }
478
479 /* free all separately allocated pointers in mms */
482
483 return 0;
484 }
485
487 {
491 bytestream_put_le64(&mms->
write_out_ptr, 0);
// seek timestamp
492 bytestream_put_le32(&mms->
write_out_ptr, 0xffffffff);
// unknown
493 bytestream_put_le32(&mms->
write_out_ptr, 0xffffffff);
// packet offset
494 bytestream_put_byte(&mms->
write_out_ptr, 0xff);
// max stream time limit
495 bytestream_put_byte(&mms->
write_out_ptr, 0xff);
// max stream time limit
496 bytestream_put_byte(&mms->
write_out_ptr, 0xff);
// max stream time limit
497 bytestream_put_byte(&mms->
write_out_ptr, 0x00);
// stream time limit flag
498
502 }
503
504
506 {
509 }
510
512 {
515 int port, err;
516 char tcpname[256];
517
520
521 // only for MMS over TCP, so set proto = NULL
524 sizeof(mmst->
path), uri);
525
526 if(port<0)
527 port = 1755; // default MMS protocol port
528
529 // establish tcp connection.
532 &
h->interrupt_callback,
NULL,
533 h->protocol_whitelist,
h->protocol_blacklist,
h);
534 if (err)
536
537 mmst->
packet_id = 3;
// default, initial value.
540 if (err)
543 if (err)
546 if (err)
549 if (err)
552 if (err)
555 if (err)
559 "The server does not support MMST (try MMSH or RTSP)\n");
562 }
564 if (err) {
567 }
569
572
575 if (err)
577 // send media packet request
579 if (err) {
581 }
583 return 0;
587 return err;
588 }
589
590 /** Read ASF data through the protocol. */
592 {
593 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
597
598 do {
600 /* Read from ASF header buffer */
603 /* Read remaining packet data to buffer.
604 * the result can not be zero because remaining_in_len is positive.*/
606 } else {
607 /* Read from network */
609 if (err == 0) {
612 "Incoming pktlen %d is larger than ASF pktsize %d\n",
615 } else {
616 // copy the data to the packet buffer.
620 break;
621 }
622 }
623 } else {
625 break;
626 }
627 }
628 }
while(!
result);
// only return one packet.
630 }
631
639 };