diff --git a/core/socket.c b/core/socket.c index 72ae5b6b..734d9f09 100644 --- a/core/socket.c +++ b/core/socket.c @@ -1810,10 +1810,11 @@ setup_proto: if (uwsgi.offload_threads > 0) uwsgi_sock->can_offload = 1; } + else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) { uwsgi_sock->proto = uwsgi_proto_fastcgi_parser; uwsgi_sock->proto_accept = uwsgi_proto_base_accept; - uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers; + uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers; uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header; uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers; uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body; @@ -1822,6 +1823,46 @@ setup_proto: uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile; uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close; } + else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) { + uwsgi_sock->proto = uwsgi_proto_fastcgi_parser; + uwsgi_sock->proto_accept = uwsgi_proto_base_accept; + uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers; + uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header; + uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers; + uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body; + uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write; + uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write; + uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile; + uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close; + } + + else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) { + uwsgi_sock->proto = uwsgi_proto_scgi_parser; + uwsgi_sock->proto_accept = uwsgi_proto_base_accept; + uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers; + uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header; + uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers; + uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body; + uwsgi_sock->proto_write = uwsgi_proto_base_write; + uwsgi_sock->proto_write_headers = uwsgi_proto_base_write; + uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile; + uwsgi_sock->proto_close = uwsgi_proto_base_close; + } + + else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) { + uwsgi_sock->proto = uwsgi_proto_scgi_parser; + uwsgi_sock->proto_accept = uwsgi_proto_base_accept; + uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers; + uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header; + uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers; + uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body; + uwsgi_sock->proto_write = uwsgi_proto_base_write; + uwsgi_sock->proto_write_headers = uwsgi_proto_base_write; + uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile; + uwsgi_sock->proto_close = uwsgi_proto_base_close; + } + + #ifdef UWSGI_ZEROMQ else if (requested_protocol && !strcmp("zmq", requested_protocol)) { uwsgi.zeromq = 1; diff --git a/core/uwsgi.c b/core/uwsgi.c index d328904c..62707a78 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -37,12 +37,21 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS; static struct uwsgi_option uwsgi_base_options[] = { {"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0}, {"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0}, + {"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0}, {"http-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier1, 0}, {"http-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier2, 0}, + {"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi", 0}, + {"fastcgi-nph-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol (nph mode)", uwsgi_opt_add_socket, "fastcgi-nph", 0}, {"fastcgi-modifier1", required_argument, 0, "force the specified modifier1 when using FastCGI protocol", uwsgi_opt_set_64bit, &uwsgi.fastcgi_modifier1, 0}, {"fastcgi-modifier2", required_argument, 0, "force the specified modifier2 when using FastCGI protocol", uwsgi_opt_set_64bit, &uwsgi.fastcgi_modifier2, 0}, + + {"scgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using SCGI protocol", uwsgi_opt_add_socket, "scgi", 0}, + {"scgi-nph-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using SCGI protocol (nph mode)", uwsgi_opt_add_socket, "scgi-nph", 0}, + {"scgi-modifier1", required_argument, 0, "force the specified modifier1 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier1, 0}, + {"scgi-modifier2", required_argument, 0, "force the specified modifier2 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier2, 0}, + {"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0}, {"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0}, {"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0}, diff --git a/proto/base.c b/proto/base.c index dc495bcb..915e816a 100644 --- a/proto/base.c +++ b/proto/base.c @@ -153,6 +153,16 @@ end: return NULL; } +struct uwsgi_buffer *uwsgi_proto_base_cgi_prepare_headers(struct wsgi_request *wsgi_req, char *s, uint16_t sl) { + struct uwsgi_buffer *ub = uwsgi_buffer_new(7 + 1 + sl + 2); + ub = uwsgi_buffer_new(7 + 1 + sl + 2); + if (uwsgi_buffer_append(ub, "\r\n", 2)) goto end; + return ub; +end: + uwsgi_buffer_destroy(ub); + return NULL; +} + int uwsgi_proto_base_write(struct wsgi_request * wsgi_req, char *buf, size_t len) { ssize_t wlen = write(wsgi_req->fd, buf+wsgi_req->write_pos, len-wsgi_req->write_pos); diff --git a/proto/scgi.c b/proto/scgi.c new file mode 100644 index 00000000..95837f32 --- /dev/null +++ b/proto/scgi.c @@ -0,0 +1,40 @@ +/* async SCGI protocol parser */ + +#include + +extern struct uwsgi_server uwsgi; + +int uwsgi_proto_scgi_parser(struct wsgi_request *wsgi_req) { + char *ptr = (char *) wsgi_req->uh; + ssize_t len = read(wsgi_req->fd, ptr + wsgi_req->proto_parser_pos, (uwsgi.buffer_size+4) - wsgi_req->proto_parser_pos); + if (len > 0) { + wsgi_req->proto_parser_pos += len; + if (wsgi_req->proto_parser_pos >= 4) { + if ((wsgi_req->proto_parser_pos-4) == wsgi_req->uh->pktsize) { + return UWSGI_OK; + } + if ((wsgi_req->proto_parser_pos-4) > wsgi_req->uh->pktsize) { + wsgi_req->proto_parser_remains = wsgi_req->proto_parser_pos-(4+wsgi_req->uh->pktsize); + wsgi_req->proto_parser_remains_buf = wsgi_req->buffer + wsgi_req->uh->pktsize; + return UWSGI_OK; + } + if (wsgi_req->uh->pktsize > uwsgi.buffer_size) { + uwsgi_log("invalid request block size: %u (max %u)...skip\n", wsgi_req->uh->pktsize, uwsgi.buffer_size); + return -1; + } + } + return UWSGI_AGAIN; + } + if (len < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) { + return UWSGI_AGAIN; + } + uwsgi_error("uwsgi_proto_uwsgi_parser()"); + return -1; + } + // 0 len + if (wsgi_req->proto_parser_pos > 0) { + uwsgi_error("uwsgi_proto_uwsgi_parser()"); + } + return -1; +} diff --git a/uwsgi.h b/uwsgi.h index 963f216f..9726a9d1 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1520,6 +1520,8 @@ struct uwsgi_server { uint64_t fastcgi_modifier2; uint64_t http_modifier1; uint64_t http_modifier2; + uint64_t scgi_modifier1; + uint64_t scgi_modifier2; // enable lazy mode int lazy; @@ -2869,6 +2871,8 @@ int uwsgi_proto_fastcgi_sendfile(struct wsgi_request *, int, size_t, size_t); void uwsgi_proto_fastcgi_close(struct wsgi_request *); ssize_t uwsgi_proto_fastcgi_read_body(struct wsgi_request *, char *, size_t); +int uwsgi_proto_scgi_parser(struct wsgi_request *); + int uwsgi_proto_base_accept(struct wsgi_request *, int); void uwsgi_proto_base_close(struct wsgi_request *); @@ -3745,6 +3749,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *); void uwsgi_request_body_seek(struct wsgi_request *, off_t); struct uwsgi_buffer *uwsgi_proto_base_prepare_headers(struct wsgi_request *, char *, uint16_t); +struct uwsgi_buffer *uwsgi_proto_base_cgi_prepare_headers(struct wsgi_request *, char *, uint16_t); int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t); int uwsgi_proto_base_sendfile(struct wsgi_request *, int, size_t, size_t); diff --git a/uwsgiconfig.py b/uwsgiconfig.py index 57888809..e80aed35 100644 --- a/uwsgiconfig.py +++ b/uwsgiconfig.py @@ -456,6 +456,7 @@ class uConf(object): self.gcc_list.append('proto/uwsgi') self.gcc_list.append('proto/http') self.gcc_list.append('proto/fastcgi') + self.gcc_list.append('proto/scgi') self.include_path = [] self.cflags = ['-O2', '-I.', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()