mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
an attempt at differentiated error handling for timeouts and eof.
really this needs to be propagated all the way to the callback. svn:r273
This commit is contained in:
parent
51fde16666
commit
ce436242ad
@ -17,6 +17,12 @@
|
|||||||
#define HTTP_PREFIX "http://"
|
#define HTTP_PREFIX "http://"
|
||||||
#define HTTP_DEFAULTPORT 80
|
#define HTTP_DEFAULTPORT 80
|
||||||
|
|
||||||
|
enum evhttp_connection_error {
|
||||||
|
EVCON_HTTP_TIMEOUT,
|
||||||
|
EVCON_HTTP_EOF,
|
||||||
|
EVCON_HTTP_INVALID_HEADER
|
||||||
|
};
|
||||||
|
|
||||||
struct evbuffer;
|
struct evbuffer;
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct evhttp_request;
|
struct evhttp_request;
|
||||||
@ -85,7 +91,8 @@ void evhttp_connection_reset(struct evhttp_connection *);
|
|||||||
int evhttp_connection_connect(struct evhttp_connection *);
|
int evhttp_connection_connect(struct evhttp_connection *);
|
||||||
|
|
||||||
/* notifies the current request that it failed; resets connection */
|
/* notifies the current request that it failed; resets connection */
|
||||||
void evhttp_connection_fail(struct evhttp_connection *);
|
void evhttp_connection_fail(struct evhttp_connection *,
|
||||||
|
enum evhttp_connection_error error);
|
||||||
|
|
||||||
void evhttp_get_request(struct evhttp *, int, struct sockaddr *, socklen_t);
|
void evhttp_get_request(struct evhttp *, int, struct sockaddr *, socklen_t);
|
||||||
|
|
||||||
|
64
http.c
64
http.c
@ -398,8 +398,36 @@ evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
evhttp_connection_incoming_fail(struct evhttp_request *req,
|
||||||
|
enum evhttp_connection_error error)
|
||||||
|
{
|
||||||
|
switch (error) {
|
||||||
|
case EVCON_HTTP_TIMEOUT:
|
||||||
|
case EVCON_HTTP_EOF:
|
||||||
|
/*
|
||||||
|
* these are cases in which we probably should just close
|
||||||
|
* the connection and actually send a reply. this case may
|
||||||
|
* happen when a browser keeps a persistent connection open
|
||||||
|
* and we timeout on the read.
|
||||||
|
*/
|
||||||
|
return (-1);
|
||||||
|
case EVCON_HTTP_INVALID_HEADER:
|
||||||
|
default: /* xxx: probably should just error on default */
|
||||||
|
/* the callback looks at the uri to determine errors */
|
||||||
|
if (req->uri) {
|
||||||
|
free(req->uri);
|
||||||
|
req->uri = NULL;
|
||||||
|
}
|
||||||
|
(*req->cb)(req, req->cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evhttp_connection_fail(struct evhttp_connection *evcon)
|
evhttp_connection_fail(struct evhttp_connection *evcon,
|
||||||
|
enum evhttp_connection_error error)
|
||||||
{
|
{
|
||||||
struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
|
struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
|
||||||
assert(req != NULL);
|
assert(req != NULL);
|
||||||
@ -412,15 +440,11 @@ evhttp_connection_fail(struct evhttp_connection *evcon)
|
|||||||
* kill the connection.
|
* kill the connection.
|
||||||
*/
|
*/
|
||||||
if (evcon->flags & EVHTTP_CON_INCOMING) {
|
if (evcon->flags & EVHTTP_CON_INCOMING) {
|
||||||
/* the callback looks at the uri to determine errors */
|
if (evhttp_connection_incoming_fail(req, error) == 0)
|
||||||
if (req->uri) {
|
return;
|
||||||
free(req->uri);
|
} else {
|
||||||
req->uri = NULL;
|
(*req->cb)(NULL, req->cb_arg);
|
||||||
}
|
|
||||||
(*req->cb)(req, req->cb_arg);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
(*req->cb)(NULL, req->cb_arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset the connection */
|
/* reset the connection */
|
||||||
@ -444,20 +468,20 @@ evhttp_write(int fd, short what, void *arg)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (what == EV_TIMEOUT) {
|
if (what == EV_TIMEOUT) {
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = evbuffer_write(evcon->output_buffer, fd);
|
n = evbuffer_write(evcon->output_buffer, fd);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
event_warn("%s: evbuffer_write", __func__);
|
event_warn("%s: evbuffer_write", __func__);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
event_warnx("%s: write nothing\n", __func__);
|
event_warnx("%s: write nothing\n", __func__);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +553,7 @@ evhttp_read(int fd, short what, void *arg)
|
|||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (what == EV_TIMEOUT) {
|
if (what == EV_TIMEOUT) {
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +562,7 @@ evhttp_read(int fd, short what, void *arg)
|
|||||||
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
event_warn("%s: evbuffer_read", __func__);
|
event_warn("%s: evbuffer_read", __func__);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,7 +993,7 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
|
|||||||
event_warnx("%s: we got no content length, but the server"
|
event_warnx("%s: we got no content length, but the server"
|
||||||
" wants to keep the connection open: %s.\n",
|
" wants to keep the connection open: %s.\n",
|
||||||
__func__, connection);
|
__func__, connection);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||||
return;
|
return;
|
||||||
} else if (content_length == NULL)
|
} else if (content_length == NULL)
|
||||||
req->ntoread = -1;
|
req->ntoread = -1;
|
||||||
@ -1005,19 +1029,19 @@ evhttp_read_header(int fd, short what, void *arg)
|
|||||||
|
|
||||||
if (what == EV_TIMEOUT) {
|
if (what == EV_TIMEOUT) {
|
||||||
event_warnx("%s: timeout on %d\n", __func__, fd);
|
event_warnx("%s: timeout on %d\n", __func__, fd);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = evbuffer_read(evcon->input_buffer, fd, -1);
|
n = evbuffer_read(evcon->input_buffer, fd, -1);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
event_warnx("%s: no more data on %d\n", __func__, fd);
|
event_warnx("%s: no more data on %d\n", __func__, fd);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
event_warnx("%s: bad read on %d\n", __func__, fd);
|
event_warnx("%s: bad read on %d\n", __func__, fd);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1025,7 +1049,7 @@ evhttp_read_header(int fd, short what, void *arg)
|
|||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
/* Error while reading, terminate */
|
/* Error while reading, terminate */
|
||||||
event_debug(("%s: bad header lines on %d\n", __func__, fd));
|
event_debug(("%s: bad header lines on %d\n", __func__, fd));
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||||
return;
|
return;
|
||||||
} else if (res == 0) {
|
} else if (res == 0) {
|
||||||
/* Need more header lines */
|
/* Need more header lines */
|
||||||
@ -1051,7 +1075,7 @@ evhttp_read_header(int fd, short what, void *arg)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
event_warnx("%s: bad header on %d\n", __func__, fd);
|
event_warnx("%s: bad header on %d\n", __func__, fd);
|
||||||
evhttp_connection_fail(evcon);
|
evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user