--- libaitrpc/src/srv.c 2012/11/05 17:06:51 1.11.2.4 +++ libaitrpc/src/srv.c 2012/11/16 08:33:06 1.12.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: srv.c,v 1.11.2.4 2012/11/05 17:06:51 misho Exp $ +* $Id: srv.c,v 1.12.2.1 2012/11/16 08:33:06 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -46,6 +46,15 @@ SUCH DAMAGE. #include "global.h" +static void *acceptClients(sched_task_t *); +static void *closeClient(sched_task_t *); +static sched_task_func_t cbProto[SOCK_RAW][2] = { + { acceptClients, closeClient }, + { acceptClients, closeClient }, + { NULL, NULL } +}; + + static void * closeClient(sched_task_t *task) { @@ -114,7 +123,8 @@ txPacket(sched_task_t *task) ret = send(TASK_FD(task), buf, wlen, MSG_NOSIGNAL); if (ret == -1 || ret != wlen) { /* close connection */ - schedEvent(TASK_ROOT(task), closeClient, c, 42, NULL, 0); + schedEvent(TASK_ROOT(task), cbProto[s->srv_proto][CB_CLOSECLIENT], + c, 42, NULL, 0); } return NULL; @@ -192,7 +202,8 @@ rxPacket(sched_task_t *task) rlen = recv(TASK_FD(task), buf + off, AIT_LEN(&c->cli_buf) - off, 0); if (rlen < 1) { /* close connection */ - schedEvent(TASK_ROOT(task), closeClient, c, 42, NULL, 0); + schedEvent(TASK_ROOT(task), cbProto[s->srv_proto][CB_CLOSECLIENT], + c, 42, NULL, 0); return NULL; } else { rlen += off; /* add reminded bytes from previous rxPacket, if exists! */ @@ -691,20 +702,23 @@ rpc_srv_loopBLOBServer(rpc_srv_t * __restrict srv) * @netBuf = Network buffer length (min:512 bytes), if =0 == BUFSIZ (also meaning max RPC packet) * @csHost = Host name or address for bind server, if NULL any address * @Port = Port for bind server, if Port == 0 default port is selected + * @proto = Protocol, if == 0 choose SOCK_STREAM * return: NULL == error or !=NULL bind and created RPC server instance */ rpc_srv_t * rpc_srv_initServer(u_int regProgID, u_char regProcID, int concurentClients, - int netBuf, const char *csHost, u_short Port) + int netBuf, const char *csHost, u_short Port, int proto) { int n = 1; rpc_srv_t *srv = NULL; io_sockaddr_t sa = IO_SOCKADDR_INIT; - if (!concurentClients || !regProgID) { + if (!concurentClients || !regProgID || (proto < 0 || proto > SOCK_DGRAM)) { rpc_SetErr(EINVAL, "Invalid parameters can`t init RPC server"); return NULL; } + if (!proto) + proto = SOCK_STREAM; if (!io_gethostbyname(csHost, Port, &sa)) return NULL; if (!Port) @@ -729,6 +743,7 @@ rpc_srv_initServer(u_int regProgID, u_char regProcID, } else memset(srv, 0, sizeof(rpc_srv_t)); + srv->srv_proto = proto; srv->srv_netbuf = netBuf; srv->srv_session.sess_version = RPC_VERSION; srv->srv_session.sess_program = regProgID; @@ -737,13 +752,16 @@ rpc_srv_initServer(u_int regProgID, u_char regProcID, srv->srv_server.cli_parent = srv; memcpy(&srv->srv_server.cli_sa, &sa, sizeof srv->srv_server.cli_sa); - /* init functions list */ - TAILQ_INIT(&srv->srv_funcs); + /* init functions */ + pthread_mutex_init(&srv->srv_funcs.mtx, NULL); + SLIST_INIT(&srv->srv_funcs); + AVL_INIT(&srv->srv_funcs); /* init scheduler */ srv->srv_root = schedBegin(); if (!srv->srv_root) { rpc_SetErr(sched_GetErrno(), "%s", sched_GetError()); + pthread_mutex_destroy(&srv->srv_funcs.mtx); io_free(srv); return NULL; } @@ -753,16 +771,18 @@ rpc_srv_initServer(u_int regProgID, u_char regProcID, if (!srv->srv_clients) { rpc_SetErr(io_GetErrno(), "%s", io_GetError()); schedEnd(&srv->srv_root); + pthread_mutex_destroy(&srv->srv_funcs.mtx); io_free(srv); return NULL; } /* create server socket */ - srv->srv_server.cli_sock = socket(srv->srv_server.cli_sa.sa.sa_family, SOCK_STREAM, 0); + srv->srv_server.cli_sock = socket(srv->srv_server.cli_sa.sa.sa_family, srv->srv_proto, 0); if (srv->srv_server.cli_sock == -1) { LOGERR; io_arrayDestroy(&srv->srv_clients); schedEnd(&srv->srv_root); + pthread_mutex_destroy(&srv->srv_funcs.mtx); io_free(srv); return NULL; } @@ -792,6 +812,7 @@ err: /* error condition */ close(srv->srv_server.cli_sock); io_arrayDestroy(&srv->srv_clients); schedEnd(&srv->srv_root); + pthread_mutex_destroy(&srv->srv_funcs.mtx); io_free(srv); return NULL; } @@ -815,6 +836,7 @@ rpc_srv_endServer(rpc_srv_t ** __restrict psrv) (*psrv)->srv_kill = 1; sleep(RPC_SCHED_POLLING); + pthread_mutex_destroy(&(*psrv)->srv_funcs.mtx); io_free(*psrv); *psrv = NULL; } @@ -830,7 +852,7 @@ rpc_srv_loopServer(rpc_srv_t * __restrict srv) { rpc_cli_t *c; register int i; - rpc_func_t *f, *tmp; + rpc_func_t *f; struct timespec ts = { RPC_SCHED_POLLING, 0 }; if (!srv) { @@ -845,7 +867,8 @@ rpc_srv_loopServer(rpc_srv_t * __restrict srv) fcntl(srv->srv_server.cli_sock, F_SETFL, fcntl(srv->srv_server.cli_sock, F_GETFL) | O_NONBLOCK); - if (!schedRead(srv->srv_root, acceptClients, srv, srv->srv_server.cli_sock, NULL, 0)) { + if (!schedRead(srv->srv_root, cbProto[srv->srv_proto][CB_ACCEPTCLIENT], srv, + srv->srv_server.cli_sock, NULL, 0)) { rpc_SetErr(sched_GetErrno(), "%s", sched_GetError()); return -1; } @@ -872,12 +895,15 @@ rpc_srv_loopServer(rpc_srv_t * __restrict srv) close(srv->srv_server.cli_sock); /* detach exported calls */ - TAILQ_FOREACH_SAFE(f, &srv->srv_funcs, func_node, tmp) { - TAILQ_REMOVE(&srv->srv_funcs, f, func_node); + RPC_FUNCS_LOCK(&srv->srv_funcs); + while ((f = SLIST_FIRST(&srv->srv_funcs))) { + SLIST_REMOVE_HEAD(&srv->srv_funcs, func_next); AIT_FREE_VAL(&f->func_name); io_free(f); } + srv->srv_funcs.avlh_root = NULL; + RPC_FUNCS_UNLOCK(&srv->srv_funcs); schedEnd(&srv->srv_root); return 0;