Annotation of libaitrpc/src/cli.c, revision 1.16.6.1
1.1 misho 1: /*************************************************************************
2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.16.6.1! misho 6: * $Id: cli.c,v 1.16 2013/05/30 09:22:01 misho Exp $
1.1 misho 7: *
1.2 misho 8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.14 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
1.2 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
1.1 misho 46: #include "global.h"
47:
48:
49: /*
1.7 misho 50: * rpc_cli_openBLOBClient() - Connect to BLOB Server
51: *
1.2 misho 52: * @rpccli = RPC Client session
53: * @Port = Port for bind server, if Port == 0 default port is selected
54: * return: NULL == error or !=NULL connection to BLOB server established
55: */
56: rpc_cli_t *
57: rpc_cli_openBLOBClient(rpc_cli_t * __restrict rpccli, u_short Port)
58: {
59: rpc_cli_t *cli = NULL;
1.13 misho 60: int n;
1.4 misho 61:
1.10 misho 62: if (!rpccli) {
1.7 misho 63: rpc_SetErr(EINVAL, "Invalid parameters can`t connect to BLOB server");
1.2 misho 64: return NULL;
65: }
66:
1.14 misho 67: cli = e_malloc(sizeof(rpc_cli_t));
1.2 misho 68: if (!cli) {
69: LOGERR;
70: return NULL;
71: } else
72: memcpy(cli, rpccli, sizeof(rpc_cli_t));
73:
1.16.6.1! misho 74: cli->cli_buf = ait_allocVars(1);
! 75: if (!cli->cli_buf) {
! 76: rpc_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
! 77: e_free(cli);
! 78: return NULL;
! 79: }
! 80:
1.14 misho 81: memcpy(&cli->cli_sa, &rpccli->cli_sa, sizeof(sockaddr_t));
1.10 misho 82: switch (cli->cli_sa.sa.sa_family) {
1.4 misho 83: case AF_INET:
1.10 misho 84: cli->cli_sa.sin.sin_port =
85: htons(Port ? Port : ntohs(cli->cli_sa.sin.sin_port) + 1);
1.4 misho 86: break;
87: case AF_INET6:
1.10 misho 88: cli->cli_sa.sin6.sin6_port =
89: htons(Port ? Port : ntohs(cli->cli_sa.sin6.sin6_port) + 1);
1.4 misho 90: break;
91: case AF_LOCAL:
1.10 misho 92: strlcat(cli->cli_sa.sun.sun_path, ".blob", sizeof cli->cli_sa.sun.sun_path);
1.4 misho 93: break;
1.10 misho 94: default:
95: rpc_SetErr(EINVAL, "Invalid socket type %d", cli->cli_sa.sa.sa_family);
96: return NULL;
1.2 misho 97: }
1.10 misho 98:
1.16.6.1! misho 99: AIT_COPY_VAL(array(cli->cli_buf, 0, ait_val_t*), array(rpccli->cli_buf, 0, ait_val_t*));
! 100: n = AIT_LEN(array(cli->cli_buf, 0, ait_val_t*));
1.2 misho 101:
1.4 misho 102: /* connect to BLOB server */
1.6 misho 103: cli->cli_sock = socket(cli->cli_sa.sa.sa_family, SOCK_STREAM, 0);
1.2 misho 104: if (cli->cli_sock == -1) {
105: LOGERR;
1.14 misho 106: e_free(cli);
1.2 misho 107: return NULL;
108: }
1.13 misho 109: if (setsockopt(cli->cli_sock, SOL_SOCKET, SO_SNDBUF, &n, sizeof n) == -1) {
110: LOGERR;
111: close(cli->cli_sock);
1.14 misho 112: e_free(cli);
1.13 misho 113: return NULL;
114: }
115: if (setsockopt(cli->cli_sock, SOL_SOCKET, SO_RCVBUF, &n, sizeof n) == -1) {
116: LOGERR;
117: close(cli->cli_sock);
1.14 misho 118: e_free(cli);
1.13 misho 119: return NULL;
120: }
1.6 misho 121: if (connect(cli->cli_sock, &cli->cli_sa.sa, cli->cli_sa.sa.sa_len) == -1) {
1.2 misho 122: LOGERR;
1.5 misho 123: close(cli->cli_sock);
1.14 misho 124: e_free(cli);
1.2 misho 125: return NULL;
1.10 misho 126: } else
127: fcntl(cli->cli_sock, F_SETFL, fcntl(cli->cli_sock, F_GETFL) | O_NONBLOCK);
1.2 misho 128:
129: return cli;
130: }
131:
132: /*
1.7 misho 133: * rpc_cli_closeBLOBClient() - Close connection to BLOB server and free resources
134: *
1.2 misho 135: * @cli = BLOB Client session
136: * return: none
137: */
138: void
1.10 misho 139: rpc_cli_closeBLOBClient(rpc_cli_t ** __restrict cli)
1.2 misho 140: {
1.10 misho 141: if (!cli || !*cli)
1.2 misho 142: return;
143:
1.10 misho 144: shutdown((*cli)->cli_sock, SHUT_RDWR);
145: close((*cli)->cli_sock);
146:
1.16.6.1! misho 147: ait_freeVars(&(*cli)->cli_buf);
1.2 misho 148:
1.14 misho 149: e_free(*cli);
1.10 misho 150: *cli = NULL;
1.2 misho 151: }
152:
1.10 misho 153: /* -------------------------------------------------------------- */
1.2 misho 154:
155: /*
1.7 misho 156: * rpc_cli_openClient() - Connect to RPC Server
157: *
1.15 misho 158: * @InstID = InstID for RPC session request
1.10 misho 159: * @netBuf = Network buffer length (min:512 bytes), if =0 == BUFSIZ (also meaning max RPC packet)
1.1 misho 160: * @csHost = Host name or IP address for bind server
161: * @Port = Port for bind server, if Port == 0 default port is selected
1.13 misho 162: * @proto = Protocol, if == 0 choose SOCK_STREAM
1.1 misho 163: * return: NULL == error or !=NULL connection to RPC server established
164: */
165: rpc_cli_t *
1.15 misho 166: rpc_cli_openClient(u_char InstID, int netBuf, const char *csHost, u_short Port, int proto)
1.1 misho 167: {
168: rpc_cli_t *cli = NULL;
1.14 misho 169: sockaddr_t sa = E_SOCKADDR_INIT;
1.1 misho 170:
1.14 misho 171: if (!e_gethostbyname(csHost, Port, &sa))
1.1 misho 172: return NULL;
173: if (!Port)
174: Port = RPC_DEFPORT;
1.13 misho 175: if (!proto)
176: proto = SOCK_STREAM;
1.10 misho 177: if (netBuf < RPC_MIN_BUFSIZ)
1.5 misho 178: netBuf = BUFSIZ;
1.10 misho 179: else
1.14 misho 180: netBuf = E_ALIGN(netBuf, 2); /* align netBuf length */
1.10 misho 181:
182: #ifdef HAVE_SRANDOMDEV
183: srandomdev();
184: #else
185: time_t tim;
186:
187: srandom((time(&tim) ^ getpid()));
188: #endif
1.1 misho 189:
1.14 misho 190: cli = e_malloc(sizeof(rpc_cli_t));
1.1 misho 191: if (!cli) {
192: LOGERR;
193: return NULL;
194: } else
195: memset(cli, 0, sizeof(rpc_cli_t));
1.5 misho 196:
1.10 misho 197: /* build session */
1.14 misho 198: cli->cli_parent = e_malloc(sizeof(rpc_sess_t));
1.1 misho 199: if (!cli->cli_parent) {
200: LOGERR;
1.14 misho 201: e_free(cli);
1.1 misho 202: return NULL;
203: } else {
204: ((rpc_sess_t*) cli->cli_parent)->sess_version = RPC_VERSION;
1.15 misho 205: ((rpc_sess_t*) cli->cli_parent)->sess_instance = InstID;
1.1 misho 206: }
207:
1.16.6.1! misho 208: cli->cli_buf = ait_allocVars(2);
! 209: if (!cli->cli_buf) {
! 210: rpc_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
! 211: e_free(cli->cli_parent);
! 212: e_free(cli);
! 213: return NULL;
! 214: } else
! 215: AIT_SET_BUFSIZ(array(cli->cli_buf, 0, ait_val_t*), 0, netBuf);
! 216:
1.13 misho 217: cli->cli_id = proto;
1.6 misho 218: memcpy(&cli->cli_sa, &sa, sizeof cli->cli_sa);
1.4 misho 219:
220: /* connect to RPC server */
1.13 misho 221: cli->cli_sock = socket(cli->cli_sa.sa.sa_family, cli->cli_id, 0);
1.1 misho 222: if (cli->cli_sock == -1) {
223: LOGERR;
1.13 misho 224: goto err;
225: }
226: if (setsockopt(cli->cli_sock, SOL_SOCKET, SO_SNDBUF,
227: &netBuf, sizeof netBuf) == -1) {
228: LOGERR;
229: goto err;
1.5 misho 230: }
1.13 misho 231: if (setsockopt(cli->cli_sock, SOL_SOCKET, SO_RCVBUF,
232: &netBuf, sizeof netBuf) == -1) {
1.1 misho 233: LOGERR;
1.13 misho 234: goto err;
235: }
236: if (cli->cli_id == SOCK_STREAM)
237: if (connect(cli->cli_sock, &cli->cli_sa.sa, cli->cli_sa.sa.sa_len) == -1) {
238: LOGERR;
239: goto err;
240: }
1.1 misho 241:
1.13 misho 242: fcntl(cli->cli_sock, F_SETFL, fcntl(cli->cli_sock, F_GETFL) | O_NONBLOCK);
1.1 misho 243: return cli;
1.13 misho 244: err:
1.16.6.1! misho 245: ait_freeVars(&cli->cli_buf);
1.13 misho 246: if (cli->cli_sock > 2)
247: close(cli->cli_sock);
1.14 misho 248: e_free(cli->cli_parent);
249: e_free(cli);
1.13 misho 250: return NULL;
1.1 misho 251: }
252:
253: /*
1.7 misho 254: * rpc_cli_closeClient() - Close connection to RPC server and free resources
255: *
1.1 misho 256: * @cli = RPC Client session
257: * return: none
258: */
259: void
1.10 misho 260: rpc_cli_closeClient(rpc_cli_t ** __restrict cli)
1.1 misho 261: {
1.10 misho 262: if (!cli || !*cli)
1.1 misho 263: return;
264:
1.13 misho 265: if ((*cli)->cli_id == SOCK_STREAM)
266: shutdown((*cli)->cli_sock, SHUT_RDWR);
1.10 misho 267: close((*cli)->cli_sock);
268:
1.16.6.1! misho 269: ait_freeVars(&(*cli)->cli_buf);
1.10 misho 270:
271: if ((*cli)->cli_parent)
1.14 misho 272: e_free((*cli)->cli_parent);
1.1 misho 273:
1.14 misho 274: e_free(*cli);
1.10 misho 275: *cli = NULL;
1.1 misho 276: }
277:
278: /*
1.14 misho 279: * rpc_pkt_Send() - Send RPC packet
1.7 misho 280: *
1.14 misho 281: * @sock = Socket
282: * @type = Type of socket
283: * @sa = Server address
284: * @pkt = RPC packet
285: * @len = Length of packet
286: * return: -1 error or !=-1 sended bytes
1.1 misho 287: */
288: int
1.14 misho 289: rpc_pkt_Send(int sock, int type, sockaddr_t * __restrict sa, ait_val_t * __restrict pkt, int len)
1.1 misho 290: {
1.14 misho 291: struct pollfd pfd;
292: int ret;
1.10 misho 293: u_char *buf;
1.1 misho 294:
1.14 misho 295: if (!pkt) {
296: rpc_SetErr(EINVAL, "Invalid argument(s)!");
1.1 misho 297: return -1;
1.10 misho 298: } else
1.14 misho 299: buf = AIT_GET_BUF(pkt);
1.7 misho 300:
1.14 misho 301: pfd.fd = sock;
1.10 misho 302: pfd.events = POLLOUT;
303: if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
1.9 misho 304: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.4 misho 305: if (ret)
1.1 misho 306: LOGERR;
1.4 misho 307: else
1.10 misho 308: rpc_SetErr(ETIMEDOUT, "Timeout, can't send to RPC server");
1.1 misho 309: return -1;
310: }
1.10 misho 311: do {
1.14 misho 312: if (type == SOCK_STREAM)
313: ret = send(sock, buf, len, MSG_NOSIGNAL);
314: else if (sa)
315: ret = sendto(sock, buf, len, MSG_NOSIGNAL, &sa->sa, sa->sa.sa_len);
316: else {
317: rpc_SetErr(EINVAL, "Invalid argument(s)!");
318: return -1;
319: }
1.13 misho 320: if (ret == -1) {
1.10 misho 321: if (errno == EAGAIN)
322: continue;
323: LOGERR;
324: return -1;
1.14 misho 325: } else if (ret != len) {
1.10 misho 326: rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, "
1.14 misho 327: "really sended %d bytes", len, ret);
1.10 misho 328: return -1;
329: }
330: } while (0);
331:
1.14 misho 332: return ret;
333: }
334:
335: /*
336: * rpc_pkt_Receive() - Receive RPC packet
337: *
338: * @sock = Socket
339: * @type = Type of socket
340: * @sa = Server address
341: * @pkt = RPC packet
342: * return: -1 error or !=-1 sended bytes
343: */
344: int
345: rpc_pkt_Receive(int sock, int type, sockaddr_t * __restrict sa, ait_val_t * __restrict pkt)
346: {
347: struct pollfd pfd;
348: int ret, len = 0;
349: u_char *buf;
350: sockaddr_t sa2;
351: socklen_t salen;
352:
353: if (!pkt) {
354: rpc_SetErr(EINVAL, "Invalid argument(s)!");
355: return -1;
356: } else
357: buf = AIT_GET_BUF(pkt);
1.10 misho 358:
359: /* reply from RPC server */
1.14 misho 360: pfd.fd = sock;
1.10 misho 361: pfd.events = POLLIN | POLLPRI;
362: do {
363: if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||
364: pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
1.13 misho 365: if (ret) {
1.10 misho 366: LOGERR;
1.13 misho 367: } else {
1.14 misho 368: if (len++ < 7)
1.10 misho 369: continue;
370: else
1.14 misho 371: rpc_SetErr(ETIMEDOUT,
372: "Timeout, no answer from RPC server");
1.10 misho 373: }
1.13 misho 374:
1.10 misho 375: return -1;
376: }
1.13 misho 377:
1.14 misho 378: memset(buf, 0, AIT_LEN(pkt));
379: if (type == SOCK_STREAM)
380: ret = recv(sock, buf, AIT_LEN(pkt), 0);
381: else {
382: memset(&sa2, 0, sizeof sa2);
383: salen = sa2.ss.ss_len = sizeof(sockaddr_t);
384: ret = recvfrom(sock, buf, AIT_LEN(pkt), 0, &sa2.sa, &salen);
385: }
1.13 misho 386: if (ret < 1) {
1.10 misho 387: if (ret) {
388: if (errno == EAGAIN)
389: continue;
390: else
391: LOGERR;
392: }
393: return -1;
394: }
1.13 misho 395:
1.14 misho 396: /* check for response from known address */
397: if (type == SOCK_DGRAM)
398: if (e_addrcmp(sa, &sa2, 42)) {
399: rpc_SetErr(ERPCMISMATCH,
400: "Received RPC response from unknown address");
1.13 misho 401: continue;
402: }
1.10 misho 403: } while (0);
1.7 misho 404: if (ret < sizeof(struct tagRPCCall)) {
1.10 misho 405: rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret);
1.8 misho 406: return -1;
1.7 misho 407: }
1.8 misho 408:
1.14 misho 409: return ret;
410: }
411:
412: /*
413: * rpc_pkt_Request() - Build RPC Request packet
414: *
415: * @pkt = Packet buffer
416: * @sess = RPC session info
417: * @tag = Function tag for execution
418: * @vars = Function argument array of values, may be NULL
419: * @noreply = We not want RPC reply
1.15 misho 420: * @nocrc = Without CRC calculation
1.14 misho 421: * return: -1 error or != -1 prepared bytes into packet
422: */
423: int
424: rpc_pkt_Request(ait_val_t * __restrict pkt, rpc_sess_t * __restrict sess, u_short tag,
1.15 misho 425: array_t * __restrict vars, int noreply, int nocrc)
1.14 misho 426: {
427: struct tagRPCCall *rpc;
428: int ret = 0, len = sizeof(struct tagRPCCall);
429: u_char *buf;
430:
431: if (!pkt || !sess) {
432: rpc_SetErr(EINVAL, "Invalid argument(s)!");
433: return -1;
434: } else
435: buf = AIT_GET_BUF(pkt);
436:
437: /* prepare RPC call */
438: rpc = (struct tagRPCCall*) buf;
439: rpc_addPktSession(&rpc->call_session, sess);
440: rpc->call_tag = htons(tag);
441: if (!vars)
442: rpc->call_argc = 0;
443: else
444: rpc->call_argc = htons(array_Size(vars));
445:
446: /* set reply */
447: rpc->call_req.flags = noreply ? RPC_NOREPLY : RPC_REPLY;
448:
449: if (array_Size(vars)) {
450: /* marshaling variables */
451: ret = ait_vars2buffer(buf + len, AIT_LEN(pkt) - len, vars);
452: if (ret == -1) {
453: rpc_SetErr(EBADRPC, "Failed to prepare RPC packet values");
454: return -1;
455: } else
456: len += ret;
457: }
458:
459: /* total packet length */
460: rpc->call_len = htons(len);
461:
1.15 misho 462: if (!nocrc) {
463: /* calculate CRC */
464: rpc->call_crc ^= rpc->call_crc;
465: rpc->call_crc = htons(crcFletcher16((u_short*) buf, len / 2));
466: }
1.14 misho 467:
468: return len;
469: }
470:
471: /*
472: * rpc_pkt_Replay() - Decode RPC Replay packet
473: *
474: * @pkt = Packet buffer
475: * @sess = RPC session info
476: * @tag = Function tag
477: * @vars = Function argument array of values, may be NULL
1.15 misho 478: * @nocrc = Without CRC calculation
1.14 misho 479: * return: -1 error or != -1 return value from function
480: */
481: int
482: rpc_pkt_Replay(ait_val_t * __restrict pkt, rpc_sess_t * __restrict sess, u_short tag,
1.15 misho 483: array_t ** __restrict vars, int nocrc)
1.14 misho 484: {
485: struct tagRPCCall *rpc;
486: int len;
487: u_char *buf;
488: uint16_t crc;
489:
490: if (!pkt || !sess) {
491: rpc_SetErr(EINVAL, "Invalid argument(s)!");
492: return -1;
493: } else
494: buf = AIT_GET_BUF(pkt);
495:
496: rpc = (struct tagRPCCall*) buf;
1.15 misho 497: if (!nocrc) {
498: /* calculate CRC */
499: crc = ntohs(rpc->call_crc);
500: rpc->call_crc ^= rpc->call_crc;
501: if (crc != crcFletcher16((u_short*) buf, ntohs(rpc->call_len) / 2)) {
502: rpc_SetErr(ERPCMISMATCH, "Bad CRC RPC packet");
503: return -1;
504: }
1.8 misho 505: }
506:
1.3 misho 507: /* check RPC packet session info */
1.14 misho 508: if (rpc_chkPktSession(&rpc->call_session, sess)) {
1.10 misho 509: rpc_SetErr(ERPCMISMATCH, "Get invalid RPC session");
1.8 misho 510: return -1;
1.14 misho 511: }
1.10 misho 512: if (ntohs(rpc->call_tag) != tag) {
513: rpc_SetErr(ERPCMISMATCH, "Get wrong RPC reply");
1.8 misho 514: return -1;
1.6 misho 515: }
1.10 misho 516: if (ntohl(rpc->call_rep.eno) && ntohl(rpc->call_rep.ret) == -1) {
1.8 misho 517: rpc_SetErr(ntohl(rpc->call_rep.eno), "Server side: retcode=%d #%d %s",
1.7 misho 518: ntohl(rpc->call_rep.ret), ntohl(rpc->call_rep.eno),
519: strerror(ntohl(rpc->call_rep.eno)));
1.8 misho 520: return -1;
1.1 misho 521: }
1.14 misho 522: len = ntohs(rpc->call_argc) * sizeof(ait_val_t);
523: if (len > AIT_LEN(pkt) - sizeof(struct tagRPCCall)) {
524: rpc_SetErr(EMSGSIZE, "Reply RPC packet not enough buffer space ...");
525: return -1;
526: }
527: if (len > ntohs(rpc->call_len) - sizeof(struct tagRPCCall)) {
528: rpc_SetErr(EMSGSIZE, "Reply RPC packet is too short ...");
1.8 misho 529: return -1;
1.5 misho 530: }
531:
532: /* RPC is OK! Go de-marshaling variables ... */
1.14 misho 533: if (vars && ntohs(rpc->call_argc)) {
1.12 misho 534: #ifdef CLI_RES_ZCOPY
1.14 misho 535: *vars = ait_buffer2vars(buf + sizeof(struct tagRPCCall), len,
1.12 misho 536: ntohs(rpc->call_argc), 42);
537: #else
1.14 misho 538: *vars = ait_buffer2vars(buf + sizeof(struct tagRPCCall), len,
1.7 misho 539: ntohs(rpc->call_argc), 0);
1.12 misho 540: #endif
1.14 misho 541: if (!*vars) {
542: rpc_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.1 misho 543: return -1;
1.5 misho 544: }
1.1 misho 545: }
546:
1.14 misho 547: return ntohl(rpc->call_rep.ret);
548: }
549:
550: /*
551: * rpc_cli_execCall() - Execute RPC call
552: *
553: * @cli = RPC Client session
554: * @noreply = We not want RPC reply
555: * @tag = Function tag for execution
556: * @in_vars = IN function argument array of values, may be NULL
557: * @out_vars = OUT returned array of rpc values, if !=NULL must be free after use with ait_freeVars()
558: * return: -1 error or != -1 ok result
559: */
560: int
561: rpc_cli_execCall(rpc_cli_t *cli, int noreply, u_short tag,
562: array_t * __restrict in_vars, array_t ** __restrict out_vars)
563: {
1.15 misho 564: int type = 0, wlen;
1.14 misho 565:
566: if (!cli) {
567: rpc_SetErr(EINVAL, "Can`t execute call because parameter is null or invalid!");
568: return -1;
1.15 misho 569: }
1.16.6.1! misho 570: if (cli->cli_id == SOCK_STREAM)
! 571: type = cli->cli_id;
1.14 misho 572: if (out_vars)
573: *out_vars = NULL;
574:
1.16.6.1! misho 575: if ((wlen = rpc_pkt_Request(rpc_getBufVar(cli), cli->cli_parent, tag, in_vars, noreply, type)) == -1)
1.14 misho 576: return -1;
577:
1.16.6.1! misho 578: if (rpc_pkt_Send(cli->cli_sock, cli->cli_id, &cli->cli_sa, rpc_getBufVar(cli), wlen) == -1)
1.14 misho 579: return -1;
580:
581: if (noreply) /* we not want reply */
582: return 0;
583:
1.16.6.1! misho 584: if (rpc_pkt_Receive(cli->cli_sock, cli->cli_id, &cli->cli_sa, rpc_getBufVar(cli)) == -1)
1.14 misho 585: return -1;
586:
1.16.6.1! misho 587: if ((wlen = rpc_pkt_Replay(rpc_getBufVar(cli), cli->cli_parent, tag, out_vars, type)) == -1)
1.14 misho 588: return -1;
589:
1.15 misho 590: return 0;
1.10 misho 591: }
592:
593: /*
1.12 misho 594: * rpc_cli_freeCall() - Free resouce allocated by RPC call
595: *
596: * @out_vars = Returned array with variables from RPC call
597: * return: none
598: */
1.16 misho 599: void
1.12 misho 600: rpc_cli_freeCall(array_t ** __restrict out_vars)
601: {
602: #ifdef CLI_RES_ZCOPY
1.14 misho 603: array_Destroy(out_vars);
1.12 misho 604: #else
1.14 misho 605: ait_freeVars(out_vars);
1.12 misho 606: #endif
607: }
608:
609: /*
1.10 misho 610: * rpc_cli_ping() - Ping RPC server
611: *
612: * @cli = connected client
613: * return: -1 error or !=-1 ping seq id
614: */
1.16 misho 615: int
1.10 misho 616: rpc_cli_ping(rpc_cli_t *cli)
617: {
618: int ret = 0;
619: array_t *arr = NULL;
620:
621: if (!cli)
622: return -1;
623:
624: if (rpc_cli_execCall(cli, RPC_REPLY, CALL_SRVPING, NULL, &arr))
625: return -1;
626: else
1.14 misho 627: ret = AIT_GET_U16(array(arr, 0, ait_val_t*));
1.12 misho 628: rpc_cli_freeCall(&arr);
1.10 misho 629:
1.5 misho 630: return ret;
1.1 misho 631: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>