| Line 293... |
Line 293... |
| 293 |
workers[i] = NULL;
|
293 |
workers[i] = NULL;
|
| 294 |
DBG(printf("removing worker %p\n", (void*) c));
|
294 |
DBG(printf("removing worker %p\n", (void*) c));
|
| 295 |
free(c);
|
295 |
free(c);
|
| 296 |
}
|
296 |
}
|
| 297 |
|
297 |
|
| - |
|
298 |
#ifndef Win32
|
| - |
|
299 |
extern int R_ignore_SIGPIPE; /* defined in src/main/main.c on unix */
|
| - |
|
300 |
#else
|
| - |
|
301 |
static int R_ignore_SIGPIPE; /* for simplicity of the code below */
|
| - |
|
302 |
#endif
|
| - |
|
303 |
|
| 298 |
static int send_response(SOCKET s, const char *buf, unsigned int len)
|
304 |
static int send_response(SOCKET s, const char *buf, unsigned int len)
|
| 299 |
{
|
305 |
{
|
| 300 |
unsigned int i = 0;
|
306 |
unsigned int i = 0;
|
| - |
|
307 |
/* we have to tell R to ignore SIGPIPE otherwise it can raise an error
|
| - |
|
308 |
and get us into deep trouble */
|
| - |
|
309 |
R_ignore_SIGPIPE = 1;
|
| 301 |
while (i < len) {
|
310 |
while (i < len) {
|
| 302 |
int n = send(s, buf + i, len - i, 0);
|
311 |
int n = send(s, buf + i, len - i, 0);
|
| - |
|
312 |
if (n < 1) {
|
| - |
|
313 |
R_ignore_SIGPIPE = 0;
|
| 303 |
if (n < 1) return -1;
|
314 |
return -1;
|
| - |
|
315 |
}
|
| 304 |
i += n;
|
316 |
i += n;
|
| 305 |
}
|
317 |
}
|
| - |
|
318 |
R_ignore_SIGPIPE = 0;
|
| 306 |
return 0;
|
319 |
return 0;
|
| 307 |
}
|
320 |
}
|
| 308 |
|
321 |
|
| 309 |
/* sends HTTP/x.x plus the text (which should be of the form " XXX ...") */
|
322 |
/* sends HTTP/x.x plus the text (which should be of the form " XXX ...") */
|
| 310 |
static int send_http_response(httpd_conn_t *c, const char *text) {
|
323 |
static int send_http_response(httpd_conn_t *c, const char *text) {
|
| 311 |
char buf[96];
|
324 |
char buf[96];
|
| 312 |
const char *s = HTTP_SIG(c);
|
325 |
const char *s = HTTP_SIG(c);
|
| 313 |
int l = strlen(text);
|
326 |
int l = strlen(text), res;
|
| 314 |
/* reduce the number of packets by sending the payload en-block from buf */
|
327 |
/* reduce the number of packets by sending the payload en-block from buf */
|
| 315 |
if (l < sizeof(buf) - 10) {
|
328 |
if (l < sizeof(buf) - 10) {
|
| 316 |
strcpy(buf, s);
|
329 |
strcpy(buf, s);
|
| 317 |
strcpy(buf + 8, text);
|
330 |
strcpy(buf + 8, text);
|
| 318 |
return send_response(c->sock, buf, l + 8);
|
331 |
return send_response(c->sock, buf, l + 8);
|
| 319 |
}
|
332 |
}
|
| - |
|
333 |
R_ignore_SIGPIPE = 1;
|
| 320 |
if (send(c->sock, s, 8, 0) < 8) return -1;
|
334 |
res = send(c->sock, s, 8, 0);
|
| - |
|
335 |
R_ignore_SIGPIPE = 0;
|
| - |
|
336 |
if (res < 8) return -1;
|
| 321 |
return send_response(c->sock, text, strlen(text));
|
337 |
return send_response(c->sock, text, strlen(text));
|
| 322 |
}
|
338 |
}
|
| 323 |
|
339 |
|
| 324 |
/* decode URI in place (decoding never expands) */
|
340 |
/* decode URI in place (decoding never expands) */
|
| 325 |
static void uri_decode(char *s)
|
341 |
static void uri_decode(char *s)
|
| Line 721... |
Line 737... |
| 721 |
/* move the body part to the beginning of the buffer */
|
737 |
/* move the body part to the beginning of the buffer */
|
| 722 |
c->line_pos -= s - c->line_buf;
|
738 |
c->line_pos -= s - c->line_buf;
|
| 723 |
memmove(c->line_buf, s, c->line_pos);
|
739 |
memmove(c->line_buf, s, c->line_pos);
|
| 724 |
if (c->method != METHOD_POST) { /* anything but POST can be processed right away */
|
740 |
if (c->method != METHOD_POST) { /* anything but POST can be processed right away */
|
| 725 |
if (c->attr & CONTENT_LENGTH) {
|
741 |
if (c->attr & CONTENT_LENGTH) {
|
| 726 |
send(c->sock, "HTTP/1.0 400 Bad Request (GET/HEAD with body)\r\n\r\n", 49, 0);
|
742 |
send_http_response(c, " 400 Bad Request (GET/HEAD with body)\r\n\r\n");
|
| 727 |
remove_worker(c);
|
743 |
remove_worker(c);
|
| 728 |
return;
|
744 |
return;
|
| 729 |
}
|
745 |
}
|
| 730 |
process_request(c);
|
746 |
process_request(c);
|
| 731 |
if (c->attr & CONNECTION_CLOSE) {
|
747 |
if (c->attr & CONNECTION_CLOSE) {
|
| Line 758... |
Line 774... |
| 758 |
if (!*s) { /* incomplete line */
|
774 |
if (!*s) { /* incomplete line */
|
| 759 |
if (bol == c->line_buf) {
|
775 |
if (bol == c->line_buf) {
|
| 760 |
if (c->line_pos < LINE_BUF_SIZE) /* one, incomplete line, but the buffer is not full yet, just return */
|
776 |
if (c->line_pos < LINE_BUF_SIZE) /* one, incomplete line, but the buffer is not full yet, just return */
|
| 761 |
return;
|
777 |
return;
|
| 762 |
/* the buffer is full yet the line is incomplete - we're in trouble */
|
778 |
/* the buffer is full yet the line is incomplete - we're in trouble */
|
| 763 |
send(c->sock, "HTTP/1.0 413 Request entity too large\r\nConnection: close\r\n\r\n", 60, 0);
|
779 |
send_http_response(c, " 413 Request entity too large\r\nConnection: close\r\n\r\n");
|
| 764 |
remove_worker(c);
|
780 |
remove_worker(c);
|
| 765 |
return;
|
781 |
return;
|
| 766 |
}
|
782 |
}
|
| 767 |
/* move the line to the begining of the buffer for later requests */
|
783 |
/* move the line to the begining of the buffer for later requests */
|
| 768 |
c->line_pos -= bol - c->line_buf;
|
784 |
c->line_pos -= bol - c->line_buf;
|
| Line 775... |
Line 791... |
| 775 |
if (c->part == PART_REQUEST) {
|
791 |
if (c->part == PART_REQUEST) {
|
| 776 |
/* --- process request line --- */
|
792 |
/* --- process request line --- */
|
| 777 |
unsigned int rll = strlen(bol); /* request line length */
|
793 |
unsigned int rll = strlen(bol); /* request line length */
|
| 778 |
char *url = bol + 5;
|
794 |
char *url = bol + 5;
|
| 779 |
if (rll < 14 || strncmp(bol + rll - 9, " HTTP/1.", 8)) { /* each request must have at least 14 characters [GET / HTTP/1.0] and have HTTP/1.x */
|
795 |
if (rll < 14 || strncmp(bol + rll - 9, " HTTP/1.", 8)) { /* each request must have at least 14 characters [GET / HTTP/1.0] and have HTTP/1.x */
|
| 780 |
send(c->sock, "HTTP/1.0 400 Bad Request\r\n\r\n", 28, 0);
|
796 |
send_response(c->sock, "HTTP/1.0 400 Bad Request\r\n\r\n", 28);
|
| 781 |
remove_worker(c);
|
797 |
remove_worker(c);
|
| 782 |
return;
|
798 |
return;
|
| 783 |
}
|
799 |
}
|
| 784 |
if (!strncmp(bol + rll - 3, "1.0", 3)) c->attr |= HTTP_1_0;
|
800 |
if (!strncmp(bol + rll - 3, "1.0", 3)) c->attr |= HTTP_1_0;
|
| 785 |
if (!strncmp(bol, "GET ", 4)) { c->method = METHOD_GET; url--; }
|
801 |
if (!strncmp(bol, "GET ", 4)) { c->method = METHOD_GET; url--; }
|
| 786 |
if (!strncmp(bol, "POST ", 5)) c->method = METHOD_POST;
|
802 |
if (!strncmp(bol, "POST ", 5)) c->method = METHOD_POST;
|
| 787 |
if (!strncmp(bol, "HEAD ", 5)) c->method = METHOD_HEAD;
|
803 |
if (!strncmp(bol, "HEAD ", 5)) c->method = METHOD_HEAD;
|
| 788 |
if (!c->method) {
|
804 |
if (!c->method) {
|
| 789 |
send(c->sock, "HTTP/1.0 501 Invalid or unimplemented method\r\n\r\n", 48, 0);
|
805 |
send_http_response(c, " 501 Invalid or unimplemented method\r\n\r\n");
|
| 790 |
remove_worker(c);
|
806 |
remove_worker(c);
|
| 791 |
return;
|
807 |
return;
|
| 792 |
}
|
808 |
}
|
| 793 |
bol[strlen(bol) - 9] = 0;
|
809 |
bol[strlen(bol) - 9] = 0;
|
| 794 |
c->url = strdup(url);
|
810 |
c->url = strdup(url);
|