diff --git a/Makefile.PyLua b/Makefile.PyLua new file mode 100644 index 00000000..cba1e0bf --- /dev/null +++ b/Makefile.PyLua @@ -0,0 +1,2 @@ +all: + python uwsgiconfig.py --build pylua diff --git a/buildconf/pylua.ini b/buildconf/pylua.ini new file mode 100644 index 00000000..64268227 --- /dev/null +++ b/buildconf/pylua.ini @@ -0,0 +1,31 @@ +[uwsgi] +xml = true +ini = true +snmp = true +sctp = false +erlang = false +spooler = true +embedded = true +udp = true +multicast = true +threading = true +sendfile = true +proxy = true +minterpreters = true +async = true +http = true +evdis = false +ldap = false +routing = false +stackless = false +debug = false +unbit = false +xml_implementation = libxml2 +plugins = +bin_name = uwsgi +plugin_dir = . +embedded_plugins = python, ping, nagios, lua + +[python] +paste = true +web3 = true diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 3a5d0fc2..460adc74 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -61,6 +61,38 @@ static int uwsgi_api_log(lua_State *L) { return 0; } +static int uwsgi_api_register_rpc(lua_State *L) { + + uint8_t argc = lua_gettop(L); + const char *name; + // a hack for 64bit; + int func; + long lfunc; + + if (argc < 2) { + lua_pushnil(L); + return 1; + } + + name = lua_tolstring(L, 1, NULL); + + lua_pushvalue(L, 2); + func = luaL_ref(L, LUA_REGISTRYINDEX); + + uwsgi_log("registered function %d in global table\n", func); + lfunc = func; + + if (uwsgi_register_rpc((char *)name, 6, 0, (void *) lfunc)) { + lua_pushnil(L); + } + else { + lua_pushboolean(L, 1); + } + + return 1; +} + + static char *encode_lua_table(lua_State *L, int index, uint16_t *size) { @@ -141,7 +173,7 @@ static int uwsgi_api_register_signal(lua_State *L) { int args = lua_gettop(L); uint8_t sig, kind; - const void *handler; + long lhandler; const char *payload; size_t payload_size; @@ -150,14 +182,14 @@ static int uwsgi_api_register_signal(lua_State *L) { sig = lua_tonumber(L, 1); kind = lua_tonumber(L, 2); lua_pushvalue(L, 3); - handler = (void *) luaL_ref(L, LUA_REGISTRYINDEX); + lhandler = luaL_ref(L, LUA_REGISTRYINDEX); if (args > 3) { payload = lua_tolstring(L, 4, &payload_size); - uwsgi_register_signal(sig, kind, (void *) handler, 6, (char *) payload, payload_size); + uwsgi_register_signal(sig, kind, (void *) lhandler, 6, (char *) payload, payload_size); } else { - uwsgi_register_signal(sig, kind, (void *) handler, 6, NULL, 0); + uwsgi_register_signal(sig, kind, (void *) lhandler, 6, NULL, 0); } } @@ -286,6 +318,7 @@ static const luaL_reg uwsgi_api[] = { {"cache_get", uwsgi_api_cache_get}, {"cache_set", uwsgi_api_cache_set}, {"register_signal", uwsgi_api_register_signal}, + {"register_rpc", uwsgi_api_register_rpc}, {NULL, NULL} }; @@ -579,7 +612,7 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler, char *payload, uint8_t uwsgi_log("managing signal handler on core %d\n", wsgi_req->async_id); - lua_rawgeti(L, LUA_REGISTRYINDEX, (int) handler); + lua_rawgeti(L, LUA_REGISTRYINDEX, (long) handler); lua_pushnumber(L, sig); if (!payload_size) { @@ -602,6 +635,44 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler, char *payload, uint8_t } +uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) { + + uint8_t i; + const char *sv; + size_t sl; + long lfunc = (long) func; + int ifunc = lfunc; + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + lua_State *L = ulua.L[wsgi_req->async_id]; + + uwsgi_log("get function %d\n", ifunc); + lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc); + + for(i=0;i 0) { + return PyString_FromStringAndSize(buffer, size); + } + +clear: + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) { + + char buffer[0xffff]; + char *node, *func; + uint16_t size = 0; + PyObject *py_node, *py_func; + struct uwsgi_header uh; + int argc = PyTuple_Size(args) ; + char *argv[0xff]; + int i, fd; + uint16_t pktsize = 0, ulen; + char *bufptr; + int rlen; + + struct pollfd upoll; + + // TODO better error reporting + if (argc < 2) goto clear; + + py_node = PyTuple_GetItem(args, 0); + + if (PyString_Check(py_node)) { + node = PyString_AsString(py_node); + } + else { + node = ""; + } + + py_func = PyTuple_GetItem(args, 1); + + if (!PyString_Check(py_func)) goto clear; + + func = PyString_AsString(py_func); + + for(i=0;i<(argc-2);i++) { + argv[i] = PyString_AsString( PyTuple_GetItem(args, i+2) ); + } + + if (node == (char *) "") { + size = uwsgi_rpc(func, 0, NULL, buffer); + } + else { + + + // connect to node + fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0); + + if (fd < 0) goto clear; + // prepare a uwsgi array + + pktsize = 2 + strlen(func); + for(i=0;i>8) & 0xff); + memcpy(bufptr, func, ulen); bufptr += ulen; + + for(i=0;i>8) & 0xff); + memcpy(bufptr, argv[i], ulen); bufptr += ulen; + } + + if (write(fd, &uh, 4) != 4) { + uwsgi_error("write()"); + close(fd); + goto clear; + } + + if (write(fd, buffer, pktsize) != pktsize) { + uwsgi_error("write()"); + close(fd); + goto clear; + } + + rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); + if (rlen > 0) { + upoll.fd = fd; + upoll.events = POLLIN; + if (uwsgi_parse_response(&upoll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &uh, buffer)) { + size = uh.pktsize; + } + } + + } + + if (size > 0) { + return PyString_FromStringAndSize(buffer, size); + } + +clear: + + Py_INCREF(Py_None); + return Py_None; +} + PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) { uint8_t argc = 0; @@ -1969,6 +2111,8 @@ static PyMethodDef uwsgi_advanced_methods[] = { {"register_timer", py_uwsgi_register_timer, METH_VARARGS, ""}, {"register_rpc", py_uwsgi_register_rpc, METH_VARARGS, ""}, + {"rpc", py_uwsgi_rpc, METH_VARARGS, ""}, + {"call", py_uwsgi_call, METH_VARARGS, ""}, #ifdef UWSGI_SENDFILE {"sendfile", py_uwsgi_advanced_sendfile, METH_VARARGS, ""}, #endif diff --git a/rpc.c b/rpc.c index f33d78f7..baca7e3e 100644 --- a/rpc.c +++ b/rpc.c @@ -20,6 +20,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) uwsgi.shared->rpc_count++; ret = 0; + uwsgi_log("registered RPC function %s\n", name); } uwsgi_unlock(uwsgi.rpc_table_lock); diff --git a/tests/rpc.lua b/tests/rpc.lua new file mode 100644 index 00000000..aba50fe0 --- /dev/null +++ b/tests/rpc.lua @@ -0,0 +1,20 @@ +function hello() + return "Hello i am Lua" +end + +function hello2() + return "Hello i am Lua [2]" +end + +function hello3(arg1) + return "Hello i am a Lua function with 1 arg "..arg1 +end + +function hello4(arg1, arg2) + return "Hello i am a Lua function with 2 args "..arg1.." "..arg2 +end + +uwsgi.register_rpc("hello", hello) +uwsgi.register_rpc("hello2", hello2) +uwsgi.register_rpc("hello3", hello3) +uwsgi.register_rpc("hello4", hello4) diff --git a/tests/rpc.py b/tests/rpc.py index 5d0f30f7..bbf329d0 100644 --- a/tests/rpc.py +++ b/tests/rpc.py @@ -5,3 +5,6 @@ def hello(): return "Hello World" print uwsgi.register_rpc("hello", hello) + + +print uwsgi.rpc(None, "hello") diff --git a/uwsgi.h b/uwsgi.h index 8341a53f..58617397 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -400,7 +400,7 @@ struct uwsgi_plugin { char* (*decode_string)(void *); int (*signal_handler)(uint8_t, void *, char *, uint8_t); - uint16_t (*rpc)(void *, uint8_t argc, char **, char *); + uint16_t (*rpc)(void *, uint8_t, char **, char *); };