From 23b3d7483f7c220cf6dab6f9fe1ebfc25fb93712 Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 30 Sep 2013 13:43:13 +0200 Subject: [PATCH] introducing raw mode --- core/socket.c | 15 ++++++++++++++- core/utils.c | 2 +- core/uwsgi.c | 4 ++++ plugins/python/python_plugin.c | 9 ++++++++- plugins/python/raw.c | 24 ++++++++++++++++++++++++ plugins/python/uwsgi_python.h | 7 ++++++- plugins/python/uwsgiplugin.py | 2 +- plugins/python/wsgi_handlers.c | 2 ++ proto/base.c | 10 ++++++++-- uwsgi.h | 5 +++++ 10 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 plugins/python/raw.c diff --git a/core/socket.c b/core/socket.c index 0016aea4..33e14008 100644 --- a/core/socket.c +++ b/core/socket.c @@ -1877,7 +1877,20 @@ setup_proto: if (uwsgi.offload_threads > 0) uwsgi_sock->can_offload = 1; } - + else if (requested_protocol && !strcmp("raw", requested_protocol)) { + uwsgi_sock->proto = uwsgi_proto_raw_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; + 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; diff --git a/core/utils.c b/core/utils.c index 21df5ddf..75bd5f63 100644 --- a/core/utils.c +++ b/core/utils.c @@ -1029,7 +1029,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) { } // after_request hook - if (uwsgi.p[wsgi_req->uh->modifier1]->after_request) + if (!wsgi_req->is_raw && uwsgi.p[wsgi_req->uh->modifier1]->after_request) uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req); if (uwsgi.threads > 1) { diff --git a/core/uwsgi.c b/core/uwsgi.c index 0db57e3a..2cac0d82 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -53,6 +53,10 @@ static struct uwsgi_option uwsgi_base_options[] = { {"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}, + {"raw-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using RAW protocol", uwsgi_opt_add_socket, "raw", 0}, + {"raw-modifier1", required_argument, 0, "force the specified modifier1 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_modifier1, 0}, + {"raw-modifier2", required_argument, 0, "force the specified modifier2 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_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/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index 69dd44f7..57cc581a 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -160,6 +160,8 @@ struct uwsgi_option uwsgi_python_options[] = { {"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE}, + {"python-raw", required_argument, 0, "load a python file for managing raw requests", uwsgi_opt_set_str, &up.raw, 0}, + {0, 0, 0, 0, 0, 0, 0}, }; @@ -1074,7 +1076,6 @@ void uwsgi_python_init_apps() { up.loaders[LOADER_CALLABLE] = uwsgi_callable_loader; up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader; - struct uwsgi_string_list *upli = up.import_list; while(upli) { if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) { @@ -1125,6 +1126,12 @@ next: uppa = uppa->next; } + if (up.raw) { + up.raw_callable = uwsgi_file_loader(up.raw); + if (up.raw_callable) { + Py_INCREF(up.raw_callable); + } + } if (up.wsgi_config != NULL) { init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI); diff --git a/plugins/python/raw.c b/plugins/python/raw.c new file mode 100644 index 00000000..52ceba54 --- /dev/null +++ b/plugins/python/raw.c @@ -0,0 +1,24 @@ +#include "uwsgi_python.h" + +extern struct uwsgi_server uwsgi; +extern struct uwsgi_python up; + +static int manage_raw_response(struct wsgi_request *wsgi_req) { + return 0; +} + +int uwsgi_request_python_raw(struct wsgi_request *wsgi_req) { + if (!up.raw_callable) return UWSGI_OK; + + UWSGI_GET_GIL + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, PyInt_FromLong(wsgi_req->fd)); + wsgi_req->async_result = PyEval_CallObject(up.raw_callable, args); + if (wsgi_req->async_result) { + manage_raw_response(wsgi_req); + Py_DECREF((PyObject *) wsgi_req->async_result); + } + Py_DECREF(args); + UWSGI_RELEASE_GIL; + return UWSGI_OK; +} diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index 3420e89d..79d4b017 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -1,4 +1,4 @@ -#include "../../uwsgi.h" +#include #include #include @@ -181,6 +181,9 @@ struct uwsgi_python { char *programname; int wsgi_strict; + + char *raw; + PyObject *raw_callable; }; @@ -277,6 +280,8 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *); struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *); void uwsgi_python_exception_log(struct wsgi_request *); +int uwsgi_request_python_raw(struct wsgi_request *); + #define py_current_wsgi_req() current_wsgi_req();\ if (!wsgi_req) {\ return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\ diff --git a/plugins/python/uwsgiplugin.py b/plugins/python/uwsgiplugin.py index 13c29cdc..687da1a2 100644 --- a/plugins/python/uwsgiplugin.py +++ b/plugins/python/uwsgiplugin.py @@ -11,7 +11,7 @@ def get_python_version(): return version NAME='python' -GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker'] +GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker', 'raw'] CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ] LDFLAGS = [] diff --git a/plugins/python/wsgi_handlers.c b/plugins/python/wsgi_handlers.c index 518ddfa9..badb1ae9 100644 --- a/plugins/python/wsgi_handlers.c +++ b/plugins/python/wsgi_handlers.c @@ -292,6 +292,8 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) { int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) { + if (wsgi_req->is_raw) return uwsgi_request_python_raw(wsgi_req); + struct uwsgi_app *wi; if (wsgi_req->async_force_again) { diff --git a/proto/base.c b/proto/base.c index 6b424db0..4a413c24 100644 --- a/proto/base.c +++ b/proto/base.c @@ -1,8 +1,14 @@ - -#include "../uwsgi.h" +#include extern struct uwsgi_server uwsgi; +int uwsgi_proto_raw_parser(struct wsgi_request *wsgi_req) { + wsgi_req->is_raw = 1; + wsgi_req->uh->modifier1 = uwsgi.raw_modifier1; + wsgi_req->uh->modifier2 = uwsgi.raw_modifier2; + return UWSGI_OK; +} + uint16_t proto_base_add_uwsgi_header(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) { diff --git a/uwsgi.h b/uwsgi.h index b1cc53c9..694318df 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1524,6 +1524,8 @@ struct wsgi_request { char *transformed_chunk; size_t transformed_chunk_len; + int is_raw; + struct msghdr msg; union { struct cmsghdr cmsg; @@ -1726,6 +1728,8 @@ struct uwsgi_server { uint64_t http_modifier2; uint64_t scgi_modifier1; uint64_t scgi_modifier2; + uint64_t raw_modifier1; + uint64_t raw_modifier2; // enable lazy mode int lazy; @@ -3203,6 +3207,7 @@ int uwsgi_proto_scgi_parser(struct wsgi_request *); int uwsgi_proto_base_accept(struct wsgi_request *, int); +int uwsgi_proto_raw_parser(struct wsgi_request *); void uwsgi_proto_base_close(struct wsgi_request *); uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t); uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);