📄 mmsh.c
字号:
return -1; } ret = mmsh_parse_response(stream->stream_ctrl->mmsh_ctrl,http_hdr); if(ret < 0) { display(MSDL_ERR,"mmsh_parse_response failed\n"); return -1; } return http_hdr->status_code;}/* * mmsh_parse_response : addtional header parse for mmsh * do this after http_parse_response * basically parse Pragma lines. * return value: 1 ... success * -1 ... failure */static int mmsh_parse_response(struct mmsh_ctrl_t *mmsh_ctrl, struct http_header_t *http_hdr){ char *content_type, *pragma; char features[128] = "\0"; content_type = http_get_field(http_hdr, "Content-Type"); pragma = http_get_field(http_hdr, "Pragma"); while(pragma != NULL) { char *p = NULL; /* we have to get features="" string to judge mmsh stream type */ if((p = xstrcasestr(pragma,"features=")) != NULL) { /* found */ char *startp = NULL; char *endp = NULL; p += 9; while(*p == ' ') p++; /* skip whitespace */ startp = p; /* save start pos */ if(*p == '\"') { /* if '"', go to next '"' or EOS */ p++; while(*p != '\"' && *p != '\0') p++; } if(*p == '\0') { /* EOS */ endp = p; } else if(*p == '\"'){ endp = p+1; /* char after '"' */ } /* "aaa", */ if(endp - startp < 128) { strncpy(features,startp,endp-startp); features[endp - startp] = '\0'; } else { strncpy(features,startp,127); features[127] = '\0'; } } /* ==caution== if there are multipule features, get the newest one */ pragma = http_get_next_field(http_hdr); /* keep getting Pragma lines. */ } mmsh_ctrl->streaming_type = mmsh_streaming_type(content_type,features,http_hdr); return 1;}/* * interpret asf_stream_chunk. * return value: type of chunk */static int asf_streaming(struct asf_stream_chunk_t *stream_chunk){ /* little endian */ display(MSDL_DBG,"ASF chunk == type: 0x%02x, size: %d (0x%02x), seq: 0x%04x\n", le2me_16(stream_chunk->type), le2me_16(stream_chunk->size),le2me_16(stream_chunk->size), le2me_32(stream_chunk->seqnum)); switch(le2me_16(stream_chunk->type)) { case ASF_STREAMING_CLEAR: /* $C Clear ASF configuration */ display(MSDL_DBG,"Clearing ASF stream configuration\n"); break; case ASF_STREAMING_DATA: /* $D Data follows */ case ASF_STREAMING_DATA2: /*display(MSDL_DBG,"Data follows\n"); */ break; case ASF_STREAMING_END_TRANS: /* $E End of transfer */ display(MSDL_DBG,"Transfer complete!!\n"); break; case ASF_STREAMING_HEADER: /* $H ASF Header chunk follows */ /* display(MSDL_DBG,"ASF header chunk follows\n"); */ break; case ASF_STREAMING_IGNORE: break; default: display(MSDL_DBG,"not ASF chunk: [0x%x]!!\n", le2me_16(stream_chunk->type)); } return le2me_16(stream_chunk->type);}/* * fallback from mmsh to http WITHOUT re-sending GET * message to server. * this will be more pleasant to server. * * this function must be called when * [ no data in http_hdr->body (already moved)] * [ http_hdr is alreadyh set ] * return value: */int mmsh_fallback_to_http(struct stream_t *stream, struct http_header_t *http_hdr){ struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl; int ret; display(MSDL_VER,"probably not mmsh. fallback to http.\n"); /* quit mmsh, and start http */ free_mmsh_ctrl_t(stream_ctrl->mmsh_ctrl); stream_ctrl->http_ctrl = new_http_ctrl_t(); stream->start = http_streaming_start; stream->read = http_streaming_read; stream->close = http_streaming_close; /* read content-length */ ret = http_parse_response(stream_ctrl->http_ctrl,http_hdr); stream->stream_ctrl->file_size = stream_ctrl->http_ctrl->content_length; /* free_http_header(http_hdr); don't free it here. it will be free()ed later */ stream_ctrl->protocol = HTTP; return ret;}/* * get entire asf header. * this function is needed because asf_header might come * within more than 2 packets. * *** CAUTION *** * DO NOT FORGET TO free() asfheader later!! * all header is going to stored in buffer. * return value: -1 ... failure * other ... length of asf header */static int mmsh_get_asf_header(struct stream_t *stream,uint8_t **asfheader, struct asf_stream_chunk_t *first_chunk){ struct asf_stream_chunk_t chunk; struct asf_stream_chunk_extra_t chunk_extra; struct asf_header_t asfh; uint8_t *buffer = NULL; int asf_header_len = 0; int total; int ret; total = 0; memcpy(&chunk,first_chunk,sizeof(chunk)); for(;;) { /* read chunk extra */ read_data(stream,&chunk_extra,sizeof(chunk_extra)); ret = le2me_16(chunk.size) - sizeof(chunk); buffer = (uint8_t *)xrealloc(buffer,ret + total); stream->stream_ctrl->packet_count++; /* increment packet count */ ret = read_data(stream,buffer + total,ret); if(ret < 0) { goto failed; } if(asf_header_len == 0) { /* first loop */ if(ret < sizeof(struct asf_header_t)) { display(MSDL_ERR,"1st chunk %d shorter than asf_header_t\n",ret); goto failed; } memcpy(&asfh,buffer,sizeof(struct asf_header_t)); asf_header_len = le2me_64(asfh.objh.size); if(asf_header_len == 0) { display(MSDL_ERR,"asf_header_len is zero\n"); goto failed; } } total += ret; if(total >= asf_header_len) { break; /* got entire header --- break */ } else { int chunk_type; /* get chunk for next loop */ read_data(stream,&chunk,sizeof(chunk)); chunk_type = asf_streaming(&chunk); if(chunk_type != ASF_STREAMING_HEADER) { /* not a header packet */ display(MSDL_ERR,"non-header paceket when header packet expected\n"); goto failed; } } } *asfheader = buffer; return total; failed: free(buffer); *asfheader = NULL; return -1;}/* * starts mms over http streaming. (mmsh) * * return value : negative or 0 ... error * 1 ... success */int mmsh_streaming_start(struct stream_t *stream){ struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl; struct mmsh_ctrl_t *mmsh_ctrl = stream_ctrl->mmsh_ctrl; struct url_t *url = stream->url; struct download_opts_t *dlopts = stream->dlopts; struct http_header_t *http_hdr = NULL; int asf_header_len = 0; int sock = 0; /* socket to use */ int ret = 0; stream_ctrl->status = STREAMING_HANDSHAKING; mmsh_ctrl->streaming_type = ASF_Unknown_e; if(dlopts->bandwidth) { stream_ctrl->bandwidth = dlopts->bandwidth; } else { stream_ctrl->bandwidth = INT_MAX_BANDWIDTH; } set_serverinfo_by_proxy_string(stream->serverinfo,url->hostname,url->port, dlopts->http_proxy, HTTP_PORT,HTTP_PROXY_PORT); /* proxy setting: done */ sock = server_connect(stream->serverinfo->connect_host,stream->serverinfo->connect_port); if(sock < 0) { return sock; /* failure */ } stream->netsock->sock = sock; /* set socket# to stream_t */ /* send 1st request */ stream_ctrl->packet_count = 0; http_hdr = new_http_header(); if(dlopts->resume_download) { http_prepare_resuming(stream); } /* byte range specified */ if(dlopts->byterange) { http_set_byterange_field(http_hdr,dlopts->byterange); } mmsh_1st_request(stream,http_hdr); http_send_header(stream,http_hdr); free_http_header(http_hdr); http_hdr = NULL; /* get 1st reply */ http_hdr = new_http_header(); mmsh_recv_header(stream,http_hdr); ret = http_process_reply(stream,http_hdr); // interpret http_hdr which just received if(ret < 0) { goto failed; // including complete } switch(mmsh_ctrl->streaming_type) { case ASF_Seekable_e: case ASF_Nonseekable_e: stream->stream_ctrl->protocol = MMSH; struct asf_stream_chunk_t chunk; /* for chunk header for asf header */ int chunk_type; /* little endian */ uint8_t *buffer = NULL; /* we are supposed to get the ASF header! ( 100% ) */ display(MSDL_VER,"1st response from server... \n"); /* keep getting chunk until stop getting IGNORE */ for(;;) { read_data(stream,&chunk,sizeof(chunk)); chunk_type = asf_streaming(&chunk); if(chunk_type != ASF_STREAMING_IGNORE) break; buffer = xmalloc(chunk.size - 4); read_data(stream,buffer,chunk.size - 4); free(buffer); } if(chunk_type == ASF_STREAMING_HEADER) { /* header may come within more than 2 packets */ asf_header_len = mmsh_get_asf_header(stream,&buffer,&chunk); if(asf_header_len < 0) goto failed; display(MSDL_VER,"ASF header received (size = %d)\n",asf_header_len); /* interpret M$ asf header */ ret = asf_interpret_header(mmsh_ctrl->hinfo,stream_ctrl->bandwidth, buffer,asf_header_len); /* set necessary information to mmsh_ctrl */ stream_ctrl->file_size = mmsh_ctrl->hinfo->fileh->file_size; stream_ctrl->packet_length = mmsh_ctrl->packet_size = mmsh_ctrl->hinfo->fileh->max_packet_size; /* and everything is done */ free(buffer); buffer = NULL; if(ret < 0) goto failed; if(mmsh_ctrl->hinfo->streams->n_audio == 0 && mmsh_ctrl->hinfo->streams->n_video == 0) { /* this means no stream to DL */ display(MSDL_ERR,"No stream to download!\n"); goto failed; } display(MSDL_VER,"\n"); } else if(chunk_type == ASF_STREAMING_CLEAR || chunk_type == ASF_STREAMING_DATA || chunk_type == ASF_STREAMING_END_TRANS) { display(MSDL_ERR,"ASF header expected!!\n"); goto failed; } else { /* not mmsh, try http here. */ /* push back "chunk" to be read again */ stream_data_push_back(stream,&chunk,sizeof(chunk)); mmsh_fallback_to_http(stream,http_hdr); goto http_fallback; } break; case ASF_Unknown_e: mmsh_fallback_to_http(stream,http_hdr); goto http_fallback; default: /* should not come here */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -