提交 7434ba6d 编写于 作者: P Philip Gladstone

* Improve logging -- now actually gives you the number of bytes sent

* Print out the logging information that comes from WMP (you'd be suprised what
  it sends!
* Fix a remotely exploitable buffer overflow (argh!)
* Add support for automatically serving up .asx files. It generates an automatic
  redirect to the associated .asf file (with the same parameters). I guess that
  someone who understands the realaudio equivalent could hack that it as well.

Originally committed as revision 482 to svn://svn.ffmpeg.org/ffmpeg/trunk
上级 8d1335ea
...@@ -93,6 +93,10 @@ typedef struct HTTPContext { ...@@ -93,6 +93,10 @@ typedef struct HTTPContext {
struct FFStream *stream; struct FFStream *stream;
AVFormatContext fmt_ctx; AVFormatContext fmt_ctx;
int last_packet_sent; /* true if last data packet was sent */ int last_packet_sent; /* true if last data packet was sent */
int suppress_log;
char protocol[16];
char method[16];
char url[128];
UINT8 buffer[IOBUFFER_MAX_SIZE]; UINT8 buffer[IOBUFFER_MAX_SIZE];
UINT8 pbuffer[PACKET_MAX_SIZE]; UINT8 pbuffer[PACKET_MAX_SIZE];
} HTTPContext; } HTTPContext;
...@@ -161,11 +165,34 @@ static void http_log(char *fmt, ...) ...@@ -161,11 +165,34 @@ static void http_log(char *fmt, ...)
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if (logfile) if (logfile) {
vfprintf(logfile, fmt, ap); vfprintf(logfile, fmt, ap);
fflush(logfile);
}
va_end(ap); va_end(ap);
} }
static void log_connection(HTTPContext *c)
{
char buf1[32], buf2[32], *p;
time_t ti;
if (c->suppress_log)
return;
/* XXX: reentrant function ? */
p = inet_ntoa(c->from_addr.sin_addr);
strcpy(buf1, p);
ti = time(NULL);
p = ctime(&ti);
strcpy(buf2, p);
p = buf2 + strlen(p) - 1;
if (*p == '\n')
*p = '\0';
http_log("%s - - [%s] \"%s %s %s\" %d %lld\n",
buf1, buf2, c->method, c->url, c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
}
/* main loop of the http server */ /* main loop of the http server */
static int http_server(struct sockaddr_in my_addr) static int http_server(struct sockaddr_in my_addr)
{ {
...@@ -264,6 +291,7 @@ static int http_server(struct sockaddr_in my_addr) ...@@ -264,6 +291,7 @@ static int http_server(struct sockaddr_in my_addr)
c = *cp; c = *cp;
if (handle_http (c, cur_time) < 0) { if (handle_http (c, cur_time) < 0) {
/* close and free the connection */ /* close and free the connection */
log_connection(c);
close(c->fd); close(c->fd);
if (c->fmt_in) if (c->fmt_in)
av_close_input_file(c->fmt_in); av_close_input_file(c->fmt_in);
...@@ -408,11 +436,13 @@ static int handle_http(HTTPContext *c, long cur_time) ...@@ -408,11 +436,13 @@ static int handle_http(HTTPContext *c, long cur_time)
return 0; return 0;
} }
/* parse http request and prepare header */ /* parse http request and prepare header */
static int http_parse_request(HTTPContext *c) static int http_parse_request(HTTPContext *c)
{ {
char *p; char *p;
int post; int post;
int doing_asx;
char cmd[32]; char cmd[32];
char info[1024], *filename; char info[1024], *filename;
char url[1024], *q; char url[1024], *q;
...@@ -429,6 +459,9 @@ static int http_parse_request(HTTPContext *c) ...@@ -429,6 +459,9 @@ static int http_parse_request(HTTPContext *c)
p++; p++;
} }
*q = '\0'; *q = '\0';
strlcpy(c->method, cmd, sizeof(c->method));
if (!strcmp(cmd, "GET")) if (!strcmp(cmd, "GET"))
post = 0; post = 0;
else if (!strcmp(cmd, "POST")) else if (!strcmp(cmd, "POST"))
...@@ -445,6 +478,8 @@ static int http_parse_request(HTTPContext *c) ...@@ -445,6 +478,8 @@ static int http_parse_request(HTTPContext *c)
} }
*q = '\0'; *q = '\0';
strlcpy(c->url, url, sizeof(c->url));
while (isspace(*p)) p++; while (isspace(*p)) p++;
q = protocol; q = protocol;
while (!isspace(*p) && *p != '\0') { while (!isspace(*p) && *p != '\0') {
...@@ -456,6 +491,8 @@ static int http_parse_request(HTTPContext *c) ...@@ -456,6 +491,8 @@ static int http_parse_request(HTTPContext *c)
if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1")) if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
return -1; return -1;
strlcpy(c->protocol, protocol, sizeof(c->protocol));
/* find the filename and the optional info string in the request */ /* find the filename and the optional info string in the request */
p = url; p = url;
if (*p == '/') if (*p == '/')
...@@ -463,12 +500,19 @@ static int http_parse_request(HTTPContext *c) ...@@ -463,12 +500,19 @@ static int http_parse_request(HTTPContext *c)
filename = p; filename = p;
p = strchr(p, '?'); p = strchr(p, '?');
if (p) { if (p) {
strcpy(info, p); strlcpy(info, p, sizeof(info));
*p = '\0'; *p = '\0';
} else { } else {
info[0] = '\0'; info[0] = '\0';
} }
if (strlen(filename) > 4 && strcmp(".asx", filename + strlen(filename) - 4) == 0) {
doing_asx = 1;
filename[strlen(filename)-1] = 'f';
} else {
doing_asx = 0;
}
stream = first_stream; stream = first_stream;
while (stream != NULL) { while (stream != NULL) {
if (!strcmp(stream->filename, filename)) if (!strcmp(stream->filename, filename))
...@@ -479,30 +523,98 @@ static int http_parse_request(HTTPContext *c) ...@@ -479,30 +523,98 @@ static int http_parse_request(HTTPContext *c)
sprintf(msg, "File '%s' not found", url); sprintf(msg, "File '%s' not found", url);
goto send_error; goto send_error;
} }
c->stream = stream; if (doing_asx) {
char *hostinfo = 0;
/* should do it after so that the size can be computed */ for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
{ if (strncasecmp(p, "Host:", 5) == 0) {
char buf1[32], buf2[32], *p; hostinfo = p + 5;
time_t ti; break;
/* XXX: reentrant function ? */ }
p = inet_ntoa(c->from_addr.sin_addr); p = strchr(p, '\n');
strcpy(buf1, p); if (!p)
ti = time(NULL); break;
p = ctime(&ti);
strcpy(buf2, p); p++;
p = buf2 + strlen(p) - 1; }
if (*p == '\n')
*p = '\0'; if (hostinfo) {
http_log("%s - - [%s] \"%s %s %s\" %d %d\n", char *eoh;
buf1, buf2, cmd, url, protocol, 200, 1024); char hostbuf[260];
while (isspace(*hostinfo))
hostinfo++;
eoh = strchr(hostinfo, '\n');
if (eoh) {
if (eoh[-1] == '\r')
eoh--;
if (eoh - hostinfo < sizeof(hostbuf) - 1) {
memcpy(hostbuf, hostinfo, eoh - hostinfo);
hostbuf[eoh - hostinfo] = 0;
c->http_error = 200;
q = c->buffer;
q += sprintf(q, "HTTP/1.0 200 ASX Follows\r\n");
q += sprintf(q, "Content-type: video/x-ms-asf\r\n");
q += sprintf(q, "\r\n");
q += sprintf(q, "<ASX Version=\"3\">\r\n");
q += sprintf(q, "<!-- Autogenerated by ffserver -->\r\n");
q += sprintf(q, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",
hostbuf, filename, info);
q += sprintf(q, "</ASX>\r\n");
/* prepare output buffer */
c->buffer_ptr = c->buffer;
c->buffer_end = q;
c->state = HTTPSTATE_SEND_HEADER;
return 0;
}
}
} }
sprintf(msg, "ASX file not handled");
goto send_error;
}
c->stream = stream;
/* XXX: add there authenticate and IP match */ /* XXX: add there authenticate and IP match */
if (post) { if (post) {
/* if post, it means a feed is being sent */ /* if post, it means a feed is being sent */
if (!stream->is_feed) { if (!stream->is_feed) {
/* However it might be a status report from WMP! Lets log the data
* as it might come in handy one day
*/
char *logline = 0;
for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
logline = p;
break;
}
p = strchr(p, '\n');
if (!p)
break;
p++;
}
if (logline) {
char *eol = strchr(logline, '\n');
logline += 17;
if (eol) {
if (eol[-1] == '\r')
eol--;
http_log("%.*s\n", eol - logline, logline);
c->suppress_log = 1;
}
}
sprintf(msg, "POST command not handled"); sprintf(msg, "POST command not handled");
goto send_error; goto send_error;
} }
...@@ -535,7 +647,9 @@ static int http_parse_request(HTTPContext *c) ...@@ -535,7 +647,9 @@ static int http_parse_request(HTTPContext *c)
/* for asf, we need extra headers */ /* for asf, we need extra headers */
if (!strcmp(c->stream->fmt->name,"asf")) { if (!strcmp(c->stream->fmt->name,"asf")) {
q += sprintf(q, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=1234\r\nPragma: features=\"broadcast\"\r\n"); q += sprintf(q, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=1234\r\nPragma: features=\"broadcast\"\r\n");
mime_type = "application/octet-stream"; /* mime_type = "application/octet-stream"; */
/* video/x-ms-asf seems better -- netscape doesn't crash any more! */
mime_type = "video/x-ms-asf";
} }
q += sprintf(q, "Content-Type: %s\r\n", mime_type); q += sprintf(q, "Content-Type: %s\r\n", mime_type);
q += sprintf(q, "\r\n"); q += sprintf(q, "\r\n");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册