[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[570] mplayerxp/libmpstream2
Brought to you by:
olov
From: <nic...@us...> - 2012-12-17 17:03:58
|
Revision: 570 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=570&view=rev Author: nickols_k Date: 2012-12-17 17:03:47 +0000 (Mon, 17 Dec 2012) Log Message: ----------- on respone.404 segfault--: convert networking into classes Modified Paths: -------------- mplayerxp/libmpstream2/Makefile mplayerxp/libmpstream2/http.cpp mplayerxp/libmpstream2/http.h mplayerxp/libmpstream2/network.cpp mplayerxp/libmpstream2/network.h mplayerxp/libmpstream2/s_network.cpp mplayerxp/libmpstream2/s_rtsp.cpp mplayerxp/libmpstream2/s_udp.cpp mplayerxp/libmpstream2/stream.cpp mplayerxp/libmpstream2/udp.h Added Paths: ----------- mplayerxp/libmpstream2/network_asf.cpp mplayerxp/libmpstream2/network_asf.h mplayerxp/libmpstream2/network_asf_mmst.cpp mplayerxp/libmpstream2/network_asf_mmst.h mplayerxp/libmpstream2/network_nop.cpp mplayerxp/libmpstream2/network_nop.h mplayerxp/libmpstream2/network_pnm.cpp mplayerxp/libmpstream2/network_pnm.h mplayerxp/libmpstream2/network_real_rtsp.cpp mplayerxp/libmpstream2/network_real_rtsp.h mplayerxp/libmpstream2/network_rtp.cpp mplayerxp/libmpstream2/network_rtp.h mplayerxp/libmpstream2/network_rtsp.cpp mplayerxp/libmpstream2/network_rtsp.h Removed Paths: ------------- mplayerxp/libmpstream2/asf_mmst_streaming.cpp mplayerxp/libmpstream2/asf_streaming.cpp mplayerxp/libmpstream2/asf_streaming.h Modified: mplayerxp/libmpstream2/Makefile =================================================================== --- mplayerxp/libmpstream2/Makefile 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/Makefile 2012-12-17 17:03:47 UTC (rev 570) @@ -31,11 +31,16 @@ SUBDIRS = tvi ifeq ($(HAVE_STREAMING),yes) SUBDIRS += freesdp librtsp realrtsp -CXXSRCS += asf_streaming.cpp \ - asf_mmst_streaming.cpp \ - cookies.cpp \ +CXXSRCS += cookies.cpp \ http.cpp \ network.cpp \ + network_asf.cpp \ + network_asf_mmst.cpp \ + network_nop.cpp \ + network_pnm.cpp \ + network_real_rtsp.cpp \ + network_rtp.cpp \ + network_rtsp.cpp \ pnm.cpp \ rtp.cpp \ tcp.cpp \ Deleted: mplayerxp/libmpstream2/asf_mmst_streaming.cpp =================================================================== --- mplayerxp/libmpstream2/asf_mmst_streaming.cpp 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/asf_mmst_streaming.cpp 2012-12-17 17:03:47 UTC (rev 570) @@ -1,649 +0,0 @@ -#include "mp_config.h" -#include "osdep/mplib.h" -using namespace mpxp; -// mmst implementation taken from the xine-mms plugin made by majormms (http://geocities.com/majormms/) -// -// ported to mplayer by Abhijeet Phatak <abh...@ya...> -// date : 16 April 2002 -// -// information about the mms protocol can be find at http://get.to/sdp -// - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <inttypes.h> - -#include "mplayerxp.h" -#include "tcp.h" -#include "url.h" -#include "stream.h" - -#include "network.h" - -#ifndef HAVE_WINSOCK2 -#define closesocket close -#else -#include <winsock2.h> -#endif -#ifndef USE_SETLOCALE -#undef USE_ICONV -#endif - -#ifdef USE_ICONV -#ifdef HAVE_GICONV -#include <giconv.h> -#else -#include <iconv.h> -#endif -#ifdef USE_LANGINFO -#include <langinfo.h> -#endif -#endif -#include "stream_msg.h" - -#define BUF_SIZE 102400 -#define HDR_BUF_SIZE 8192 -#define MAX_STREAMS 20 - -typedef struct -{ - uint8_t buf[BUF_SIZE]; - int num_bytes; - -} command_t; - -static int seq_num; -static int num_stream_ids; -static int stream_ids[MAX_STREAMS]; - -static int get_data (Tcp& s,unsigned char *buf, size_t count); - -static void put_32 (command_t *cmd, uint32_t value) -{ - cmd->buf[cmd->num_bytes ] = value % 256; - value = value >> 8; - cmd->buf[cmd->num_bytes+1] = value % 256 ; - value = value >> 8; - cmd->buf[cmd->num_bytes+2] = value % 256 ; - value = value >> 8; - cmd->buf[cmd->num_bytes+3] = value % 256 ; - - cmd->num_bytes += 4; -} - -static uint32_t get_32 (unsigned char *cmd, int offset) -{ - uint32_t ret; - - ret = cmd[offset] ; - ret |= cmd[offset+1]<<8 ; - ret |= cmd[offset+2]<<16 ; - ret |= cmd[offset+3]<<24 ; - - return ret; -} - -static void send_command (Tcp& tcp, int command, uint32_t switches, - uint32_t extra, int length, - unsigned char *data) -{ - command_t cmd; - int len8; - - len8 = (length + 7) / 8; - - cmd.num_bytes = 0; - - put_32 (&cmd, 0x00000001); /* start sequence */ - put_32 (&cmd, 0xB00BFACE); /* #-)) */ - put_32 (&cmd, len8*8 + 32); - put_32 (&cmd, 0x20534d4d); /* protocol type "MMS " */ - put_32 (&cmd, len8 + 4); - put_32 (&cmd, seq_num); - seq_num++; - put_32 (&cmd, 0x0); /* unknown */ - put_32 (&cmd, 0x0); - put_32 (&cmd, len8+2); - put_32 (&cmd, 0x00030000 | command); /* dir | command */ - put_32 (&cmd, switches); - put_32 (&cmd, extra); - - memcpy (&cmd.buf[48], data, length); - if (length & 7) - memset(&cmd.buf[48 + length], 0, 8 - (length & 7)); - - if (tcp.write (cmd.buf, len8*8+48) != (len8*8+48)) { - MSG_ERR ("write error\n"); - } -} - -#ifdef USE_ICONV -static iconv_t url_conv; -#endif - -static void string_utf16(unsigned char *dest,const char *src, int len) -{ - int i; -#ifdef USE_ICONV - size_t len1, len2; - char *ip, *op; - - if (url_conv != (iconv_t)(-1)) - { - memset(dest, 0, 1000); - len1 = len; len2 = 1000; - ip = src; op = dest; - - iconv(url_conv, &ip, &len1, &op, &len2); - } - else - { -#endif - if (len > 499) len = 499; - for (i=0; i<len; i++) { - dest[i*2] = src[i]; - dest[i*2+1] = 0; - } - /* trailing zeroes */ - dest[i*2] = 0; - dest[i*2+1] = 0; -#ifdef USE_ICONV - } -#endif -} - -static void get_answer (Tcp& tcp) -{ - unsigned char data[BUF_SIZE]; - int command = 0x1b; - - while (command == 0x1b) { - int len; - - len = tcp.read(data, BUF_SIZE); - if (!len) { - MSG_ERR ("\nalert! eof\n"); - return; - } - - command = get_32 (data, 36) & 0xFFFF; - - if (command == 0x1b) - send_command (tcp, 0x1b, 0, 0, 0, data); - } -} - -static int get_data (Tcp& tcp,unsigned char *buf, size_t count) -{ - ssize_t len; - size_t total = 0; - - while (total < count) { - - len = tcp.read(&buf[total], count-total); - - if (len<=0) { - MSG_ERR ("read error:"); - return 0; - } - - total += len; - - if (len != 0) { -// printf ("[%d/%d]", total, count); - fflush (stdout); - } - - } - - return 1; - -} - -static int get_header (Tcp& tcp, uint8_t *header, networking_t& networking) -{ - unsigned char pre_header[8]; - int header_len; - - header_len = 0; - - while (1) { - if (!get_data (tcp, pre_header, 8)) { - MSG_ERR ("pre-header read failed\n"); - return 0; - } - if (pre_header[4] == 0x02) { - - int packet_len; - - packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; - -// printf ("asf header packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > HDR_BUF_SIZE - header_len) { - MSG_FATAL("Invalid header size, giving up\n"); - return 0; - } - - if (!get_data (tcp, &header[header_len], packet_len)) { - MSG_ERR("header data read failed\n"); - return 0; - } - - header_len += packet_len; - - if ( (header[header_len-1] == 1) && (header[header_len-2]==1)) { - - - if( networking_bufferize( networking, header, header_len )<0 ) { - return -1; - } - - // printf ("get header packet finished\n"); - - return (header_len); - - } - - } else { - - int32_t packet_len; - int command; - unsigned char data[BUF_SIZE]; - - if (!get_data (tcp, (unsigned char*)&packet_len, 4)) { - MSG_ERR ("packet_len read failed\n"); - return 0; - } - - packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; - -// printf ("command packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (tcp, data, packet_len)) { - MSG_ERR ("command data read failed\n"); - return 0; - } - - command = get_32 (data, 24) & 0xFFFF; - -// printf ("command: %02x\n", command); - - if (command == 0x1b) - send_command (tcp, 0x1b, 0, 0, 0, data); - - } - -// printf ("get header packet succ\n"); - } -} - -static int interp_header (uint8_t *header, int header_len) -{ - int i; - int packet_length=-1; - - /* - * parse header - */ - - i = 30; - while (i<header_len) { - - uint64_t guid_1, guid_2, length; - - guid_2 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - i += 8; - - guid_1 = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - i += 8; - -// printf ("guid found: %016llx%016llx\n", guid_1, guid_2); - - length = (uint64_t)header[i] | ((uint64_t)header[i+1]<<8) - | ((uint64_t)header[i+2]<<16) | ((uint64_t)header[i+3]<<24) - | ((uint64_t)header[i+4]<<32) | ((uint64_t)header[i+5]<<40) - | ((uint64_t)header[i+6]<<48) | ((uint64_t)header[i+7]<<56); - - i += 8; - - if ( (guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22630ULL) ) { - MSG_V ("header object\n"); - } else if ((guid_1 == 0x6cce6200aa00d9a6ULL) && (guid_2 == 0x11cf668e75b22636ULL)) { - MSG_V ("data object\n"); - } else if ((guid_1 == 0x6553200cc000e48eULL) && (guid_2 == 0x11cfa9478cabdca1ULL)) { - - packet_length = get_32(header, i+92-24); - - MSG_V ("file object, packet length = %d (%d)\n", - packet_length, get_32(header, i+96-24)); - - - } else if ((guid_1 == 0x6553200cc000e68eULL) && (guid_2 == 0x11cfa9b7b7dc0791ULL)) { - - int stream_id = header[i+48] | header[i+49] << 8; - - MSG_V ("stream object, stream id: %d\n", stream_id); - - if (num_stream_ids < MAX_STREAMS) { - stream_ids[num_stream_ids] = stream_id; - num_stream_ids++; - } else { - MSG_ERR("asf_mmst: too many id, stream skipped"); - } - - } else { - MSG_V ("unknown object\n"); - } - -// printf ("length : %lld\n", length); - - i += length-24; - - } - - return packet_length; - -} - - -static int get_media_packet (Tcp& tcp, int padding, networking_t& stream_ctrl) { - unsigned char pre_header[8]; - unsigned char data[BUF_SIZE]; - - if (!get_data (tcp, pre_header, 8)) { - MSG_ERR ("pre-header read failed\n"); - return 0; - } - -// for (i=0; i<8; i++) -// printf ("pre_header[%d] = %02x (%d)\n", -// i, pre_header[i], pre_header[i]); - - if (pre_header[4] == 0x04) { - - int packet_len; - - packet_len = (pre_header[7] << 8 | pre_header[6]) - 8; - -// printf ("asf media packet detected, len=%d\n", packet_len); - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (tcp, data, packet_len)) { - MSG_ERR ("media data read failed\n"); - return 0; - } - - networking_bufferize(stream_ctrl, data, padding); - - } else { - - int32_t packet_len; - int command; - - if (!get_data (tcp, (unsigned char*)&packet_len, 4)) { - MSG_ERR ("packet_len read failed\n"); - return 0; - } - - packet_len = get_32 ((unsigned char*)&packet_len, 0) + 4; - - if (packet_len < 0 || packet_len > BUF_SIZE) { - MSG_FATAL("Invalid rtsp packet size, giving up\n"); - return 0; - } - - if (!get_data (tcp, data, packet_len)) { - MSG_ERR ("command data read failed\n"); - return 0; - } - - if ( (pre_header[7] != 0xb0) || (pre_header[6] != 0x0b) - || (pre_header[5] != 0xfa) || (pre_header[4] != 0xce) ) { - - MSG_ERR ("missing signature\n"); - return -1; - } - - command = get_32 (data, 24) & 0xFFFF; - -// printf ("\ncommand packet detected, len=%d cmd=0x%X\n", packet_len, command); - - if (command == 0x1b) - send_command (tcp, 0x1b, 0, 0, 0, data); - else if (command == 0x1e) { - MSG_OK ("everything done. Thank you for downloading a media file containing proprietary and patentend technology.\n"); - return 0; - } - else if (command == 0x21 ) { - // Looks like it's new in WMS9 - // Unknown command, but ignoring it seems to work. - return 0; - } - else if (command != 0x05) { - MSG_ERR ("unknown command %02x\n", command); - return -1; - } - } - -// printf ("get media packet succ\n"); - - return 1; -} - - -static int packet_length1; - -static int asf_mmst_networking_read(Tcp& tcp, char *buffer, int size, networking_t& stream_ctrl ) -{ - int len; - - while( stream_ctrl.buffer_size==0 ) { - // buffer is empty - fill it! - int ret = get_media_packet(tcp, packet_length1, stream_ctrl); - if( ret<0 ) { - MSG_ERR("get_media_packet error : %s\n",strerror(errno)); - return -1; - } else if (ret==0) //EOF? - return ret; - } - - len = stream_ctrl.buffer_size-stream_ctrl.buffer_pos; - if(len>size) len=size; - memcpy( buffer, (stream_ctrl.buffer)+(stream_ctrl.buffer_pos), len ); - stream_ctrl.buffer_pos += len; - if( stream_ctrl.buffer_pos>=stream_ctrl.buffer_size ) { - delete stream_ctrl.buffer ; - stream_ctrl.buffer = NULL; - stream_ctrl.buffer_size = 0; - stream_ctrl.buffer_pos = 0; - } - return len; - -} - -static int asf_mmst_networking_seek(Tcp& tcp, off_t pos, networking_t& networking ) -{ - UNUSED(tcp); - UNUSED(pos); - UNUSED(networking); - return -1; -} - -MPXP_Rc asf_mmst_networking_start(Tcp& tcp, networking_t& networking) -{ - char str[1024]; - uint8_t data[BUF_SIZE]; - uint8_t asf_header[HDR_BUF_SIZE]; - int asf_header_len; - int len, i, packet_length; - char* path, *unescpath; - URL* url1 = networking.url; - - tcp.close(); - - /* parse url */ - path = strchr(url1->file,'/') + 1; - - /* mmst filename are not url_escaped by MS MediaPlayer and are expected as - * "plain text" by the server, so need to decode it here - */ - unescpath=new char [strlen(path)+1]; - if (!unescpath) { - MSG_FATAL("Memory allocation failed!\n"); - return MPXP_False; - } - url2string(unescpath,path); - path=unescpath; - - if( url1->port==0 ) url1->port=1755; - tcp.open(url1->hostname, url1->port, Tcp::IP4); - if( !tcp.established()) { - delete path; - return MPXP_False; - } - MSG_INFO ("connected\n"); - - seq_num=0; - - /* - * Send the initial connect info including player version no. Client GUID (random) and the host address being connected to. - * This command is sent at the very start of protocol initiation. It sends local information to the serve - * cmd 1 0x01 - * */ - - /* prepare for the url encoding conversion */ -#ifdef USE_ICONV -#ifdef USE_LANGINFO - url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET)); -#else - url_conv = iconv_open("UTF-16LE", NULL); -#endif -#endif - - snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname); - string_utf16 (data, str, strlen(str)); -// send_command(s, commandno ....) - send_command (tcp, 1, 0, 0x0004000b, strlen(str) * 2+2, data); - - len = tcp.read (data, BUF_SIZE); - - /*This sends details of the local machine IP address to a Funnel system at the server. - * Also, the TCP or UDP transport selection is sent. - * - * here 192.168.0.129 is local ip address TCP/UDP states the tronsport we r using - * and 1037 is the local TCP or UDP socket number - * cmd 2 0x02 - * */ - - string_utf16 (&data[8], "\002\000\\\\192.168.0.1\\TCP\\1037", 24); - memset (data, 0, 8); - send_command (tcp, 2, 0, 0, 24*2+10, data); - - len = tcp.read(data, BUF_SIZE); - - /* This command sends file path (at server) and file name request to the server. - * 0x5 */ - - string_utf16 (&data[8], path, strlen(path)); - memset (data, 0, 8); - send_command (tcp, 5, 0, 0, strlen(path)*2+10, data); - delete path; - - get_answer (tcp); - - /* The ASF header chunk request. Includes ?session' variable for pre header value. - * After this command is sent, - * the server replies with 0x11 command and then the header chunk with header data follows. - * 0x15 */ - - memset (data, 0, 40); - data[32] = 2; - - send_command (tcp, 0x15, 1, 0, 40, data); - - num_stream_ids = 0; - /* get_headers(s, asf_header); */ - - asf_header_len = get_header (tcp, asf_header, networking); -// printf("---------------------------------- asf_header %d\n",asf_header); - if (asf_header_len==0) { //error reading header - tcp.close(); - return MPXP_False; - } - packet_length = interp_header (asf_header, asf_header_len); - - /* - * This command is the media stream MBR selector. Switches are always 6 bytes in length. - * After all switch elements, data ends with bytes [00 00] 00 20 ac 40 [02]. - * Where: - * [00 00] shows 0x61 0x00 (on the first 33 sent) or 0xff 0xff for ASF files, and with no ending data for WMV files. - * It is not yet understood what all this means. - * And the last [02] byte is probably the header ?session' value. - * - * 0x33 */ - - memset (data, 0, 40); - - if (mp_conf.audio_id > 0) { - data[2] = 0xFF; - data[3] = 0xFF; - data[4] = mp_conf.audio_id; - send_command(tcp, 0x33, num_stream_ids, 0xFFFF | mp_conf.audio_id << 16, 8, data); - } else { - for (i=1; i<num_stream_ids; i++) { - data [ (i-1) * 6 + 2 ] = 0xFF; - data [ (i-1) * 6 + 3 ] = 0xFF; - data [ (i-1) * 6 + 4 ] = stream_ids[i]; - data [ (i-1) * 6 + 5 ] = 0x00; - } - send_command (tcp, 0x33, num_stream_ids, 0xFFFF | stream_ids[0] << 16, (num_stream_ids-1)*6+2 , data); - } - - get_answer (tcp); - - /* Start sending file from packet xx. - * This command is also used for resume downloads or requesting a lost packet. - * Also used for seeking by sending a play point value which seeks to the media time point. - * Includes ?session' value in pre header and the maximum media stream time. - * 0x07 */ - - memset (data, 0, 40); - - for (i=8; i<16; i++) data[i] = 0xFF; - data[20] = 0x04; - - send_command (tcp, 0x07, 1, 0xFFFF | stream_ids[0] << 16, 24, data); - - networking.networking_read = asf_mmst_networking_read; - networking.networking_seek = asf_mmst_networking_seek; - networking.buffering = 1; - networking.status = networking_playing_e; - - packet_length1 = packet_length; - MSG_V("mmst packet_length = %d\n",packet_length); - -#ifdef USE_ICONV - if (url_conv != (iconv_t)(-1)) iconv_close(url_conv); -#endif - return MPXP_Ok; -} Deleted: mplayerxp/libmpstream2/asf_streaming.cpp =================================================================== --- mplayerxp/libmpstream2/asf_streaming.cpp 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/asf_streaming.cpp 2012-12-17 17:03:47 UTC (rev 570) @@ -1,845 +0,0 @@ -#include "mp_config.h" -#include "osdep/mplib.h" -using namespace mpxp; -#include <limits> - -#include <stdio.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "mplayerxp.h" -#ifndef HAVE_WINSOCK2 -#define closesocket close -#else -#include <winsock2.h> -#endif - -#include "url.h" -#include "tcp.h" -#include "http.h" - -#include "stream.h" -#include "asf_streaming.h" -#include "libmpdemux/asf.h" -#include "network.h" -#include "stream_msg.h" - -#if defined( ARCH_X86 ) || defined(ARCH_X86_64) -static inline uint32_t ASF_LOAD_GUID_PREFIX(uint8_t* guid) { return *(uint32_t*)guid; } -#else -static inline uint32_t ASF_LOAD_GUID_PREFIX(uint8_t* guid) { return bswap_32(*(uint32_t*)guid); } -#endif - -// ASF networking support several network protocol. -// One use UDP, not known, yet! -// Another is HTTP, this one is known. -// So for now, we use the HTTP protocol. -// -// We can try several protocol for asf networking -// * first the UDP protcol, if there is a firewall, UDP -// packets will not come back, so the mmsu will failed. -// * Then we can try TCP, but if there is a proxy for -// internet connection, the TCP connection will not get -// through -// * Then we can try HTTP. -// -// Note: MMS/HTTP support is now a "well known" support protocol, -// it has been tested for while, not like MMST support. -// WMP sequence is MMSU then MMST and then HTTP. -// In MPlayer case since HTTP support is more reliable, -// we are doing HTTP first then we try MMST if HTTP fail. -static MPXP_Rc asf_http_networking_start(Tcp& fd, networking_t& networking ); - -/* - ASF networking support several network protocol. - One use UDP, not known, yet! - Another is HTTP, this one is known. - So for now, we use the HTTP protocol. - - We can try several protocol for asf networking - * first the UDP protcol, if there is a firewall, UDP - packets will not come back, so the mmsu will failed. - * Then we can try TCP, but if there is a proxy for - internet connection, the TCP connection will not get - through - * Then we can try HTTP. - - Note: MMS/HTTP support is now a "well known" support protocol, - it has been tested for while, not like MMST support. - WMP sequence is MMSU then MMST and then HTTP. - In MPlayer case since HTTP support is more reliable, - we are doing HTTP first then we try MMST if HTTP fail. -*/ -MPXP_Rc asf_networking_start(Tcp& tcp,networking_t& networking) { - char *proto = networking.url->protocol; - int port = networking.url->port; - MPXP_Rc rc; - - // Is protocol even valid mms,mmsu,mmst,http,http_proxy? - if (!(!strncasecmp(proto, "mmst", 4) || !strncasecmp(proto, "mmsu", 4) || - !strncasecmp(proto, "http_proxy", 10) || !strncasecmp(proto, "mms", 3) || - !strncasecmp(proto, "http", 4))) { - MSG_ERR("Unknown protocol: %s\n", proto ); - return MPXP_False; - } - - // Is protocol mms or mmsu? - if (!strncasecmp(proto, "mmsu", 4) || !strncasecmp(proto, "mms", 3)) { - MSG_V("Trying ASF/UDP...\n"); - //fd = asf_mmsu_networking_start( stream ); - //mmsu support is not implemented yet - using this code - MSG_V(" ===> ASF/UDP failed\n"); - return MPXP_False; - } - - //Is protocol mms or mmst? - if (!strncasecmp(proto, "mmst", 4) || !strncasecmp(proto, "mms", 3)) { - MSG_V("Trying ASF/TCP...\n"); - rc = asf_mmst_networking_start(tcp,networking); - networking.url->port = port; - if( rc==MPXP_Ok ) return MPXP_Ok; - MSG_V(" ===> ASF/TCP failed\n"); - return MPXP_False; - } - - //Is protocol http, http_proxy, or mms? - if (!strncasecmp(proto, "http_proxy", 10) || !strncasecmp(proto, "http", 4) || - !strncasecmp(proto, "mms", 3)) { - MSG_V("Trying ASF/HTTP...\n"); - rc = asf_http_networking_start(tcp,networking); - networking.url->port = port; - if( rc==MPXP_Ok ) return MPXP_Ok; - MSG_V(" ===> ASF/HTTP failed\n"); - return MPXP_False; - } - //everything failed - return MPXP_False; -} - -static int -asf_networking(ASF_stream_chunck_t *stream_chunck, int *drop_packet ) { - if( drop_packet!=NULL ) *drop_packet = 0; - - if( stream_chunck->size<8 ) { - MSG_ERR("Ahhhh, stream_chunck size is too small: %d\n", stream_chunck->size); - return -1; - } - if( stream_chunck->size!=stream_chunck->size_confirm ) { - MSG_ERR("size_confirm mismatch!: %d %d\n", stream_chunck->size, stream_chunck->size_confirm); - return -1; - } - switch(stream_chunck->type) { - case ASF_STREAMING_CLEAR: // $C Clear ASF configuration - MSG_V("=====> Clearing ASF stream configuration!\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case ASF_STREAMING_DATA: // $D Data follows - break; - case ASF_STREAMING_END_TRANS: // $E Transfer complete - MSG_V("=====> Transfer complete\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case ASF_STREAMING_HEADER: // $H ASF header chunk follows - MSG_V("=====> ASF header chunk follows\n"); - break; - default: - MSG_V("=====> Unknown stream type 0x%x\n", stream_chunck->type ); - } - return stream_chunck->size+4; -} - -static const char asf_stream_header_guid[16] = {0x91, 0x07, 0xdc, 0xb7, - 0xb7, 0xa9, 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}; -static const char asf_file_header_guid[16] = {0xa1, 0xdc, 0xab, 0x8c, - 0x47, 0xa9, 0xcf, 0x11, 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}; -static const char asf_content_desc_guid[16] = {0x33, 0x26, 0xb2, 0x75, - 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; -static const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b, - 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}; -static const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75, - 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; -static int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len) -{ - int i; - for (i = cur_pos; i < buf_len - 19; i++) { - if (memcmp(&buf[i], guid, 16) == 0) - return i + 16 + 8; // point after guid + length - } - return -1; -} - -static int max_idx(int s_count, int *s_rates, int bound) { - int i, best = -1, rate = -1; - for (i = 0; i < s_count; i++) { - if (s_rates[i] > rate && s_rates[i] <= bound) { - rate = s_rates[i]; - best = i; - } - } - return best; -} - -static MPXP_Rc -asf_networking_parse_header(Tcp& tcp, networking_t& networking) { - ASF_header_t asfh; - ASF_stream_chunck_t chunk; - asf_http_networking_t* asf_ctrl = (asf_http_networking_t*) networking.data; - char* buffer=NULL, *chunk_buffer=NULL; - int i,r,size,pos = 0; - int start; - int buffer_size = 0; - int chunk_size2read = 0; - int bw = networking.bandwidth; - int *v_rates = NULL, *a_rates = NULL; - int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1; - - if(asf_ctrl == NULL) return MPXP_False; - - // The ASF header can be in several network chunks. For example if the content description - // is big, the ASF header will be split in 2 network chunk. - // So we need to retrieve all the chunk before starting to parse the header. - do { - for( r=0; r < (int)sizeof(ASF_stream_chunck_t) ; ) { - i = nop_networking_read(tcp,((char*)&chunk)+r,sizeof(ASF_stream_chunck_t) - r,networking); - if(i <= 0) return MPXP_False; - r += i; - } - // Endian handling of the stream chunk - le2me_ASF_stream_chunck_t(&chunk); - size = asf_networking( &chunk, &r) - sizeof(ASF_stream_chunck_t); - if(r) MSG_WARN("Warning : drop header ????\n"); - if(size < 0){ - MSG_ERR("Error while parsing chunk header\n"); - return MPXP_False; - } - if (chunk.type != ASF_STREAMING_HEADER) { - MSG_ERR("Don't got a header as first chunk !!!!\n"); - return MPXP_False; - } - // audit: do not overflow buffer_size - if (size > std::numeric_limits<size_t>::max() - buffer_size) return MPXP_False; - buffer = (char*) mp_malloc(size+buffer_size); - if(buffer == NULL) { - MSG_FATAL("Error can't allocate %d bytes buffer\n",size+buffer_size); - return MPXP_False; - } - if( chunk_buffer!=NULL ) { - memcpy( buffer, chunk_buffer, buffer_size ); - delete chunk_buffer ; - } - chunk_buffer = buffer; - buffer += buffer_size; - buffer_size += size; - - for(r = 0; r < size;) { - i = nop_networking_read(tcp,buffer+r,size-r,networking); - if(i < 0) { - MSG_ERR("Error while reading network stream\n"); - return MPXP_False; - } - r += i; - } - - if( chunk_size2read==0 ) { - if(size < (int)sizeof(asfh)) { - MSG_ERR("Error chunk is too small\n"); - return MPXP_False; - } else MSG_DBG2("Got chunk\n"); - memcpy(&asfh,buffer,sizeof(asfh)); - le2me_ASF_header_t(&asfh); - chunk_size2read = asfh.objh.size; - MSG_DBG2("Size 2 read=%d\n", chunk_size2read); - } - } while( buffer_size<chunk_size2read); - buffer = chunk_buffer; - size = buffer_size; - - if(asfh.cno > 256) { - MSG_ERR("Error sub chunks number is invalid\n"); - return MPXP_False; - } - - start = sizeof(asfh); - - pos = find_asf_guid(buffer, asf_file_header_guid, start, size); - if (pos >= 0) { - ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos]; - pos += sizeof(ASF_file_header_t); - if (pos > size) goto len_err_out; - le2me_ASF_file_header_t(fileh); - asf_ctrl->packet_size = fileh->max_packet_size; - // before playing. - // preroll: time in ms to bufferize before playing - networking.prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0)); - } - - pos = start; - while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0) { - ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos]; - pos += sizeof(ASF_stream_header_t); - if (pos > size) goto len_err_out; - le2me_ASF_stream_header_t(streamh); - switch(ASF_LOAD_GUID_PREFIX(streamh->type)) { - case 0xF8699E40 : // audio stream - if(asf_ctrl->audio_streams == NULL){ - asf_ctrl->audio_streams = (int*)mp_malloc(sizeof(int)); - asf_ctrl->n_audio = 1; - } else { - asf_ctrl->n_audio++; - asf_ctrl->audio_streams = (int*)mp_realloc(asf_ctrl->audio_streams, - asf_ctrl->n_audio*sizeof(int)); - } - asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = streamh->stream_no; - break; - case 0xBC19EFC0 : // video stream - if(asf_ctrl->video_streams == NULL){ - asf_ctrl->video_streams = (int*)mp_malloc(sizeof(int)); - asf_ctrl->n_video = 1; - } else { - asf_ctrl->n_video++; - asf_ctrl->video_streams = (int*)mp_realloc(asf_ctrl->video_streams, - asf_ctrl->n_video*sizeof(int)); - } - asf_ctrl->video_streams[asf_ctrl->n_video-1] = streamh->stream_no; - break; - } - } - - // always allocate to avoid lots of ifs later - v_rates =new(zeromem) int [asf_ctrl->n_video]; - a_rates =new(zeromem) int [asf_ctrl->n_audio]; - - pos = find_asf_guid(buffer, asf_stream_group_guid, start, size); - if (pos >= 0) { - // stream bitrate properties object - int stream_count; - char *ptr = &buffer[pos]; - - MSG_V("Stream bitrate properties object\n"); - stream_count = le2me_16(*(uint16_t*)ptr); - ptr += sizeof(uint16_t); - if (ptr > &buffer[size]) goto len_err_out; - MSG_V(" stream count=[0x%x][%u]\n",stream_count, stream_count ); - for( i=0 ; i<stream_count ; i++ ) { - uint32_t rate; - int id; - int j; - id = le2me_16(*(uint16_t*)ptr); - ptr += sizeof(uint16_t); - if (ptr > &buffer[size]) goto len_err_out; - memcpy(&rate, ptr, sizeof(uint32_t));// workaround unaligment bug on sparc - ptr += sizeof(uint32_t); - if (ptr > &buffer[size]) goto len_err_out; - rate = le2me_32(rate); - MSG_V(" stream id=[0x%x][%u]\n", id, id); - MSG_V(" max bitrate=[0x%x][%u]\n", rate, rate); - for (j = 0; j < asf_ctrl->n_video; j++) { - if (id == asf_ctrl->video_streams[j]) { - MSG_V(" is video stream\n"); - v_rates[j] = rate; - break; - } - } - for (j = 0; j < asf_ctrl->n_audio; j++) { - if (id == asf_ctrl->audio_streams[j]) { - MSG_V( " is audio stream\n"); - a_rates[j] = rate; - break; - } - } - } - } - delete buffer; - - // automatic stream selection based on bandwidth - if (bw == 0) bw = INT_MAX; - MSG_V( "Max bandwidth set to %d\n", bw); - - if (asf_ctrl->n_audio) { - // find lowest-bitrate audio stream - a_rate = a_rates[0]; - a_idx = 0; - for (i = 0; i < asf_ctrl->n_audio; i++) { - if (a_rates[i] < a_rate) { - a_rate = a_rates[i]; - a_idx = i; - } - } - if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) { - // both audio and video are not possible, try video only next - a_idx = -1; - a_rate = 0; - } - } - // find best video stream - v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate); - if (v_idx >= 0) v_rate = v_rates[v_idx]; - // find best audio stream - a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate); - - delete v_rates; - delete a_rates; - - if (a_idx < 0 && v_idx < 0) { - MSG_FATAL( "bandwidth too small, file cannot be played!\n"); - return MPXP_False; - } - - // a audio stream was forced - if (mp_conf.audio_id > 0) asf_ctrl->audio_id = mp_conf.audio_id; - else if (a_idx >= 0) asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx]; - else if (asf_ctrl->n_audio) { - MSG_WARN( "bandwidth too small, deselected audio stream\n"); - mp_conf.audio_id = -2; - } - - // a video stream was forced - if (mp_conf.video_id > 0) asf_ctrl->video_id = mp_conf.video_id; - else if (v_idx >= 0) asf_ctrl->video_id = asf_ctrl->video_streams[v_idx]; - else if (asf_ctrl->n_video) { - MSG_WARN( "bandwidth too small, deselected video stream\n"); - mp_conf.video_id = -2; - } - return MPXP_Ok; - -len_err_out: - MSG_FATAL( "Invalid length in ASF header!\n"); - if (buffer) delete buffer; - if (v_rates) delete v_rates; - if (a_rates) delete a_rates; - return MPXP_False; -} - -static int -asf_http_networking_read( Tcp& tcp, char *buffer, int size, networking_t& networking ) { - static ASF_stream_chunck_t chunk; - int read,chunk_size = 0; - static int rest = 0, drop_chunk = 0, waiting = 0; - asf_http_networking_t* asf_http_ctrl = (asf_http_networking_t*)networking.data; - - while(1) { - if (rest == 0 && waiting == 0) { - read = 0; - while(read < (int)sizeof(ASF_stream_chunck_t)){ - int r = nop_networking_read( tcp, ((char*)&chunk) + read, - sizeof(ASF_stream_chunck_t)-read, - networking ); - if(r <= 0){ - if( r < 0) - MSG_ERR("Error while reading chunk header\n"); - return -1; - } - read += r; - } - - // Endian handling of the stream chunk - le2me_ASF_stream_chunck_t(&chunk); - chunk_size = asf_networking( &chunk, &drop_chunk ); - if(chunk_size < 0) { - MSG_ERR("Error while parsing chunk header\n"); - return -1; - } - chunk_size -= sizeof(ASF_stream_chunck_t); - - if(chunk.type != ASF_STREAMING_HEADER && (!drop_chunk)) { - if (asf_http_ctrl->packet_size < chunk_size) { - MSG_ERR("Error chunk_size > packet_size\n"); - return -1; - } - waiting = asf_http_ctrl->packet_size; - } else { - waiting = chunk_size; - } - - } else if (rest){ - chunk_size = rest; - rest = 0; - } - - read = 0; - if ( waiting >= chunk_size) { - if (chunk_size > size){ - rest = chunk_size - size; - chunk_size = size; - } - while(read < chunk_size) { - int got = nop_networking_read( tcp,buffer+read,chunk_size-read,networking ); - if(got <= 0) { - if(got < 0) - MSG_ERR("Error while reading chunk\n"); - return -1; - } - read += got; - } - waiting -= read; - if (drop_chunk) continue; - } - if (rest == 0 && waiting > 0 && size-read > 0) { - int s = MIN(waiting,size-read); - memset(buffer+read,0,s); - waiting -= s; - read += s; - } - break; - } - - return read; -} - -static int -asf_http_networking_seek( Tcp& tcp, off_t pos, networking_t& networking ) { - UNUSED(tcp); - UNUSED(pos); - UNUSED(networking); - return -1; -} - -static int -asf_header_check( HTTP_Header& http_hdr ) { - ASF_obj_header_t *objh; - if( http_hdr.get_body()==NULL || http_hdr.get_body_size()<sizeof(ASF_obj_header_t) ) return -1; - - objh = (ASF_obj_header_t*)http_hdr.get_body(); - if( ASF_LOAD_GUID_PREFIX(objh->guid)==0x75B22630 ) return 0; - return -1; -} - -static ASF_StreamType_e -asf_http_networking_type(const char *content_type,const char *features, HTTP_Header& 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") || // New in Corona, first request - !strcasecmp(content_type, "application/x-mms-framed") || // New in Corana, second request - !strcasecmp(content_type, "video/x-ms-asf")) { - - if( strstr(features, "broadcast") ) { - MSG_V("=====> ASF Live stream\n"); - return ASF_Live_e; - } else { - MSG_V("=====> ASF Prerecorded\n"); - return ASF_Prerecorded_e; - } - } else { - // Ok in a perfect world, web servers should be well configured - // so we could used mime type to know the stream type, - // but guess what? All of them are not well configured. - // So we have to check for an asf header :(, but it works :p - if( http_hdr.get_body_size()>sizeof(ASF_obj_header_t) ) { - if( asf_header_check( http_hdr )==0 ) { - MSG_V("=====> ASF Plain text\n"); - return ASF_PlainText_e; - } else if( (!strcasecmp(content_type, "text/html")) ) { - MSG_V("=====> HTML, mplayer is not a browser...yet!\n"); - return ASF_Unknown_e; - } else { - MSG_V("=====> ASF Redirector\n"); - return ASF_Redirector_e; - } - } else { - if( (!strcasecmp(content_type, "audio/x-ms-wax")) || - (!strcasecmp(content_type, "audio/x-ms-wma")) || - (!strcasecmp(content_type, "video/x-ms-asf")) || - (!strcasecmp(content_type, "video/x-ms-afs")) || - (!strcasecmp(content_type, "video/x-ms-wvx")) || - (!strcasecmp(content_type, "video/x-ms-wmv")) || - (!strcasecmp(content_type, "video/x-ms-wma")) ) { - MSG_ERR("=====> ASF Redirector\n"); - return ASF_Redirector_e; - } else if( !strcasecmp(content_type, "text/plain") ) { - MSG_V("=====> ASF Plain text\n"); - return ASF_PlainText_e; - } else { - MSG_V("=====> ASF unknown content-type: %s\n", content_type ); - return ASF_Unknown_e; - } - } - } - return ASF_Unknown_e; -} - -static HTTP_Header* asf_http_request(networking_t& networking) { - HTTP_Header* http_hdr = new(zeromem) HTTP_Header; - URL *url = NULL; - URL *server_url = NULL; - asf_http_networking_t* asf_http_ctrl; - char str[250]; - char *ptr; - int i, enable; - - int offset_hi=0, offset_lo=0, length=0; - int asf_nb_stream=0, stream_id; - - // Sanity check - url = networking.url; - asf_http_ctrl = (asf_http_networking_t*)networking.data; - if( url==NULL || asf_http_ctrl==NULL ) return NULL; - - // Common header for all requests. - http_hdr->set_field("Accept: */*" ); - http_hdr->set_field("User-Agent: NSPlayer/4.1.0.3856" ); - http_hdr->add_basic_authentication(url->username?url->username:"", url->password?url->password:"" ); - - // Check if we are using a proxy - if( !strcasecmp( url->protocol, "http_proxy" ) ) { - server_url = url_new( (url->file)+1 ); - if( server_url==NULL ) { - MSG_ERR("Invalid proxy URL\n"); - delete http_hdr; - return NULL; - } - http_hdr->set_uri(server_url->url ); - sprintf( str, "Host: %.220s:%d", server_url->hostname, server_url->port ); - delete server_url; - } else { - http_hdr->set_uri(url->file ); - sprintf( str, "Host: %.220s:%d", url->hostname, url->port ); - } - - http_hdr->set_field(str ); - http_hdr->set_field("Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" ); - sprintf(str, - "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u", - offset_hi, offset_lo, asf_http_ctrl->request, length ); - http_hdr->set_field( str ); - - switch( asf_http_ctrl->networking_type ) { - case ASF_Live_e: - case ASF_Prerecorded_e: - http_hdr->set_field("Pragma: xPlayStrm=1" ); - ptr = str; - ptr += sprintf( ptr, "Pragma: stream-switch-entry="); - if(asf_http_ctrl->n_audio > 0) { - for( i=0; i<asf_http_ctrl->n_audio ; i++ ) { - stream_id = asf_http_ctrl->audio_streams[i]; - if(stream_id == asf_http_ctrl->audio_id) { - enable = 0; - } else { - enable = 2; - continue; - } - asf_nb_stream++; - ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable); - } - } - if(asf_http_ctrl->n_video > 0) { - for( i=0; i<asf_http_ctrl->n_video ; i++ ) { - stream_id = asf_http_ctrl->video_streams[i]; - if(stream_id == asf_http_ctrl->video_id) { - enable = 0; - } else { - enable = 2; - continue; - } - asf_nb_stream++; - ptr += sprintf(ptr, "ffff:%d:%d ", stream_id, enable); - } - } - http_hdr->set_field(str ); - sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream ); - http_hdr->set_field( str ); - break; - case ASF_Redirector_e: - break; - case ASF_Unknown_e: - // First request goes here. - break; - default: - MSG_ERR("Unknown asf stream type\n"); - } - - http_hdr->set_field("Connection: Close" ); - http_hdr->build_request( ); - - return http_hdr; -} - -static int -asf_http_parse_response(asf_http_networking_t& asf_http_ctrl, HTTP_Header& http_hdr ) { - const char *content_type, *pragma; - char features[64] = "\0"; - size_t len; - if( http_hdr.response_parse()<0 ) { - MSG_ERR("Failed to parse HTTP response\n"); - return -1; - } - switch( http_hdr.get_status()) { - case 200: - break; - case 401: // Authentication required - return ASF_Authenticate_e; - default: - MSG_ERR("Server return %d:%s\n", http_hdr.get_status(), http_hdr.get_reason_phrase()); - return -1; - } - - content_type = http_hdr.get_field("Content-Type"); - - pragma = http_hdr.get_field("Pragma"); - while( pragma!=NULL ) { - const char *comma_ptr=NULL; - const char *end; - // The pragma line can get severals attributes - // separeted with a comma ','. - do { - if( !strncasecmp( pragma, "features=", 9) ) { - pragma += 9; - end = strstr( pragma, "," ); - if( end==NULL ) { - size_t s = strlen(pragma); - if(s > sizeof(features)) { - MSG_WARN("ASF HTTP PARSE WARNING : Pragma %s cuted from %d bytes to %d\n",pragma,s,sizeof(features)); - len = sizeof(features); - } else { - len = s; - } - } else { - len = MIN((unsigned int)(end-pragma),sizeof(features)); - } - strncpy( features, pragma, len ); - features[len]='\0'; - break; - } - comma_ptr = strstr( pragma, "," ); - if( comma_ptr!=NULL ) { - pragma = comma_ptr+1; - if( pragma[0]==' ' ) pragma++; - } - } while( comma_ptr!=NULL ); - pragma = http_hdr.get_next_field(); - } - asf_http_ctrl.networking_type = asf_http_networking_type( content_type, features, http_hdr ); - return 0; -} - -static MPXP_Rc asf_http_networking_start(Tcp& tcp, networking_t& networking) { - HTTP_Header *http_hdr=NULL; - URL *url = networking.url; - asf_http_networking_t* asf_http_ctrl; - uint8_t buffer[BUFFER_SIZE]; - int i, ret; - int done; - int auth_retry = 0; - - asf_http_ctrl = new(zeromem) asf_http_networking_t; - if( asf_http_ctrl==NULL ) { - MSG_FATAL("Memory allocation failed\n"); - return MPXP_False; - } - asf_http_ctrl->networking_type = ASF_Unknown_e; - asf_http_ctrl->request = 1; - asf_http_ctrl->audio_streams = asf_http_ctrl->video_streams = NULL; - asf_http_ctrl->n_audio = asf_http_ctrl->n_video = 0; - networking.data = asf_http_ctrl; - - do { - done = 1; - tcp.close(); - - if( !strcasecmp( url->protocol, "http_proxy" ) ) { - if( url->port==0 ) url->port = 8080; - } else { - if( url->port==0 ) url->port = 80; - } - tcp.open(url->hostname, url->port, Tcp::IP4); - if( !tcp.established()) return MPXP_False; - - http_hdr = asf_http_request( networking ); - MSG_DBG2("Request [%s]\n", http_hdr->get_buffer() ); - for(i=0; i < (int)http_hdr->get_buffer_size() ; ) { - int r = tcp.write((uint8_t*)(http_hdr->get_buffer()+i), http_hdr->get_buffer_size()-i); - if(r<0) { - MSG_ERR("Socket write error : %s\n",strerror(errno)); - return MPXP_False; - } - i += r; - } - delete http_hdr; - http_hdr = new(zeromem) HTTP_Header; - do { - i = tcp.read(buffer, BUFFER_SIZE); - if( i<=0 ) { - perror("read"); - delete http_hdr; - return MPXP_False; - } - http_hdr->response_append(buffer,i); - } while( !http_hdr->is_header_entire()); - if( mp_conf.verbose>0 ) { - MSG_DBG2("Response [%s]\n", http_hdr->get_buffer() ); - } - ret = asf_http_parse_response(*asf_http_ctrl, *http_hdr); - if( ret<0 ) { - MSG_ERR("Failed to parse header\n"); - delete http_hdr; - return MPXP_False; - } - switch( asf_http_ctrl->networking_type ) { - case ASF_Live_e: - case ASF_Prerecorded_e: - case ASF_PlainText_e: - if( http_hdr->get_body_size()>0 ) { - if( networking_bufferize( networking, (unsigned char *)(http_hdr->get_body()), http_hdr->get_body_size())<0 ) { - delete http_hdr; - return MPXP_False; - } - } - if( asf_http_ctrl->request==1 ) { - if( asf_http_ctrl->networking_type!=ASF_PlainText_e ) { - // First request, we only got the ASF header. - ret = asf_networking_parse_header(tcp,networking); - if(ret < 0) return MPXP_False; - if(asf_http_ctrl->n_audio == 0 && asf_http_ctrl->n_video == 0) { - MSG_ERR("No stream found\n"); - return MPXP_False; - } - asf_http_ctrl->request++; - done = 0; - } else done = 1; - } - break; - case ASF_Redirector_e: - if( http_hdr->get_body_size()>0 ) { - if( networking_bufferize( networking, (unsigned char*)http_hdr->get_body(), http_hdr->get_body_size())<0 ) { - delete http_hdr; - return MPXP_False; - } - } -// type |= STREAMTYPE_TEXT; - done = 1; - break; - case ASF_Authenticate_e: - if( http_authenticate( *http_hdr, url, &auth_retry)<0 ) return MPXP_False; - asf_http_ctrl->networking_type = ASF_Unknown_e; - done = 0; - break; - case ASF_Unknown_e: - default: - MSG_ERR("Unknown ASF networking type\n"); - tcp.close(); - delete http_hdr; - return MPXP_False; - } - // Check if we got a redirect. - } while(!done); - - if( asf_http_ctrl->networking_type==ASF_PlainText_e || asf_http_ctrl->networking_type==ASF_Redirector_e ) { - networking.networking_read = nop_networking_read; - networking.networking_seek = nop_networking_seek; - } else { - networking.networking_read = asf_http_networking_read; - networking.networking_seek = asf_http_networking_seek; - networking.buffering = 1; - } - networking.status = networking_playing_e; - - delete http_hdr; - return MPXP_Ok; -} - -asf_http_networking_t::asf_http_networking_t() {} -asf_http_networking_t::~asf_http_networking_t() {} \ No newline at end of file Deleted: mplayerxp/libmpstream2/asf_streaming.h =================================================================== --- mplayerxp/libmpstream2/asf_streaming.h 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/asf_streaming.h 2012-12-17 17:03:47 UTC (rev 570) @@ -1,39 +0,0 @@ -#ifndef __ASF_STEAMING_H_INCLUDED -#define __ASF_STEAMING_H_INCLUDED 1 -#include "mp_config.h" -#include "osdep/mplib.h" -using namespace mpxp; - -#include "stream.h" - -struct networking_t; -namespace mpxp { - class Tcp; -} - -// Definition of the differents type of ASF streaming -enum ASF_StreamType_e { - ASF_Unknown_e, - ASF_Live_e, - ASF_Prerecorded_e, - ASF_Redirector_e, - ASF_PlainText_e, - ASF_Authenticate_e -}; - -struct asf_http_networking_t : public Opaque { - public: - asf_http_networking_t(); - virtual ~asf_http_networking_t(); - - ASF_StreamType_e networking_type; - int request; - int packet_size; - int *audio_streams,n_audio,*video_streams,n_video; - int audio_id, video_id; -}; - -extern MPXP_Rc asf_networking_start(Tcp& fd, networking_t& networking); -extern MPXP_Rc asf_mmst_networking_start(Tcp& fd, networking_t& networking); - -#endif Modified: mplayerxp/libmpstream2/http.cpp =================================================================== --- mplayerxp/libmpstream2/http.cpp 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/http.cpp 2012-12-17 17:03:47 UTC (rev 570) @@ -16,7 +16,9 @@ #include "http.h" #include "url.h" +#include "help_mp.h" #include "stream_msg.h" +#include "network.h" namespace mpxp { HTTP_Header::HTTP_Header() {} @@ -300,6 +302,57 @@ MSG_V("--- HTTP DEBUG HEADER --- END ---\n"); } +int HTTP_Header::authenticate(URL *url, int *auth_retry) { + const char *aut; + + if( *auth_retry==1 ) { + MSG_ERR(MSGTR_ConnAuthFailed); + return -1; + } + if( *auth_retry>0 ) { + if( url->username ) { + delete url->username ; + url->username = NULL; + } + if( url->password ) { + delete url->password ; + url->password = NULL; + } + } + + aut = get_field("WWW-Authenticate"); + if( aut!=NULL ) { + const char *aut_space; + aut_space = strstr(aut, "realm="); + if( aut_space!=NULL ) aut_space += 6; + MSG_INFO("Authentication required for %s\n", aut_space); + } else { + MSG_INFO("Authentication required\n"); + } + if( net_conf.username ) { + url->username = mp_strdup(net_conf.username); + if( url->username==NULL ) { + MSG_FATAL(MSGTR_OutOfMemory); + return -1; + } + } else { + MSG_ERR(MSGTR_ConnAuthFailed); + return -1; + } + if( net_conf.password ) { + url->password = mp_strdup(net_conf.password); + if( url->password==NULL ) { + MSG_FATAL(MSGTR_OutOfMemory); + return -1; + } + } else { + MSG_INFO("No password provided, trying blank password\n"); + } + (*auth_retry)++; + return 0; +} + + int base64_encode(const any_t*enc, int encLen, char *out, int outMax) { static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; Modified: mplayerxp/libmpstream2/http.h =================================================================== --- mplayerxp/libmpstream2/http.h 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/http.h 2012-12-17 17:03:47 UTC (rev 570) @@ -12,6 +12,8 @@ #include <vector> #include <stdint.h> +#include "url.h" + namespace mpxp { class HTTP_Header : public Opaque { public: @@ -28,6 +30,7 @@ virtual void set_method(const std::string& method ); virtual void set_uri(const std::string& uri ); virtual int add_basic_authentication(const std::string& username, const std::string& password ); + virtual int authenticate(URL *url, int *auth_retry); virtual void debug_hdr(); virtual void cookies_set(const std::string& hostname, const std::string& url); Modified: mplayerxp/libmpstream2/network.cpp =================================================================== --- mplayerxp/libmpstream2/network.cpp 2012-12-17 12:05:45 UTC (rev 569) +++ mplayerxp/libmpstream2/network.cpp 2012-12-17 17:03:47 UTC (rev 570) @@ -19,7 +19,13 @@ #include <ctype.h> #include "mplayerxp.h" -#include "asf_streaming.h" +#include "network_asf.h" +#include "network_asf_mmst.h" +#include "network_nop.h" +#include "network_pnm.h" +#include "network_real_rtsp.h" +#include "network_rtp.h" +#include "network_rtsp.h" #ifndef HAVE_WINSOCK2 #define closesocket close #else @@ -27,8 +33,8 @@ #include <ws2tcpip.h> #endif -#include "stream.h" #include "libmpconf/cfgparser.h" +#include "stream.h" #include "help_mp.h" #include "tcp.h" @@ -37,14 +43,10 @@ #include "cookies.h" #include "url.h" #include "udp.h" -#include "pnm.h" -#ifndef STREAMING_LIVE_DOT_COM -#include "rtp.h" -#endif -#include "librtsp/rtsp_session.h" #include "version.h" #include "stream_msg.h" +namespace mpxp { /* Variables for the command line option -user, -passwd & -bandwidth */ net_config_t::net_config_t() :username(NULL), @@ -60,19 +62,6 @@ net_config_t::~net_config_t() {} net_config_t net_conf; -networking_t* new_networking() { - networking_t* networking = new(zeromem) networking_t; - networking->mime="application/octet-stream"; - return networking; -} - -void free_networking( networking_t& networking ) { - if( networking.url ) delete networking.url; - if( networking.buffer ) delete networking.buffer ; - if( networking.data ) delete networking.data ; - delete &networking; -} - URL* check4proxies( URL *url ) { URL *url_out = NULL; @@ -225,58 +214,7 @@ return http_hdr; } -int -http_authenticate(HTTP_Header& http_hdr, URL *url, int *auth_retry) { - const char *aut; - - if( *auth_retry==1 ) { - MSG_ERR(MSGTR_ConnAuthFailed); - return -1; - } - if( *auth_retry>0 ) { - if( url->username ) { - delete url->username ; - url->username = NULL; - } - if( url->password ) { - delete url->password ; - url->password = NULL; - } - } - - aut = http_hdr.get_field("WWW-Authenticate"); - if( aut!=NULL ) { - const char *aut_space; - aut_space = strstr(aut, "realm="); - if( aut_space!=NULL ) aut_space += 6; - MSG_INFO("Authentication required for %s\n", aut_space); - } else { - MSG_INFO("Authentication required\n"); - } - if( net_conf.username ) { - url->username = mp_strdup(net_conf.username); - if( url->username==NULL ) { - MSG_FATAL(MSGTR_OutOfMemory); - return -1; - } - } else { - MSG_ERR(MSGTR_ConnAuthFailed); - return -1; - } - if( net_conf.password ) { - url->password = mp_strdup(net_conf.password); - if( url->password==NULL ) { - MSG_FATAL(MSGTR_OutOfMemory); - return -1; - } - } else { - MSG_INFO("No password provided, trying blank password\n"); - } - (*auth_retry)++; - return 0; -} - -off_t http_seek(Tcp& tcp, networking_t& networking, off_t pos ) { +off_t http_seek(Tcp& tcp, Networking& networking, off_t pos ) { HTTP_Header* http_hdr = NULL; tcp.close(); @@ -292,7 +230,7 @@ MSG_V("Content-Type: [%s]\n", http_hdr->get_field("Content-Type") ); MSG_V("Content-Length: [%s]\n", http_hdr->get_field("Content-Length") ); if( http_hdr->get_body_size()>0 ) { - if( networking_bufferize( networking, (unsigned char *)http_hdr->get_body(), http_hdr->get_body_size() )<0 ) { + if( networking.bufferize((unsigned char *)http_hdr->get_body(), http_hdr->get_body_size() )<0 ) { delete http_hdr; return 0; } @@ -311,9 +249,18 @@ return pos; } +Networking::Networking() + :mime("application/octet-stream") {} + +Networking::~Networking() { + if( url ) delete url; + if( buffer ) delete buffer ; + if( data ) delete data ; +} + // By using the protocol, the extension of the file or the content-type // we might be able to guess the networking type. -static MPXP_Rc autodetectProtocol(networking_t& networking, Tcp& tcp) { +MPXP_Rc Networking::autodetectProtocol(network_protocol_t& networking, Tcp& tcp) { HTTP_Header *http_hdr=NULL; int redirect; int auth_retry=0; @@ -432,7 +379,7 @@ } break; case 401: // Authentication required - if( http_authenticate(*http_hdr,url, &auth_retry)<0 ) goto err_out; + if( http_hdr->authenticate(url, &auth_retry)<0 ) goto err_out; redirect = 1; break; default: @@ -450,301 +397,72 @@ return MPXP_False; } -int -networking_bufferize( networking_t& networking,unsigned char *buffer, int size) { +int Networking::bufferize(unsigned char *_buffer, int size) { //printf("networking_bufferize\n"); - networking.buffer = new char [size]; - if( networking.buffer==NULL ) { + buffer = new char [size]; + if( buffer==NULL ) { MSG_FATAL(MSGTR_OutOfMemory); return -1; } - memcpy( networking.buffer, buffer, size ); - networking.buffer_size = size; + memcpy( buffer, _buffer, size ); + buffer_size = size; return size; } -int -nop_networking_read(Tcp& tcp, char *buffer, int size, networking_t& stream_ctrl ) { - int len=0; -//printf("nop_networking_read\n"); - if( stream_ctrl.buffer_size!=0 ) { - int buffer_len = stream_ctrl.buffer_size-stream_ctrl.buffer_pos; -//printf("%d bytes in buffer\n", stream_ctrl.buffer_size); - len = (size<buffer_len)?size:buffer_len; - memcpy( buffer, (stream_ctrl.buffer)+(stream_ctrl.buffer_pos), len ); - stream_ctrl.buffer_pos += len; -//printf("buffer_pos = %d\n", stream_ctrl.buffer_pos ); - if( stream_ctrl.buffer_pos>=stream_ctrl.buffer_size ) { - delete stream_ctrl.buffer ; - stream_ctrl.buffer = NULL; - stream_ctrl.buffer_size = 0; - stream_ctrl.buffer_pos = 0; -//printf("buffer cleaned\n"); - } -//printf("read %d bytes from buffer\n", len ); - } - if( len<size ) { - int ret; - ret = tcp.read((uint8_t*)(buffer+len), size-len); - if( ret<0 ) { - MSG_ERR("nop_networking_read error : %s\n",strerror(errno)); - } - len += ret; -//printf("read %d bytes from network\n", len ); - } - return len; -} - -int -nop_networking_seek(Tcp& tcp, off_t pos, networking_t& n ) { - UNUSED(tcp); - UNUSED(pos); - UNUSED(n); - return -1; -} - -MPXP_Rc nop_networking_start(Tcp& tcp,networking_t& networking ) { - HTTP_Header *http_hdr = NULL; - const char *next_url=NULL; - URL *rd_url=NULL; - MPXP_Rc ret; - - if( !tcp.established() ) { - http_send_request(tcp, networking.url,0); - if( !tcp.established() ) return MPXP_False; - http_hdr = http_read_response(tcp); - if( http_hdr==NULL ) return MPXP_False; - - switch( http_hdr->get_status() ) { - case 200: // OK - MSG_V("Content-Type: [%s]\n", http_hdr->get_field("Content-Type") ); - MSG_V("Content-Length: [%s]\n", http_hdr->get_field("Content-Length") ); - if( http_hdr->get_body_size()>0 ) { - if( networking_bufferize( networking, (unsigned char *)http_hdr->get_body(), http_hdr->get_body_size() )<0 ) { - delete http_hdr; - return MPXP_False; - } - } - break; - // Redirect - case 301: // Permanently - case 302: // Temporarily - ret=MPXP_False; - next_url = http_hdr->get_field("Location" ); - - if (next_url != NULL) - rd_url=url_new(next_url); - - if (next_url != NULL && rd_url != NULL) { - MSG_STATUS("Redirected: Using this url instead %s\n",next_url); - networking.url=check4proxies(rd_url); - ret=nop_networking_start(tcp,networking); //recursively get networking started - } else { - MSG_ERR("Redirection failed\n"); - tcp.close(); - } - return ret; - break; - case 401: //Authorization required - case 403: //Forbidden - case 404: //Not found - case 500: //Server Error - default: - MSG_ERR("Server return %d: %s\n", http_hdr->get_status(), http_hdr->get_reason_phrase()); - tcp.close(); - return MPXP_False; - break; - } - } else { - http_hdr = (HTTP_Header*)networking.data; - if( http_hdr->get_body_size()>0 ) { - if( networking_bufferize( networking, (unsigned char*)http_hdr->get_body(), http_hdr->get_body_size() )<0 ) { - delete http_hdr; - networking.data = NULL; - return MPXP_False; - } - } - } - - if( http_hdr ) { - delete http_hdr; - networking.data = NULL; - } - - networking.networking_read = nop_networking_read; - networking.networking_seek = nop_networking_seek; - networking.prebuffer_size = 64*1024; // KBytes - networking.buffering = 1; - networking.status = networking_playing_e; - return MPXP_Ok; -} - -void fixup_network_stream_cache(networking_t& networking) { - if(networking.buffering) { +void Networking::fixup_cache() { + if(buffering) { if(mp_conf.s_cache_size<0) { // cache option not set, will use our computed value. // buffer in KBytes, *5 because the prefill is 20% of the buffer. - mp_conf.s_cache_size = (networking.prebuffer_size/1024)*5; + mp_conf.s_cache_size = (prebuffer_size/1024)*5; if( mp_conf.s_cache_size<64 ) mp_conf.s_cache_size = 64; // 16KBytes min buffer } MSG_INFO("[network] cache size set to: %i\n", mp_conf.s_cache_size); } } -int -pnm_networking_read(Tcp& tcp, char *buffer, int size, networking_t& stream_ctrl ) { - Pnm& pnm=*static_cast<Pnm*>(stream_ctrl.data); - UNUSED(tcp); - return pnm.read(buffer, size); -} +Networking* Networking::start(Tcp& tcp, URL *_url) { + Networking* rc; + network_protocol_t net_protocol; + URL* url = check4proxies( _url ); -MPXP_Rc pnm_networking_start(Tcp& tcp,networking_t& networking ) { - Pnm* pnm = new(zeromem) Pnm(tcp); + net_protocol.url=url; - tcp.open(networking.url->hostname, - networking.url->port ? networking.url->port : 7070); - if(!tcp.established()) return MPXP_False; + if( autodetectProtocol(net_protocol,tcp)!=MPXP_Ok ) return NULL; + rc = NULL; + url=net_protocol.url; - if(pnm->connect(networking.url->file)!=MPXP_Ok) { - delete pnm; - return MPXP_NA; - } - networking.data=pnm; - networking.networking_read = pnm_networking_read; - networking.prebuffer_size = 8*1024; // 8 KBytes - networking.buffering = 1; - networking.status = networking_playing_e; - return MPXP_Ok; -} - -int -realrts... [truncated message content] |