Mercurial > libavformat.hg
annotate http.c @ 594:89a09ede50ad libavformat
First implementation of nsv demuxer.
Get libavformat linked with lavc and lmp3lame is required. BeOS requires no undefined syms on link! (besides it's bad to leave undef syms)
author | mmu_man |
---|---|
date | Sat, 20 Nov 2004 23:10:07 +0000 |
parents | 056991ab9f10 |
children | 0b52743104ac |
rev | line source |
---|---|
0 | 1 /* |
2 * HTTP protocol for ffmpeg client | |
3 * Copyright (c) 2000, 2001 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avformat.h" | |
20 #include <unistd.h> | |
21 #include <sys/types.h> | |
22 #include <sys/socket.h> | |
23 #include <netinet/in.h> | |
24 #ifndef __BEOS__ | |
25 # include <arpa/inet.h> | |
26 #else | |
27 # include "barpainet.h" | |
28 #endif | |
29 #include <netdb.h> | |
30 | |
31 | |
32 /* XXX: POST protocol is not completly implemented because ffmpeg use | |
33 only a subset of it */ | |
34 | |
35 //#define DEBUG | |
36 | |
37 /* used for protocol handling */ | |
38 #define BUFFER_SIZE 1024 | |
39 #define URL_SIZE 4096 | |
40 | |
41 typedef struct { | |
42 URLContext *hd; | |
43 unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end; | |
44 int line_count; | |
45 int http_code; | |
46 char location[URL_SIZE]; | |
47 } HTTPContext; | |
48 | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
49 static int http_connect(URLContext *h, const char *path, const char *hoststr, |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
50 const char *auth); |
65 | 51 static int http_write(URLContext *h, uint8_t *buf, int size); |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
52 static char *b64_encode( unsigned char *src ); |
0 | 53 |
54 | |
55 /* return non zero if error */ | |
56 static int http_open(URLContext *h, const char *uri, int flags) | |
57 { | |
58 const char *path, *proxy_path; | |
59 char hostname[1024], hoststr[1024]; | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
60 char auth[1024]; |
0 | 61 char path1[1024]; |
62 char buf[1024]; | |
63 int port, use_proxy, err; | |
64 HTTPContext *s; | |
65 URLContext *hd = NULL; | |
66 | |
67 h->is_streamed = 1; | |
68 | |
69 s = av_malloc(sizeof(HTTPContext)); | |
70 if (!s) { | |
71 return -ENOMEM; | |
72 } | |
73 h->priv_data = s; | |
74 | |
75 proxy_path = getenv("http_proxy"); | |
76 use_proxy = (proxy_path != NULL) && !getenv("no_proxy") && | |
77 strstart(proxy_path, "http://", NULL); | |
78 | |
79 /* fill the dest addr */ | |
80 redo: | |
81 /* needed in any case to build the host string */ | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
82 url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, |
0 | 83 path1, sizeof(path1), uri); |
84 if (port > 0) { | |
85 snprintf(hoststr, sizeof(hoststr), "%s:%d", hostname, port); | |
86 } else { | |
87 pstrcpy(hoststr, sizeof(hoststr), hostname); | |
88 } | |
89 | |
90 if (use_proxy) { | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
91 url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, |
0 | 92 NULL, 0, proxy_path); |
93 path = uri; | |
94 } else { | |
95 if (path1[0] == '\0') | |
96 path = "/"; | |
97 else | |
98 path = path1; | |
99 } | |
100 if (port < 0) | |
101 port = 80; | |
102 | |
103 snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port); | |
104 err = url_open(&hd, buf, URL_RDWR); | |
105 if (err < 0) | |
106 goto fail; | |
107 | |
108 s->hd = hd; | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
109 if (http_connect(h, path, hoststr, auth) < 0) |
0 | 110 goto fail; |
111 if (s->http_code == 303 && s->location[0] != '\0') { | |
112 /* url moved, get next */ | |
113 uri = s->location; | |
114 url_close(hd); | |
115 goto redo; | |
116 } | |
117 return 0; | |
118 fail: | |
119 if (hd) | |
120 url_close(hd); | |
121 av_free(s); | |
482 | 122 return AVERROR_IO; |
0 | 123 } |
124 | |
125 static int http_getc(HTTPContext *s) | |
126 { | |
127 int len; | |
128 if (s->buf_ptr >= s->buf_end) { | |
129 len = url_read(s->hd, s->buffer, BUFFER_SIZE); | |
130 if (len < 0) { | |
482 | 131 return AVERROR_IO; |
0 | 132 } else if (len == 0) { |
133 return -1; | |
134 } else { | |
135 s->buf_ptr = s->buffer; | |
136 s->buf_end = s->buffer + len; | |
137 } | |
138 } | |
139 return *s->buf_ptr++; | |
140 } | |
141 | |
142 static int process_line(HTTPContext *s, char *line, int line_count) | |
143 { | |
144 char *tag, *p; | |
145 | |
146 /* end of header */ | |
147 if (line[0] == '\0') | |
148 return 0; | |
149 | |
150 p = line; | |
151 if (line_count == 0) { | |
152 while (!isspace(*p) && *p != '\0') | |
153 p++; | |
154 while (isspace(*p)) | |
155 p++; | |
156 s->http_code = strtol(p, NULL, 10); | |
157 #ifdef DEBUG | |
158 printf("http_code=%d\n", s->http_code); | |
159 #endif | |
160 } else { | |
161 while (*p != '\0' && *p != ':') | |
162 p++; | |
163 if (*p != ':') | |
164 return 1; | |
165 | |
166 *p = '\0'; | |
167 tag = line; | |
168 p++; | |
169 while (isspace(*p)) | |
170 p++; | |
171 if (!strcmp(tag, "Location")) { | |
172 strcpy(s->location, p); | |
173 } | |
174 } | |
175 return 1; | |
176 } | |
177 | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
178 static int http_connect(URLContext *h, const char *path, const char *hoststr, |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
179 const char *auth) |
0 | 180 { |
181 HTTPContext *s = h->priv_data; | |
182 int post, err, ch; | |
183 char line[1024], *q; | |
184 | |
185 | |
186 /* send http header */ | |
187 post = h->flags & URL_WRONLY; | |
188 | |
189 snprintf(s->buffer, sizeof(s->buffer), | |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
190 "%s %s HTTP/1.0\r\n" |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
191 "User-Agent: %s\r\n" |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
192 "Accept: */*\r\n" |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
193 "Host: %s\r\n" |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
194 "Authorization: Basic %s\r\n" |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
195 "\r\n", |
0 | 196 post ? "POST" : "GET", |
197 path, | |
327 | 198 LIBAVFORMAT_IDENT, |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
199 hoststr, |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
200 b64_encode(auth)); |
0 | 201 |
202 if (http_write(h, s->buffer, strlen(s->buffer)) < 0) | |
482 | 203 return AVERROR_IO; |
0 | 204 |
205 /* init input buffer */ | |
206 s->buf_ptr = s->buffer; | |
207 s->buf_end = s->buffer; | |
208 s->line_count = 0; | |
209 s->location[0] = '\0'; | |
210 if (post) { | |
211 sleep(1); | |
212 return 0; | |
213 } | |
214 | |
215 /* wait for header */ | |
216 q = line; | |
217 for(;;) { | |
218 ch = http_getc(s); | |
219 if (ch < 0) | |
482 | 220 return AVERROR_IO; |
0 | 221 if (ch == '\n') { |
222 /* process line */ | |
223 if (q > line && q[-1] == '\r') | |
224 q--; | |
225 *q = '\0'; | |
226 #ifdef DEBUG | |
227 printf("header='%s'\n", line); | |
228 #endif | |
229 err = process_line(s, line, s->line_count); | |
230 if (err < 0) | |
231 return err; | |
232 if (err == 0) | |
233 return 0; | |
234 s->line_count++; | |
235 q = line; | |
236 } else { | |
237 if ((q - line) < sizeof(line) - 1) | |
238 *q++ = ch; | |
239 } | |
240 } | |
241 } | |
242 | |
243 | |
65 | 244 static int http_read(URLContext *h, uint8_t *buf, int size) |
0 | 245 { |
246 HTTPContext *s = h->priv_data; | |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
247 int len; |
0 | 248 |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
249 /* read bytes from input buffer first */ |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
250 len = s->buf_end - s->buf_ptr; |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
251 if (len > 0) { |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
252 if (len > size) |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
253 len = size; |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
254 memcpy(buf, s->buf_ptr, len); |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
255 s->buf_ptr += len; |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
256 } else { |
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
257 len = url_read(s->hd, buf, size); |
0 | 258 } |
385
2f56d366a787
no read loop tcp/http and http CRLF fix by (Leon van Stuivenberg <l dot vanstuivenberg at chello dot nl>)
michael
parents:
327
diff
changeset
|
259 return len; |
0 | 260 } |
261 | |
262 /* used only when posting data */ | |
65 | 263 static int http_write(URLContext *h, uint8_t *buf, int size) |
0 | 264 { |
265 HTTPContext *s = h->priv_data; | |
266 return url_write(s->hd, buf, size); | |
267 } | |
268 | |
269 static int http_close(URLContext *h) | |
270 { | |
271 HTTPContext *s = h->priv_data; | |
272 url_close(s->hd); | |
273 av_free(s); | |
274 return 0; | |
275 } | |
276 | |
277 URLProtocol http_protocol = { | |
278 "http", | |
279 http_open, | |
280 http_read, | |
281 http_write, | |
282 NULL, /* seek */ | |
283 http_close, | |
284 }; | |
285 | |
511
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
286 /***************************************************************************** |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
287 * b64_encode: stolen from VLC's http.c |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
288 *****************************************************************************/ |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
289 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
290 static char *b64_encode( unsigned char *src ) |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
291 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
292 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
293 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
294 char *dst = av_malloc( strlen( src ) * 4 / 3 + 12 ); |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
295 char *ret = dst; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
296 unsigned i_bits = 0; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
297 unsigned i_shift = 0; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
298 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
299 for( ;; ) |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
300 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
301 if( *src ) |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
302 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
303 i_bits = ( i_bits << 8 )|( *src++ ); |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
304 i_shift += 8; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
305 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
306 else if( i_shift > 0 ) |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
307 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
308 i_bits <<= 6 - i_shift; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
309 i_shift = 6; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
310 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
311 else |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
312 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
313 *dst++ = '='; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
314 break; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
315 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
316 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
317 while( i_shift >= 6 ) |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
318 { |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
319 i_shift -= 6; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
320 *dst++ = b64[(i_bits >> i_shift)&0x3f]; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
321 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
322 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
323 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
324 *dst++ = '\0'; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
325 |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
326 return ret; |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
327 } |
056991ab9f10
HTTP Authentication Patch by (Petr Doubek <doubek at vision dot ee dot ethz dot ch>)
michael
parents:
482
diff
changeset
|
328 |