Skip to content

Instantly share code, notes, and snippets.

@nwalker
Created January 15, 2013 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nwalker/4540148 to your computer and use it in GitHub Desktop.
Save nwalker/4540148 to your computer and use it in GitHub Desktop.
diff --git a/plugins/erlang/erlang.c b/plugins/erlang/erlang.c
index 4ac45cc..a8d23b8 100644
--- a/plugins/erlang/erlang.c
+++ b/plugins/erlang/erlang.c
@@ -84,6 +84,91 @@ void dump_eterm(ei_x_buff *x) {
21
}
+int erl_to_rpc_args(ei_x_buff *x, int *argc, char **argv, uint16_t *argvs) {
+ int etype, esize;
+ int arity;
+ int i;
+ size_t rsize;
+
+ long long lnum;
+ double fnum;
+ char *buf;
+ long bin_size;
+
+
+ ei_get_type(x->buff, &x->index, &etype, &esize);
+
+ if (etype != ERL_STRING_EXT && etype != ERL_LIST_EXT && etype != ERL_NIL_EXT)
+ return 1; // Wrong argument type
+ if (esize>255)
+ return 2; // Too long parameter list
+
+ // ERL_STRING_EXT here means "list of short integers".
+ // If it is really string - someone didn't read docs of rpc:call and should be punished
+ if(etype == ERL_STRING_EXT) {
+ buf = uwsgi_malloc(esize);
+ ei_decode_string(x->buff, &x->index, buf);
+
+ for(i=0; i<esize+1; i++) {
+ argv[i] = uwsgi_malloc(4); //
+ argvs[i] = snprintf(argv[i], 4, "%i", buf[i]);
+ }
+
+ *argc = esize;
+ free(buf);
+ return 0;
+ }
+
+ ei_decode_list_header(x->buff, &x->index, &arity);
+ *argc = arity;
+
+ for (i=0; i<arity; 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, &lnum);
+ rsize = snprintf(NULL, 0, "%lli", lnum);
+ argv[i] = uwsgi_malloc(rsize+1);
+ argvs[i] = rsize;
+ snprintf(argv[i], rsize+1, "%lli", lnum);
+ break;
+ case ERL_FLOAT_EXT:
+ ei_decode_double(x->buff, &x->index, &fnum);
+ rsize = snprintf(NULL, 0, "%f", fnum); // be careful of precision loss
+ argv[i] = uwsgi_malloc(rsize+1);
+ argvs[i] = rsize;
+ snprintf(argv[i], rsize+1, "%f", fnum);
+ break;
+ case ERL_ATOM_EXT:
+ argv[i] = uwsgi_malloc(esize)+1;
+ argvs[i] = esize;
+ ei_decode_atom(x->buff, &x->index, argv[i]);
+ break;
+ // TODO: string and binary size should be checked
+ case ERL_STRING_EXT:
+ argv[i] = uwsgi_malloc(esize)+1;
+ argvs[i] = esize;
+ ei_decode_string(x->buff, &x->index, argv[i]);
+ break;
+ case ERL_BINARY_EXT:
+ argv[i] = uwsgi_malloc(esize)+1;
+ ei_decode_binary(x->buff, &x->index, argv[i], &bin_size);
+ argvs[i] = bin_size;
+ break;
+ default:
+#ifdef UWSGI_DEBUG
+ uwsgi_log("unsupported Erlang RPC argument at %i\n", i);
+ dump_eterm(x);
+#endif
+ return 3;
+ }
+ }
+ return 0;
+}
+
void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
int etype, esize;
@@ -98,6 +183,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
uint16_t argvs[256] ;
int argc = 0;
uint16_t ret;
+ int err;
ei_x_buff xr;
erlang_ref eref;
@@ -210,19 +296,10 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
uwsgi_log("RPC %s %s\n", module, call);
#endif
- ei_get_type(x->buff, &x->index, &etype, &esize);
-
- if (etype == ERL_ATOM_EXT) {
- argc = 1;
- argv[0] = uwsgi_malloc(esize+1);
- ei_decode_atom(x->buff, &x->index, argv[0]);
- argvs[1] = esize;
- }
- else if (etype == ERL_STRING_EXT) {
- argc = 1;
- argv[0] = uwsgi_malloc(esize+1);
- ei_decode_string(x->buff, &x->index, argv[0]);
- argvs[1] = esize;
+ err = erl_to_rpc_args(x, &argc, argv, argvs);
+ if(err) {
+ uwsgi_log("Malformed Erlang RPC request");
+ return;
}
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
@@ -240,8 +317,6 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_send(fd, from, xr.buff, xr.index));
//uwsgi_log("ei_send to %d %s %d %d %d: %d %d\n", fd, from->node, from->num , from->serial, from->creation, xr.index, ei_reg_send(&uerl.cnode, fd, "rex", xr.buff, xr.index));
-
-
}
void erlang_loop(int id, void *data) {
@@ -290,8 +365,9 @@ void erlang_loop(int id, void *data) {
if (em.msgtype == ERL_TICK)
continue;
+#ifdef UWSGI_DEBUG
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
-
+#endif
x.index = 0;
import uwsgi, atexit
def func(*args, **kwargs):
print('call: ', args, kwargs)
return "test"
uwsgi.register_rpc('hello', func)
-module(uwsgi_test).
-export([start/2, loop/3]).
start(Name, Fun) ->
Str = random_string(30*1024, "abcdefgh1234567890"),
spawn(uwsgi_test, loop, [Name, Fun, Str]).
loop(Name, Fun, Str) ->
rpc:call(Name, unused, Fun, [Str]),
loop(Name, Fun, Str).
random_string(Length, AllowedChars) ->
lists:foldl(fun(_, Acc) ->
[lists:nth(random:uniform(length(AllowedChars)),
AllowedChars)]
++ Acc
end, [], lists:seq(1, Length)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment