version 1.5.6.4, 2012/05/15 22:47:10
|
version 1.20.2.3, 2016/08/02 12:00:39
|
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 | Copyright 2004 - 2016 |
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 int | int |
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 void | void |
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 int | int |
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 (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 int | int |
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_program = htonl(s->sess_program); | p->sess_instance = s->sess_instance; |
p->sess_process = 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 |
*/ |
*/ |
int | ssize_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; |
| 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; |
| #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; |
| #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, crcFletcher16((u_short*) CALL_SRVSHUTDOWN, | switch (type) { |
strlen(CALL_SRVSHUTDOWN) / 2), CALL_SRVSHUTDOWN, 0); | case SOCK_STREAM: |
rpc_srv_registerCall(srv, crcFletcher16((u_short*) CALL_SRVCLIENTS, | ret = recv(sock, buf, blen, flags); |
strlen(CALL_SRVCLIENTS) / 2), CALL_SRVCLIENTS, 1); | break; |
rpc_srv_registerCall(srv, crcFletcher16((u_short*) CALL_SRVSESSIONS, | case SOCK_EXT: |
strlen(CALL_SRVSESSIONS) / 2), CALL_SRVSESSIONS, 4); | ret = read(sock, buf, blen); |
rpc_srv_registerCall(srv, crcFletcher16((u_short*) CALL_SRVCALLS, | break; |
strlen(CALL_SRVCALLS) / 2), CALL_SRVCALLS, 1); | #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) { |
| 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; |
| } |
| |
| /* |
| * 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, sizeof sa->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))); |
} |
} |