0
0
mirror of https://github.com/darkk/redsocks.git synced 2025-08-28 20:55:30 +00:00

Libevent2 fix: bad default line-extracting strategy

Libevent 2 deprecates evbuffer_readline() function, where any sequence
of any number of carriage return and linefeed characters is treated like
end of line, and introduces better evbuffer_readln(), where termination
format can be explicitly set to: \n, [\r]\n, \r\n or already mentioned
old behaviour.

Change past evbuffer_readline() calls to new
redsocks_evbuffer_readline() function. If libevent 2 is present, use
there evbuffer_readln() with eol_style set to an optional carriage
return, followed by a linefeed (EVBUFFER_EOL_CRLF) instead of obsolete
evbuffer_readln().

  Important note:
Consuming all CR and LF characters in one go (behaviour of
evbuffer_readline(), nowadays aliasing to evbuffer_readln() with
eol_style set to EVBUFFER_EOL_ANY) hangs up parsing of HTTP request
header ending with "\r\n\r\n", because it misses the empty line.

Conflicts (resolved):

	utils.c
	utils.h
This commit is contained in:
Bin Jin 2011-02-20 13:36:38 +08:00 committed by Leonid Evdokimov
parent 457c5eb79a
commit dcbdcae943
4 changed files with 17 additions and 7 deletions

View File

@ -64,7 +64,7 @@ static char *get_auth_request_header(struct evbuffer *buf)
{ {
char *line; char *line;
for (;;) { for (;;) {
line = evbuffer_readline(buf); line = redsocks_evbuffer_readline(buf);
if (line == NULL || *line == '\0' || strchr(line, ':') == NULL) { if (line == NULL || *line == '\0' || strchr(line, ':') == NULL) {
free(line); free(line);
return NULL; return NULL;
@ -86,7 +86,7 @@ static void httpc_read_cb(struct bufferevent *buffev, void *_arg)
if (client->state == httpc_request_sent) { if (client->state == httpc_request_sent) {
size_t len = EVBUFFER_LENGTH(buffev->input); size_t len = EVBUFFER_LENGTH(buffev->input);
char *line = evbuffer_readline(buffev->input); char *line = redsocks_evbuffer_readline(buffev->input);
if (line) { if (line) {
unsigned int code; unsigned int code;
if (sscanf(line, "HTTP/%*u.%*u %u", &code) == 1) { // 1 == one _assigned_ match if (sscanf(line, "HTTP/%*u.%*u %u", &code) == 1) { // 1 == one _assigned_ match
@ -163,7 +163,7 @@ static void httpc_read_cb(struct bufferevent *buffev, void *_arg)
return; return;
while (client->state == httpc_reply_came) { while (client->state == httpc_reply_came) {
char *line = evbuffer_readline(buffev->input); char *line = redsocks_evbuffer_readline(buffev->input);
if (line) { if (line) {
if (strlen(line) == 0) { if (strlen(line) == 0) {
client->state = httpc_headers_skipped; client->state = httpc_headers_skipped;

View File

@ -130,7 +130,7 @@ static char *get_auth_request_header(struct evbuffer *buf)
{ {
char *line; char *line;
for (;;) { for (;;) {
line = evbuffer_readline(buf); line = redsocks_evbuffer_readline(buf);
if (line == NULL || *line == '\0' || strchr(line, ':') == NULL) { if (line == NULL || *line == '\0' || strchr(line, ':') == NULL) {
free(line); free(line);
return NULL; return NULL;
@ -156,7 +156,7 @@ static void httpr_relay_read_cb(struct bufferevent *buffev, void *_arg)
if (client->state == httpr_request_sent) { if (client->state == httpr_request_sent) {
size_t len = EVBUFFER_LENGTH(buffev->input); size_t len = EVBUFFER_LENGTH(buffev->input);
char *line = evbuffer_readline(buffev->input); char *line = redsocks_evbuffer_readline(buffev->input);
if (line) { if (line) {
httpr_buffer_append(&httpr->relay_buffer, line, strlen(line)); httpr_buffer_append(&httpr->relay_buffer, line, strlen(line));
httpr_buffer_append(&httpr->relay_buffer, "\r\n", 2); httpr_buffer_append(&httpr->relay_buffer, "\r\n", 2);
@ -236,7 +236,7 @@ static void httpr_relay_read_cb(struct bufferevent *buffev, void *_arg)
return; return;
while (client->state == httpr_reply_came) { while (client->state == httpr_reply_came) {
char *line = evbuffer_readline(buffev->input); char *line = redsocks_evbuffer_readline(buffev->input);
if (line) { if (line) {
httpr_buffer_append(&httpr->relay_buffer, line, strlen(line)); httpr_buffer_append(&httpr->relay_buffer, line, strlen(line));
httpr_buffer_append(&httpr->relay_buffer, "\r\n", 2); httpr_buffer_append(&httpr->relay_buffer, "\r\n", 2);
@ -491,7 +491,7 @@ static void httpr_client_read_cb(struct bufferevent *buffev, void *_arg)
char *line = NULL; char *line = NULL;
int connect_relay = 0; int connect_relay = 0;
while (!connect_relay && (line = evbuffer_readline(buffev->input))) { while (!connect_relay && (line = redsocks_evbuffer_readline(buffev->input))) {
int skip_line = 0; int skip_line = 0;
int do_drop = 0; int do_drop = 0;

View File

@ -60,6 +60,15 @@ time_t redsocks_time(time_t *t)
return retval; return retval;
} }
char *redsocks_evbuffer_readline(struct evbuffer *buf)
{
#if _EVENT_NUMERIC_VERSION >= 0x02000000
return evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
#else
return evbuffer_readline(buf);
#endif
}
struct bufferevent* red_connect_relay(struct sockaddr_in *addr, evbuffercb writecb, everrorcb errorcb, void *cbarg) struct bufferevent* red_connect_relay(struct sockaddr_in *addr, evbuffercb writecb, everrorcb errorcb, void *cbarg)
{ {
struct bufferevent *retval = NULL; struct bufferevent *retval = NULL;

View File

@ -32,6 +32,7 @@ struct sockaddr_in;
(type *)( (char *)__mptr - offsetof(type,member) );}) (type *)( (char *)__mptr - offsetof(type,member) );})
time_t redsocks_time(time_t *t); time_t redsocks_time(time_t *t);
char *redsocks_evbuffer_readline(struct evbuffer *buf);
struct bufferevent* red_connect_relay(struct sockaddr_in *addr, evbuffercb writecb, everrorcb errorcb, void *cbarg); struct bufferevent* red_connect_relay(struct sockaddr_in *addr, evbuffercb writecb, everrorcb errorcb, void *cbarg);
int red_socket_geterrno(struct bufferevent *buffev); int red_socket_geterrno(struct bufferevent *buffev);
int red_is_socket_connected_ok(struct bufferevent *buffev); int red_is_socket_connected_ok(struct bufferevent *buffev);