FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mmst.c
Go to the documentation of this file.
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 
31 #include "avformat.h"
32 #include "mms.h"
33 #include "internal.h"
34 #include "avio_internal.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavcodec/bytestream.h"
37 #include "network.h"
38 #include "url.h"
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. */
43 typedef enum {
56 
57 /** Server to client packet types. */
58 typedef enum {
59  /** Control packets. */
60  /*@{*/
73  /*@}*/
74 
75  /** Pseudo packets. */
76  /*@{*/
79  /*@}*/
80 
81  /** Data packets. */
82  /*@{*/
83  SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in case of
84  SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets.
85  /*@}*/
87 
88 typedef struct {
90  int outgoing_packet_seq; ///< Outgoing packet sequence number.
91  char path[256]; ///< Path of the resource being asked for.
92  char host[128]; ///< Host of the resources.
93  int incoming_packet_seq; ///< Incoming packet sequence number.
94  int incoming_flags; ///< Incoming packet flags.
95  int packet_id; ///< Identifier for packets in the current stream.
96  unsigned int header_packet_id; ///< default is 2.
97 } MMSTContext;
98 
99 /** Create MMST command packet header */
100 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
101 {
102  MMSContext *mms = &mmst->mms;
103  mms->write_out_ptr = mms->out_buffer;
104 
105  bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence
106  bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
107  bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes
108  bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
109  bytestream_put_le32(&mms->write_out_ptr, 0);
110  bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++);
111  bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp
112  bytestream_put_le32(&mms->write_out_ptr, 0);
113  bytestream_put_le16(&mms->write_out_ptr, packet_type);
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 {
128  MMSContext *mms = &mmst->mms;
129  int len= mms->write_out_ptr - mms->out_buffer;
130  int exact_length = FFALIGN(len, 8);
131  int first_length= exact_length - 16;
132  int len8= first_length/8;
133  int write_result;
134 
135  // update packet length fields.
136  AV_WL32(mms->out_buffer + 8, first_length);
137  AV_WL32(mms->out_buffer + 16, len8);
138  AV_WL32(mms->out_buffer + 32, len8-2);
139  memset(mms->write_out_ptr, 0, exact_length - len);
140 
141  // write it out.
142  write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length);
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");
149  return AVERROR(EIO);
150  }
151 
152  return 0;
153 }
154 
155 static void mms_put_utf16(MMSContext *mms, const uint8_t *src)
156 {
157  AVIOContext bic;
158  int size = mms->write_out_ptr - mms->out_buffer;
159  int len;
160  ffio_init_context(&bic, mms->write_out_ptr,
161  sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
162 
163  len = avio_put_str16le(&bic, src);
164  mms->write_out_ptr += len;
165 }
166 
168 {
170  insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
171  return send_command_packet(mmst);
172 }
173 
175 {
176  char data_string[256];
177  MMSContext *mms = &mmst->mms;
178 
180  insert_command_prefixes(mms, 0, 0xffffffff);
181  bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes
182  bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate
183  bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode
184  snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
185  (LOCAL_ADDRESS>>24)&0xff,
186  (LOCAL_ADDRESS>>16)&0xff,
187  (LOCAL_ADDRESS>>8)&0xff,
188  LOCAL_ADDRESS&0xff,
189  "TCP", // or UDP
190  LOCAL_PORT);
191 
192  mms_put_utf16(mms, data_string);
193  return send_command_packet(mmst);
194 }
195 
197 {
198  MMSContext *mms = &mmst->mms;
200  insert_command_prefixes(mms, 1, 0xffffffff);
201  bytestream_put_le32(&mms->write_out_ptr, 0);
202  bytestream_put_le32(&mms->write_out_ptr, 0);
203  mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/"
204 
205  return send_command_packet(mmst);
206 }
207 
209 {
210  MMSContext *mms = &mmst->mms;
211  av_dlog(NULL, "Stream changing!\n");
212 
213  // 40 is the packet header size, 7 is the prefix size.
214  mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
215  av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id);
216 }
217 
219 {
220  // respond to a keepalive with a keepalive...
222  insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
223  return send_command_packet(mmst);
224 }
225 
226 /** Pad media packets smaller than max_packet_size and/or adjust read position
227  * after a seek. */
228 static void pad_media_packet(MMSContext *mms)
229 {
230  if(mms->remaining_in_len<mms->asf_packet_len) {
231  int padding_size = mms->asf_packet_len - mms->remaining_in_len;
232  memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
233  mms->remaining_in_len += padding_size;
234  }
235 }
236 
237 /** Read incoming MMST media, header or command packet. */
239 {
240  int read_result;
241  MMSSCPacketType packet_type= -1;
242  MMSContext *mms = &mmst->mms;
243  for(;;) {
244  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8);
245  if (read_result != 8) {
246  if(read_result < 0) {
248  "Error reading packet header: %d (%s)\n",
249  read_result, strerror(AVUNERROR(read_result)));
250  packet_type = SC_PKT_CANCEL;
251  } else {
253  "The server closed the connection\n");
254  packet_type = SC_PKT_NO_DATA;
255  }
256  return packet_type;
257  }
258 
259  // handle command packet.
260  if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
261  int length_remaining, hr;
262 
263  mmst->incoming_flags= mms->in_buffer[3];
264  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
265  if(read_result != 4) {
267  "Reading command packet length failed: %d (%s)\n",
268  read_result,
269  read_result < 0 ? strerror(AVUNERROR(read_result)) :
270  "The server closed the connection");
271  return read_result < 0 ? read_result : AVERROR(EIO);
272  }
273 
274  length_remaining= AV_RL32(mms->in_buffer+8) + 4;
275  av_dlog(NULL, "Length remaining is %d\n", length_remaining);
276  // read the rest of the packet.
277  if (length_remaining < 0
278  || length_remaining > sizeof(mms->in_buffer) - 12) {
280  "Incoming packet length %d exceeds bufsize %zu\n",
281  length_remaining, sizeof(mms->in_buffer) - 12);
282  return AVERROR_INVALIDDATA;
283  }
284  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12,
285  length_remaining) ;
286  if (read_result != length_remaining) {
288  "Reading pkt data (length=%d) failed: %d (%s)\n",
289  length_remaining, read_result,
290  read_result < 0 ? strerror(AVUNERROR(read_result)) :
291  "The server closed the connection");
292  return read_result < 0 ? read_result : AVERROR(EIO);
293  }
294  packet_type= AV_RL16(mms->in_buffer+36);
295  if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
297  "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
298  return AVERROR(EINVAL);
299  }
300  } else {
301  int length_remaining;
302  int packet_id_type;
303  int tmp;
304 
305  // note we cache the first 8 bytes,
306  // then fill up the buffer with the others
307  tmp = AV_RL16(mms->in_buffer + 6);
308  length_remaining = (tmp - 8) & 0xffff;
309  mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
310  packet_id_type = mms->in_buffer[4];
311  mmst->incoming_flags = mms->in_buffer[5];
312 
313  if (length_remaining < 0
314  || length_remaining > sizeof(mms->in_buffer) - 8) {
316  "Data length %d is invalid or too large (max=%zu)\n",
317  length_remaining, sizeof(mms->in_buffer));
318  return AVERROR_INVALIDDATA;
319  }
320  mms->remaining_in_len = length_remaining;
321  mms->read_in_ptr = mms->in_buffer;
322  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
323  if(read_result != length_remaining) {
325  "Failed to read packet data of size %d: %d (%s)\n",
326  length_remaining, read_result,
327  read_result < 0 ? strerror(AVUNERROR(read_result)) :
328  "The server closed the connection");
329  return read_result < 0 ? read_result : AVERROR(EIO);
330  }
331 
332  // if we successfully read everything.
333  if(packet_id_type == mmst->header_packet_id) {
334  packet_type = SC_PKT_ASF_HEADER;
335  // Store the asf header
336  if(!mms->header_parsed) {
337  void *p = av_realloc(mms->asf_header,
338  mms->asf_header_size + mms->remaining_in_len);
339  if (!p) {
340  av_freep(&mms->asf_header);
341  return AVERROR(ENOMEM);
342  }
343  mms->asf_header = p;
344  memcpy(mms->asf_header + mms->asf_header_size,
345  mms->read_in_ptr, mms->remaining_in_len);
346  mms->asf_header_size += mms->remaining_in_len;
347  }
348  // 0x04 means asf header is sent in multiple packets.
349  if (mmst->incoming_flags == 0x04)
350  continue;
351  } else if(packet_id_type == mmst->packet_id) {
352  packet_type = SC_PKT_ASF_MEDIA;
353  } else {
354  av_dlog(NULL, "packet id type %d is old.", packet_id_type);
355  continue;
356  }
357  }
358 
359  // preprocess some packet type
360  if(packet_type == SC_PKT_KEEPALIVE) {
361  send_keepalive_packet(mmst);
362  continue;
363  } else if(packet_type == SC_PKT_STREAM_CHANGING) {
365  } else if(packet_type == SC_PKT_ASF_MEDIA) {
366  pad_media_packet(mms);
367  }
368  return packet_type;
369  }
370 }
371 
373  int (*send_fun)(MMSTContext *mmst),
374  const MMSSCPacketType expect_type)
375 {
376  MMSSCPacketType type;
377  if(send_fun) {
378  int ret = send_fun(mmst);
379  if (ret < 0) {
380  av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
381  return ret;
382  }
383  }
384 
385  if ((type = get_tcp_server_response(mmst)) != expect_type) {
387  "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
388  type, expect_type);
389  return AVERROR_INVALIDDATA;
390  } else {
391  return 0;
392  }
393 }
394 
396 {
397  MMSContext *mms = &mmst->mms;
399  insert_command_prefixes(mms, 1, 0);
400  bytestream_put_le32(&mms->write_out_ptr, 0);
401  bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
402  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
403  bytestream_put_le32(&mms->write_out_ptr, 0);
404  bytestream_put_le32(&mms->write_out_ptr, 0);
405  bytestream_put_le32(&mms->write_out_ptr, 0);
406 
407  // the media preroll value in milliseconds?
408  bytestream_put_le32(&mms->write_out_ptr, 0);
409  bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
410  bytestream_put_le32(&mms->write_out_ptr, 2);
411  bytestream_put_le32(&mms->write_out_ptr, 0);
412 
413  return send_command_packet(mmst);
414 }
415 
416 /** Send the initial handshake. */
418 {
419  char data_string[256];
420  MMSContext *mms = &mmst->mms;
421  // SubscriberName is defined in MS specification linked below.
422  // The guid value can be any valid value.
423  // http://download.microsoft.com/
424  // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
425  snprintf(data_string, sizeof(data_string),
426  "NSPlayer/7.0.0.1956; {%s}; Host: %s",
427  "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
428 
430  insert_command_prefixes(mms, 0, 0x0004000b);
431  bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
432  mms_put_utf16(mms, data_string);
433  return send_command_packet(mmst);
434 }
435 
436 /** Send MMST stream selection command based on the AVStream->discard values. */
438 {
439  int i;
440  MMSContext *mms = &mmst->mms;
441  // send the streams we want back...
443  bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums
444  for(i= 0; i<mms->stream_num; i++) {
445  bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags
446  bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id
447  bytestream_put_le16(&mms->write_out_ptr, 0); // selection
448  }
449  return send_command_packet(mmst);
450 }
451 
453 {
455  insert_command_prefixes(&mmst->mms, 1, 1);
456 
457  return send_command_packet(mmst);
458 }
459 
460 /** Close the MMSH/MMST connection */
461 static int mms_close(URLContext *h)
462 {
463  MMSTContext *mmst = (MMSTContext *)h->priv_data;
464  MMSContext *mms = &mmst->mms;
465  if(mms->mms_hd) {
466  send_close_packet(mmst);
467  ffurl_close(mms->mms_hd);
468  }
469 
470  /* free all separately allocated pointers in mms */
471  av_free(mms->streams);
472  av_free(mms->asf_header);
473 
474  return 0;
475 }
476 
478 {
479  MMSContext *mms = &mmst->mms;
481  insert_command_prefixes(mms, 1, 0x0001FFFF);
482  bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp
483  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown
484  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset
485  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
486  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
487  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
488  bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag
489 
490  mmst->packet_id++; // new packet_id
491  bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
492  return send_command_packet(mmst);
493 }
494 
495 
497 {
498  mms->remaining_in_len = 0;
499  mms->read_in_ptr = mms->in_buffer;
500 }
501 
502 static int mms_open(URLContext *h, const char *uri, int flags)
503 {
504  MMSTContext *mmst = h->priv_data;
505  MMSContext *mms;
506  int port, err;
507  char tcpname[256];
508 
509  h->is_streamed = 1;
510  mms = &mmst->mms;
511 
512  // only for MMS over TCP, so set proto = NULL
513  av_url_split(NULL, 0, NULL, 0,
514  mmst->host, sizeof(mmst->host), &port, mmst->path,
515  sizeof(mmst->path), uri);
516 
517  if(port<0)
518  port = 1755; // defaut mms protocol port
519 
520  // establish tcp connection.
521  ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
522  err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
523  &h->interrupt_callback, NULL);
524  if (err)
525  goto fail;
526 
527  mmst->packet_id = 3; // default, initial value.
528  mmst->header_packet_id = 2; // default, initial value.
530  if (err)
531  goto fail;
533  if (err)
534  goto fail;
536  if (err)
537  goto fail;
539  if (err)
540  goto fail;
542  if (err)
543  goto fail;
545  if (err)
546  goto fail;
547  if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
549  "The server does not support MMST (try MMSH or RTSP)\n");
550  err = AVERROR(EINVAL);
551  goto fail;
552  }
553  err = ff_mms_asf_header_parser(mms);
554  if (err) {
555  av_dlog(NULL, "asf header parsed failed!\n");
556  goto fail;
557  }
558  mms->header_parsed = 1;
559 
560  if (!mms->asf_packet_len || !mms->stream_num)
561  goto fail;
562 
565  if (err)
566  goto fail;
567  // send media packet request
569  if (err) {
570  goto fail;
571  }
572  av_dlog(NULL, "Leaving open (success)\n");
573  return 0;
574 fail:
575  mms_close(h);
576  av_dlog(NULL, "Leaving open (failure: %d)\n", err);
577  return err;
578 }
579 
580 /** Read ASF data through the protocol. */
581 static int mms_read(URLContext *h, uint8_t *buf, int size)
582 {
583  /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
584  MMSTContext *mmst = h->priv_data;
585  MMSContext *mms = &mmst->mms;
586  int result = 0;
587 
588  do {
589  if(mms->asf_header_read_size < mms->asf_header_size) {
590  /* Read from ASF header buffer */
591  result = ff_mms_read_header(mms, buf, size);
592  } else if(mms->remaining_in_len) {
593  /* Read remaining packet data to buffer.
594  * the result can not be zero because remaining_in_len is positive.*/
595  result = ff_mms_read_data(mms, buf, size);
596  } else {
597  /* Read from network */
598  int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
599  if (err == 0) {
600  if(mms->remaining_in_len>mms->asf_packet_len) {
602  "Incoming pktlen %d is larger than ASF pktsize %d\n",
603  mms->remaining_in_len, mms->asf_packet_len);
604  result= AVERROR(EIO);
605  } else {
606  // copy the data to the packet buffer.
607  result = ff_mms_read_data(mms, buf, size);
608  if (result == 0) {
609  av_dlog(NULL, "Read ASF media packet size is zero!\n");
610  break;
611  }
612  }
613  } else {
614  av_dlog(NULL, "read packet error!\n");
615  break;
616  }
617  }
618  } while(!result); // only return one packet.
619  return result;
620 }
621 
623  .name = "mmst",
624  .url_open = mms_open,
625  .url_read = mms_read,
626  .url_close = mms_close,
627  .priv_data_size = sizeof(MMSTContext),
629 };