903
|
1 /*
|
|
2 * Network layer for MPlayer
|
|
3 * by Bertrand BAUDET <bertrand_baudet@yahoo.com>
|
|
4 * (C) 2001, MPlayer team.
|
|
5 */
|
|
6
|
833
|
7 #include <unistd.h>
|
841
|
8 #include <netinet/in.h>
|
|
9 #include <netdb.h>
|
833
|
10 #include <sys/types.h>
|
|
11 #include <sys/socket.h>
|
903
|
12 #include <arpa/inet.h>
|
833
|
13
|
903
|
14 #include <ctype.h>
|
|
15 #include <string.h>
|
|
16 #include <stdlib.h>
|
833
|
17 #include <stdio.h>
|
|
18
|
841
|
19 #include "network.h"
|
903
|
20 #include "http.h"
|
|
21 #include "url.h"
|
|
22 #include "asf.h"
|
841
|
23
|
903
|
24 // Connect to a server using a TCP connection
|
833
|
25 int
|
|
26 connect2Server(char *host, int port) {
|
|
27 int socket_server_fd;
|
|
28 struct sockaddr_in server_address;
|
903
|
29 printf("Connecting to server %s:%d ...\n", host, port );
|
833
|
30 socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
31 if( socket_server_fd==-1 ) {
|
|
32 perror("Failed to create socket");
|
841
|
33 return -1;
|
833
|
34 }
|
|
35
|
|
36 if( isalpha(host[0]) ) {
|
841
|
37 struct hostent *hp =(struct hostent*)gethostbyname( host );
|
|
38 if( hp==NULL ) {
|
833
|
39 printf("Unknown host: %s\n", host);
|
841
|
40 return -1;
|
833
|
41 }
|
841
|
42 memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length );
|
833
|
43 } else {
|
|
44 inet_pton(AF_INET, host, &server_address.sin_addr);
|
|
45 }
|
|
46 server_address.sin_family=AF_INET;
|
|
47 server_address.sin_port=htons(port);
|
|
48
|
|
49 if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) {
|
|
50 perror("Failed to connect to server");
|
841
|
51 close(socket_server_fd);
|
|
52 return -1;
|
833
|
53 }
|
|
54 return socket_server_fd;
|
|
55 }
|
|
56
|
903
|
57 // By using the protocol, the extension of the file or the content-type
|
|
58 // we might be able to guess the streaming type.
|
|
59 int
|
|
60 autodetectProtocol(URL_t *url, int *fd_out) {
|
|
61 HTTP_header_t *http_hdr;
|
|
62 int fd=-1;
|
|
63 int i;
|
|
64 char *extension;
|
|
65 char *content_type;
|
|
66 char *next_url;
|
|
67 char response[1024];
|
|
68
|
|
69 redo_request:
|
|
70 *fd_out=-1;
|
|
71 next_url = NULL;
|
|
72 extension = NULL;
|
|
73 content_type = NULL;
|
|
74
|
|
75 if( url==NULL ) return STREAMING_TYPE_UNKNOWN;
|
|
76
|
|
77 // Get the extension of the file if present
|
|
78 if( url->file!=NULL ) {
|
|
79 for( i=strlen(url->file) ; i>0 ; i-- ) {
|
|
80 if( url->file[i]=='.' ) {
|
|
81 extension=(url->file)+i+1;
|
|
82 break;
|
|
83 }
|
|
84 }
|
|
85 }
|
|
86
|
|
87 if( extension!=NULL ) {
|
|
88 printf("Extension: %s\n", extension );
|
|
89 if( !strcasecmp(extension, "asf") ||
|
|
90 !strcasecmp(extension, "wmv") ||
|
|
91 !strcasecmp(extension, "asx") ) {
|
|
92 if( url->port==0 ) url->port = 80;
|
|
93 return STREAMING_TYPE_ASF;
|
|
94 }
|
|
95 }
|
|
96
|
|
97 // Checking for RTSP
|
|
98 if( !strcasecmp(url->protocol, "rtsp") ) {
|
|
99 printf("RTSP protocol not yet implemented!\n");
|
|
100 return STREAMING_TYPE_UNKNOWN;
|
|
101 }
|
|
102
|
|
103 // Checking for ASF
|
|
104 if( !strcasecmp(url->protocol, "mms") ) {
|
|
105 if( url->port==0 ) url->port = 80;
|
|
106 return STREAMING_TYPE_ASF;
|
|
107 }
|
|
108
|
|
109 // HTTP based protocol
|
|
110 if( !strcasecmp(url->protocol, "http") ) {
|
|
111 if( url->port==0 ) url->port = 80;
|
|
112
|
|
113 http_hdr = http_new_header();
|
|
114 http_set_uri( http_hdr, url->file );
|
|
115 http_set_field( http_hdr, "User-Agent: MPlayer");
|
|
116 http_set_field( http_hdr, "Connection: closed");
|
|
117 if( http_build_request( http_hdr )==NULL ) {
|
|
118 return STREAMING_TYPE_UNKNOWN;
|
|
119 }
|
|
120
|
|
121 fd = connect2Server( url->hostname, url->port );
|
|
122 if( fd<0 ) {
|
|
123 *fd_out=-1;
|
|
124 return STREAMING_TYPE_UNKNOWN;
|
|
125 }
|
|
126 write( fd, http_hdr->buffer, http_hdr->buffer_size );
|
|
127 // http_free( http_hdr );
|
|
128
|
|
129 http_hdr = http_new_header();
|
|
130 if( http_hdr==NULL ) {
|
|
131 close( fd );
|
|
132 *fd_out=-1;
|
|
133 return STREAMING_TYPE_UNKNOWN;
|
|
134 }
|
|
135
|
|
136 do {
|
|
137 i = read( fd, response, 1024 );
|
|
138 http_response_append( http_hdr, response, i );
|
|
139 } while( !http_is_header_entired( http_hdr ) );
|
|
140 http_response_parse( http_hdr );
|
|
141
|
|
142 *fd_out=fd;
|
|
143 //http_debug_hdr( http_hdr );
|
|
144
|
|
145 // Check if the response is an ICY status_code reason_phrase
|
|
146 if( !strcasecmp(http_hdr->protocol, "ICY") ) {
|
|
147 // Ok, we have detected an mp3 streaming
|
|
148 return STREAMING_TYPE_MP3;
|
|
149 }
|
|
150
|
|
151 switch( http_hdr->status_code ) {
|
|
152 case 200: // OK
|
|
153 // Look if we can use the Content-Type
|
|
154 content_type = http_get_field( http_hdr, "Content-Type" );
|
|
155 if( content_type!=NULL ) {
|
|
156 printf("Content-Type: %s\n", content_type );
|
|
157 // Check for ASF
|
|
158 if( asf_http_streaming_type(content_type, NULL)!=ASF_Unknown_e ) {
|
|
159 return STREAMING_TYPE_ASF;
|
|
160 }
|
|
161 // Check for MP3 streaming
|
|
162 // Some MP3 streaming server answer with audio/mpeg
|
|
163 if( !strcasecmp(content_type, "audio/mpeg") ) {
|
|
164 return STREAMING_TYPE_MP3;
|
|
165 }
|
|
166 }
|
|
167 break;
|
|
168 // Redirect
|
|
169 case 301: // Permanently
|
|
170 case 302: // Temporarily
|
|
171 // RFC 2616, recommand to detect infinite redirection loops
|
|
172 next_url = http_get_field( http_hdr, "Location" );
|
|
173 if( next_url!=NULL ) {
|
|
174 close( fd );
|
|
175 url_free( url );
|
|
176 url_new( next_url );
|
|
177 goto redo_request;
|
|
178 }
|
|
179 //break;
|
|
180 default:
|
|
181 printf("Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase );
|
|
182 close( fd );
|
|
183 *fd_out=-1;
|
|
184 return STREAMING_TYPE_UNKNOWN;
|
|
185 }
|
|
186 }
|
|
187 return STREAMING_TYPE_UNKNOWN;
|
|
188 }
|
|
189
|
|
190
|
|
191 void
|
|
192 network_streaming() {
|
|
193 int ret;
|
|
194 /*
|
|
195 do {
|
|
196 ret = select( );
|
|
197
|
|
198 } while( );
|
|
199 */
|
|
200 }
|
|
201
|
|
202 int
|
|
203 streaming_start(URL_t **url, int fd, int streaming_type) {
|
|
204 switch( streaming_type ) {
|
|
205 case STREAMING_TYPE_ASF:
|
|
206 // Send a the appropriate HTTP request
|
|
207 if( fd>0 ) close( fd );
|
|
208 fd = asf_http_streaming_start( url );
|
|
209 break;
|
|
210 case STREAMING_TYPE_MP3:
|
|
211 // Nothing else to do the server is already feeding the pipe.
|
|
212 break;
|
|
213 case STREAMING_TYPE_UNKNOWN:
|
|
214 default:
|
|
215 printf("Unable to detect the streaming type\n");
|
|
216 close( fd );
|
|
217 return -1;
|
|
218 }
|
|
219
|
|
220 return fd;
|
|
221 }
|
|
222
|
|
223 int
|
|
224 streaming_stop( ) {
|
|
225
|
|
226 }
|