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

📄 mmsh.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************** *    mmsh.c:  downloading via mmsh (Microsoft Media Service over HTTP) *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * * This file is based on mmsh 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. * ***********************************************************************//* * Some code or data in this file is based on * MPlayer project * (MPlayer-1.0rc2/stream/stream/asf_streaming.c) */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "network.h"#include "http.h"#include "asf.h"#include "mmsh.h"/* Windows Media Player stuff */const char mmsh_useragent[] = "User-Agent: NSPlayer/11.08.0005.0000";const char mmsh_xclientguid[] = "Pragma: xclientGuid={00000000-0000-0000-0000-000000000000}";const char mmsh_xacceptauth[] = "X-Accept-Authentication: Negotiate, NTLM, Digest, Basic";/* * definitions of type of ASF streaming */enum {      ASF_Unknown_e,    ASF_Seekable_e,    ASF_Nonseekable_e,    ASF_Authenticate_e,} ASF_streaming_types;/*  * asf chunk magics */enum {    ASF_STREAMING_CLEAR     = 0x4324,          /* $C */    ASF_STREAMING_DATA      = 0x4424,          /* $D */    ASF_STREAMING_END_TRANS = 0x4524,          /* $E */    ASF_STREAMING_HEADER    = 0x4824,          /* $H */    ASF_STREAMING_IGNORE    = 0x4d24,          /* $M */      ASF_STREAMING_DATA2     = 0x44a4,};static struct mmsh_ctrl_t *new_mmsh_ctrl_t(void);static void free_mmsh_ctrl_t(struct mmsh_ctrl_t *ctrlt);static int mmsh_request_common(struct stream_t *stream,			       struct http_header_t *http_hdr);static struct http_header_t *mmsh_1st_request(struct stream_t *stream,					      struct http_header_t *http_hdr);static struct http_header_t *mmsh_media_request(struct stream_t *stream,					  struct http_header_t *http_hdr);static int mmsh_parse_response(struct mmsh_ctrl_t *mmsh_ctrl,			       struct http_header_t *http_hdr);static int asf_streaming(struct asf_stream_chunk_t *stream_chunk);static int mmsh_get_asf_header(struct stream_t *stream,uint8_t **asfheader,			       struct asf_stream_chunk_t *first_chunk);static int mmsh_get_media_packet(struct stream_t *stream,				 uint8_t *buffer, size_t max_size);/* * allocate/free mmsh_ctrl_t */static struct mmsh_ctrl_t *new_mmsh_ctrl_t(void){    struct mmsh_ctrl_t *ctrlt = 	(struct mmsh_ctrl_t *)xmalloc(sizeof(struct mmsh_ctrl_t));    ctrlt->hinfo = new_asf_headerinfo_t();    return ctrlt;}static void free_mmsh_ctrl_t(struct mmsh_ctrl_t *ctrlt){    if(!ctrlt) return;    if(ctrlt->hinfo) free_asf_headerinfo_t(ctrlt->hinfo);    free(ctrlt);}/* * set common part for mmsh request (for 1st and 2nd request) * return value:   1 ... success *                -1 ... failure */static int mmsh_request_common(struct stream_t *stream,			       struct http_header_t *http_hdr){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct url_t *url = NULL;    struct download_opts_t *dlopts = NULL;      char str[BUFSIZE_1K];      /* Sanity Check */    if(stream_ctrl == NULL || http_hdr == NULL) {	display(MSDL_ERR,		"mmsh_request_common: argument invalid\n");	return -1;    }        url = stream->url;    dlopts = stream->dlopts;    if((url == NULL) || (dlopts == NULL)) {	return -1;    }      http_set_field(http_hdr, "Accept: */*");    http_set_field(http_hdr, mmsh_useragent);        http_add_basic_authentication(http_hdr,				  (url->username) ? url->username : stream->dlopts->username,				  (url->password) ? url->password : stream->dlopts->password);        /* proxy check. use "http://" for proxy. */    if(dlopts->http_proxy) {	char *new_url = xmalloc(7 + strlen(url->file) + 1);	/* use "http://" because it is http proxy!! */	sprintf(new_url,"http://%s",url->file);	http_set_uri(http_hdr,new_url);	free(new_url);    }    else {	http_set_uri(http_hdr,url->filepath);    }      snprintf(str,BUFSIZE_1K,"Host: %.220s",url->hostname); /* %.220s:%d,port*/    http_set_field(http_hdr,str);      http_set_field(http_hdr,mmsh_xclientguid);        return 1;}/* very first mmsh request */static struct http_header_t *mmsh_1st_request(struct stream_t *stream,					      struct http_header_t *http_hdr){    char str[BUFSIZE_1K];    if(mmsh_request_common(stream,http_hdr) < 0) {	display(MSDL_ERR,		"mmsh_request_common fialed\n");	return NULL;    }    snprintf(str,BUFSIZE_1K,	     "Pragma: no-cache,rate=1.000,stream-time=0,stream-offset=%u:%u,packet-num=%u,max-duration=%u",	     0xffffffff,0xffffffff,0,0);    /* for some reason this is required */    http_set_field(http_hdr,str);        http_set_field(http_hdr,"Connection: Close");    http_request_get(http_hdr);    return http_hdr;}/* * mmsh_request : make request to the server */static struct http_header_t *mmsh_media_request(struct stream_t *stream,						struct http_header_t *http_hdr){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct mmsh_ctrl_t *mmsh_ctrl = stream_ctrl->mmsh_ctrl;        char *ptr = NULL;    int asf_streams_count = 0;    char str[BUFSIZE_1K];        if(mmsh_request_common(stream,http_hdr) < 0) {	display(MSDL_ERR,		"mmsh_request_common fialed\n");	return NULL;    }    snprintf(str,BUFSIZE_1K,	     "Pragma: no-cache,rate=1.000,stream-time=%d,stream-offset=%u:%u,packet-num=%u,max-duration=%u",	     /*offset_lo,offset_hi,stream_ctrl->packet_count,0);*/	     0, /* start time in milliseconds */	     0xffffffff,0xffffffff,0xffffffff,	     0);    /* for some reason this is required */    http_set_field(http_hdr,str);        /* MMSH part */        http_set_field(http_hdr,"Pragma: xPlayStrm=1");    http_set_field(http_hdr,"Pragma: version11-enabled=1");        ptr = str;    ptr += sprintf(ptr,"Pragma: stream-switch-entry=");    if(mmsh_ctrl->hinfo->streams->n_audio > 0) {	int enable = 0;	int stream_id = 0;	int i = 0;	/*printf("mmsh_ctrl->n_audio : %d\n",mmsh_ctrl->n_audio); */	for(i = 0; i < mmsh_ctrl->hinfo->streams->n_audio; i++) {	    stream_id = mmsh_ctrl->hinfo->streams->audio_streams[i];	    /*printf("stream_id = %d %d\n",stream_id,mmsh_ctrl->audio_id); */	    if(stream_id == mmsh_ctrl->hinfo->streams->audio_id) {		enable = 0; /* enable stream  */	    }	    else {		enable = 2; /* disable stream */	    }	    asf_streams_count++;	    ptr += sprintf(ptr,"ffff:%d:%d ",stream_id,enable);	}    }    if(mmsh_ctrl->hinfo->streams->n_video > 0) {	int enable = 0;	int stream_id = 0;	int i = 0;	for(i = 0; i < mmsh_ctrl->hinfo->streams->n_video; i++) {	    stream_id = mmsh_ctrl->hinfo->streams->video_streams[i];	    if(stream_id == mmsh_ctrl->hinfo->streams->video_id) {		enable = 0; /* enable stream  */	    }	    else {		enable = 2; /* disable stream */	    }	    asf_streams_count++;	    ptr += sprintf(ptr,"ffff:%d:%d ",stream_id,enable);	}    }    http_set_field(http_hdr,str);    snprintf(str,BUFSIZE_1K,"Pragma: stream-switch-count=%d",asf_streams_count);    http_set_field(http_hdr,str);	    if(stream->dlopts->speed) {	char *reason = NULL;	int  guessed_speed = 0;	    	if(speed_valid_and_guess(stream->dlopts->speed,&guessed_speed,&reason)) {	    snprintf(str,BUFSIZE_1K - 1,"Pragma: Speed=%s",stream->dlopts->speed);	}	else { /* invlalid, use guessed value */	    if(guessed_speed == 0) {		guessed_speed = 1; /* default speed 1.000 */	    }	    snprintf(str,BUFSIZE_1K - 1,"Pragma: Speed=%d.000",guessed_speed);	    display(MSDL_ERR,		    "option \"-s %s\" is invalid as mmsh speed request\n"		    ": %s\n"		    "send \"%s\" instead\n",		    stream->dlopts->speed,reason,str);	}	http_set_field(http_hdr,str);    }      http_set_field(http_hdr,"Connection: Close");    http_request_get(http_hdr);    return http_hdr;}/* *  asf_header_check :  check if http_hdr->body is ASF object. *                     return value :  0 ... it was NOT asf object *                                     1 ... OK it was ASF object! */int asf_header_check(struct http_header_t *http_hdr){    struct asf_obj_header_t *asfobjh;    if(!http_hdr) return 0;    if(http_hdr->body == NULL || http_hdr->body_len < sizeof(struct asf_obj_header_t))	return 0;    asfobjh = (struct asf_obj_header_t *)http_hdr->body;    /* get GUID first 4 byte for check */    if(get32_le(asfobjh->guid) == 0x75b22630) return 1;    return 0;}/* * returns content_type value. * this function is based on MPlayer /MPlayer/stream/asf_streaming.c */int mmsh_streaming_type(char *content_type,char *features,			struct http_header_t *http_hdr){    if(content_type == NULL) return ASF_Unknown_e;        if(!strcasecmp(content_type, "application/octet-stream") ||       !strcasecmp(content_type, "application/vnd.ms.wms-hdr.asfv1") ||       !strcasecmp(content_type, "application/x-mms-framed") ||       !strcasecmp(content_type, "video/x-ms-asf")) {                   	if(strstr(features, "seekable") ) {	    display(MSDL_VER,"seekable ASF stream\n");	    return ASF_Seekable_e;	} else {	    display(MSDL_VER,"non-seekable ASF stream\n");	    return ASF_Nonseekable_e;	}    }    else {	display(MSDL_VER,"content type: %s\n",content_type);	return ASF_Unknown_e;    }}/* * receive mmsh message from stream->sock. * use http_recv_header first. *               return status code : success *                               -1 : failure */int mmsh_recv_header(struct stream_t *stream,struct http_header_t *http_hdr){    int ret = 0;    ret = http_recv_header_get(stream,http_hdr);        if(ret < 0) {	display(MSDL_ERR,"MMSH header parse error by http header parse error\n");

⌨️ 快捷键说明

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