diff --git a/plugins/erlang/erlang.c b/plugins/erlang/erlang.c index b0ffda9c..cd71119e 100644 --- a/plugins/erlang/erlang.c +++ b/plugins/erlang/erlang.c @@ -338,6 +338,9 @@ int erlang_init() { char *host; struct sockaddr_in sin; socklen_t slen = sizeof(struct sockaddr_in); + char *ip = NULL; + char *nodename; + struct in_addr addr; if (uerl.name) { @@ -351,8 +354,35 @@ int erlang_init() { exit(1); } } + else { + nodename = uwsgi_concat2n(uerl.name, host-uerl.name, "",0); + ip = uwsgi_resolve_ip(host+1); + if (ip) { +#ifdef UWSGI_DEBUG + uwsgi_log("ip: %s\n", ip); +#endif + addr.s_addr = inet_addr(ip); + if (ei_connect_xinit(&uerl.cnode, host+1, nodename, uerl.name, &addr, uerl.cookie, 0) < 0) { + uwsgi_log("unable to initialize erlang connection\n"); + exit(1); + } + } + else { + if (ei_connect_init(&uerl.cnode, nodename, uerl.cookie, 0) < 0) { + uwsgi_log("unable to initialize erlang connection\n"); + exit(1); + } + } + free(nodename); + } + + if (ip) { + uerl.fd = bind_to_tcp(ip, uwsgi.listen_queue, NULL); + } + else { + uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL); + } - uerl.fd = bind_to_tcp("", uwsgi.listen_queue, NULL); if (uerl.fd < 0) { exit(1); } diff --git a/plugins/pyerl/pyerl.c b/plugins/pyerl/pyerl.c index cf86313c..f3583a03 100644 --- a/plugins/pyerl/pyerl.c +++ b/plugins/pyerl/pyerl.c @@ -15,46 +15,224 @@ PyObject *pyerl_connect(PyObject * self, PyObject * args) { int py_to_erl(PyObject *, ei_x_buff*); -PyObject *pyerl_simple_send(PyObject * self, PyObject * args) { +PyObject *erl_to_py(ei_x_buff* x) { - char *node; + int etype, esize, arity; + long long num; + double fnum; + char *atom, *binary; + long bin_size; + PyObject *pobj; + PyObject *zero; + erlang_pid epid; + int i; + + ei_get_type(x->buff, &x->index, &etype, &esize); + + switch(etype) { + case ERL_SMALL_INTEGER_EXT: + case ERL_INTEGER_EXT: + case ERL_SMALL_BIG_EXT: + case ERL_LARGE_BIG_EXT: + ei_decode_longlong(x->buff, &x->index, &num); + return PyLong_FromLong(num); + case ERL_FLOAT_EXT: + ei_decode_double(x->buff, &x->index, &fnum); + return PyFloat_FromDouble(fnum); + case ERL_STRING_EXT: + atom = uwsgi_malloc(esize+1); + ei_decode_string(x->buff, &x->index, atom); + pobj = PyString_FromString(atom); + free(atom); + return pobj; + case ERL_ATOM_EXT: + atom = uwsgi_malloc(esize+1); + ei_decode_atom(x->buff, &x->index, atom); + pobj = PyUnicode_FromString(atom); + free(atom); + return pobj; + case ERL_SMALL_TUPLE_EXT: + case ERL_LARGE_TUPLE_EXT: + ei_decode_tuple_header(x->buff, &x->index, &arity); + pobj = PyTuple_New(arity); + for(i=0;ibuff, &x->index, &arity); + if (!arity) { + Py_INCREF(Py_None); + return Py_None; + } + pobj = PyList_New(0); + for(i=0;ibuff, &x->index, binary, &bin_size); + pobj = PyString_FromStringAndSize(binary, bin_size); + free(binary); + return pobj; + case ERL_PID_EXT: + ei_decode_pid(x->buff, &x->index, &epid); + pobj = PyTuple_New(3); + PyTuple_SetItem(pobj, 0, PyInt_FromLong(epid.num)); + PyTuple_SetItem(pobj, 1, PyInt_FromLong(epid.serial)); + PyTuple_SetItem(pobj, 2, PyInt_FromLong(epid.creation)); + return pobj; + default: + ei_skip_term(x->buff, &x->index); + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject *pyerl_sr(PyObject * self, PyObject * args) { + + PyObject *node; char *reg; + char *cnode; PyObject *pobj; ei_x_buff x; int fd; + int close_fd = 0; + erlang_msg em; + int eversion; + PyObject *res; - if (!PyArg_ParseTuple(args, "ssO:erlang_simple_send", &node, ®, &pobj)) { + if (!PyArg_ParseTuple(args, "OsO:erlang_sr", &node, ®, &pobj)) { return NULL; } - fd = ei_connect(pyerl_cnode, node); + if (PyString_Check(node)) { + cnode = PyString_AsString(node); + fd = ei_connect(pyerl_cnode, cnode); + close_fd = 1; + } + else if (PyInt_Check(node)) { + fd = PyInt_AsLong(node); + } + else { + return PyErr_Format(PyExc_ValueError, "invalid erlang node/descriptor"); + } if (fd < 0) { - return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node %s", node); + return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node"); } ei_x_new_with_version(&x); if (py_to_erl(pobj, &x) < 0) { ei_x_free(&x); + if (close_fd) close(fd); return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation"); } ei_reg_send(pyerl_cnode, fd, reg, x.buff, x.index); - close(fd); - ei_x_free(&x); + ei_x_new(&x); + + if (ei_xreceive_msg(fd, &em, &x) == ERL_MSG) { + x.index = 0; + ei_decode_version(x.buff, &x.index, &eversion); + res = erl_to_py(&x); + ei_x_free(&x); + if (close_fd) close(fd); + return res; + } + + ei_x_free(&x); + if (close_fd) close(fd); + Py_INCREF(Py_None); return Py_None; } +PyObject *pyerl_rpc(PyObject * self, PyObject * args) { + + PyObject *node; + char *mod, *fun; + char *cnode; + PyObject *pobj; + ei_x_buff x; + ei_x_buff xr; + int fd; + int close_fd = 0; + int eversion; + PyObject *res; + + if (!PyArg_ParseTuple(args, "OssO:erlang_rpc", &node, &mod, &fun, &pobj)) { + return NULL; + } + + if (PyString_Check(node)) { + cnode = PyString_AsString(node); + fd = ei_connect(pyerl_cnode, cnode); + close_fd = 1; + } + else if (PyInt_Check(node)) { + fd = PyInt_AsLong(node); + } + else { + return PyErr_Format(PyExc_ValueError, "Invalid erlang node/descriptor"); + } + + if (fd < 0) { + return PyErr_Format(PyExc_ValueError, "Unable to connect to erlang node"); + } + + ei_x_new(&x); + + if (py_to_erl(pobj, &x) < 0) { + ei_x_free(&x); + if (close_fd) close(fd); + return PyErr_Format(PyExc_ValueError, "Unsupported object in Python->Erlang translation"); + } + + + ei_x_new(&xr); + if (ei_rpc(pyerl_cnode, fd, mod, fun, x.buff, x.index, &xr) < 0) { + if (close_fd) close(fd); + ei_x_free(&x); + ei_x_free(&xr); + return PyErr_Format(PyExc_ValueError, "Error in Erlang rpc"); + } + + xr.index = 0; + ei_decode_version(xr.buff, &xr.index, &eversion); + + res = erl_to_py(&xr); + + if (close_fd) close(fd); + ei_x_free(&x); + ei_x_free(&xr); + return res; + +} + + static PyMethodDef uwsgi_pyerl_methods[] = { {"erlang_connect", pyerl_connect, METH_VARARGS, ""}, - {"erlang_simple_send", pyerl_simple_send, METH_VARARGS, ""}, + //{"erlang_send_message", pyerl_send, METH_VARARGS, ""}, + //{"erlang_recv_message", pyerl_recv, METH_VARARGS, ""}, + {"erlang_sr", pyerl_sr, METH_VARARGS, ""}, + {"erlang_rpc", pyerl_rpc, METH_VARARGS, ""}, {NULL, NULL}, }; @@ -62,6 +240,8 @@ void py_erl_init_functions() { PyMethodDef *uwsgi_function; + PyDict_SetItemString(up.embedded_dict, "erlang_node", PyString_FromString(ei_thisnodename(pyerl_cnode))); + for (uwsgi_function = uwsgi_pyerl_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) { PyObject *func = PyCFunction_New(uwsgi_function, NULL); PyDict_SetItemString(up.embedded_dict, uwsgi_function->ml_name, func); @@ -80,6 +260,9 @@ int py_to_erl(PyObject *pobj, ei_x_buff *x) { else if (PyString_Check(pobj)) { ei_x_encode_string(x, PyString_AsString(pobj)); } + else if (PyUnicode_Check(pobj)) { + ei_x_encode_atom(x, PyString_AsString(pobj)); + } else if (PyInt_Check(pobj)) { ei_x_encode_long(x, PyInt_AsLong(pobj)); } diff --git a/plugins/python/wsgi_subhandler.c b/plugins/python/wsgi_subhandler.c index a68a5a7a..7312ea93 100644 --- a/plugins/python/wsgi_subhandler.c +++ b/plugins/python/wsgi_subhandler.c @@ -83,14 +83,21 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_ PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ); } - PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", PyString_FromString(UWSGI_VERSION)); + zero = PyString_FromString(UWSGI_VERSION); + PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", zero); + Py_DECREF(zero); + if (uwsgi.cores > 1) { PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id)); } if (uwsgi.cluster_fd >= 0) { - PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", PyString_FromString(uwsgi.cluster)); - PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", PyString_FromString(uwsgi.hostname)); + zero = PyString_FromString(uwsgi.cluster); + PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero); + Py_DECREF(zero); + zero = PyString_FromString(uwsgi.hostname); + PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero); + Py_DECREF(zero); } diff --git a/utils.c b/utils.c index 5cbb0192..0184bdfd 100644 --- a/utils.c +++ b/utils.c @@ -1256,6 +1256,17 @@ char *uwsgi_cheap_string(char *buf, int len) { return buf-1; } +char *uwsgi_resolve_ip(char *domain) { + + struct hostent *he; + + he = gethostbyname(domain); + if (!he || !*he->h_addr_list || he->h_addrtype != AF_INET) { + return NULL; + } + + return inet_ntoa( *( struct in_addr*) he->h_addr_list[0]); +} char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[]) { @@ -1267,7 +1278,6 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[ char *uri, *colon; char *domain ; char *ip ; - struct hostent *he; int body = 0; char *magic_buf; @@ -1289,13 +1299,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[ } - he = gethostbyname(domain); - if (!he || !*he->h_addr_list || he->h_addrtype != AF_INET) { - uwsgi_log("unable to resolve address %s\n", domain); - exit(1); - } - - ip = inet_ntoa( *( struct in_addr*) he->h_addr_list[0]); + ip = uwsgi_resolve_ip(domain); if (!ip) { uwsgi_log("unable to resolve address %s\n", domain); exit(1); diff --git a/uwsgi.h b/uwsgi.h index c78e5ebb..983ca979 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1416,3 +1416,5 @@ int uwsgi_simple_send_string(char *, uint8_t, uint8_t, char *, uint16_t, int); int is_unix(char *, int); int is_a_number(char *); + +char *uwsgi_resolve_ip(char *);