Skip to content

Commit

Permalink
erlang: fix function call in event route
Browse files Browse the repository at this point in the history
- allow call functions for RPC and message send in event route
- detect RPC loop
- function/api call is possible in event route if event route is not
triggered by handling REX call (avoid deadlock)

(cherry picked from commit b0c04dd)
  • Loading branch information
seudin committed Apr 26, 2016
1 parent 615b252 commit 3fdf046
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 9 deletions.
88 changes: 87 additions & 1 deletion modules/erlang/erl_api.c
Expand Up @@ -83,6 +83,48 @@ int _impl_api_rpc_call(ei_x_buff *reply, const str *module,const str *function,
int buffsz=0;
int rc;

if (!csockfd) {

if (!enode) {
LM_NOTICE("there is no connected Erlang node\n");
/* reply up with error */
ei_x_format(reply, "{error,cnode,~a}", "no_erlang_node");
return -1;
}

if (rex_call_in_progress) {
LM_ERR("RPC loop detected\n");
ei_x_format(reply, "{badrpc,cnode,~a}", "rpc_loop_detected");
return -1;
}

/* do RPC from event route */
if (ei_rpc(&enode->ec,enode->sockfd,module->s,function->s,args->buff,args->index,reply) == ERL_ERROR)
{
reply->index = 0; /* re-use reply buffer */

if (erl_errno)
{
ei_x_format(reply, "{error,cnode,~s}", strerror(erl_errno));
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
}
else if (errno)
{
ei_x_format(reply, "{error,cnode,~s}", strerror(errno));
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
}
else
{
ei_x_format(reply, "{error,cnode,~s}", "Unknown error.");
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd);
}
return -1;
}
/* reset response */
enode->response.index = 0;
return 0;
}

memset(&msgh, 0, sizeof(msgh));
memset(&cnt, 0, sizeof(cnt));

Expand Down Expand Up @@ -187,6 +229,39 @@ int _impl_reg_send(const str *server, const ei_x_buff *msg)
return -1;
}

if (!csockfd) {

if (!enode) {
LM_NOTICE("there is no connected Erlang node\n");
return -1;
}

if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}

/* do ERL_REG_SEND in event route */
if ((rc = ei_reg_send(&enode->ec,enode->sockfd,server->s,msg->buff,msg->buffsz)) == ERL_ERROR)
{
if (erl_errno)
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
}
else if (errno)
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
}
else
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd);
}
}
/* reset response */
enode->response.index = 0;
return 0;
}

/* Kamailio PID */
cnt[0].iov_base = (void*)&pid_no;
cnt[0].iov_len = sizeof(pid_no);
Expand Down Expand Up @@ -245,6 +320,12 @@ int _impl_reply(const ei_x_buff *msg)
LM_ERR("not connected\n");
return -1;
}

if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}

/* copy into reply */
if (enode->response.buffsz < msg->buffsz) {
/* realocate */
Expand Down Expand Up @@ -277,11 +358,16 @@ int _impl_send(const erlang_pid *pid, const ei_x_buff *msg)
return -1;
}

if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}

if (enode) {

/* copy into reply */
if (enode->response.buffsz < msg->buffsz) {
/* realocate */
/* reallocate */
enode->response.buff=realloc(enode->response.buff,msg->buffsz);
if (!enode->response.buff) {
LM_ERR("realloc failed: not enough memory\n");
Expand Down
14 changes: 6 additions & 8 deletions modules/erlang/handle_emsg.c
Expand Up @@ -571,7 +571,9 @@ int handle_rex_call(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *
ctx.size = arity;

/* call rpc */
rex_call_in_progress = 1;
exp->function(&erl_rpc_func_param,(void*)&ctx);
rex_call_in_progress = 0;

if (ctx.no_params)
{
Expand Down Expand Up @@ -813,19 +815,15 @@ int handle_erlang_msg(cnode_handler_t *phandler, erlang_msg * msg)
LM_ERR("ei_send failed on node=<%s> socket=<%d>, %s\n",
phandler->ec.thisnodename,phandler->sockfd, strerror(erl_errno));
}

/* reset pid */
cnode_reply_to_pid = NULL;
return ret;
}
else
{
LM_DBG("** no reply **\n");

/* reset pid */
cnode_reply_to_pid = NULL;
return 0;
}

/* reset pid */
cnode_reply_to_pid = NULL;
return 0;
}

void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg )
Expand Down
2 changes: 2 additions & 0 deletions modules/erlang/handle_emsg.h
Expand Up @@ -27,6 +27,8 @@
#include "erl_helpers.h"
#include "cnode.h"

extern int rex_in_progress;

int handle_erlang_msg(cnode_handler_t *handler, erlang_msg * msg);

#endif /* HANDLE_EMSG_H_ */
2 changes: 2 additions & 0 deletions modules/erlang/mod_erlang.c
Expand Up @@ -88,6 +88,8 @@ int rpc_reply_with_struct = 0;
str erlang_nodename = STR_NULL;
str erlang_node_sname = STR_NULL;

int rex_call_in_progress = 0;

int *usocks[2];
int csockfd;

Expand Down
2 changes: 2 additions & 0 deletions modules/erlang/mod_erlang.h
Expand Up @@ -39,6 +39,8 @@ extern int rpc_reply_with_struct;
extern str erlang_nodename;
extern str erlang_node_sname;

extern int rex_call_in_progress;

/* sockets kamailio <-> cnode */
extern int *usocks[2];

Expand Down

0 comments on commit 3fdf046

Please sign in to comment.