📄 mmsh.c
字号:
goto failed; break; } /* allways comes here to free http_hdr */ if(http_hdr) free_http_header(http_hdr); http_hdr = NULL; close(sock); 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 */ http_hdr = new_http_header(); mmsh_media_request(stream,http_hdr); ret = http_send_header(stream,http_hdr); free_http_header(http_hdr); http_hdr = NULL; http_hdr = new_http_header(); ret = mmsh_recv_header(stream,http_hdr); if(ret < 0) { display(MSDL_ERR,"MMSH connection failed\n"); goto failed; } if(!is_http_response_ok(ret)) { /* MMSH request error */ display(MSDL_ERR,"%d %s\n",http_hdr->status_code,http_hdr->reason_phrase); goto failed; } free_http_header(http_hdr); http_hdr = NULL; if(mmsh_ctrl->streaming_type != ASF_Seekable_e && mmsh_ctrl->streaming_type != ASF_Nonseekable_e) { display(MSDL_ERR,"mmsh request failed\n"); goto failed; } stream->stream_ctrl->status = STREAMING_DOWNLOADING; return 1; http_fallback: free_http_header(http_hdr); http_hdr = NULL; return 1; failed: free_http_header(http_hdr); if(sock) close(sock); http_hdr = NULL; return 0;}/* * read from media stream. * * fill 'buffer' with data, and buffer size is 'max_size'. * receive one chunk from stream->sock, and fills 'max_size' bytes to buffer. * and if there are more bytes in the chunk, the data is stored to * stream->stream_ctrl->buffer. * * return value: positive value ... bytes written to buffer. * 0 ... END OF FILE * or ... Clear EVERYTHING!!! RESET!!! * -1 ... ERROR */static int mmsh_get_media_packet(struct stream_t *stream, uint8_t *buffer, size_t max_size){ static struct asf_stream_chunk_t chunk; static struct asf_stream_chunk_extra_t chunk_extra; int chunk_size = 0; int chunk_type; int ret; int data_follows_f; struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl; struct mmsh_ctrl_t *mmsh_ctrl = stream_ctrl->mmsh_ctrl; do { data_follows_f = 1; /* get chunk header from network. */ if(read_data(stream,&chunk,sizeof(chunk)) < sizeof(chunk)) { goto failed; } /* little endian. (asf streaming interpret as little endian.) */ chunk_type = asf_streaming(&chunk); /*HTTP message packet ... continue */ if(!(memcmp((uint8_t *)&chunk,"HTTP",4))) { struct http_header_t *http_hdr; char *field = NULL; int len = 0; stream_data_push_back(stream,(uint8_t *)&chunk,sizeof(chunk)); http_hdr = new_http_header(); http_recv_header(stream,http_hdr); if((field = http_get_field(http_hdr,"Content-Length")) != NULL) { while(*field == ' ') field++; len = atoi(field); } free_http_header(http_hdr); if(len) { uint8_t *buf = xmalloc(len); read_data(stream,buf,len); free(buf); /* Ignore all */ } data_follows_f = 0; /* don't forget to clear this. as no data follows */ } else if(chunk_type == ASF_STREAMING_END_TRANS) { stream_ctrl->status = STREAMING_FINISHED; display(MSDL_DBG,"Transaction finished normally!\n"); return 0; } else if(chunk_type == ASF_STREAMING_CLEAR) { stream_ctrl->status = STREAMING_REWIND; /* reset every headerinfo data */ free_asf_headerinfo_t(mmsh_ctrl->hinfo); mmsh_ctrl->hinfo = new_asf_headerinfo_t(); display(MSDL_VER,"\nClear Configuration! reset!\n"); data_follows_f = 0; /* loop again , and get header/data/eof packet */ } else if(chunk_type == ASF_STREAMING_DATA || chunk_type == ASF_STREAMING_DATA2 || chunk_type == ASF_STREAMING_HEADER) { if(read_data(stream,&chunk_extra,sizeof(chunk_extra)) < 0) { goto failed; } } else if(chunk_type == ASF_STREAMING_IGNORE){ char *buffer; buffer = xmalloc(chunk.size - 4); read_data(stream,buffer,chunk.size - 4); display(MSDL_DBG,"Metadata ----\n"); dbgdump(buffer, chunk.size - 4); display(MSDL_DBG,"-(%d B)--------\n",chunk.size - 4); free(buffer); data_follows_f = 0; } else { /* ignore this*/ display(MSDL_ERR,"unknown packet type!!\n"); } } while(data_follows_f == 0); /* size of this chunk. ( media stream data ) >>> CAUTION <<< chunk_size is size of chunk to get from network, but have to write mmsh_ctrl->packet_size bytes in ASF file. so 0 padding of 'mmsh_ctrl->packet_size - chunk_size' bytes is necessary. */ chunk_size = le2me_16(chunk.size) - sizeof(chunk); stream_ctrl->packet_count++; /* increment received packet count */ /* header or data, as other packets are already processed */ if(chunk_type == ASF_STREAMING_HEADER) { struct asf_headerinfo_t *hinfo = mmsh_ctrl->hinfo; display(MSDL_DBG,"ASF Header received\n"); if(chunk_size <= max_size) { /* header can be stored in buffer */ /* buffer is long enogh. */ ret = read_data(stream,buffer,chunk_size); if(ret < 0) { goto failed; } /* no padding, because this is ASF header */ } else { /* buffer is not long enough for header. */ /* data is to be written in file, so it goes to write_buffer */ if(read_data(stream, stream->stream_ctrl->write_buffer, chunk_size) < 0) { goto failed; } memcpy(buffer, stream_ctrl->write_buffer, max_size); stream_ctrl->write_pos = max_size; stream_ctrl->write_data_len = chunk_size - max_size; ret = max_size; } /* interpret asf_header. it has to be done here and doing complecated stuff because . there is "clear configuration" packet, thus header comes multiple times. . header we receive in 'mmsh_streaming_start' and one which we got in this function differs. . we don't know in how many packets the header will come. and there are necessary stuff after asf_header, so asf_header_len is not likely asfh.objh.size(pure header length, not including the "necessary stuff"). :) it sucks... */ /* copy asf header */ hinfo->asf_header = xrealloc(hinfo->asf_header, hinfo->asf_header_len + chunk_size); memcpy(hinfo->asf_header + hinfo->asf_header_len, (chunk_size <= max_size) ? buffer : stream_ctrl->write_buffer, chunk_size); hinfo->asf_header_len += chunk_size; /* accumulate */ if(hinfo->asf_header_len >= sizeof(struct asf_header_t) && hinfo->asf_header_len >= le2me_64(((struct asf_header_t *)hinfo->asf_header)->objh.size)) { asf_get_file_property(hinfo->asf_header, hinfo->asf_header_len, hinfo->fileh); if(ret < 0) { /* error */ display(MSDL_ERR,"asf_get_file_property error\n"); goto failed; } stream_ctrl->packet_length = mmsh_ctrl->packet_size = hinfo->fileh->max_packet_size; stream_ctrl->file_size = hinfo->fileh->file_size; } return ret; } else { display(MSDL_DBG,"ASF Data received\n"); if(mmsh_ctrl->packet_size < chunk_size) { display(MSDL_ERR,"chunk size bigger than pakcet size..\n"); goto failed; } if(mmsh_ctrl->packet_size <= max_size) { /* buffer is bigger enough for this chunk. */ if(read_data(stream, buffer, chunk_size) < 0) { goto failed; } /*{ int j = 0; for(;j < 16; j++) { printf("%02x ",buffer[j]); } printf("\n"); }*/ memset(buffer + chunk_size, 0, /* padding */ mmsh_ctrl->packet_size - chunk_size); ret = stream->stream_ctrl->mmsh_ctrl->packet_size; } else { /* max_size < packet_size .. cannot write in buffer. */ if(read_data(stream, stream_ctrl->write_buffer, chunk_size) < 0) { goto failed; } /* this is OK because netsock->buffer is empty when entered this function. */ memset(stream_ctrl->write_buffer + chunk_size, 0, /* padding */ mmsh_ctrl->packet_size - chunk_size); memcpy(buffer,stream_ctrl->write_buffer, max_size); ret = stream_ctrl->write_pos = max_size; stream_ctrl->write_data_len = mmsh_ctrl->packet_size - max_size; } return ret; } failed: /* probably timeout error */ return -1; }/* * read mms over http stream. filles buffer, and buffer size is 'size' * * read cached data from stream->netsock->buffer * check for to see if network access is necessary * get chunk(media packet) from network. * * return value: bytes written to buffer. -1 if error. */int mmsh_streaming_read(struct stream_t *stream, uint8_t *buffer, size_t buffer_size){ struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl; size_t pos = 0; /* how many bytes are in 'buffer' */ int network_read = 0; if(buffer_size == 0) { display(MSDL_ERR,"buffer_size must be bigger than 0\n"); return -1; } if(stream_ctrl->write_data_len) { /* there are waiting data to be written */ if(buffer_size <= stream_ctrl->write_data_len) { /* buffer_size < stream_ctrl->write_data_len... fill buffer, and return. */ memcpy(buffer,stream_ctrl->write_buffer + stream_ctrl->write_pos, buffer_size); stream_ctrl->write_data_len -= buffer_size; stream_ctrl->write_pos += buffer_size; return buffer_size; } else { /* stream_ctrl->write_data_len < buffer_size, have to read from network. */ memcpy(buffer,stream_ctrl->write_buffer + stream_ctrl->write_pos, stream_ctrl->write_data_len); pos = stream_ctrl->write_data_len; /* and stream_ctrl->write_buffer is empty. */ stream_ctrl->write_data_len = 0; stream_ctrl->write_pos = 0; } } stream_ctrl->write_data_len = 0; stream_ctrl->write_pos = 0; /* still have to get data from network. */ if(stream_ctrl->status != STREAMING_FINISHED) { /* not finished */ network_read = mmsh_get_media_packet(stream, buffer + pos, buffer_size - pos); } if(network_read >= 0) { /* network read success */ return (network_read + pos); } else { return -1; /* error */ }}struct stream_t *mmsh_streaming_init(){ struct stream_t *stream = streaming_init_common(); stream->stream_ctrl->mmsh_ctrl = new_mmsh_ctrl_t(); stream->start = mmsh_streaming_start; stream->read = mmsh_streaming_read; stream->close = mmsh_streaming_close; return stream;}void mmsh_streaming_close(struct stream_t *stream){ if(stream->netsock->sock > 0) { close(stream->netsock->sock); } free_mmsh_ctrl_t(stream->stream_ctrl->mmsh_ctrl); streaming_close_common(stream);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -