Mercurial > libavformat.hg
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 |
