/** * internal implementation */ int worker_rpc_impl(ei_cnode *ec, int s,int wpid) { str module = STR_NULL; str function = STR_NULL; ei_x_buff args; ei_x_buff reply; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&args,0,sizeof(args)); memset((void*)&reply,0,sizeof(reply)); memset((void*)&msgh,0,sizeof(msgh)); /* module name length */ cnt[0].iov_base = &module.len; cnt[0].iov_len = sizeof(int); /* function name length */ cnt[1].iov_base = &function.len; cnt[1].iov_len = sizeof(int); /* Erlang args size */ cnt[2].iov_base = &args.buffsz; cnt[2].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 3; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* allocate space */ module.s = (char*)pkg_malloc(module.len+1); if (!module.s) { LM_ERR("not enough memory\n"); goto err; } function.s = (char*)pkg_malloc(function.len+1); if (!function.s) { LM_ERR("not enough memory\n"); goto err; } args.buff = (char*)malloc(args.buffsz); if (!args.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[3].iov_base = module.s; cnt[3].iov_len = module.len; cnt[4].iov_base = function.s; cnt[4].iov_len = function.len; cnt[5].iov_base = args.buff; cnt[5].iov_len = args.buffsz; /* get whole data */ msgh.msg_iovlen = 6; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ module.s[module.len] = 0; function.s[function.len] = 0; LM_DBG("rpc: %.*s:%.*s(args)\n",STR_FMT(&module),STR_FMT(&function)); EI_X_BUFF_PRINT(&args); 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"); goto reply; } /* do RPC */ if ((rc = ei_rpc(ec,enode->sockfd,module.s,function.s,args.buff,args.buffsz,&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",ec->thisalivename,enode->sockfd); } } reply: EI_X_BUFF_PRINT(&reply); cnt[0].iov_base = (void*)&wpid; cnt[0].iov_len = sizeof(int); /* send reply to Kamailio worker */ cnt[1].iov_base = (void*)&reply.buffsz; cnt[1].iov_len = sizeof(int); cnt[2].iov_base = (void*)reply.buff; cnt[2].iov_len = reply.buffsz; msgh.msg_iovlen = 3; while ((rc = sendmsg(s, &msgh, 0)) == -1 && errno == EAGAIN) ; if (rc == -1) { LM_ERR("sendmsg failed on socket=%d rpid_no=%d; %s\n",s, wpid, strerror(errno)); goto err; }; pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); return 0; err: pkg_free(module.s); pkg_free(function.s); free(args.buff); ei_x_free(&reply); abort(); /* cant't recover */ return -1; }
int worker_reg_send_impl(ei_cnode *ec, int s,int wpid) { str server = STR_NULL; ei_x_buff emsg; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&emsg,0,sizeof(emsg)); memset((void*)&msgh,0,sizeof(msgh)); /* server name length */ cnt[0].iov_base = &server.len; cnt[0].iov_len = sizeof(int); /* Erlang args size */ cnt[1].iov_base = &emsg.buffsz; cnt[1].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 2; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); return -1; } /* allocate space */ server.s = (char*)pkg_malloc(server.len+1); if (!server.s) { LM_ERR("not enough memory\n"); goto err; } emsg.buff = (char*)malloc(emsg.buffsz); if (!emsg.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[2].iov_base = server.s; cnt[2].iov_len = server.len; cnt[3].iov_base = emsg.buff; cnt[3].iov_len = emsg.buffsz; /* get whole data */ msgh.msg_iovlen = 4; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } /* fix str */ server.s[server.len] = 0; if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); goto err; } LM_DBG(">> {%.*s,'%s'} ! emsg\n",STR_FMT(&server),enode->conn.nodename); EI_X_BUFF_PRINT(&emsg); /* do ERL_REG_SEND */ if ((rc = ei_reg_send(ec,enode->sockfd,server.s,emsg.buff,emsg.buffsz)) == ERL_ERROR) { if (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) { LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } pkg_free(server.s); free(emsg.buff); return 0; err: pkg_free(server.s); free(emsg.buff); return -1; }
int worker_send_impl(ei_cnode *ec, int s,int wpid) { erlang_pid pid; ei_x_buff emsg; struct msghdr msgh; struct iovec cnt[6]; int rc; memset((void*)&emsg,0,sizeof(emsg)); memset((void*)&msgh,0,sizeof(msgh)); /* Erlang args size */ cnt[0].iov_base = &emsg.buffsz; cnt[0].iov_len = sizeof(int); /* get data size */ msgh.msg_iov = cnt; msgh.msg_iovlen = 1; while ((rc = recvmsg(s, &msgh, MSG_PEEK)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); return -1; } emsg.buff = (char*)malloc(emsg.buffsz); if (!emsg.buff) { LM_ERR("malloc: not enough memory\n"); goto err; } /* buffers */ cnt[1].iov_base = &pid; cnt[1].iov_len = sizeof(erlang_pid); cnt[2].iov_base = emsg.buff; cnt[2].iov_len = emsg.buffsz; /* get whole data */ msgh.msg_iovlen = 3; while ((rc = recvmsg(s, &msgh, MSG_WAITALL)) == -1 && errno == EAGAIN) ; if (rc == -1){ LM_ERR("recvmsg failed (socket=%d): %s\n",s,strerror(errno)); goto err; } if(!enode) { LM_NOTICE("there is no connected Erlang node\n"); goto err; } LM_DBG(">> <%s.%d.%d> ! emsg\n",pid.node,pid.num,pid.serial); EI_X_BUFF_PRINT(&emsg); /* do ERL_SEND */ if ((rc = ei_send(enode->sockfd,&pid,emsg.buff,emsg.buffsz)) == ERL_ERROR) { if (erl_errno) { LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno)); } else if (errno) { LM_ERR("ei_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno)); } else { LM_ERR("ei_send failed on node=<%s> socket=<%d>, Unknown error.\n",ec->thisalivename,enode->sockfd); } } free(emsg.buff); return 0; err: free(emsg.buff); return -1; }