version 1.12, 2013/11/11 22:48:53
|
version 1.18, 2015/05/18 15:09:59
|
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, 2013 | Copyright 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, len, hlen, cx = 0; |
| ait_val_t v = AIT_VAL_INIT; |
| 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; |
|
|
|
if (type == SOCK_BPF && sa) { |
|
AIT_SET_BUF(&v, NULL, blen); |
|
h = (struct bpf_hdr*) AIT_GET_BUF(&v); |
|
} |
|
|
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 (type == SOCK_STREAM) { | for (len = blen; len > 0; len -= ret, buf += ret) { |
for (len = blen; len > 0; len -= ret, buf += ret) { | if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | if (ret) |
LOGERR; |
LOGERR; |
return -1; | else |
} else | rpc_SetErr(ETIMEDOUT, "Timeout reached! Server not respond"); |
ret = recv(sock, buf, len, flags); | if (type == SOCK_BPF) |
if (ret == -1) { | AIT_FREE_VAL(&v); |
LOGERR; | return -1; |
return -1; | } |
| if (type == SOCK_STREAM) |
| ret = recv(sock, buf, len, flags); |
| else if (type == SOCK_EXT) |
| ret = read(sock, buf, len); |
| else if (type == SOCK_BPF && sa) { |
| 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)) { |
| if (cx < 3) { |
| cx++; |
| ret ^= ret; |
| continue; /* wait for known address */ |
| } else { |
| AIT_FREE_VAL(&v); |
| 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)) { |
| if (cx < 3) { |
| cx++; |
| ret ^= ret; |
| continue; /* wait for known address */ |
| } else { |
| AIT_FREE_VAL(&v); |
| return -1; |
| } |
| } |
| |
| if (!memcmp(bcst.octet, eh->ether_dhost, sizeof bcst) || |
| !memcmp(bcst.octet, eh->ether_shost, sizeof bcst)) { |
| if (cx < 3) { |
| cx++; |
| ret ^= ret; |
| continue; /* wait for known address */ |
| } else { |
| AIT_FREE_VAL(&v); |
| return -1; |
| } |
| } |
| memcpy(buf, (u_char*) (eh + 1), MIN(ret, len)); |
| AIT_FREE_VAL(&v); |
| return ret; |
} |
} |
|
} else { |
|
ret = recvfrom(sock, buf, len, flags, &sa2.sa, &salen); |
|
if (ret > -1 && sa && e_addrcmp(sa, &sa2, 42)) { |
|
if (cx < 3) { |
|
cx++; |
|
ret ^= ret; |
|
continue; /* wait for known address */ |
|
} else |
|
return -1; |
|
} |
} |
} |
if (ret > -1) | if (ret < 0) { |
ret = blen - len; | LOGERR; |
} else { | if (type == SOCK_BPF) |
do { | AIT_FREE_VAL(&v); |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | return -1; |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | } |
LOGERR; | if (!ret) { /* EOF */ |
| if (type == SOCK_BPF) |
| AIT_FREE_VAL(&v); |
| return 0; |
| } |
| |
| /* check RPC packet header */ |
| if ((u_char*) rpc == buf) { |
| 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)) { |
| rpc_SetErr(ERPCMISMATCH, "Short RPC packet %d bytes", ret); |
| if (type == SOCK_BPF) |
| AIT_FREE_VAL(&v); |
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)) | /* check for loop request */ |
rpc_SetErr(ERPCMISMATCH, "Received RPC response from unknown address"); | if (!(rpc->call_io & RPC_ACK)) { |
else | ret ^= ret; |
break; | continue; |
} while (42); | } |
| /* calc estimated length */ |
| blen = len = ntohl(rpc->call_len); |
| if (blen > AIT_LEN(pkt)) { |
| AIT_RE_BUF(pkt, blen); |
| buf = AIT_GET_BUF(pkt); |
| rpc = (struct tagRPCCall*) buf; |
| } |
| } |
} |
} |
|
ret = blen - len; |
|
|
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
return ret; |
return ret; |
} |
} |
|
|
Line 210 rpc_Read(int sock, int type, int flags, sockaddr_t * _
|
Line 302 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, len = 0; |
|
ait_val_t v = AIT_VAL_INIT; |
|
struct ether_header *eh; |
|
u_char *buf = AIT_GET_BUF(pkt); |
|
|
|
if (type == SOCK_BPF && sa) { |
|
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); |
|
} |
|
|
pfd.fd = sock; |
pfd.fd = sock; |
pfd.events = POLLOUT; |
pfd.events = POLLOUT; |
| for (len = blen; len > 0; len -= ret, buf += ret) { |
if (type == SOCK_STREAM) { | if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || |
for (len = blen; len > 0; len -= ret, buf += ret) { | pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | #if 0 |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | if (!ret) |
if (!ret) | continue; |
continue; | #endif |
if (ret > 0) | if (ret > 0) |
rpc_SetErr(EPIPE, "Disconnected RPC session\n"); | rpc_SetErr(EPIPE, "Disconnected RPC session\n"); |
else | else |
LOGERR; | |
return -1; | |
} else | |
ret = send(sock, buf, len, flags); | |
if (ret == -1) { | |
LOGERR; |
LOGERR; |
return -1; | if (type == SOCK_BPF) |
} | AIT_FREE_VAL(&v); |
| return -1; |
} |
} |
if (ret > -1) | if (type == SOCK_STREAM) |
ret = blen - len; | ret = send(sock, buf, len, flags); |
} else if (sa) { | else if (type == SOCK_EXT) |
do { | ret = write(sock, buf, len); |
if ((ret = poll(&pfd, 1, DEF_RPC_TIMEOUT * 1000)) < 1 || | else if (type == SOCK_BPF && sa) { |
pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { | ret = write(sock, AIT_GET_BUF(&v), AIT_LEN(&v)); |
if (!ret) | } else if (sa) |
continue; | ret = sendto(sock, buf, len, flags, &sa->sa, sa->sa.sa_len); |
if (ret > 0) | else { |
rpc_SetErr(EPIPE, "Disconnected RPC session\n"); | rpc_SetErr(EINVAL, "Invalid argument(s)!"); |
else | if (type == SOCK_BPF) |
LOGERR; | AIT_FREE_VAL(&v); |
return -1; | return -1; |
} else | } |
ret = sendto(sock, buf, blen, flags, &sa->sa, sa->sa.sa_len); | if (ret < 0) { |
} while (0); | LOGERR; |
} else { | if (type == SOCK_BPF) |
rpc_SetErr(EINVAL, "Invalid argument(s)!"); | AIT_FREE_VAL(&v); |
return -1; | return -1; |
| } |
| if (!ret) { /* EOF */ |
| if (type == SOCK_BPF) |
| AIT_FREE_VAL(&v); |
| return 0; |
| } |
} |
} |
if (ret == -1) { | ret = blen - len; |
LOGERR; | if (ret != blen) { |
return -1; | |
} else 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); |
| if (type == SOCK_BPF) |
| AIT_FREE_VAL(&v); |
return -1; |
return -1; |
} |
} |
|
|
|
if (type == SOCK_BPF) |
|
AIT_FREE_VAL(&v); |
return ret; |
return ret; |
} |
} |