--- libaitrpc/src/cli.c 2012/03/28 11:07:36 1.7.2.1 +++ libaitrpc/src/cli.c 2012/05/14 15:22:22 1.9.2.1 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: cli.c,v 1.7.2.1 2012/03/28 11:07:36 misho Exp $ +* $Id: cli.c,v 1.9.2.1 2012/05/14 15:22:22 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -115,6 +115,7 @@ rpc_cli_openBLOBClient(rpc_cli_t * __restrict rpccli, return NULL; } + cli->cli_kill = enable; return cli; } @@ -131,6 +132,7 @@ rpc_cli_closeBLOBClient(rpc_cli_t * __restrict cli) rpc_SetErr(EINVAL, "Can`t close connection because parameter is null!"); return; } + cli->cli_kill = disable; shutdown(cli->cli_sock, SHUT_RDWR); close(cli->cli_sock); @@ -158,51 +160,17 @@ rpc_cli_openClient(u_int ProgID, u_int ProcID, int net u_short family, const char *csHost, u_short Port) { rpc_cli_t *cli = NULL; - struct hostent *host = NULL; io_sockaddr_t sa; int n; - if (!csHost || (family != AF_INET && family != AF_INET6 && family != AF_LOCAL)) { - rpc_SetErr(EINVAL, "Error:: Invalid parameters can`t connect to RPC server ...\n"); + if (!io_gethostbyname(csHost, Port, &sa)) return NULL; - } if (!Port) Port = RPC_DEFPORT; if (!netBuf) netBuf = BUFSIZ; if (!Timeout) Timeout = DEF_RPC_TIMEOUT; - if (csHost && family != AF_LOCAL) { - host = gethostbyname2(csHost, family); - if (!host) { - rpc_SetErr(h_errno, "Error:: %s\n", hstrerror(h_errno)); - return NULL; - } - } - memset(&sa, 0, sizeof sa); - sa.sa.sa_family = family; - switch (family) { - case AF_INET: - sa.sin.sin_len = sizeof(struct sockaddr_in); - sa.sin.sin_port = htons(Port); - if (csHost) - memcpy(&sa.sin.sin_addr, host->h_addr, host->h_length); - break; - case AF_INET6: - sa.sin6.sin6_len = sizeof(struct sockaddr_in6); - sa.sin6.sin6_port = htons(Port); - if (csHost) - memcpy(&sa.sin6.sin6_addr, host->h_addr, host->h_length); - break; - case AF_LOCAL: - sa.sun.sun_len = sizeof(struct sockaddr_un); - if (csHost) - strlcpy(sa.sun.sun_path, csHost, sizeof sa.sun.sun_path); - break; - default: - rpc_SetErr(EINVAL, "Error:: Invalid parameters can`t connect to RPC server ...\n"); - return NULL; - } cli = malloc(sizeof(rpc_cli_t)); if (!cli) { @@ -227,7 +195,7 @@ rpc_cli_openClient(u_int ProgID, u_int ProcID, int net memcpy(&cli->cli_sa, &sa, sizeof cli->cli_sa); /* connect to RPC server */ - cli->cli_sock = socket(family, SOCK_STREAM, 0); + cli->cli_sock = socket(cli->cli_sa.sa.sa_family, SOCK_STREAM, 0); if (cli->cli_sock == -1) { LOGERR; free(cli->cli_parent); @@ -299,14 +267,13 @@ int rpc_cli_execCall(rpc_cli_t *cli, int noreply, const char *csModule, const char *csFunc, array_t * __restrict in_vars, array_t ** __restrict out_vars) { - fd_set fds; u_char *buf; rpc_func_t func; struct tagRPCCall *rpc; int ret = 0, wlen = sizeof(struct tagRPCCall); - struct timeval tv = { DEF_RPC_TIMEOUT, 0 }; - uint16_t tag; + uint16_t tag, crc; uint32_t hash; + struct pollfd pfd; if (!cli || !csFunc) { rpc_SetErr(EINVAL, "Can`t execute call because parameter is null or invalid!"); @@ -353,9 +320,11 @@ rpc_cli_execCall(rpc_cli_t *cli, int noreply, const ch wlen += ret; } + rpc->call_len = htons(wlen); + /* calculate CRC */ rpc->call_crc ^= rpc->call_crc; - rpc->call_crc = htons(crcFletcher16((u_short*) buf, io_align(wlen, 1) / 2)); + rpc->call_crc = htons(crcFletcher16((u_short*) buf, wlen / 2)); if ((ret = send(cli->cli_sock, buf, wlen, 0)) == -1) { LOGERR; @@ -375,13 +344,14 @@ rpc_cli_execCall(rpc_cli_t *cli, int noreply, const ch } /* reply from RPC server */ - FD_ZERO(&fds); - FD_SET(cli->cli_sock, &fds); - if ((ret = select(cli->cli_sock + 1, &fds, NULL, NULL, &tv)) < 1) { + pfd.fd = cli->cli_sock; + pfd.events = POLLIN | POLLPRI; + if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) == -1 || + pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { if (ret) LOGERR; else - rpc_SetErr(ETIMEDOUT, "Error:: timeout, no return from RPC server?\n"); + rpc_SetErr(ETIMEDOUT, "Timeout, no return from RPC server?"); free(buf); return -1; @@ -390,40 +360,50 @@ rpc_cli_execCall(rpc_cli_t *cli, int noreply, const ch if ((ret = recv(cli->cli_sock, buf, cli->cli_netbuf, 0)) == -1) { LOGERR; free(buf); - return -3; + return -1; } if (!ret) { /* receive EOF! */ free(buf); return 0; } if (ret < sizeof(struct tagRPCCall)) { - rpc_SetErr(ERPCMISMATCH, "Error:: too short RPC packet ...\n"); + rpc_SetErr(ERPCMISMATCH, "Too short RPC packet ..."); free(buf); - return -4; + return -1; } + + /* calculate CRC */ + crc = ntohs(rpc->call_crc); + rpc->call_crc ^= rpc->call_crc; + if (crc != crcFletcher16((u_short*) buf, ret / 2)) { + rpc_SetErr(ERPCMISMATCH, "Bad CRC RPC packet"); + free(buf); + return -1; + } + /* check RPC packet session info */ if (rpc_chkPktSession(&rpc->call_session, cli->cli_parent)) { - rpc_SetErr(ERPCMISMATCH, "Error:: get invalid RPC session ...\n"); + rpc_SetErr(ERPCMISMATCH, "Get invalid RPC session ..."); free(buf); - return -5; + return -1; } else wlen = sizeof(struct tagRPCCall); if (rpc->call_tag != tag || rpc->call_hash != hash) { - rpc_SetErr(ERPCMISMATCH, "Error:: get wrong RPC reply ...\n"); + rpc_SetErr(ERPCMISMATCH, "Get wrong RPC reply ..."); free(buf); - return -5; + return -1; } if (ntohl(rpc->call_rep.ret) < 0 && ntohl(rpc->call_rep.eno)) { - rpc_SetErr(ntohl(rpc->call_rep.eno), "Error::Server side: retcode=%d #%d %s\n", + rpc_SetErr(ntohl(rpc->call_rep.eno), "Server side: retcode=%d #%d %s", ntohl(rpc->call_rep.ret), ntohl(rpc->call_rep.eno), strerror(ntohl(rpc->call_rep.eno))); free(buf); - return -6; + return -1; } if (ntohs(rpc->call_argc) * sizeof(ait_val_t) > cli->cli_netbuf - wlen) { - rpc_SetErr(EMSGSIZE, "Error:: reply RPC packet is too long ...\n"); + rpc_SetErr(EMSGSIZE, "Reply RPC packet is too long ..."); free(buf); - return -7; + return -1; } /* RPC is OK! Go de-marshaling variables ... */