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

📄 wmserver.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************** *   wmserver.c : for downloading from WMServer using rtsp *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * * This file is based on information shown on wireshark, * analyzing transaction of Windows media player. * * * 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. * ***********************************************************************/ #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 "rtsp.h"#include "asf.h"#include "sdpcommon.h"#include "sdpwms.h"#include "wmserver.h"/* * Windows Media Player provided RTSP strings */static const char wms_useragent[] =    "User-Agent: WMPlayer/11.0.5721.5145 guid/3300AD50-2C39-46C0-AE0A-E1D79F0FD2D8";static const char wms_supported[] =    "Supported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.fastcache, com.microsoft.wm.packetpairssrc, com.microsoft.wm.startupprofile";static const char wms_authentication[]=    "X-Accept-Authentication: Negotiate, NTLM, Digest, Basic";static const char wms_transport[] =    "Transport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=75afe1e1;mode=PLAY";static int wmserver_process_header(struct stream_t *stream);static int wmserver_process_media_packet(struct stream_t *stream,uint8_t *header,					 uint8_t *buffer,size_t max_size);int wmserver_prepare_resuming(struct stream_t *stream);/* * send DESCRIBE  * return value:   -1: failed   1: success   0: retry with other protocol */static int wmserver_rtsp_describe(struct stream_t *stream,char **description_ret){    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;    struct rtsp_header_t *rtsp_hdr = NULL;    char *description = NULL;    int ret = 0;    char *field = 0;    int len = 0;    /* send DESCRIBE request */    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);    rtsp_set_field(rtsp_hdr, wms_useragent);    rtsp_set_field(rtsp_hdr, wms_supported);    rtsp_request_describe(rtsp_hdr,rtsp_ctrl->mrl);    rtsp_send_request_and_free(stream,rtsp_hdr);    /* receive reply for DESCRIBE */    rtsp_hdr = new_rtsp_header();    ret  = rtsp_recv_header(stream,rtsp_hdr);    if(ret < 0) {	free_rtsp_header(rtsp_hdr);	goto failed_retry;    }        /* NOT OK */    if(!is_rtsp_response_ok(rtsp_hdr->status_code)) { 	display(MSDL_ERR,"DESCRIBE request returned: %d (%s)\n",		rtsp_hdr->status_code,rtsp_hdr->reason_phrase);		field = rtsp_get_field(rtsp_hdr,"Alert");	if(field) {	    while(*field == ' ') field++;	    display(MSDL_ERR,"message from server --> %s\n",field);	}	free_rtsp_header(rtsp_hdr);	goto failed;    }        len = 0;        /* Content-length must be present */    if((field = rtsp_get_field(rtsp_hdr,"Content-Length")) != NULL) {	while(*field == ' ') field++;	len = atoi(field);    }    else { /* no Content-length */	display(MSDL_ERR,"warning: No Content-Length in fields!!\n");    }      if((field = rtsp_get_field(rtsp_hdr,"ETag")) == NULL) {	display(MSDL_VER,"warning: No ETag!!\n"); /* in MS-RTSP Etag is not necessary */    }    free_rtsp_header(rtsp_hdr);        /*      copy description (sdp)    */    description = (char *)xmalloc(len + 1);    len = read_data(stream,(uint8_t *)description,len);    description[len] = '\0';        display(MSDL_DBG,"=desc=================\n%s\n=(%d bytes)========desc=\n",	    description,(int)strlen(description));    *description_ret = description;        return 1;	  failed:    if(description) free(description);    *description_ret = NULL;    return -1;  failed_retry:    if(description) free(description);    *description_ret = NULL;    return 0;}/* * send SETUP request * return value:   -1: failed  last status code: SETUP request sent */static int wmserver_rtsp_setup(struct stream_t *stream,			       struct asf_headerinfo_t *asf_headerinfo,struct sdpwms_t *sdpwms){    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;    char *buffer = NULL;    int ret = 0;    int i = 0;        if(!stream || !asf_headerinfo || !sdpwms) { /* NULL check */	return -1;    }        if(!(asf_headerinfo->streams->n_audio + asf_headerinfo->streams->n_video)) {	return -1;    }    buffer = xmalloc(BUFSIZE_1K);    for(i = 0; i < 2; i++) { /* 0 --> audio, 1 --> video */	int n  = 0;	int id = 0;	char *default_control = NULL;	if(i == 0) {	    n  = asf_headerinfo->streams->n_audio;	    id = asf_headerinfo->streams->audio_id;	    default_control = "audio";	}	else {	    n  = asf_headerinfo->streams->n_video;	    id = asf_headerinfo->streams->video_id;	    default_control = "video";	}		if(n) {	    struct list_h *p = NULL;	    char *controlstr = NULL;	    struct rtsp_header_t *rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);	    rtsp_set_field(rtsp_hdr,wms_supported);	    rtsp_set_field(rtsp_hdr,wms_transport);		    /* find control for audio_id */	    for(p = sdpwms->streams ; p ; p = p->next) {		struct sdpwms_stream_t *sdpwmsstream = p->p;		if(sdpwmsstream->streamnum == id) {		    controlstr = sdpwmsstream->control;		    break;		}	    }    	    if(!controlstr) {		controlstr = default_control; /* default */	    }    	    if(strstr(controlstr,"://")) { /* --> absolute URL */		snprintf(buffer,BUFSIZE_1K - 1,"%s",controlstr);	    }	    else {		snprintf(buffer,BUFSIZE_1K - 1,"%s/%s",rtsp_ctrl->mrl,controlstr);	    }		    rtsp_request_setup(rtsp_hdr,buffer);	    rtsp_send_request_and_free(stream,rtsp_hdr);		    /* receive message for SETUP */	    ret = rtsp_recv_header_ignore_message(stream);	}    }    free(buffer);    return ret;}/* * send SET_PARAMETER request * return value:  -1:failure   status code: success */static int wmserver_rtsp_set_parameter(struct stream_t *stream){    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;    struct rtsp_header_t *rtsp_hdr = NULL;    char *buffer = xmalloc(BUFSIZE_1K);    int ret = 0;        rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);    rtsp_set_field(rtsp_hdr,wms_useragent);    rtsp_request_set_parameter(rtsp_hdr,rtsp_ctrl->mrl);    rtsp_send_request_and_free(stream,rtsp_hdr);        /*      receive message for SET_PARAMETER       if something needs to be done to message, use rtsp_recv_header     */    ret = rtsp_recv_header_ignore_message(stream);        free(buffer);    return ret;}/* * send PLAY request * return value:  -1:failure   status code: success */static int wmserver_rtsp_play(struct stream_t *stream){    struct rtsp_ctrl_t *rtsp_ctrl = stream->stream_ctrl->rtsp_ctrl;    struct rtsp_header_t *rtsp_hdr = NULL;    char *buffer = xmalloc(BUFSIZE_1K);    int ret = 0;    int bandwidth_to_send = 0;    char *field = NULL;    /*      * Sending part      */    rtsp_hdr = new_rtsp_header_with_standard_fields(rtsp_ctrl);    rtsp_set_field(rtsp_hdr,wms_useragent);    if(stream->dlopts->resume_download) {	wmserver_prepare_resuming(stream);    }        rtsp_set_range_field(rtsp_hdr,stream->dlopts->range);    rtsp_set_speed_field(rtsp_hdr,stream->dlopts->speed);        /* bandwidth specified */    bandwidth_to_send =	(stream->dlopts->bandwidth) ? (stream->dlopts->bandwidth) : INT_MAX_BANDWIDTH;    snprintf(buffer,BUFSIZE_1K - 1,"Bandwidth: %d",bandwidth_to_send);    rtsp_set_field(rtsp_hdr,buffer);    snprintf(buffer,BUFSIZE_1K - 1,	     "X-Accelerate-Streaming: AccelDuration = 18000;AccelBandwidth=%d",bandwidth_to_send);    rtsp_set_field(rtsp_hdr,buffer);        rtsp_request_play(rtsp_hdr,rtsp_ctrl->mrl);    rtsp_send_request_and_free(stream,rtsp_hdr);    rtsp_hdr = NULL;    /*      * Receiving part      */    /* receive message for PLAY request */    rtsp_hdr = new_rtsp_header();    ret = rtsp_recv_header(stream,rtsp_hdr);        if(!is_rtsp_response_ok(ret)) {	display(MSDL_ERR,"PLAY request returned: %d (%s)\n",		rtsp_hdr->status_code,rtsp_hdr->reason_phrase);		field = rtsp_get_field(rtsp_hdr,"Alert");	if(field) {	    while(*field == ' ') field++;	    display(MSDL_ERR,"message from server --> %s\n",field);	}	free_rtsp_header(rtsp_hdr);	goto failed;    }    /* display real speed (might differ from user requested) */    if((field = rtsp_get_field(rtsp_hdr,"Speed")) != NULL) {    	if(stream->dlopts->speed) {	    while(*field == ' ') field++;	    display(MSDL_NOR,"Speed: %s\n",field);	}    }    if((field = rtsp_get_field(rtsp_hdr,"Range")) != NULL) {    	if(stream->dlopts->range) {	    while(*field == ' ') field++;	    display(MSDL_NOR,"Range: %s\n",field);	}    }    /* skip content-length bytes from network */    rtsp_ignore_data_after_header(stream,rtsp_hdr);    free_rtsp_header(rtsp_hdr);    free(buffer);    return ret;      failed:    free(buffer);    return -1;}/*  * get asf_headerinfo and sdpwms by sdpstr, and stream->stream_ctrl->bandwidth * return value: 0 : failed       1: success */static int wmserver_get_info_from_sdp_string(struct stream_t *stream,char *sdpstr,					     struct asf_headerinfo_t **asf_headerinfo_ret,					     struct sdpwms_t **sdpwms_ret){    struct asf_headerinfo_t *asf_headerinfo = NULL;    struct sdpwms_t *sdpwms = NULL;    if(!stream || !sdpstr) { /* stream could not be NULL */	goto failed;    }    /* parse sdp and get information about file to download */    sdpwms = wmserver_parse_sdp(sdpstr);    if(sdpwms->asf_header_len <= sizeof(struct asf_header_t)) {	display(MSDL_ERR,"asf header smaller than asf_header_t\n");	goto failed;    }      asf_headerinfo = new_asf_headerinfo_t();    asf_interpret_header(asf_headerinfo,stream->stream_ctrl->bandwidth,			 sdpwms->asf_header,sdpwms->asf_header_len);    /* set asf header len */    asf_headerinfo->asf_header_len = sdpwms->asf_header_len;        /* copy raw header */    asf_headerinfo->asf_header = xmalloc(sdpwms->asf_header_len);    memcpy(asf_headerinfo->asf_header,sdpwms->asf_header,sdpwms->asf_header_len);      /* return structures */    *asf_headerinfo_ret = asf_headerinfo;    *sdpwms_ret         = sdpwms;    return 1;  failed:    if(asf_headerinfo) free_asf_headerinfo_t(asf_headerinfo);    if(sdpwms) free_sdpwms_t(sdpwms);    *asf_headerinfo_ret = NULL;    *sdpwms_ret = NULL;    return 0;}/* * send SETUP,SEND_REQUEST,PLAY requests. * *      return value                1 : success *                                  0 : error, retry via mms *                                 -1 : error. */int wmserver_setup_and_get_header(struct stream_t *stream,				  struct asf_headerinfo_t **asf_headerinfo_ret){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;    struct asf_headerinfo_t *asf_headerinfo = NULL;    struct sdpwms_t *sdpwms = NULL;    char *description = NULL;    int ret = 0;      /*      use "-b" option 4 low bandwidth..    */    if(stream->dlopts->bandwidth) {	stream_ctrl->bandwidth = stream->dlopts->bandwidth;    }    else {	stream_ctrl->bandwidth = INT_MAX_BANDWIDTH;    }        rtsp_ctrl->cseq = 1;    ret = wmserver_rtsp_describe(stream,&description);    if(ret == 0) { /* retry */	goto failed_retry;    }    else if(ret < 0) {	goto failed;    }                if(!wmserver_get_info_from_sdp_string(stream,description,&asf_headerinfo,&sdpwms)) {	goto failed;    }        /* SETUP requests (for audio and video) */    if(wmserver_rtsp_setup(stream,asf_headerinfo,sdpwms) < 0) {	goto failed;    }    /* send SET_PARAMETER request to download stream */    if(wmserver_rtsp_set_parameter(stream) < 0) {	goto failed;    }      /*  send PLAY request to download stream */    if(wmserver_rtsp_play(stream) < 0) {	goto failed;    }    /* copy to write buffer */    stream_ctrl->write_pos = 0;    memcpy(stream_ctrl->write_buffer, sdpwms->asf_header, sdpwms->asf_header_len);    stream_ctrl->write_data_len = sdpwms->asf_header_len;        free_sdpwms_t(sdpwms);    free(description);    *asf_headerinfo_ret = asf_headerinfo;    return 1;    failed:    if(asf_headerinfo) free_asf_headerinfo_t(asf_headerinfo);    if(sdpwms) free_sdpwms_t(sdpwms);    if(description) free(description);        *asf_headerinfo_ret = NULL;    return -1;  failed_retry: /* retry with other protocol */    if(asf_headerinfo) free_asf_headerinfo_t(asf_headerinfo);    if(sdpwms) free_sdpwms_t(sdpwms);    if(description) free(description);        *asf_headerinfo_ret = NULL;    return 0;}/* * After reveiving EOF packet, ANNOUNCE may come when * streaming still continues. (this is most likely to be a download protection) *  * * */struct asf_headerinfo_t *wmserver_announce_continue(struct stream_t *stream){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;  

⌨️ 快捷键说明

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