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

📄 mmst.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************** *    mmst.c:  downloading via mmst (Microsoft Media Service over TCP) *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * * This file is based on mms implementation of mplayer, * and Windows Media Player transaction I saw through * packet monitoring program, wireshark (http://www.wireshark.org/) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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., * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * ***********************************************************************//* * Copyright notice of MPlayer project * which some part of msdl is based on. * (from MPlayer-1.0rc2/stream/asf_mmst_streaming.c) *//* * MMST implementation taken from the xine-mms plugin made by * Major MMS (http://geocities.com/majormms/). * Ported to MPlayer by Abhijeet Phatak <abhijeetphatak@yahoo.com>. * * Information about the MMS protocol can be found at http://get.to/sdp * * copyright (C) 2002 Abhijeet Phatak <abhijeetphatak@yahoo.com> * copyright (C) 2002 the xine project * copyright (C) 2000-2001 major mms * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPlayer 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 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <ctype.h>#include <sys/types.h>#include <sys/socket.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "network.h"#include "asf.h"#include "mmst.h"static struct mmst_ctrl_t *new_mmst_ctrl_t(void);static void free_mmst_ctrl_t(struct mmst_ctrl_t *mctrl);static int mmst_get_command_packet(struct stream_t *stream);static struct mmst_ctrl_t *new_mmst_ctrl_t(void){    struct mmst_ctrl_t *mctrl = xmalloc(sizeof(struct mmst_ctrl_t));    mctrl->seq_num = 0;    mctrl->num_stream_ids = 0;    mctrl->hinfo = new_asf_headerinfo_t();    return mctrl;}static void free_mmst_ctrl_t(struct mmst_ctrl_t *mctrl){    if(mctrl->hinfo) free_asf_headerinfo_t(mctrl->hinfo);    if(mctrl) free(mctrl);}/* * send command */static void send_command(struct stream_t *stream,int command,			 uint32_t f1,uint32_t f2,			 int length,uint8_t *data){    int len8 = (length+7) / 8;    uint8_t *cmd = (uint8_t *)xmalloc(len8 * 8 + 0x30); // 0x30 for header.      /* put data in little endian */    put32_le(cmd + 0x00,0x00000001);   /* rep | version | versionMinor | padding */    put32_le(cmd + 0x04,0xB00BFACE);   /* sessionId                              */    put32_le(cmd + 0x08,len8*8 + 32);  /* messageLength                          */    put32_le(cmd + 0x0C,0x20534d4d);   /* "MMS "                                 */    put32_le(cmd + 0x10,len8 + 4);     /* chunkCount                             */    put32_le(cmd + 0x14,stream->stream_ctrl->mmst_ctrl->seq_num); /*  seq | MBZ  */    stream->stream_ctrl->mmst_ctrl->seq_num++;    put32_le(cmd + 0x18,0x00);         /* timeSent */    put32_le(cmd + 0x1C,0x00);         /* timeSent */            put32_le(cmd + 0x20,len8+2);       /* chunkLen */    put32_le(cmd + 0x24,0x00030000 | command); /* dir | command */    put32_le(cmd + 0x28,f1);    put32_le(cmd + 0x2C,f2);      memcpy(cmd + 0x30, data, length);    if(length & 0x07) { /* do padding */	memset(cmd + 0x30 + length, 0, 8 - (length & 0x07));    }        display(MSDL_DBG,"=-send-------------------------------------------=\n");    dbgdump(cmd,len8 * 8 + 0x30);    display(MSDL_DBG,"\n=------------------------------------------------=\n");        if(xsend(stream->netsock->sock,cmd,len8*8+0x30) != (len8*8+0x30)){	perror("send() failed");    }      free(cmd);}/* * convert string to UTF16, so that mms server can understand. */static void string_utf16(char *dst,char *src,int len){    int i;    if(len > 499) len = 499;    for(i = 0; i < len; i ++) {	dst[i * 2] = src[i];	dst[i * 2 + 1] = 0;    }    dst[i * 2] = 0;    dst[i * 2 + 1] = 0;}/* * get Micro$oft ASF header. * return value:      asf header length : success *                             negative : failure */static int mmst_get_asf_header(struct stream_t *stream, uint8_t *header){    int header_len = 0;       /* total header length. */    uint32_t packet_len = 0;  /* length of this packet. */    int command;    uint8_t pre_header[8];    /* pre_header, before header. */        while(1) { /* we have to collect all header packet together. */    	/* first, for each packet,get pre_header and know packet length etc... */	if(read_data(stream,pre_header,8) <= 0) { /* read_data() failed. */	    goto failed;	}	if(pre_header[4] == 0x02) { /*   header packet   */	    packet_len = get16_le(((uint8_t *)&pre_header) + 6) - 8;      	    if(packet_len < 0 || HDR_BUF_SIZE - header_len < packet_len) {		display(MSDL_ERR,"invalid header size\n");		goto failed;	    }      	    if(read_data(stream,header + header_len, packet_len) <= 0) {		/* read_data failed */		goto failed;	    }      	    header_len += packet_len; /* accumulate */      	    /* end of header. */	    if(header[header_len - 1] == 1 && header[header_len - 2] == 1) {		/* success, got M$ ASF header, in header packet */		return header_len;	    }	}	else { /* command packet received. */	    uint8_t *combuf;      	    if(read_data(stream,&packet_len,4) <= 0) {		display(MSDL_ERR,"read_data for packet_len failed\n");		goto failed;	    }      	    packet_len = get32_le(&packet_len) + 4;	    if(packet_len < 0 || BUF_SIZE < packet_len) {		display(MSDL_ERR,"%x: invalid packet size\n",packet_len,BUF_SIZE);		goto failed;	    }	    combuf = xmalloc(packet_len);      	    if(read_data(stream,combuf,packet_len) <= 0) {		/* error */		free(combuf);		goto failed;	    }      	    command = get32_le(combuf + 24) & 0xFFFF;	    if(command == 0x1b) {		send_command(stream,0x1b,			     0,			     0,			     0,			     combuf);	    }	    free(combuf);	}    }  failed:    return -1;}/* * start mmst streaming. *  *    return value :   negative or 0  ... error *                                 1  ... success */int mmst_streaming_start(struct stream_t *stream){    struct url_t *url = stream->url;    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct mmst_ctrl_t *mmst_ctrl = stream_ctrl->mmst_ctrl;        uint8_t *buffer = NULL;    uint8_t *buffer2 = NULL;    uint8_t *asf_header = NULL;    int ret = 0;    int asf_header_len = 0;    char *path, *escaped_path;    int sock; /* socket to use */    int pos;    int i;      stream->stream_ctrl->status = STREAMING_HANDSHAKING;      buffer = (uint8_t *)xmalloc(BUFSIZE_1K);  /* send buffer. used for data to send */    buffer2 = (uint8_t *)xmalloc(BUFSIZE_1K); /* working buffer                     */            escaped_path = strchr(url->file,'/') + 1;    path = (char *)xmalloc(strlen(escaped_path) + 1);          /* remove something like '%41' in url. */    url_unescape_string(path,escaped_path);        if(stream->dlopts->bandwidth) {	stream_ctrl->bandwidth = stream->dlopts->bandwidth;    }    else {	stream_ctrl->bandwidth = INT_MAX_BANDWIDTH;    }        set_serverinfo(stream->serverinfo,url->hostname,url->port,NULL,0,MMS_PORT);    sock = server_connect(stream->serverinfo->connect_host,stream->serverinfo->connect_port);    if(sock < 0) { /* couldn't connect for some reason. */	free(path);	goto failed;    }      stream->netsock->sock = sock;    mmst_ctrl->seq_num = 0;      /*     * first thing to do: 0x01 command, do the protocol initiation.     */    snprintf((char *)buffer2,BUFSIZE_1K - 1,	     "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s",	     stream->serverinfo->host);      string_utf16((char *)buffer,(char *)buffer2,		 strlen((char *)buffer2));      /*  send !! */    send_command(stream,1,		 0,		 0x0004000b,		 strlen((char *)buffer2)*2+2,		 buffer);      /* 1st reply */    mmst_get_command_packet(stream);      /*     * 0x02 command. send details of the local IP addr     */    string_utf16((char *)buffer + 8,		 "\002\000\\\\192.168.0.1\\TCP\\1037", 24);    memset(buffer,0,8);    send_command(stream,2,		 0,		 0,		 24*2+10,		 buffer);      /* 2nd reply */    mmst_get_command_packet(stream);      /*     * 0x05 command, send request file path.     */    string_utf16((char *)buffer + 8,path,strlen(path));    memset(buffer,0,8);    send_command(stream,5,		 0,		 0,		 strlen(path) * 2 + 10,		 buffer);      free(path);      mmst_get_command_packet(stream);        /*     * 0x15 cmmand  The ASF header chunk request, include ?session variable     * for pre header.     * After this command sent server should reply with 0x11 command and then     * header chunk with header comes.     */    memset(buffer,0,40);    buffer[0x20] = 2;    send_command(stream,0x15,		 1,		 0,		 40,		 buffer);      /*     * header goes to asf_header, which is actually stream_ctrl->write_buffer.     *    ( write_buffer because this header is directly written to file)     */    asf_header_len = mmst_get_asf_header(stream,stream_ctrl->write_buffer);    if(asf_header_len <= 0) { /* failed */	display(MSDL_ERR,"cannot receive M$ asf header\n");	goto failed;    }    asf_header = stream_ctrl->write_buffer;    stream_ctrl->write_pos = 0;        /* asf header starting from stream_ctrl->write_buffer + 0. */    stream_ctrl->write_data_len = asf_header_len;      mmst_ctrl->hinfo->asf_header = xmalloc(asf_header_len);    memcpy(mmst_ctrl->hinfo->asf_header,asf_header,asf_header_len);      ret = asf_interpret_header(mmst_ctrl->hinfo,stream_ctrl->bandwidth,			       asf_header,asf_header_len);    {	display(MSDL_DBG,"ASF_HEADER---------------------\n");	dbgdump(asf_header,asf_header_len);	display(MSDL_DBG,"\n-------------------------------\n");    }    if(ret < 0) {	display(MSDL_ERR,"cannot receive packet length\n");	goto failed;    }    /* set file size to download */    stream_ctrl->file_size = mmst_ctrl->hinfo->fileh->file_size;      display(MSDL_VER,	    "ASF header length: %d bytes\n"

⌨️ 快捷键说明

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