The R Project SVN R

Rev

Rev 59184 | Rev 62724 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 59184 Rev 59338
Line 170... Line 170...
170
    struct buffer *next, *prev;
170
    struct buffer *next, *prev;
171
    size_t size, length;
171
    size_t size, length;
172
    char data[1];
172
    char data[1];
173
};
173
};
174
 
174
 
-
 
175
/* we have to protect re-entrance and not continue processing if there is
-
 
176
   a worker inside R already. If we did not then another client connection
-
 
177
   would trigger handler and pile up eval on top of the stack, leading to
-
 
178
   exhaustion very quickly and a big mess */
-
 
179
static int in_process;
-
 
180
 
175
/* --- connection/worker structure holding all data for an active connection --- */
181
/* --- connection/worker structure holding all data for an active connection --- */
176
typedef struct httpd_conn {
182
typedef struct httpd_conn {
177
    SOCKET sock;         /* client socket */
183
    SOCKET sock;         /* client socket */
178
    struct in_addr peer; /* IP address of the peer */
184
    struct in_addr peer; /* IP address of the peer */
179
#ifdef WIN32
185
#ifdef WIN32
Line 545... Line 551...
545
    DBG(Rprintf(" - falling back to default httpd\n"));
551
    DBG(Rprintf(" - falling back to default httpd\n"));
546
    return install("httpd");
552
    return install("httpd");
547
}
553
}
548
 
554
 
549
/* process a request by calling the httpd() function in R */
555
/* process a request by calling the httpd() function in R */
550
static void process_request(httpd_conn_t *c)
556
static void process_request_(void *ptr)
551
{
557
{
-
 
558
    httpd_conn_t *c = (httpd_conn_t*) ptr;
552
    const char *ct = "text/html";
559
    const char *ct = "text/html";
553
    char *query = 0, *s;
560
    char *query = 0, *s;
554
    SEXP sHeaders = R_NilValue;
561
    SEXP sHeaders = R_NilValue;
555
    int code = 200;
562
    int code = 200;
556
    DBG(Rprintf("process request for %p\n", (void*) c));
563
    DBG(Rprintf("process request for %p\n", (void*) c));
Line 729... Line 736...
729
    }
736
    }
730
    send_http_response(c, " 500 Invalid response from R\r\nConnection: close\r\nContent-type: text/plain\r\n\r\nServer error: invalid response from R\r\n");
737
    send_http_response(c, " 500 Invalid response from R\r\nConnection: close\r\nContent-type: text/plain\r\n\r\nServer error: invalid response from R\r\n");
731
    c->attr |= CONNECTION_CLOSE; /* force close */
738
    c->attr |= CONNECTION_CLOSE; /* force close */
732
}
739
}
733
 
740
 
-
 
741
/* wrap the actual call with ToplevelExec since we need to have a guaranteed
-
 
742
   return so we can track the presence of a worker code inside R to prevent
-
 
743
   re-entrance from other clients */
-
 
744
static void process_request(httpd_conn_t *c)
-
 
745
{
-
 
746
    in_process = 1;
-
 
747
    R_ToplevelExec(process_request_, c);
-
 
748
    in_process = 0;
-
 
749
}
-
 
750
 
734
#ifdef WIN32
751
#ifdef WIN32
735
#undef process_request
752
#undef process_request
736
#endif
753
#endif
737
 
754
 
738
/* this function is called to fetch new data from the client
755
/* this function is called to fetch new data from the client
Line 741... Line 758...
741
    httpd_conn_t *c = (httpd_conn_t*) data;
758
    httpd_conn_t *c = (httpd_conn_t*) data;
742
 
759
 
743
    DBG(printf("worker_input_handler, data=%p\n", data));
760
    DBG(printf("worker_input_handler, data=%p\n", data));
744
    if (!c) return;
761
    if (!c) return;
745
 
762
 
-
 
763
    if (in_process) return; /* we don't allow recursive entrance */
-
 
764
 
746
    DBG(printf("input handler for worker %p (sock=%d, part=%d, method=%d, line_pos=%d)\n", (void*) c, (int)c->sock, (int)c->part, (int)c->method, (int)c->line_pos));
765
    DBG(printf("input handler for worker %p (sock=%d, part=%d, method=%d, line_pos=%d)\n", (void*) c, (int)c->sock, (int)c->part, (int)c->method, (int)c->line_pos));
747
 
766
 
748
    /* FIXME: there is one edge case that is not caught on unix: if
767
    /* FIXME: there is one edge case that is not caught on unix: if
749
     * recv reads two or more full requests into the line buffer then
768
     * recv reads two or more full requests into the line buffer then
750
     * this function exits after the first one, but input handlers may
769
     * this function exits after the first one, but input handlers may