Diff for /libaitrpc/src/aitrpc.c between versions 1.5.6.2 and 1.22

version 1.5.6.2, 2012/05/15 16:06:13 version 1.22, 2024/03/20 17:32:30
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012Copyright 2004 - 2024
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 54  char rpc_Error[STRSIZ]; Line 54  char rpc_Error[STRSIZ];
 #pragma GCC visibility pop  #pragma GCC visibility pop
   
 // rpc_GetErrno() Get error code of last operation  // rpc_GetErrno() Get error code of last operation
inline intint
 rpc_GetErrno()  rpc_GetErrno()
 {  {
         return rpc_Errno;          return rpc_Errno;
 }  }
   
 // rpc_GetError() Get error text of last operation  // rpc_GetError() Get error text of last operation
inline const char *const char *
 rpc_GetError()  rpc_GetError()
 {  {
         return rpc_Error;          return rpc_Error;
 }  }
   
 // rpc_SetErr() Set error to variables for internal use!!!  // rpc_SetErr() Set error to variables for internal use!!!
inline voidvoid
 rpc_SetErr(int eno, char *estr, ...)  rpc_SetErr(int eno, char *estr, ...)
 {  {
         va_list lst;          va_list lst;
   
         rpc_Errno = eno;          rpc_Errno = eno;
        memset(rpc_Error, 0, STRSIZ);        memset(rpc_Error, 0, sizeof rpc_Error);
         va_start(lst, estr);          va_start(lst, estr);
        vsnprintf(rpc_Error, STRSIZ, estr, lst);        vsnprintf(rpc_Error, sizeof rpc_Error, estr, lst);
         va_end(lst);          va_end(lst);
 }  }
   
Line 88  rpc_SetErr(int eno, char *estr, ...) Line 88  rpc_SetErr(int eno, char *estr, ...)
  * @s = active session   * @s = active session
  * return: -1, 1, 2, 3 are errors or 0 ok   * return: -1, 1, 2, 3 are errors or 0 ok
  */   */
inline intint
 rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s)  rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s)
 {  {
         if (!p || !s)          if (!p || !s)
Line 96  rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s) Line 96  rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s)
   
         if (p->sess_version != s->sess_version)          if (p->sess_version != s->sess_version)
                 return 1;                  return 1;
        if (ntohl(p->sess_program) != s->sess_program)        if (p->sess_instance != s->sess_instance)
                 return 2;                  return 2;
         if (ntohl(p->sess_process) != s->sess_process)  
                 return 3;  
   
         return 0;          return 0;
 }  }
Line 111  rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s) Line 109  rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s)
  * @s = host session   * @s = host session
  * return: -1 error or 0 ok   * return: -1 error or 0 ok
  */   */
inline intint
 rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s)  rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s)
 {  {
         if (!p || !s)          if (!p || !s)
                 return -1;                  return -1;
   
         p->sess_version = s->sess_version;          p->sess_version = s->sess_version;
        p->sess_timeout = s->sess_timeout;        p->sess_instance = s->sess_instance;
        p->sess_program = htonl(s->sess_program); 
        p->sess_process = htons(s->sess_process); 
   
         return 0;          return 0;
 }  }
   
 /*  /*
 * rpc_register_srvServices() - Register internal service functions * rpc_Read() - RPC read operation
  *   *
 * @srv = RPC server instance * @sock = socket
 * return: -1 error or 0 ok * @type = type of socket
  * @flags = receive flags
  * @sa = check client address, if you use udp protocol
  * @pkt = RPC packet
  * return: -1 error, 0 EOF or or >0 readed bytes into buffer
  */   */
intssize_t
rpc_register_srvServices(rpc_srv_t * __restrict srv)rpc_Read(int sock, int type, int flags, sockaddr_t * __restrict sa, ait_val_t * __restrict pkt)
 {  {
        if (!srv)        struct pollfd pfd;
         sockaddr_t sa2;
         socklen_t salen;
         int ret = 0, hlen, cx = 0;
         u_char *buf = AIT_GET_BUF(pkt);
         size_t blen = AIT_LEN(pkt);
         struct tagRPCCall *rpc = (struct tagRPCCall *) buf;
 #ifndef __linux__
         struct ether_header *eh;
         struct bpf_hdr *h;
         ait_val_t v = AIT_VAL_INIT;
 #endif
 
 try2read:
         pfd.fd = sock;
         pfd.events = POLLIN | POLLPRI;
         memset(buf, 0, blen);
         memset(&sa2, 0, sizeof sa2);
         salen = E_SOCKADDR_MAX;
 #ifndef __linux__
         sa2.ss.ss_len = salen;
         ether_addr_t bcst = {{ [0 ... sizeof bcst - 1] = 0xff }};
 #endif
         if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || 
                         pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
                 if (ret)
                         LOGERR;
                 else
                         rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond");
                 return -1;                  return -1;
           }
   
        rpc_srv_registerCall(srv, NULL, CALL_SRVSHUTDOWN, 0);        switch (type) {
        rpc_srv_registerCall(srv, NULL, CALL_SRVCLIENTS, 1);                case SOCK_STREAM:
        rpc_srv_registerCall(srv, NULL, CALL_SRVSESSIONS, 4);                        ret = recv(sock, buf, blen, flags);
        rpc_srv_registerCall(srv, NULL, CALL_SRVCALLS, 1);                        break;
                 case SOCK_EXT:
                         ret = read(sock, buf, blen);
                         break;
 #ifndef __linux__
                 case SOCK_BPF:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;
                         }
   
        return 0;                        AIT_SET_BUF(&v, NULL, blen);
                         h = (struct bpf_hdr*) AIT_GET_BUF(&v);
 
                         ret = read(sock, AIT_GET_BUF(&v), AIT_LEN(&v));
                         if (ret > 0) {
                                 ret -= h->bh_hdrlen;
                                 if (ret < h->bh_caplen || h->bh_caplen != h->bh_datalen || 
                                                 ret < ETHER_HDR_LEN + sizeof(struct tagRPCCall)) {
                                         AIT_FREE_VAL(&v);
                                         if (cx < 3) {
                                                 cx++;
                                                 ret ^= ret;
                                                 goto try2read;  /* wait for known address */
                                         } else
                                                 return -1;
                                 }
                                 ret = h->bh_caplen;
                                 eh = (struct ether_header*) (AIT_GET_BUF(&v) + h->bh_hdrlen);
                                 ret -= ETHER_HDR_LEN;
                                 if (eh->ether_type != ntohs(RPC_DEFPORT)) {
                                         AIT_FREE_VAL(&v);
                                         if (cx < 3) {
                                                 cx++;
                                                 ret ^= ret;
                                                 goto try2read;  /* wait for known address */
                                         } else
                                                 return -1;
                                 }
 
                                 if (!memcmp(bcst.octet, eh->ether_dhost, sizeof bcst) || 
                                                 !memcmp(bcst.octet, eh->ether_shost, sizeof bcst)) {
                                         AIT_FREE_VAL(&v);
                                         if (cx < 3) {
                                                 cx++;
                                                 ret ^= ret;
                                                 goto try2read;  /* wait for known address */
                                         } else
                                                 return -1;
                                 }
                                 memcpy(buf, (u_char*) (eh + 1), MIN(ret, blen));
                                 AIT_FREE_VAL(&v);
                         }
                         break;
 #endif
                 case SOCK_RAW:
                 case SOCK_DGRAM:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;
                         }
 
                         ret = recvfrom(sock, buf, blen, flags, &sa2.sa, &salen);
                         if (ret > -1 && e_addrcmp(sa, &sa2, 42)) {
                                 if (cx < 3) {
                                         cx++;
                                         ret ^= ret;
                                         goto try2read;  /* wait for known address */
                                 } else
                                         return -1;
                         }
                         break;
                 default:
                         rpc_SetErr(EINVAL, "Invalid argument(s)!");
                         return -1;
         }
         if (ret < 0) {
                 LOGERR;
                 return -1;
         }
         if (!ret)       /* EOF */
                 return 0;
 
         /* check RPC packet header */
         if (type == SOCK_RAW) {
 #ifdef IPV6_REMOVE_HEADER
                 hlen = sa->sa.sa_family == AF_INET ? 
                         sizeof(struct ip) : sizeof(struct ip6_hdr);
 #else
                 hlen = sa->sa.sa_family == AF_INET ? 
                         sizeof(struct ip) : 0;
 #endif
                 ret -= hlen;
                 if (ret > 0)
                         memmove(buf, buf + hlen, blen - hlen);
         }
 
         /* 1st read for RPC header */
         if (ret < sizeof(struct tagRPCCall) || ret < ntohl(rpc->call_len)) {
                 rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret);
                 return -1;
         }
         /* check for loop request */
         if (!(rpc->call_io & RPC_ACK)) {
                 if (cx < 3) {
                         cx++;
                         ret ^= ret;
                         goto try2read;  /* wait for known address */
                 } else {
                         rpc_SetErr(ERPCMISMATCH, "Loop in RPC communication");
                         return -1;
                 }
         }
 
         return ret;
 }
 
 /*
  * rpc_Write() - RPC write operation
  *
  * @sock = socket
  * @type = type of socket
  * @flags = send flags
  * @sa = send to client address, if you use udp protocol
  * @pkt = RPC packet
  * @blen = buffer length
  * return: -1 error, 0 EOF or >0 written bytes into buffer
  */
 ssize_t
 rpc_Write(int sock, int type, int flags, sockaddr_t * __restrict sa, 
                 ait_val_t * __restrict pkt, size_t blen)
 {
         struct pollfd pfd;
         int ret = 0;
         u_char *buf = AIT_GET_BUF(pkt);
 #ifndef __linux__
         ait_val_t v = AIT_VAL_INIT;
         struct ether_header *eh;
 #endif
 
 
         pfd.fd = sock;
         pfd.events = POLLOUT;
         if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || 
                         pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
                 if (ret > 0)
                         rpc_SetErr(EPIPE, "Disconnected RPC session\n");
                 else
                         LOGERR;
                 return -1;
         }
 
         switch (type) {
                 case SOCK_STREAM:
                         ret = send(sock, buf, blen, flags);
                         break;
                 case SOCK_EXT:
                         ret = write(sock, buf, blen);
                         break;
 #ifndef __linux__
                 case SOCK_BPF:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;
                         }
 
                         AIT_SET_BUF(&v, NULL, blen + sizeof(struct ether_header));
                         eh = (struct ether_header*) AIT_GET_BUF(&v);
                         memcpy(eh->ether_dhost, LLADDR(&sa->sdl), ETHER_ADDR_LEN);
                         eh->ether_type = htons(RPC_DEFPORT);
                         memcpy(eh + 1, buf, blen);
                         blen += sizeof(struct ether_header);
 
                         ret = write(sock, AIT_GET_BUF(&v), AIT_LEN(&v));
 
                         AIT_FREE_VAL(&v);
                         break;
 #endif
                 case SOCK_RAW:
                 case SOCK_DGRAM:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;
                         }
 
                         ret = sendto(sock, buf, blen, flags, &sa->sa, e_addrlen(sa));
                         break;
                 default:
                         rpc_SetErr(EINVAL, "Invalid argument(s)!");
                         return -1;
         }
         if (ret < 0) {
                 LOGERR;
                 return -1;
         }
         if (!ret)       /* EOF */
                 return 0;
 
         if (ret != blen) {
                 rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, "
                                 "really sended %d bytes", blen, ret);
                 return -1;
         }
 
         return ret;
 }
 
 /*
  * rpc_pktFreeSpace() - Get free space for payload into RPC packet
  *
  * @c = RPC client 
  * return: remains free bytes from packet
  */
 size_t
 rpc_pktFreeSpace(rpc_cli_t * __restrict c)
 {
         return (sizeof(struct tagRPCCall) + ait_resideVars(RPC_RETVARS(c)));
 }  }

Removed from v.1.5.6.2  
changed lines
  Added in v.1.22


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>