⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mms.c

📁 libmms开发库源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2002-2004 the xine project *  * This file is part of LibMMS, an MMS protocol handling library. *  * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the ree Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * 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-1307, USA * * $Id: mms.c,v 1.21 2006/07/13 12:32:20 shawarma Exp $ * * MMS over TCP protocol *   based on work from major mms *   utility functions to handle communication with an mms server * * TODO: *   error messages *   enable seeking ! */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <unistd.h>#include <stdio.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <stdlib.h>#include <time.h>#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_CODESET)#define USE_ICONV#include <iconv.h>#include <locale.h>#include <langinfo.h>#endif/********** logging **********/#define LOG_MODULE "mms"#define LOG_VERBOSE#ifdef DEBUG# define lprintf printf#else# define lprintf(x...)#endif#include "bswap.h"#include "mms.h"#include "asfheader.h"#include "uri.h"/*  * mms specific types  */#define MMST_PORT 1755#define BUF_SIZE 102400#define CMD_HEADER_LEN   40#define CMD_PREFIX_LEN    8#define CMD_BODY_LEN   1024#define ASF_HEADER_LEN 8192#define MMS_PACKET_ERR        0#define MMS_PACKET_COMMAND    1#define MMS_PACKET_ASF_HEADER 2#define MMS_PACKET_ASF_PACKET 3#define ASF_HEADER_PACKET_ID_TYPE 2#define ASF_MEDIA_PACKET_ID_TYPE  4typedef struct mms_buffer_s mms_buffer_t;struct mms_buffer_s {  uint8_t *buffer;  int pos;};typedef struct mms_packet_header_s mms_packet_header_t;struct mms_packet_header_s {  uint32_t  packet_len;  uint8_t   flags;  uint8_t   packet_id_type;  uint32_t  packet_seq;};struct mms_s {  /* FIXME: de-xine-ification */  void *custom_data;    int           s;    /* url parsing */  char         *url;  char         *proto;  char         *host;  int           port;  char         *user;  char         *password;  char         *uri;  /* command to send */  char          scmd[CMD_HEADER_LEN + CMD_BODY_LEN];  char         *scmd_body; /* pointer to &scmd[CMD_HEADER_LEN] */  int           scmd_len; /* num bytes written in header */    char          str[1024]; /* scratch buffer to built strings */    /* receive buffer */  uint8_t       buf[BUF_SIZE];  int           buf_size;  int           buf_read;    uint8_t       asf_header[ASF_HEADER_LEN];  uint32_t      asf_header_len;  uint32_t      asf_header_read;  int           seq_num;  int           num_stream_ids;  int           stream_ids[ASF_MAX_NUM_STREAMS];  int           stream_types[ASF_MAX_NUM_STREAMS];  off_t         start_packet_seq; /* for live streams != 0, need to keep it around */  int           need_discont; /* whether we need to set start_packet_seq */  uint32_t      asf_packet_len;  uint64_t      file_len;  char          guid[37];  uint32_t      bitrates[ASF_MAX_NUM_STREAMS];  uint32_t      bitrates_pos[ASF_MAX_NUM_STREAMS];  int           bandwidth;    int           has_audio;  int           has_video;  int           live_flag;  off_t         current_pos;  int           eos;};static int fallback_io_select(void *data, int socket, int state, int timeout_msec){  fd_set set;  struct timeval tv = { timeout_msec / 1000, (timeout_msec % 1000) * 1000};  FD_ZERO(&set);  FD_SET(socket, &set);  return select(1, (state == MMS_IO_READ_READY) ? &set : NULL,		       (state == MMS_IO_WRITE_READY) ? &set : NULL, NULL, &tv);}static off_t fallback_io_read(void *data, int socket, char *buf, off_t num){  off_t len = 0, ret;/*   lprintf("%d\n", fallback_io_select(data, socket, MMS_IO_READ_READY, 1000)); */  errno = 0;  while (len < num)  {    ret = (off_t)read(socket, buf + len, num - len);    if(ret == 0)      break; /* EOF */    if(ret < 0)      switch(errno)      {	  case EAGAIN:	    lprintf("len == %lld\n", (long long int) len);	    break;	  default:	    lprintf("len == %lld\n", (long long int) len);	    perror(NULL);	    /* if already read something, return it, we will fail next time */	    return len ? len : ret;       }    len += ret;  }  lprintf("ret len == %lld\nnum == %lld\n", (long long int) len, (long long int) num);  return len;}static off_t fallback_io_write(void *data, int socket, char *buf, off_t num){  return (off_t)write(socket, buf, num);}static int fallback_io_tcp_connect(void *data, const char *host, int port){    struct hostent *h;  int i, s;    h = gethostbyname(host);  if (h == NULL) {/*     fprintf(stderr, "unable to resolve host: %s\n", host); */    return -1;  }  s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    if (s == -1) {/*     fprintf(stderr, "failed to create socket: %s", strerror(errno)); */    return -1;  }  if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) & ~O_NONBLOCK) == -1) {/*     _x_message(stream, XINE_MSG_CONNECTION_REFUSED, "can't put socket in non-blocking mode", strerror(errno), NULL); */    return -1;  }  for (i = 0; h->h_addr_list[i]; i++) {    struct in_addr ia;    struct sockaddr_in sin;     memcpy (&ia, h->h_addr_list[i], 4);    sin.sin_family = AF_INET;    sin.sin_addr   = ia;    sin.sin_port   = htons(port);        if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==-1 && errno != EINPROGRESS) {      /* FIXME: de-xine-ification *//*       _x_message(stream, XINE_MSG_CONNECTION_REFUSED, strerror(errno), NULL); */      close(s);      continue;    }        return s;  }  return -1;}static mms_io_t fallback_io =  {    &fallback_io_select,    NULL,    &fallback_io_read,    NULL,    &fallback_io_write,    NULL,    &fallback_io_tcp_connect,    NULL,  };static mms_io_t default_io =   {    &fallback_io_select,    NULL,    &fallback_io_read,    NULL,    &fallback_io_write,    NULL,    &fallback_io_tcp_connect,    NULL,  };#define io_read(io, args...) ((io) ? (io)->read(io->read_data , ## args) : default_io.read(NULL , ## args))#define io_write(io, args...) ((io) ? (io)->write(io->write_data , ## args) : default_io.write(NULL , ## args))#define io_select(io, args...) ((io) ? (io)->select(io->select_data , ## args) : default_io.select(NULL , ## args))#define io_connect(io, args...) ((io) ? (io)->connect(io->connect_data , ## args) : default_io.connect(NULL , ## args))  const mms_io_t* mms_get_default_io_impl(){  return &default_io;}void mms_set_default_io_impl(const mms_io_t *io){  if(io->select)  {    default_io.select = io->select;    default_io.select_data = io->select_data;  } else  {    default_io.select = fallback_io.select;    default_io.select_data = fallback_io.select_data;  }  if(io->read)  {    default_io.read = io->read;    default_io.read_data = io->read_data;  } else  {    default_io.read = fallback_io.read;    default_io.read_data = fallback_io.read_data;  }  if(io->write)  {    default_io.write = io->write;    default_io.write_data = io->write_data;  } else  {    default_io.write = fallback_io.write;    default_io.write_data = fallback_io.write_data;  }  if(io->connect)  {    default_io.connect = io->connect;    default_io.connect_data = io->connect_data;  } else  {    default_io.connect = fallback_io.connect;    default_io.connect_data = fallback_io.connect_data;  }}static void mms_buffer_init (mms_buffer_t *mms_buffer, uint8_t *buffer) {  mms_buffer->buffer = buffer;  mms_buffer->pos = 0;}static void mms_buffer_put_8 (mms_buffer_t *mms_buffer, uint8_t value) {  mms_buffer->buffer[mms_buffer->pos]     = value          & 0xff;  mms_buffer->pos += 1;}#if 0static void mms_buffer_put_16 (mms_buffer_t *mms_buffer, uint16_t value) {  mms_buffer->buffer[mms_buffer->pos]     = value          & 0xff;  mms_buffer->buffer[mms_buffer->pos + 1] = (value  >> 8)  & 0xff;  mms_buffer->pos += 2;}#endifstatic void mms_buffer_put_32 (mms_buffer_t *mms_buffer, uint32_t value) {  mms_buffer->buffer[mms_buffer->pos]     = value          & 0xff;  mms_buffer->buffer[mms_buffer->pos + 1] = (value  >> 8)  & 0xff;  mms_buffer->buffer[mms_buffer->pos + 2] = (value  >> 16) & 0xff;  mms_buffer->buffer[mms_buffer->pos + 3] = (value  >> 24) & 0xff;  mms_buffer->pos += 4;}static int get_guid (unsigned char *buffer, int offset) {  int i;  GUID g;    g.Data1 = LE_32(buffer + offset);  g.Data2 = LE_16(buffer + offset + 4);  g.Data3 = LE_16(buffer + offset + 6);  for(i = 0; i < 8; i++) {    g.Data4[i] = buffer[offset + 8 + i];  }    for (i = 1; i < GUID_END; i++) {    if (!memcmp(&g, &guids[i].guid, sizeof(GUID))) {      lprintf("GUID: %s\n", guids[i].name);      return i;    }  }    lprintf("unknown GUID: 0x%x, 0x%x, 0x%x, "	   "{ 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx }\n",	   g.Data1, g.Data2, g.Data3,	   g.Data4[0], g.Data4[1], g.Data4[2], g.Data4[3], 	   g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]);  return GUID_ERROR;}static void print_command (char *data, int len) {#ifdef DEBUG  int i;  int dir = LE_32 (data + 36) >> 16;  int comm = LE_32 (data + 36) & 0xFFFF;  lprintf ("----------------------------------------------\n");  if (dir == 3) {    lprintf ("send command 0x%02x, %d bytes\n", comm, len);  } else {    lprintf ("receive command 0x%02x, %d bytes\n", comm, len);  }  lprintf ("  start sequence %08x\n", LE_32 (data +  0));  lprintf ("  command id     %08x\n", LE_32 (data +  4));  lprintf ("  length         %8x \n", LE_32 (data +  8));  lprintf ("  protocol       %08x\n", LE_32 (data + 12));  lprintf ("  len8           %8x \n", LE_32 (data + 16));  lprintf ("  sequence #     %08x\n", LE_32 (data + 20));  lprintf ("  len8  (II)     %8x \n", LE_32 (data + 32));  lprintf ("  dir | comm     %08x\n", LE_32 (data + 36));  if (len >= 4)    lprintf ("  prefix1        %08x\n", LE_32 (data + 40));  if (len >= 8)    lprintf ("  prefix2        %08x\n", LE_32 (data + 44));  for (i = (CMD_HEADER_LEN + CMD_PREFIX_LEN); i < (CMD_HEADER_LEN + CMD_PREFIX_LEN + len); i += 1) {    unsigned char c = data[i];        if ((c >= 32) && (c < 128))      lprintf ("%c", c);    else      lprintf (" %02x ", c);      }  if (len > CMD_HEADER_LEN)    lprintf ("\n");  lprintf ("----------------------------------------------\n");#endif}  static int send_command (mms_io_t *io, mms_t *this, int command,                         uint32_t prefix1, uint32_t prefix2,                         int length) {  int    len8;  off_t  n;  mms_buffer_t command_buffer;  len8 = (length + 7) / 8;  this->scmd_len = 0;  mms_buffer_init(&command_buffer, this->scmd);  mms_buffer_put_32 (&command_buffer, 0x00000001);   /* start sequence */  mms_buffer_put_32 (&command_buffer, 0xB00BFACE);   /* #-)) */  mms_buffer_put_32 (&command_buffer, len8 * 8 + 32);  mms_buffer_put_32 (&command_buffer, 0x20534d4d);   /* protocol type "MMS " */  mms_buffer_put_32 (&command_buffer, len8 + 4);  mms_buffer_put_32 (&command_buffer, this->seq_num);  this->seq_num++;  mms_buffer_put_32 (&command_buffer, 0x0);          /* timestamp */  mms_buffer_put_32 (&command_buffer, 0x0);  mms_buffer_put_32 (&command_buffer, len8 + 2);  mms_buffer_put_32 (&command_buffer, 0x00030000 | command); /* dir | command */  /* end of the 40 byte command header */    mms_buffer_put_32 (&command_buffer, prefix1);  mms_buffer_put_32 (&command_buffer, prefix2);  if (length & 7)	  memset(this->scmd + length + CMD_HEADER_LEN + CMD_PREFIX_LEN, 0, 8 - (length & 7));  n = io_write(io,  this->s, this->scmd, len8 * 8 + CMD_HEADER_LEN + CMD_PREFIX_LEN);  if (n != (len8 * 8 + CMD_HEADER_LEN + CMD_PREFIX_LEN)) {    return 0;  }  print_command (this->scmd, length);  return 1;}#ifdef USE_ICONVstatic iconv_t string_utf16_open() {    return iconv_open("UTF-16LE", nl_langinfo(CODESET));}static void string_utf16_close(iconv_t url_conv) {    if (url_conv != (iconv_t)-1) {      iconv_close(url_conv);    }}static void string_utf16(iconv_t url_conv, char *dest, char *src, int len) {    memset(dest, 0, 2 * len);    if (url_conv == (iconv_t)-1) {      int i;      for (i = 0; i < len; i++) {        dest[i * 2] = src[i];        dest[i * 2 + 1] = 0;      }      dest[i * 2] = 0;      dest[i * 2 + 1] = 0;    }    else {      size_t len1, len2;      char *ip, *op;      len1 = len; len2 = 1000;      ip = src; op = dest;      iconv(url_conv, &ip, &len1, &op, &len2);    }}#elsestatic void string_utf16(int unused, char *dest, char *src, int len) {  int i;  memset (dest, 0, 2 * len);  for (i = 0; i < len; i++) {    dest[i * 2] = src[i];    dest[i * 2 + 1] = 0;  }  dest[i * 2] = 0;  dest[i * 2 + 1] = 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -