Mercurial > mplayer.hg
annotate libmpdemux/http.c @ 18150:710d4bc5f8c9
Using channel count, samplerate and input bps values from the container
instead of the decoder breaks some DTS samples where the container says
the audio has 6 channels but the decoder gives 2. In this case take the
number of channels from the decoder instead, the output will almost
certainly be badly garbled anyway if the number of channels is wrong.
patch by Uoti Urpala, uoti <<.>> urpala <<@>> pp1 <<.>> inet <<.>> fi
author | diego |
---|---|
date | Wed, 19 Apr 2006 20:12:01 +0000 |
parents | 16f2bcd5d148 |
children | 4928dd61f136 |
rev | line source |
---|---|
902 | 1 /* |
2 * HTTP Helper | |
3 * by Bertrand Baudet <bertrand_baudet@yahoo.com> | |
4 * (C) 2001, MPlayer team. | |
5 */ | |
6 | |
15614
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
7 #include "config.h" |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
8 |
870 | 9 #include <stdio.h> |
10 #include <stdlib.h> | |
11 #include <string.h> | |
15585 | 12 #include <unistd.h> |
870 | 13 |
15614
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
14 #ifndef HAVE_WINSOCK2 |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
15 #define closesocket close |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
16 #else |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
17 #include <winsock2.h> |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
18 #include <ws2tcpip.h> |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
19 #endif |
a4a46131ee71
Change header order to avoid compile error because of STREAM_SEEK
reimar
parents:
15585
diff
changeset
|
20 |
870 | 21 #include "http.h" |
4816
f1dea39a50bb
Fixed the http response parser when the http header only has the HTTP
bertrand
parents:
4311
diff
changeset
|
22 #include "url.h" |
5915 | 23 #include "mp_msg.h" |
870 | 24 |
15585 | 25 #include "stream.h" |
26 #include "demuxer.h" | |
27 #include "network.h" | |
28 #include "help_mp.h" | |
29 | |
30 | |
31 extern mime_struct_t mime_type_table[]; | |
32 extern int stream_cache_size; | |
33 extern int network_bandwidth; | |
34 | |
35 extern int http_seek(stream_t *stream, off_t pos); | |
36 | |
16013 | 37 typedef struct { |
38 unsigned metaint; | |
39 unsigned metapos; | |
40 int is_ultravox; | |
41 } scast_data_t; | |
42 | |
43 /** | |
44 * \brief first read any data from sc->buffer then from fd | |
45 * \param fd file descriptor to read data from | |
46 * \param buffer buffer to read into | |
47 * \param len how many bytes to read | |
48 * \param sc streaming control containing buffer to read from first | |
49 * \return len unless there is a read error or eof | |
50 */ | |
51 static unsigned my_read(int fd, char *buffer, int len, streaming_ctrl_t *sc) { | |
52 unsigned pos = 0; | |
53 unsigned cp_len = sc->buffer_size - sc->buffer_pos; | |
54 if (cp_len > len) | |
55 cp_len = len; | |
56 memcpy(buffer, &sc->buffer[sc->buffer_pos], cp_len); | |
57 sc->buffer_pos += cp_len; | |
58 pos += cp_len; | |
59 while (pos < len) { | |
16070 | 60 int ret = recv(fd, &buffer[pos], len - pos, 0); |
16013 | 61 if (ret <= 0) |
62 break; | |
63 pos += ret; | |
64 } | |
65 return pos; | |
66 } | |
67 | |
16032 | 68 /** |
69 * \brief read and process (i.e. discard *g*) a block of ultravox metadata | |
70 * \param fd file descriptor to read from | |
71 * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd | |
72 * \return number of real data before next metadata block starts or 0 on error | |
73 */ | |
16013 | 74 static unsigned uvox_meta_read(int fd, streaming_ctrl_t *sc) { |
75 unsigned metaint; | |
16070 | 76 unsigned char info[6] = {0, 0, 0, 0, 0, 0}; |
77 int info_read; | |
16013 | 78 do { |
16070 | 79 info_read = my_read(fd, info, 1, sc); |
16013 | 80 if (info[0] == 0x00) |
16070 | 81 info_read = my_read(fd, info, 6, sc); |
16013 | 82 else |
16070 | 83 info_read += my_read(fd, &info[1], 5, sc); |
84 if (info_read != 6) // read error or eof | |
85 return 0; | |
16031
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
86 // sync byte and reserved flags |
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
87 if (info[0] != 0x5a || (info[1] & 0xfc) != 0x00) { |
16013 | 88 mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid or unknown uvox metadata\n"); |
89 return 0; | |
90 } | |
16031
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
91 if (info[1] & 0x01) |
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
92 mp_msg(MSGT_DEMUXER, MSGL_WARN, "Encrypted ultravox data\n"); |
16013 | 93 metaint = info[4] << 8 | info[5]; |
16031
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
94 if ((info[3] & 0xf) < 0x07) { // discard any metadata nonsense |
16013 | 95 char *metabuf = malloc(metaint); |
96 my_read(fd, metabuf, metaint, sc); | |
97 free(metabuf); | |
98 } | |
16031
c2e78215f0d9
Ultravox improvements according to specs (didn't know they existed *g*)
reimar
parents:
16013
diff
changeset
|
99 } while ((info[3] & 0xf) < 0x07); |
16013 | 100 return metaint; |
101 } | |
102 | |
103 /** | |
104 * \brief read one scast meta data entry and print it | |
16032 | 105 * \param fd file descriptor to read from |
106 * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd | |
16013 | 107 */ |
108 static void scast_meta_read(int fd, streaming_ctrl_t *sc) { | |
109 unsigned char tmp = 0; | |
110 unsigned metalen; | |
111 my_read(fd, &tmp, 1, sc); | |
112 metalen = tmp * 16; | |
113 if (metalen > 0) { | |
114 char *info = (char *)malloc(metalen + 1); | |
115 unsigned nlen = my_read(fd, info, metalen, sc); | |
116 info[nlen] = 0; | |
117 mp_msg(MSGT_DEMUXER, MSGL_INFO, "\nICY Info: %s\n", info); | |
118 free(info); | |
119 } | |
120 } | |
121 | |
16032 | 122 /** |
123 * \brief read data from scast/ultravox stream without any metadata | |
124 * \param fd file descriptor to read from | |
125 * \param buffer buffer to read data into | |
126 * \param size number of bytes to read | |
127 * \param sc streaming_ctrl_t whose buffer is consumed before reading from fd | |
128 */ | |
16013 | 129 static int scast_streaming_read(int fd, char *buffer, int size, |
130 streaming_ctrl_t *sc) { | |
131 scast_data_t *sd = (scast_data_t *)sc->data; | |
132 unsigned block, ret; | |
133 unsigned done = 0; | |
134 | |
135 // first read remaining data up to next metadata | |
136 block = sd->metaint - sd->metapos; | |
137 if (block > size) | |
138 block = size; | |
139 ret = my_read(fd, buffer, block, sc); | |
140 sd->metapos += ret; | |
141 done += ret; | |
142 if (ret != block) // read problems or eof | |
143 size = done; | |
144 | |
145 while (done < size) { // now comes the metadata | |
146 if (sd->is_ultravox) | |
16070 | 147 { |
16013 | 148 sd->metaint = uvox_meta_read(fd, sc); |
16070 | 149 if (!sd->metaint) |
150 size = done; | |
151 } | |
16013 | 152 else |
153 scast_meta_read(fd, sc); // read and display metadata | |
154 sd->metapos = 0; | |
155 block = size - done; | |
156 if (block > sd->metaint) | |
157 block = sd->metaint; | |
158 ret = my_read(fd, &buffer[done], block, sc); | |
159 sd->metapos += ret; | |
160 done += ret; | |
161 if (ret != block) // read problems or eof | |
162 size = done; | |
163 } | |
164 return done; | |
165 } | |
166 | |
167 static int scast_streaming_start(stream_t *stream) { | |
168 int metaint; | |
169 int fromhdr; | |
170 scast_data_t *scast_data; | |
171 HTTP_header_t *http_hdr = stream->streaming_ctrl->data; | |
16070 | 172 int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0; |
16013 | 173 if (!stream || stream->fd < 0 || !http_hdr) |
174 return -1; | |
175 if (is_ultravox) | |
176 metaint = 0; | |
177 else { | |
178 metaint = atoi(http_get_field(http_hdr, "Icy-MetaInt")); | |
179 if (metaint <= 0) | |
180 return -1; | |
181 } | |
182 stream->streaming_ctrl->buffer = malloc(http_hdr->body_size); | |
183 stream->streaming_ctrl->buffer_size = http_hdr->body_size; | |
184 stream->streaming_ctrl->buffer_pos = 0; | |
185 memcpy(stream->streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size); | |
186 scast_data = malloc(sizeof(scast_data_t)); | |
187 scast_data->metaint = metaint; | |
188 scast_data->metapos = 0; | |
189 scast_data->is_ultravox = is_ultravox; | |
190 http_free(http_hdr); | |
191 stream->streaming_ctrl->data = scast_data; | |
192 stream->streaming_ctrl->streaming_read = scast_streaming_read; | |
193 stream->streaming_ctrl->streaming_seek = NULL; | |
194 stream->streaming_ctrl->prebuffer_size = 64 * 1024; // 64 KBytes | |
195 stream->streaming_ctrl->buffering = 1; | |
196 stream->streaming_ctrl->status = streaming_playing_e; | |
197 return 0; | |
198 } | |
199 | |
15585 | 200 static int nop_streaming_start( stream_t *stream ) { |
201 HTTP_header_t *http_hdr = NULL; | |
202 char *next_url=NULL; | |
203 URL_t *rd_url=NULL; | |
204 int fd,ret; | |
205 if( stream==NULL ) return -1; | |
206 | |
207 fd = stream->fd; | |
208 if( fd<0 ) { | |
209 fd = http_send_request( stream->streaming_ctrl->url, 0 ); | |
210 if( fd<0 ) return -1; | |
211 http_hdr = http_read_response( fd ); | |
212 if( http_hdr==NULL ) return -1; | |
213 | |
214 switch( http_hdr->status_code ) { | |
215 case 200: // OK | |
216 mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") ); | |
217 mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); | |
218 if( http_hdr->body_size>0 ) { | |
219 if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) { | |
220 http_free( http_hdr ); | |
221 return -1; | |
222 } | |
223 } | |
224 break; | |
225 // Redirect | |
226 case 301: // Permanently | |
227 case 302: // Temporarily | |
228 ret=-1; | |
229 next_url = http_get_field( http_hdr, "Location" ); | |
230 | |
231 if (next_url != NULL) | |
232 rd_url=url_new(next_url); | |
233 | |
234 if (next_url != NULL && rd_url != NULL) { | |
235 mp_msg(MSGT_NETWORK,MSGL_STATUS,"Redirected: Using this url instead %s\n",next_url); | |
236 stream->streaming_ctrl->url=check4proxies(rd_url); | |
237 ret=nop_streaming_start(stream); //recursively get streaming started | |
238 } else { | |
239 mp_msg(MSGT_NETWORK,MSGL_ERR,"Redirection failed\n"); | |
240 closesocket( fd ); | |
241 fd = -1; | |
242 } | |
243 return ret; | |
244 break; | |
245 case 401: //Authorization required | |
246 case 403: //Forbidden | |
247 case 404: //Not found | |
248 case 500: //Server Error | |
249 default: | |
250 mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned code %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); | |
251 closesocket( fd ); | |
252 fd = -1; | |
253 return -1; | |
254 break; | |
255 } | |
256 stream->fd = fd; | |
257 } else { | |
258 http_hdr = (HTTP_header_t*)stream->streaming_ctrl->data; | |
259 if( http_hdr->body_size>0 ) { | |
260 if( streaming_bufferize( stream->streaming_ctrl, http_hdr->body, http_hdr->body_size )<0 ) { | |
261 http_free( http_hdr ); | |
262 stream->streaming_ctrl->data = NULL; | |
263 return -1; | |
264 } | |
265 } | |
266 } | |
267 | |
268 if( http_hdr ) { | |
269 http_free( http_hdr ); | |
270 stream->streaming_ctrl->data = NULL; | |
271 } | |
272 | |
273 stream->streaming_ctrl->streaming_read = nop_streaming_read; | |
274 stream->streaming_ctrl->streaming_seek = nop_streaming_seek; | |
275 stream->streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes | |
276 stream->streaming_ctrl->buffering = 1; | |
277 stream->streaming_ctrl->status = streaming_playing_e; | |
278 return 0; | |
279 } | |
280 | |
870 | 281 HTTP_header_t * |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
16948
diff
changeset
|
282 http_new_header(void) { |
870 | 283 HTTP_header_t *http_hdr; |
284 | |
285 http_hdr = (HTTP_header_t*)malloc(sizeof(HTTP_header_t)); | |
286 if( http_hdr==NULL ) return NULL; | |
287 memset( http_hdr, 0, sizeof(HTTP_header_t) ); | |
288 | |
289 return http_hdr; | |
290 } | |
291 | |
292 void | |
293 http_free( HTTP_header_t *http_hdr ) { | |
3039 | 294 HTTP_field_t *field, *field2free; |
870 | 295 if( http_hdr==NULL ) return; |
296 if( http_hdr->protocol!=NULL ) free( http_hdr->protocol ); | |
297 if( http_hdr->uri!=NULL ) free( http_hdr->uri ); | |
298 if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase ); | |
299 if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); | |
902 | 300 if( http_hdr->method!=NULL ) free( http_hdr->method ); |
301 if( http_hdr->buffer!=NULL ) free( http_hdr->buffer ); | |
3039 | 302 field = http_hdr->first_field; |
303 while( field!=NULL ) { | |
304 field2free = field; | |
14460 | 305 if (field->field_name) |
306 free(field->field_name); | |
3039 | 307 field = field->next; |
308 free( field2free ); | |
309 } | |
870 | 310 free( http_hdr ); |
3039 | 311 http_hdr = NULL; |
870 | 312 } |
313 | |
902 | 314 int |
315 http_response_append( HTTP_header_t *http_hdr, char *response, int length ) { | |
1027 | 316 if( http_hdr==NULL || response==NULL || length<0 ) return -1; |
7304
7da2c2a68547
Check if realloc failed on http_hdr->buffer instead of ptr in http_response_append,
bertrand
parents:
7293
diff
changeset
|
317 |
7293 | 318 http_hdr->buffer = (char*)realloc( http_hdr->buffer, http_hdr->buffer_size+length+1 ); |
7304
7da2c2a68547
Check if realloc failed on http_hdr->buffer instead of ptr in http_response_append,
bertrand
parents:
7293
diff
changeset
|
319 if( http_hdr->buffer==NULL ) { |
7293 | 320 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory (re)allocation failed\n"); |
902 | 321 return -1; |
322 } | |
7293 | 323 memcpy( http_hdr->buffer+http_hdr->buffer_size, response, length ); |
324 http_hdr->buffer_size += length; | |
325 http_hdr->buffer[http_hdr->buffer_size]=0; // close the string! | |
902 | 326 return http_hdr->buffer_size; |
327 } | |
328 | |
329 int | |
2489
0ecc1b4f7cf8
Added ASF http server streaming (Not mms streaming).
bertrand
parents:
2310
diff
changeset
|
330 http_is_header_entire( HTTP_header_t *http_hdr ) { |
902 | 331 if( http_hdr==NULL ) return -1; |
7293 | 332 if( http_hdr->buffer==NULL ) return 0; // empty |
333 | |
3784 | 334 if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL && |
335 strstr(http_hdr->buffer, "\n\n")==NULL ) return 0; | |
336 return 1; | |
902 | 337 } |
338 | |
339 int | |
340 http_response_parse( HTTP_header_t *http_hdr ) { | |
870 | 341 char *hdr_ptr, *ptr; |
342 char *field=NULL; | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
343 int pos_hdr_sep, hdr_sep_len, len; |
902 | 344 if( http_hdr==NULL ) return -1; |
345 if( http_hdr->is_parsed ) return 0; | |
870 | 346 |
347 // Get the protocol | |
902 | 348 hdr_ptr = strstr( http_hdr->buffer, " " ); |
870 | 349 if( hdr_ptr==NULL ) { |
5915 | 350 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. No space separator found.\n"); |
902 | 351 return -1; |
870 | 352 } |
902 | 353 len = hdr_ptr-http_hdr->buffer; |
870 | 354 http_hdr->protocol = (char*)malloc(len+1); |
355 if( http_hdr->protocol==NULL ) { | |
5915 | 356 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
902 | 357 return -1; |
870 | 358 } |
902 | 359 strncpy( http_hdr->protocol, http_hdr->buffer, len ); |
360 http_hdr->protocol[len]='\0'; | |
870 | 361 if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) { |
362 if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) { | |
5915 | 363 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get HTTP minor version.\n"); |
902 | 364 return -1; |
870 | 365 } |
366 } | |
367 | |
368 // Get the status code | |
369 if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) { | |
5915 | 370 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get status code.\n"); |
902 | 371 return -1; |
870 | 372 } |
373 hdr_ptr += 4; | |
374 | |
375 // Get the reason phrase | |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
376 ptr = strstr( hdr_ptr, "\n" ); |
870 | 377 if( hdr_ptr==NULL ) { |
5915 | 378 mp_msg(MSGT_NETWORK,MSGL_ERR,"Malformed answer. Unable to get the reason phrase.\n"); |
902 | 379 return -1; |
870 | 380 } |
381 len = ptr-hdr_ptr; | |
382 http_hdr->reason_phrase = (char*)malloc(len+1); | |
383 if( http_hdr->reason_phrase==NULL ) { | |
5915 | 384 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
902 | 385 return -1; |
870 | 386 } |
387 strncpy( http_hdr->reason_phrase, hdr_ptr, len ); | |
4311 | 388 if( http_hdr->reason_phrase[len-1]=='\r' ) { |
389 len--; | |
390 } | |
870 | 391 http_hdr->reason_phrase[len]='\0'; |
392 | |
393 // Set the position of the header separator: \r\n\r\n | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
394 hdr_sep_len = 4; |
902 | 395 ptr = strstr( http_hdr->buffer, "\r\n\r\n" ); |
870 | 396 if( ptr==NULL ) { |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
397 ptr = strstr( http_hdr->buffer, "\n\n" ); |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
398 if( ptr==NULL ) { |
5915 | 399 mp_msg(MSGT_NETWORK,MSGL_ERR,"Header may be incomplete. No CRLF CRLF found.\n"); |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
400 return -1; |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
401 } |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
402 hdr_sep_len = 2; |
870 | 403 } |
902 | 404 pos_hdr_sep = ptr-http_hdr->buffer; |
870 | 405 |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
406 // Point to the first line after the method line. |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
407 hdr_ptr = strstr( http_hdr->buffer, "\n" )+1; |
870 | 408 do { |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
409 ptr = hdr_ptr; |
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
410 while( *ptr!='\r' && *ptr!='\n' ) ptr++; |
870 | 411 len = ptr-hdr_ptr; |
4816
f1dea39a50bb
Fixed the http response parser when the http header only has the HTTP
bertrand
parents:
4311
diff
changeset
|
412 if( len==0 ) break; |
870 | 413 field = (char*)realloc(field, len+1); |
414 if( field==NULL ) { | |
5915 | 415 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
902 | 416 return -1; |
870 | 417 } |
418 strncpy( field, hdr_ptr, len ); | |
419 field[len]='\0'; | |
420 http_set_field( http_hdr, field ); | |
3514
43518985def8
Handle broken server that doesn't send CRLF but jusr LF.
bertrand
parents:
3497
diff
changeset
|
421 hdr_ptr = ptr+((*ptr=='\r')?2:1); |
902 | 422 } while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) ); |
870 | 423 |
424 if( field!=NULL ) free( field ); | |
425 | |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
426 if( pos_hdr_sep+hdr_sep_len<http_hdr->buffer_size ) { |
870 | 427 // Response has data! |
8179
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
428 http_hdr->body = http_hdr->buffer+pos_hdr_sep+hdr_sep_len; |
63a5e03f4346
Removed hard coded value for the length of the header separator.
bertrand
parents:
7304
diff
changeset
|
429 http_hdr->body_size = http_hdr->buffer_size-(pos_hdr_sep+hdr_sep_len); |
870 | 430 } |
431 | |
902 | 432 http_hdr->is_parsed = 1; |
433 return 0; | |
870 | 434 } |
435 | |
436 char * | |
902 | 437 http_build_request( HTTP_header_t *http_hdr ) { |
3497 | 438 char *ptr, *uri=NULL; |
902 | 439 int len; |
3039 | 440 HTTP_field_t *field; |
870 | 441 if( http_hdr==NULL ) return NULL; |
442 | |
443 if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET"); | |
444 if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/"); | |
3497 | 445 else { |
12391 | 446 uri = (char*)malloc(strlen(http_hdr->uri) + 1); |
3497 | 447 if( uri==NULL ) { |
5915 | 448 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
3497 | 449 return NULL; |
450 } | |
12391 | 451 strcpy(uri,http_hdr->uri); |
3497 | 452 } |
870 | 453 |
3497 | 454 //**** Compute the request length |
455 // Add the Method line | |
456 len = strlen(http_hdr->method)+strlen(uri)+12; | |
457 // Add the fields | |
458 field = http_hdr->first_field; | |
3039 | 459 while( field!=NULL ) { |
460 len += strlen(field->field_name)+2; | |
461 field = field->next; | |
462 } | |
3497 | 463 // Add the CRLF |
464 len += 2; | |
465 // Add the body | |
902 | 466 if( http_hdr->body!=NULL ) { |
467 len += http_hdr->body_size; | |
468 } | |
3497 | 469 // Free the buffer if it was previously used |
902 | 470 if( http_hdr->buffer!=NULL ) { |
471 free( http_hdr->buffer ); | |
472 http_hdr->buffer = NULL; | |
473 } | |
3497 | 474 http_hdr->buffer = (char*)malloc(len+1); |
902 | 475 if( http_hdr->buffer==NULL ) { |
5915 | 476 mp_msg(MSGT_NETWORK,MSGL_ERR,"Memory allocation failed\n"); |
902 | 477 return NULL; |
478 } | |
479 http_hdr->buffer_size = len; | |
480 | |
3497 | 481 //*** Building the request |
902 | 482 ptr = http_hdr->buffer; |
3497 | 483 // Add the method line |
484 ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, uri, http_hdr->http_minor_version ); | |
3039 | 485 field = http_hdr->first_field; |
3497 | 486 // Add the field |
3039 | 487 while( field!=NULL ) { |
488 ptr += sprintf( ptr, "%s\r\n", field->field_name ); | |
489 field = field->next; | |
490 } | |
870 | 491 ptr += sprintf( ptr, "\r\n" ); |
3497 | 492 // Add the body |
870 | 493 if( http_hdr->body!=NULL ) { |
494 memcpy( ptr, http_hdr->body, http_hdr->body_size ); | |
495 } | |
3497 | 496 |
497 if( uri ) free( uri ); | |
902 | 498 return http_hdr->buffer; |
870 | 499 } |
500 | |
501 char * | |
502 http_get_field( HTTP_header_t *http_hdr, const char *field_name ) { | |
503 if( http_hdr==NULL || field_name==NULL ) return NULL; | |
3039 | 504 http_hdr->field_search_pos = http_hdr->first_field; |
505 http_hdr->field_search = (char*)realloc( http_hdr->field_search, strlen(field_name)+1 ); | |
870 | 506 if( http_hdr->field_search==NULL ) { |
5915 | 507 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 508 return NULL; |
509 } | |
510 strcpy( http_hdr->field_search, field_name ); | |
511 return http_get_next_field( http_hdr ); | |
512 } | |
513 | |
514 char * | |
515 http_get_next_field( HTTP_header_t *http_hdr ) { | |
516 char *ptr; | |
3039 | 517 HTTP_field_t *field; |
870 | 518 if( http_hdr==NULL ) return NULL; |
519 | |
3039 | 520 field = http_hdr->field_search_pos; |
521 while( field!=NULL ) { | |
522 ptr = strstr( field->field_name, ":" ); | |
870 | 523 if( ptr==NULL ) return NULL; |
3039 | 524 if( !strncasecmp( field->field_name, http_hdr->field_search, ptr-(field->field_name) ) ) { |
870 | 525 ptr++; // Skip the column |
526 while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some | |
3039 | 527 http_hdr->field_search_pos = field->next; |
870 | 528 return ptr; // return the value without the field name |
529 } | |
3039 | 530 field = field->next; |
870 | 531 } |
532 return NULL; | |
533 } | |
534 | |
535 void | |
3039 | 536 http_set_field( HTTP_header_t *http_hdr, const char *field_name ) { |
537 HTTP_field_t *new_field; | |
538 if( http_hdr==NULL || field_name==NULL ) return; | |
870 | 539 |
3039 | 540 new_field = (HTTP_field_t*)malloc(sizeof(HTTP_field_t)); |
541 if( new_field==NULL ) { | |
5915 | 542 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 543 return; |
544 } | |
3039 | 545 new_field->next = NULL; |
546 new_field->field_name = (char*)malloc(strlen(field_name)+1); | |
547 if( new_field->field_name==NULL ) { | |
5915 | 548 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
3039 | 549 return; |
550 } | |
551 strcpy( new_field->field_name, field_name ); | |
552 | |
553 if( http_hdr->last_field==NULL ) { | |
554 http_hdr->first_field = new_field; | |
555 } else { | |
556 http_hdr->last_field->next = new_field; | |
557 } | |
558 http_hdr->last_field = new_field; | |
870 | 559 http_hdr->field_nb++; |
560 } | |
561 | |
562 void | |
563 http_set_method( HTTP_header_t *http_hdr, const char *method ) { | |
564 if( http_hdr==NULL || method==NULL ) return; | |
565 | |
566 http_hdr->method = (char*)malloc(strlen(method)+1); | |
567 if( http_hdr->method==NULL ) { | |
5915 | 568 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 569 return; |
570 } | |
571 strcpy( http_hdr->method, method ); | |
572 } | |
573 | |
574 void | |
575 http_set_uri( HTTP_header_t *http_hdr, const char *uri ) { | |
576 if( http_hdr==NULL || uri==NULL ) return; | |
577 | |
578 http_hdr->uri = (char*)malloc(strlen(uri)+1); | |
579 if( http_hdr->uri==NULL ) { | |
5915 | 580 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); |
870 | 581 return; |
582 } | |
583 strcpy( http_hdr->uri, uri ); | |
584 } | |
585 | |
6514 | 586 int |
587 http_add_basic_authentication( HTTP_header_t *http_hdr, const char *username, const char *password ) { | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
588 char *auth = NULL, *usr_pass = NULL, *b64_usr_pass = NULL; |
6514 | 589 int encoded_len, pass_len=0, out_len; |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
590 int res = -1; |
6514 | 591 if( http_hdr==NULL || username==NULL ) return -1; |
592 | |
593 if( password!=NULL ) { | |
594 pass_len = strlen(password); | |
595 } | |
596 | |
597 usr_pass = (char*)malloc(strlen(username)+pass_len+2); | |
598 if( usr_pass==NULL ) { | |
599 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
600 goto out; |
6514 | 601 } |
602 | |
603 sprintf( usr_pass, "%s:%s", username, (password==NULL)?"":password ); | |
604 | |
605 // Base 64 encode with at least 33% more data than the original size | |
606 encoded_len = strlen(usr_pass)*2; | |
607 b64_usr_pass = (char*)malloc(encoded_len); | |
608 if( b64_usr_pass==NULL ) { | |
609 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
610 goto out; |
6514 | 611 } |
612 | |
613 out_len = base64_encode( usr_pass, strlen(usr_pass), b64_usr_pass, encoded_len); | |
614 if( out_len<0 ) { | |
615 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Base64 out overflow\n"); | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
616 goto out; |
6514 | 617 } |
618 | |
619 b64_usr_pass[out_len]='\0'; | |
620 | |
621 auth = (char*)malloc(encoded_len+22); | |
622 if( auth==NULL ) { | |
623 mp_msg(MSGT_NETWORK,MSGL_FATAL,"Memory allocation failed\n"); | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
624 goto out; |
6514 | 625 } |
626 | |
627 sprintf( auth, "Authorization: Basic %s", b64_usr_pass); | |
628 http_set_field( http_hdr, auth ); | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
629 res = 0; |
6514 | 630 |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
631 out: |
6514 | 632 free( usr_pass ); |
633 free( b64_usr_pass ); | |
634 free( auth ); | |
635 | |
18094
16f2bcd5d148
free memory on error in http_add_basic_authentication
reimar
parents:
17932
diff
changeset
|
636 return res; |
6514 | 637 } |
638 | |
870 | 639 void |
640 http_debug_hdr( HTTP_header_t *http_hdr ) { | |
3039 | 641 HTTP_field_t *field; |
642 int i = 0; | |
902 | 643 if( http_hdr==NULL ) return; |
870 | 644 |
5915 | 645 mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- START ---\n"); |
646 mp_msg(MSGT_NETWORK,MSGL_V,"protocol: [%s]\n", http_hdr->protocol ); | |
647 mp_msg(MSGT_NETWORK,MSGL_V,"http minor version: [%d]\n", http_hdr->http_minor_version ); | |
648 mp_msg(MSGT_NETWORK,MSGL_V,"uri: [%s]\n", http_hdr->uri ); | |
649 mp_msg(MSGT_NETWORK,MSGL_V,"method: [%s]\n", http_hdr->method ); | |
650 mp_msg(MSGT_NETWORK,MSGL_V,"status code: [%d]\n", http_hdr->status_code ); | |
651 mp_msg(MSGT_NETWORK,MSGL_V,"reason phrase: [%s]\n", http_hdr->reason_phrase ); | |
652 mp_msg(MSGT_NETWORK,MSGL_V,"body size: [%d]\n", http_hdr->body_size ); | |
870 | 653 |
5915 | 654 mp_msg(MSGT_NETWORK,MSGL_V,"Fields:\n"); |
3039 | 655 field = http_hdr->first_field; |
656 while( field!=NULL ) { | |
5915 | 657 mp_msg(MSGT_NETWORK,MSGL_V," %d - %s\n", i++, field->field_name ); |
3039 | 658 field = field->next; |
659 } | |
5915 | 660 mp_msg(MSGT_NETWORK,MSGL_V,"--- HTTP DEBUG HEADER --- END ---\n"); |
870 | 661 } |
6514 | 662 |
663 int | |
664 base64_encode(const void *enc, int encLen, char *out, int outMax) { | |
17778
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
665 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
6514 | 666 |
667 unsigned char *encBuf; | |
668 int outLen; | |
669 unsigned int bits; | |
670 unsigned int shift; | |
671 | |
672 encBuf = (unsigned char*)enc; | |
673 outLen = 0; | |
674 bits = 0; | |
675 shift = 0; | |
17778
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
676 outMax &= ~3; |
6514 | 677 |
678 while( outLen<outMax ) { | |
679 if( encLen>0 ) { | |
680 // Shift in byte | |
681 bits <<= 8; | |
682 bits |= *encBuf; | |
683 shift += 8; | |
684 // Next byte | |
685 encBuf++; | |
686 encLen--; | |
687 } else if( shift>0 ) { | |
688 // Pad last bits to 6 bits - will end next loop | |
689 bits <<= 6 - shift; | |
690 shift = 6; | |
691 } else { | |
17778
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
692 // As per RFC 2045, section 6.8, |
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
693 // pad output as necessary: 0 to 2 '=' chars. |
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
694 while( outLen & 3 ){ |
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
695 *out++ = '='; |
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
696 outLen++; |
37bfcf89c89c
Fix base64 encoding for basic auth according to RFC.
reimar
parents:
17566
diff
changeset
|
697 } |
6514 | 698 |
699 return outLen; | |
700 } | |
701 | |
702 // Encode 6 bit segments | |
703 while( shift>=6 ) { | |
704 shift -= 6; | |
705 *out = b64[ (bits >> shift) & 0x3F ]; | |
706 out++; | |
707 outLen++; | |
708 } | |
709 } | |
710 | |
711 // Output overflow | |
712 return -1; | |
713 } | |
714 | |
15585 | 715 static int http_streaming_start(stream_t *stream, int* file_format) { |
716 HTTP_header_t *http_hdr; | |
717 unsigned int i; | |
718 int fd=-1; | |
719 int redirect = 0; | |
720 int auth_retry=0; | |
721 int seekable=0; | |
722 char *content_type; | |
723 char *next_url; | |
724 URL_t *url = stream->streaming_ctrl->url; | |
6514 | 725 |
15585 | 726 do |
727 { | |
728 fd = http_send_request( url, 0 ); | |
729 if( fd<0 ) { | |
730 return -1; | |
731 } | |
732 | |
733 http_hdr = http_read_response( fd ); | |
734 if( http_hdr==NULL ) { | |
735 closesocket( fd ); | |
736 http_free( http_hdr ); | |
737 return -1; | |
738 } | |
739 | |
740 stream->fd=fd; | |
17932 | 741 if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) { |
15585 | 742 http_debug_hdr( http_hdr ); |
743 } | |
744 | |
745 stream->streaming_ctrl->data = (void*)http_hdr; | |
746 | |
747 // Check if we can make partial content requests and thus seek in http-streams | |
748 if( http_hdr!=NULL && http_hdr->status_code==200 ) { | |
749 char *accept_ranges; | |
750 if( (accept_ranges = http_get_field(http_hdr,"Accept-Ranges")) != NULL ) | |
751 seekable = strncmp(accept_ranges,"bytes",5)==0; | |
752 } | |
753 | |
754 // Check if the response is an ICY status_code reason_phrase | |
755 if( !strcasecmp(http_hdr->protocol, "ICY") ) { | |
756 switch( http_hdr->status_code ) { | |
757 case 200: { // OK | |
758 char *field_data = NULL; | |
759 // note: I skip icy-notice1 and 2, as they contain html <BR> | |
760 // and are IMHO useless info ::atmos | |
761 if( (field_data = http_get_field(http_hdr, "icy-name")) != NULL ) | |
762 mp_msg(MSGT_NETWORK,MSGL_INFO,"Name : %s\n", field_data); field_data = NULL; | |
763 if( (field_data = http_get_field(http_hdr, "icy-genre")) != NULL ) | |
764 mp_msg(MSGT_NETWORK,MSGL_INFO,"Genre : %s\n", field_data); field_data = NULL; | |
765 if( (field_data = http_get_field(http_hdr, "icy-url")) != NULL ) | |
766 mp_msg(MSGT_NETWORK,MSGL_INFO,"Website: %s\n", field_data); field_data = NULL; | |
767 // XXX: does this really mean public server? ::atmos | |
768 if( (field_data = http_get_field(http_hdr, "icy-pub")) != NULL ) | |
769 mp_msg(MSGT_NETWORK,MSGL_INFO,"Public : %s\n", atoi(field_data)?"yes":"no"); field_data = NULL; | |
770 if( (field_data = http_get_field(http_hdr, "icy-br")) != NULL ) | |
771 mp_msg(MSGT_NETWORK,MSGL_INFO,"Bitrate: %skbit/s\n", field_data); field_data = NULL; | |
772 | |
773 // If content-type == video/nsv we most likely have a winamp video stream | |
774 // otherwise it should be mp3. if there are more types consider adding mime type | |
775 // handling like later | |
776 if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "video/nsv") || !strcmp(field_data, "misc/ultravox"))) | |
777 *file_format = DEMUXER_TYPE_NSV; | |
16948
9b7925705f5b
Add another content-type for aac audio in shoutcast streams
rtognimp
parents:
16932
diff
changeset
|
778 else if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "audio/aacp") || !strcmp(field_data, "audio/aac"))) |
16917
c45409728a9d
Use correct demuxer type for aac in shoutcast streams
rtognimp
parents:
16614
diff
changeset
|
779 *file_format = DEMUXER_TYPE_AAC; |
15585 | 780 else |
781 *file_format = DEMUXER_TYPE_AUDIO; | |
782 return 0; | |
783 } | |
784 case 400: // Server Full | |
785 mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server is full, skipping!\n"); | |
786 return -1; | |
787 case 401: // Service Unavailable | |
788 mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return service unavailable, skipping!\n"); | |
789 return -1; | |
790 case 403: // Service Forbidden | |
791 mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return 'Service Forbidden'\n"); | |
792 return -1; | |
793 case 404: // Resource Not Found | |
794 mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server couldn't find requested stream, skipping!\n"); | |
795 return -1; | |
796 default: | |
797 mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: unhandled ICY-Errorcode, contact MPlayer developers!\n"); | |
798 return -1; | |
799 } | |
800 } | |
801 | |
802 // Assume standard http if not ICY | |
803 switch( http_hdr->status_code ) { | |
804 case 200: // OK | |
805 // Look if we can use the Content-Type | |
806 content_type = http_get_field( http_hdr, "Content-Type" ); | |
807 if( content_type!=NULL ) { | |
808 char *content_length = NULL; | |
809 mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", content_type ); | |
810 if( (content_length = http_get_field(http_hdr, "Content-Length")) != NULL) | |
811 mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length")); | |
812 // Check in the mime type table for a demuxer type | |
813 i = 0; | |
814 while(mime_type_table[i].mime_type != NULL) { | |
815 if( !strcasecmp( content_type, mime_type_table[i].mime_type ) ) { | |
816 *file_format = mime_type_table[i].demuxer_type; | |
817 return seekable; | |
818 } | |
819 i++; | |
820 } | |
821 } | |
822 // Not found in the mime type table, don't fail, | |
823 // we should try raw HTTP | |
824 return seekable; | |
825 // Redirect | |
826 case 301: // Permanently | |
827 case 302: // Temporarily | |
828 // TODO: RFC 2616, recommand to detect infinite redirection loops | |
829 next_url = http_get_field( http_hdr, "Location" ); | |
830 if( next_url!=NULL ) { | |
831 closesocket( fd ); | |
832 url_free( url ); | |
833 stream->streaming_ctrl->url = url = url_new( next_url ); | |
834 http_free( http_hdr ); | |
835 redirect = 1; | |
836 } | |
837 break; | |
838 case 401: // Authentication required | |
839 if( http_authenticate(http_hdr, url, &auth_retry)<0 ) return STREAM_UNSUPORTED; | |
840 redirect = 1; | |
841 break; | |
842 default: | |
843 mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); | |
844 return -1; | |
845 } | |
846 } while( redirect ); | |
847 | |
848 return -1; | |
849 } | |
850 | |
851 static int fixup_open(stream_t *stream,int seekable) { | |
16013 | 852 HTTP_header_t *http_hdr = stream->streaming_ctrl->data; |
16078
095e980cf7c0
Some ICY servers (e.g. http://broadcast.spnet.net:8000/darikhigh) do not set
reimar
parents:
16070
diff
changeset
|
853 int is_icy = http_hdr && http_get_field(http_hdr, "Icy-MetaInt"); |
16013 | 854 char *content_type = http_get_field( http_hdr, "Content-Type" ); |
16070 | 855 int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0; |
15585 | 856 |
857 stream->type = STREAMTYPE_STREAM; | |
16013 | 858 if(!is_icy && !is_ultravox && seekable) |
15585 | 859 { |
860 stream->flags |= STREAM_SEEK; | |
861 stream->seek = http_seek; | |
862 } | |
863 stream->streaming_ctrl->bandwidth = network_bandwidth; | |
16013 | 864 if ((!is_icy && !is_ultravox) || scast_streaming_start(stream)) |
15585 | 865 if(nop_streaming_start( stream )) { |
866 mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n"); | |
867 streaming_ctrl_free(stream->streaming_ctrl); | |
868 stream->streaming_ctrl = NULL; | |
869 return STREAM_UNSUPORTED; | |
870 } | |
871 | |
872 fixup_network_stream_cache(stream); | |
873 return STREAM_OK; | |
874 } | |
875 | |
876 static int open_s1(stream_t *stream,int mode, void* opts, int* file_format) { | |
877 int seekable=0; | |
878 URL_t *url; | |
879 | |
880 stream->streaming_ctrl = streaming_ctrl_new(); | |
881 if( stream->streaming_ctrl==NULL ) { | |
882 return STREAM_ERROR; | |
883 } | |
884 stream->streaming_ctrl->bandwidth = network_bandwidth; | |
885 url = url_new(stream->url); | |
886 stream->streaming_ctrl->url = check4proxies(url); | |
16417 | 887 url_free(url); |
15585 | 888 |
889 mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(1), URL: %s\n", stream->url); | |
890 seekable = http_streaming_start(stream, file_format); | |
891 if((seekable < 0) || (*file_format == DEMUXER_TYPE_ASF)) { | |
892 streaming_ctrl_free(stream->streaming_ctrl); | |
893 stream->streaming_ctrl = NULL; | |
894 return STREAM_UNSUPORTED; | |
895 } | |
896 | |
897 return fixup_open(stream, seekable); | |
898 } | |
899 | |
900 static int open_s2(stream_t *stream,int mode, void* opts, int* file_format) { | |
901 int seekable=0; | |
902 URL_t *url; | |
903 | |
904 stream->streaming_ctrl = streaming_ctrl_new(); | |
905 if( stream->streaming_ctrl==NULL ) { | |
906 return STREAM_ERROR; | |
907 } | |
908 stream->streaming_ctrl->bandwidth = network_bandwidth; | |
909 url = url_new(stream->url); | |
910 stream->streaming_ctrl->url = check4proxies(url); | |
16614 | 911 url_free(url); |
15585 | 912 |
913 mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_HTTP(2), URL: %s\n", stream->url); | |
914 seekable = http_streaming_start(stream, file_format); | |
915 if(seekable < 0) { | |
916 streaming_ctrl_free(stream->streaming_ctrl); | |
917 stream->streaming_ctrl = NULL; | |
918 return STREAM_UNSUPORTED; | |
919 } | |
920 | |
921 return fixup_open(stream, seekable); | |
922 } | |
923 | |
924 | |
925 stream_info_t stream_info_http1 = { | |
926 "http streaming", | |
927 "null", | |
928 "Bertrand, Albeau, Reimar Doeffinger, Arpi?", | |
929 "plain http", | |
930 open_s1, | |
16013 | 931 {"http", "http_proxy", "unsv", NULL}, |
15585 | 932 NULL, |
933 0 // Urls are an option string | |
934 }; | |
935 | |
936 stream_info_t stream_info_http2 = { | |
937 "http streaming", | |
938 "null", | |
939 "Bertrand, Albeu, Arpi? who?", | |
16932
c30e0970250c
fix typos: aslo->also, falback->fallback (they were just too annoying *g*)
reimar
parents:
16917
diff
changeset
|
940 "plain http, also used as fallback for many other protocols", |
15585 | 941 open_s2, |
942 {"http", "http_proxy", "pnm", "mms", "mmsu", "mmst", "rtsp", NULL}, //all the others as fallback | |
943 NULL, | |
944 0 // Urls are an option string | |
945 }; |