mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 13:53:31 +01:00
more robust http(ish) handling
svn:r123
This commit is contained in:
parent
e0f77fc36b
commit
827c7444f8
@ -131,7 +131,7 @@ int write_to_buf(char *string, int string_len,
|
|||||||
int fetch_from_buf(char *string, int string_len,
|
int fetch_from_buf(char *string, int string_len,
|
||||||
char **buf, int *buflen, int *buf_datalen) {
|
char **buf, int *buflen, int *buf_datalen) {
|
||||||
|
|
||||||
/* if there is string_len bytes in buf, write them onto string,
|
/* if there are string_len bytes in buf, write them onto string,
|
||||||
* then memmove buf back (that is, remove them from buf) */
|
* then memmove buf back (that is, remove them from buf) */
|
||||||
|
|
||||||
assert(string && buf && *buf && buflen && buf_datalen);
|
assert(string && buf && *buf && buflen && buf_datalen);
|
||||||
@ -147,3 +147,25 @@ int fetch_from_buf(char *string, int string_len,
|
|||||||
return *buf_datalen;
|
return *buf_datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_on_inbuf(char *string, int string_len,
|
||||||
|
char *buf, int buf_datalen) {
|
||||||
|
/* find first instance of needle 'string' on haystack 'buf'. return how
|
||||||
|
* many bytes from the beginning of buf to the end of string.
|
||||||
|
* If it's not there, return -1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *location;
|
||||||
|
char *last_possible = buf + buf_datalen - string_len;
|
||||||
|
|
||||||
|
assert(string && string_len > 0 && buf);
|
||||||
|
|
||||||
|
if(buf_datalen < string_len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(location = buf; location <= last_possible; location++)
|
||||||
|
if((*location == *string) && !memcmp(location+1, string+1, string_len-1))
|
||||||
|
return location-buf+string_len;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -352,6 +352,10 @@ int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
|
|||||||
return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
|
return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
|
||||||
|
return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
|
||||||
|
}
|
||||||
|
|
||||||
int connection_wants_to_flush(connection_t *conn) {
|
int connection_wants_to_flush(connection_t *conn) {
|
||||||
return conn->outbuf_flushlen;
|
return conn->outbuf_flushlen;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,10 @@ extern or_options_t options; /* command-line and config-file options */
|
|||||||
|
|
||||||
static char the_directory[MAX_DIR_SIZE+1];
|
static char the_directory[MAX_DIR_SIZE+1];
|
||||||
static int directorylen=0;
|
static int directorylen=0;
|
||||||
|
static int reading_headers=0;
|
||||||
|
|
||||||
static char getstring[] = "GET / HTTP/1.0\n\r";
|
static char getstring[] = "GET / HTTP/1.0\r\n\r\n";
|
||||||
|
static char answerstring[] = "HTTP/1.0 200 OK\r\n\r\n";
|
||||||
|
|
||||||
/********* END VARIABLES ************/
|
/********* END VARIABLES ************/
|
||||||
|
|
||||||
@ -22,11 +24,14 @@ void directory_initiate_fetch(routerinfo_t *router) {
|
|||||||
struct sockaddr_in router_addr;
|
struct sockaddr_in router_addr;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
log(LOG_DEBUG,"directory_initiate_fetch(): initiating directory fetch");
|
|
||||||
|
|
||||||
if(!router) /* i guess they didn't have one in mind for me to use */
|
if(!router) /* i guess they didn't have one in mind for me to use */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(connection_get_by_type(CONN_TYPE_DIR)) /* there's already a fetch running */
|
||||||
|
return;
|
||||||
|
|
||||||
|
log(LOG_DEBUG,"directory_initiate_fetch(): initiating directory fetch");
|
||||||
|
|
||||||
conn = connection_new(CONN_TYPE_DIR);
|
conn = connection_new(CONN_TYPE_DIR);
|
||||||
if(!conn)
|
if(!conn)
|
||||||
return;
|
return;
|
||||||
@ -107,7 +112,7 @@ int directory_send_command(connection_t *conn) {
|
|||||||
void directory_rebuild(void) {
|
void directory_rebuild(void) {
|
||||||
|
|
||||||
dump_directory_to_string(the_directory, MAX_DIR_SIZE);
|
dump_directory_to_string(the_directory, MAX_DIR_SIZE);
|
||||||
log(LOG_DEBUG,"New directory:\n'%s'",the_directory);
|
log(LOG_DEBUG,"New directory:\n%s",the_directory);
|
||||||
directorylen = strlen(the_directory);
|
directorylen = strlen(the_directory);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -155,6 +160,7 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int directory_handle_command(connection_t *conn) {
|
int directory_handle_command(connection_t *conn) {
|
||||||
|
char buf[15];
|
||||||
|
|
||||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||||
|
|
||||||
@ -163,7 +169,14 @@ int directory_handle_command(connection_t *conn) {
|
|||||||
return 0; /* not yet */
|
return 0; /* not yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for now, don't bother reading it. */
|
if(connection_fetch_from_buf(buf,strlen(getstring),conn) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strncasecmp(buf,getstring,strlen("GET / HTTP/"))) {
|
||||||
|
log(LOG_DEBUG,"directory_handle_command(): Command doesn't seem to be a get. Closing,");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(directorylen == 0) {
|
if(directorylen == 0) {
|
||||||
log(LOG_DEBUG,"directory_handle_command(): My directory is empty. Closing.");
|
log(LOG_DEBUG,"directory_handle_command(): My directory is empty. Closing.");
|
||||||
@ -171,7 +184,8 @@ int directory_handle_command(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log(LOG_DEBUG,"directory_handle_command(): Dumping directory to client.");
|
log(LOG_DEBUG,"directory_handle_command(): Dumping directory to client.");
|
||||||
if(connection_write_to_buf(the_directory, directorylen, conn) < 0) {
|
if((connection_write_to_buf(answerstring, strlen(answerstring), conn) < 0) ||
|
||||||
|
(connection_write_to_buf(the_directory, directorylen, conn) < 0)) {
|
||||||
log(LOG_DEBUG,"directory_handle_command(): my outbuf is full. Oops.");
|
log(LOG_DEBUG,"directory_handle_command(): my outbuf is full. Oops.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -182,9 +196,24 @@ int directory_handle_command(connection_t *conn) {
|
|||||||
|
|
||||||
int directory_handle_reading(connection_t *conn) {
|
int directory_handle_reading(connection_t *conn) {
|
||||||
int amt;
|
int amt;
|
||||||
|
char *headers;
|
||||||
|
|
||||||
assert(conn && conn->type == CONN_TYPE_DIR);
|
assert(conn && conn->type == CONN_TYPE_DIR);
|
||||||
|
|
||||||
|
if(reading_headers) {
|
||||||
|
amt = connection_find_on_inbuf("\r\n\r\n", 4, conn);
|
||||||
|
if(amt < 0) /* not there yet */
|
||||||
|
return 0;
|
||||||
|
headers = malloc(amt+1);
|
||||||
|
if(connection_fetch_from_buf(headers,amt,conn) < 0) {
|
||||||
|
log(LOG_DEBUG,"directory_handle_reading(): fetch_from_buf failed (reading headers).");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
headers[amt] = 0; /* null terminate it, */
|
||||||
|
free(headers); /* and then throw it away */
|
||||||
|
reading_headers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
amt = conn->inbuf_datalen;
|
amt = conn->inbuf_datalen;
|
||||||
|
|
||||||
if(amt + directorylen >= MAX_DIR_SIZE) {
|
if(amt + directorylen >= MAX_DIR_SIZE) {
|
||||||
@ -196,7 +225,7 @@ int directory_handle_reading(connection_t *conn) {
|
|||||||
amt, directorylen);
|
amt, directorylen);
|
||||||
|
|
||||||
if(connection_fetch_from_buf(the_directory+directorylen,amt,conn) < 0) {
|
if(connection_fetch_from_buf(the_directory+directorylen,amt,conn) < 0) {
|
||||||
log(LOG_DEBUG,"directory_handle_reading(): fetch_from_buf failed.");
|
log(LOG_DEBUG,"directory_handle_reading(): fetch_from_buf failed (reading dir).");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +262,7 @@ int connection_dir_finished_flushing(connection_t *conn) {
|
|||||||
case DIR_CONN_STATE_SENDING_COMMAND:
|
case DIR_CONN_STATE_SENDING_COMMAND:
|
||||||
log(LOG_DEBUG,"connection_dir_finished_flushing(): client finished sending command.");
|
log(LOG_DEBUG,"connection_dir_finished_flushing(): client finished sending command.");
|
||||||
directorylen = 0;
|
directorylen = 0;
|
||||||
|
reading_headers = 1;
|
||||||
conn->state = DIR_CONN_STATE_READING;
|
conn->state = DIR_CONN_STATE_READING;
|
||||||
connection_watch_events(conn, POLLIN);
|
connection_watch_events(conn, POLLIN);
|
||||||
return 0;
|
return 0;
|
||||||
|
11
src/or/or.h
11
src/or/or.h
@ -388,7 +388,15 @@ int write_to_buf(char *string, int string_len,
|
|||||||
int fetch_from_buf(char *string, int string_len,
|
int fetch_from_buf(char *string, int string_len,
|
||||||
char **buf, int *buflen, int *buf_datalen);
|
char **buf, int *buflen, int *buf_datalen);
|
||||||
/* if there is string_len bytes in buf, write them onto string,
|
/* if there is string_len bytes in buf, write them onto string,
|
||||||
* * then memmove buf back (that is, remove them from buf) */
|
* then memmove buf back (that is, remove them from buf)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int find_on_inbuf(char *string, int string_len,
|
||||||
|
char *buf, int buf_datalen);
|
||||||
|
/* find first instance of needle 'string' on haystack 'buf'. return how
|
||||||
|
* many bytes from the beginning of buf to the end of string.
|
||||||
|
* If it's not there, return -1.
|
||||||
|
*/
|
||||||
|
|
||||||
/********************************* cell.c ***************************/
|
/********************************* cell.c ***************************/
|
||||||
|
|
||||||
@ -463,6 +471,7 @@ int connection_read_to_buf(connection_t *conn);
|
|||||||
int connection_fetch_from_buf(char *string, int len, connection_t *conn);
|
int connection_fetch_from_buf(char *string, int len, connection_t *conn);
|
||||||
|
|
||||||
int connection_outbuf_too_full(connection_t *conn);
|
int connection_outbuf_too_full(connection_t *conn);
|
||||||
|
int connection_find_on_inbuf(char *string, int len, connection_t *conn);
|
||||||
int connection_wants_to_flush(connection_t *conn);
|
int connection_wants_to_flush(connection_t *conn);
|
||||||
int connection_flush_buf(connection_t *conn);
|
int connection_flush_buf(connection_t *conn);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user