comparison http.c @ 6104:a5eaf91edd4a libavformat

Add the capability to write custom HTTP headers Patch by Josh Allmann, joshua dot allmann at gmail
author mstorsjo
date Tue, 08 Jun 2010 10:26:16 +0000
parents 447fe3440991
children 44ee60d0c688
comparison
equal deleted inserted replaced
6103:447fe3440991 6104:a5eaf91edd4a
23 #include "avformat.h" 23 #include "avformat.h"
24 #include <unistd.h> 24 #include <unistd.h>
25 #include <strings.h> 25 #include <strings.h>
26 #include "internal.h" 26 #include "internal.h"
27 #include "network.h" 27 #include "network.h"
28 #include "http.h"
28 #include "os_support.h" 29 #include "os_support.h"
29 #include "httpauth.h" 30 #include "httpauth.h"
30 31
31 /* XXX: POST protocol is not completely implemented because ffmpeg uses 32 /* XXX: POST protocol is not completely implemented because ffmpeg uses
32 only a subset of it. */ 33 only a subset of it. */
44 int64_t chunksize; /**< Used if "Transfer-Encoding: chunked" otherwise -1. */ 45 int64_t chunksize; /**< Used if "Transfer-Encoding: chunked" otherwise -1. */
45 int64_t off, filesize; 46 int64_t off, filesize;
46 char location[URL_SIZE]; 47 char location[URL_SIZE];
47 HTTPAuthState auth_state; 48 HTTPAuthState auth_state;
48 int init; 49 int init;
50 unsigned char headers[BUFFER_SIZE];
49 } HTTPContext; 51 } HTTPContext;
50 52
51 static int http_connect(URLContext *h, const char *path, const char *hoststr, 53 static int http_connect(URLContext *h, const char *path, const char *hoststr,
52 const char *auth, int *new_location); 54 const char *auth, int *new_location);
53 static int http_write(URLContext *h, const uint8_t *buf, int size); 55 static int http_write(URLContext *h, const uint8_t *buf, int size);
54 56
57 void ff_http_set_headers(URLContext *h, const char *headers)
58 {
59 HTTPContext *s = h->priv_data;
60 int len = strlen(headers);
61
62 if (len && strcmp("\r\n", headers + len - 2))
63 av_log(NULL, AV_LOG_ERROR, "No trailing CRLF found in HTTP header.\n");
64
65 av_strlcpy(s->headers, headers, sizeof(s->headers));
66 }
55 67
56 /* return non zero if error */ 68 /* return non zero if error */
57 static int http_open_cnx(URLContext *h) 69 static int http_open_cnx(URLContext *h)
58 { 70 {
59 const char *path, *proxy_path; 71 const char *path, *proxy_path;
135 h->priv_data = s; 147 h->priv_data = s;
136 s->filesize = -1; 148 s->filesize = -1;
137 s->chunksize = -1; 149 s->chunksize = -1;
138 s->off = 0; 150 s->off = 0;
139 s->init = 0; 151 s->init = 0;
152 *s->headers = '\0';
140 memset(&s->auth_state, 0, sizeof(s->auth_state)); 153 memset(&s->auth_state, 0, sizeof(s->auth_state));
141 av_strlcpy(s->location, uri, URL_SIZE); 154 av_strlcpy(s->location, uri, URL_SIZE);
142 155
143 return 0; 156 return 0;
144 } 157 }
243 } 256 }
244 } 257 }
245 return 1; 258 return 1;
246 } 259 }
247 260
261 static inline int has_header(const char *str, const char *header)
262 {
263 /* header + 2 to skip over CRLF prefix. (make sure you have one!) */
264 return av_stristart(str, header + 2, NULL) || av_stristr(str, header);
265 }
266
248 static int http_connect(URLContext *h, const char *path, const char *hoststr, 267 static int http_connect(URLContext *h, const char *path, const char *hoststr,
249 const char *auth, int *new_location) 268 const char *auth, int *new_location)
250 { 269 {
251 HTTPContext *s = h->priv_data; 270 HTTPContext *s = h->priv_data;
252 int post, err; 271 int post, err;
253 char line[1024]; 272 char line[1024];
273 char headers[1024];
254 char *authstr = NULL; 274 char *authstr = NULL;
255 int64_t off = s->off; 275 int64_t off = s->off;
276 int len = 0;
256 277
257 278
258 /* send http header */ 279 /* send http header */
259 post = h->flags & URL_WRONLY; 280 post = h->flags & URL_WRONLY;
260 authstr = ff_http_auth_create_response(&s->auth_state, auth, path, 281 authstr = ff_http_auth_create_response(&s->auth_state, auth, path,
261 post ? "POST" : "GET"); 282 post ? "POST" : "GET");
283
284 /* set default headers if needed */
285 if (!has_header(s->headers, "\r\nUser-Agent: "))
286 len += av_strlcatf(headers + len, sizeof(headers) - len,
287 "User-Agent: %s\r\n", LIBAVFORMAT_IDENT);
288 if (!has_header(s->headers, "\r\nAccept: "))
289 len += av_strlcpy(headers + len, "Accept: */*\r\n",
290 sizeof(headers) - len);
291 if (!has_header(s->headers, "\r\nRange: "))
292 len += av_strlcatf(headers + len, sizeof(headers) - len,
293 "Range: bytes=%"PRId64"\r\n", s->off);
294 if (!has_header(s->headers, "\r\nConnection: "))
295 len += av_strlcpy(headers + len, "Connection: close\r\n",
296 sizeof(headers)-len);
297 if (!has_header(s->headers, "\r\nHost: "))
298 len += av_strlcatf(headers + len, sizeof(headers) - len,
299 "Host: %s\r\n", hoststr);
300
301 /* now add in custom headers */
302 av_strlcpy(headers+len, s->headers, sizeof(headers)-len);
303
262 snprintf(s->buffer, sizeof(s->buffer), 304 snprintf(s->buffer, sizeof(s->buffer),
263 "%s %s HTTP/1.1\r\n" 305 "%s %s HTTP/1.1\r\n"
264 "User-Agent: %s\r\n"
265 "Accept: */*\r\n"
266 "Range: bytes=%"PRId64"-\r\n"
267 "Host: %s\r\n"
268 "%s" 306 "%s"
269 "Connection: close\r\n" 307 "%s"
270 "%s" 308 "%s"
271 "\r\n", 309 "\r\n",
272 post ? "POST" : "GET", 310 post ? "POST" : "GET",
273 path, 311 path,
274 LIBAVFORMAT_IDENT, 312 post ? "Transfer-Encoding: chunked\r\n" : "",
275 s->off, 313 headers,
276 hoststr, 314 authstr ? authstr : "");
277 authstr ? authstr : "",
278 post ? "Transfer-Encoding: chunked\r\n" : "");
279 315
280 av_freep(&authstr); 316 av_freep(&authstr);
281 if (http_write(h, s->buffer, strlen(s->buffer)) < 0) 317 if (http_write(h, s->buffer, strlen(s->buffer)) < 0)
282 return AVERROR(EIO); 318 return AVERROR(EIO);
283 319