Diff for /libaitrpc/src/aitrpc.c between versions 1.12 and 1.18.2.2

version 1.12, 2013/11/11 22:48:53 version 1.18.2.2, 2015/06/29 22:29:25
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, 2012, 2013Copyright 2004 - 2015
         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 147  rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s) Line 147  rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s)
  * @type = type of socket   * @type = type of socket
  * @flags = receive flags   * @flags = receive flags
  * @sa = check client address, if you use udp protocol   * @sa = check client address, if you use udp protocol
 * @buf = buffer * @pkt = RPC packet
 * @blen = buffer length * return: -1 error, 0 EOF or or >0 readed bytes into buffer
 * return: -1 error or >-1 readed bytes into buffer 
  */   */
 ssize_t  ssize_t
rpc_Read(int sock, int type, int flags, sockaddr_t * __restrict sa, rpc_Read(int sock, int type, int flags, sockaddr_t * __restrict sa, ait_val_t * __restrict pkt)
                u_char * __restrict buf, size_t blen) 
 {  {
         struct pollfd pfd;          struct pollfd pfd;
         sockaddr_t sa2;          sockaddr_t sa2;
         socklen_t salen;          socklen_t salen;
        int ret = 0, len;        int ret = 0, hlen, cx = 0;
         struct ether_header *eh;
         struct bpf_hdr *h;
         ether_addr_t bcst = {{ [0 ... sizeof bcst - 1] = 0xff }};
         u_char *buf = AIT_GET_BUF(pkt);
         size_t blen = AIT_LEN(pkt);
         struct tagRPCCall *rpc = (struct tagRPCCall *) buf;
         ait_val_t v = AIT_VAL_INIT;
   
   try2read:
         pfd.fd = sock;          pfd.fd = sock;
         pfd.events = POLLIN | POLLPRI;          pfd.events = POLLIN | POLLPRI;
         memset(buf, 0, blen);          memset(buf, 0, blen);
         memset(&sa2, 0, sizeof sa2);          memset(&sa2, 0, sizeof sa2);
         salen = sa2.ss.ss_len = sizeof(sockaddr_t);          salen = sa2.ss.ss_len = sizeof(sockaddr_t);
           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;
           }
   
        if (type == SOCK_STREAM) {        switch (type) {
                for (len = blen; len > 0; len -= ret, buf += ret) {                case SOCK_STREAM:
                        if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||                         ret = recv(sock, buf, blen, flags);
                                        pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {                        break;
                                LOGERR;                case SOCK_EXT:
                         ret = read(sock, buf, blen);
                         break;
                 case SOCK_BPF:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;                                  return -1;
                         } else  
                                 ret = recv(sock, buf, len, flags);  
                         if (ret == -1) {  
                                 LOGERR;  
                                 return -1;  
                         }                          }
                }
                if (ret > -1)                        AIT_SET_BUF(&v, NULL, blen);
                        ret = blen - len;                        h = (struct bpf_hdr*) AIT_GET_BUF(&v);
        } else {
                do {                        ret = read(sock, AIT_GET_BUF(&v), AIT_LEN(&v));
                        if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||                         if (ret > 0) {
                                        pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {                                ret -= h->bh_hdrlen;
                                LOGERR;                                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;
                 case SOCK_RAW:
                 case SOCK_DGRAM:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;                                  return -1;
                         } else  
                                 ret = recvfrom(sock, buf, blen, flags, &sa2.sa, &salen);  
                         if (ret < 0) {  
                                 LOGERR;  
                                 return -1;  
                         }                          }
                        if (e_addrcmp(sa, &sa2, 42))
                                rpc_SetErr(ERPCMISMATCH, "Received RPC response from unknown address");                        ret = recvfrom(sock, buf, blen, flags, &sa2.sa, &salen);
                        else                        if (ret > -1 && e_addrcmp(sa, &sa2, 42)) {
                                break;                                if (cx < 3) {
                } while (42);                                        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) {
                   hlen = sa->sa.sa_family == AF_INET ? 
                           sizeof(struct ip) : sizeof(struct ip6_hdr);
                   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;          return ret;
 }  }
   
Line 210  rpc_Read(int sock, int type, int flags, sockaddr_t * _ Line 300  rpc_Read(int sock, int type, int flags, sockaddr_t * _
  * @type = type of socket   * @type = type of socket
  * @flags = send flags   * @flags = send flags
  * @sa = send to client address, if you use udp protocol   * @sa = send to client address, if you use udp protocol
 * @buf = buffer * @pkt = RPC packet
  * @blen = buffer length   * @blen = buffer length
 * return: -1 error or >-1 written bytes into buffer * return: -1 error, 0 EOF or >0 written bytes into buffer
  */   */
 ssize_t  ssize_t
 rpc_Write(int sock, int type, int flags, sockaddr_t * __restrict sa,   rpc_Write(int sock, int type, int flags, sockaddr_t * __restrict sa, 
                u_char * __restrict buf, size_t blen)                ait_val_t * __restrict pkt, size_t blen)
 {  {
         struct pollfd pfd;          struct pollfd pfd;
        int ret = 0, len = 0;        int ret = 0;
         u_char *buf = AIT_GET_BUF(pkt);
         ait_val_t v = AIT_VAL_INIT;
         struct ether_header *eh;
   
   
         pfd.fd = sock;          pfd.fd = sock;
         pfd.events = POLLOUT;          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;
           }
   
        if (type == SOCK_STREAM) {        switch (type) {
                for (len = blen; len > 0; len -= ret, buf += ret) {                case SOCK_STREAM:
                        if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||                         ret = send(sock, buf, blen, flags);
                                        pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {                        break;
                                if (!ret)                case SOCK_EXT:
                                        continue;                        ret = write(sock, buf, blen);
                                if (ret > 0)                        break;
                                        rpc_SetErr(EPIPE, "Disconnected RPC session\n");                case SOCK_BPF:
                                else                        if (!sa) {
                                        LOGERR;                                rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;                                  return -1;
                         } else  
                                 ret = send(sock, buf, len, flags);  
                         if (ret == -1) {  
                                 LOGERR;  
                                 return -1;  
                         }                          }
                }
                if (ret > -1)                        AIT_SET_BUF(&v, NULL, blen + sizeof(struct ether_header));
                        ret = blen - len;                        eh = (struct ether_header*) AIT_GET_BUF(&v);
        } else if (sa) {                        memcpy(eh->ether_dhost, LLADDR(&sa->sdl), ETHER_ADDR_LEN);
                do {                        eh->ether_type = htons(RPC_DEFPORT);
                        if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 ||                         memcpy(eh + 1, buf, blen);
                                        pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {                        blen += sizeof(struct ether_header);
                                if (!ret)
                                        continue;                        ret = write(sock, AIT_GET_BUF(&v), AIT_LEN(&v));
                                if (ret > 0)
                                        rpc_SetErr(EPIPE, "Disconnected RPC session\n");                        AIT_FREE_VAL(&v);
                                else                        break;
                                        LOGERR;                case SOCK_RAW:
                 case SOCK_DGRAM:
                         if (!sa) {
                                 rpc_SetErr(EINVAL, "Invalid argument(s)!");
                                 return -1;                                  return -1;
                        } else                        }
                                ret = sendto(sock, buf, blen, flags, &sa->sa, sa->sa.sa_len);
                } while (0);                        ret = sendto(sock, buf, blen, flags, &sa->sa, sa->sa.sa_len);
        } else {                        break;
                rpc_SetErr(EINVAL, "Invalid argument(s)!");                default:
                return -1;                        rpc_SetErr(EINVAL, "Invalid argument(s)!");
                         return -1;
         }          }
        if (ret == -1) {        if (ret < 0) {
                 LOGERR;                  LOGERR;
                 return -1;                  return -1;
        } else if (ret != blen) {        }
         if (!ret)       /* EOF */
                 return 0;
 
         if (ret != blen) {
                 rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, "                  rpc_SetErr(EPROCUNAVAIL, "RPC request, should be send %d bytes, "
                                "really sended %d bytes", len, ret);                                "really sended %d bytes", blen, ret);
                 return -1;                  return -1;
         }          }
   
         return ret;          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.12  
changed lines
  Added in v.1.18.2.2


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