| version 1.24.2.1, 2014/11/12 21:37:50 | version 1.28, 2015/07/02 22:28:14 | 
| 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 - 2014 | 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 48  SUCH DAMAGE. | Line 48  SUCH DAMAGE. | 
 |  |  | 
 |  |  | 
 | #include <assert.h> | #include <assert.h> | 
| #include <stdlib.h> | //#include <stdlib.h> | 
| #include <string.h> | //#include <string.h> | 
| #include <errno.h> | //#include <errno.h> | 
| #include <sys/types.h> | //#include <sys/types.h> | 
| #include <sys/param.h> | //#include <sys/param.h> | 
| #if !defined(__NetBSD__) | //#if !defined(__NetBSD__) | 
| #include <sys/limits.h> | //#include <sys/limits.h> | 
| #endif | //#endif | 
| #include <sys/socket.h> | //#include <sys/socket.h> | 
|  | #include <pthread.h> | 
 | #include <sys/queue.h> | #include <sys/queue.h> | 
| #include <elwix.h> | #include <aitrpc_pkt.h> | 
|  | #include <aitrpc_cli.h> | 
 | #include <aitsched.h> | #include <aitsched.h> | 
 |  |  | 
 |  |  | 
 | #define RPC_VERSION             7 |  | 
 | #define RPC_DEFPORT             2611 |  | 
 |  |  | 
 | /* RPC call request flags */ |  | 
 |  |  | 
 | #define RPC_REPLY               0x0 |  | 
 | #define RPC_NOREPLY             0x1 |  | 
 |  |  | 
 | /* RPC builtin registed calls */ |  | 
 |  |  | 
 | #define CALL_TAG_MAX            65535 |  | 
 |  |  | 
 | #define CALL_SRVPING            65534 |  | 
 |  |  | 
 | #define CALL_SRVSHUTDOWN        65533 |  | 
 | #define CALL_SRVCLIENTS         65532 |  | 
 | #define CALL_SRVCALLS           65531 |  | 
 | #define CALL_SRVSESSIONS        65530 |  | 
 |  |  | 
 | #define CALL_BLOBSHUTDOWN       65529 |  | 
 | #define CALL_BLOBCLIENTS        65528 |  | 
 | #define CALL_BLOBVARS           65527 |  | 
 |  |  | 
 | /* RPC signals */ |  | 
 | #define SIGFBLOB                54 |  | 
 |  |  | 
 | /* RPC types */ |  | 
 |  |  | 
 | typedef enum { |  | 
 | ok, error, no,                          /* for blob reply */ |  | 
 | get, set, unset                         /* for blob request */ |  | 
 | } blob_cmd_type_t; |  | 
 |  |  | 
 |  |  | 
 | #define RPC_CALLBACK_CHECK_INPUT(x)     do { \ | #define RPC_CALLBACK_CHECK_INPUT(x)     do { \ | 
 | assert((x)); \ | assert((x)); \ | 
 | if (!(x)) { \ | if (!(x)) { \ | 
| Line 106  typedef enum { | Line 74  typedef enum { | 
 | } while (0) | } while (0) | 
 |  |  | 
 |  |  | 
| /* RPC session identification */ | /* Network RPC server elements */ | 
 |  |  | 
 | typedef struct { |  | 
 | #if BYTE_ORDER == LITTLE_ENDIAN |  | 
 | uint16_t        sess_instance:8; |  | 
 | uint16_t        sess_version:8; |  | 
 | #endif |  | 
 | #if BYTE_ORDER == BIG_ENDIAN |  | 
 | uint16_t        sess_version:8; |  | 
 | uint16_t        sess_instance:8; |  | 
 | #endif |  | 
 | } __packed rpc_sess_t;  /* size == 2 bytes */ |  | 
 |  |  | 
 |  |  | 
 | /* Server managment RPC functions ... */ |  | 
 |  |  | 
 | /* Network RPC packet - Client request */ |  | 
 |  |  | 
 | struct tagRPCCall { |  | 
 | rpc_sess_t      call_session; |  | 
 |  |  | 
 | uint32_t        call_len; |  | 
 | uint16_t        call_crc; |  | 
 |  |  | 
 | union { |  | 
 | struct { |  | 
 | uint64_t        flags; |  | 
 | }       call_req; |  | 
 | struct { |  | 
 | int32_t         ret; |  | 
 | int32_t         eno; |  | 
 | }       call_rep; |  | 
 | }; |  | 
 |  |  | 
 | uint16_t        call_tag; |  | 
 | uint16_t        call_argc; |  | 
 | ait_val_t       call_argv[0]; |  | 
 | } __packed;                     /* size == 20 bytes */ |  | 
 | #define RPC_CHK_NOREPLY(x)      (ntohl((u_long) (x)->call_req.flags) & RPC_NOREPLY) |  | 
 | #define RPC_SET_ERRNO(x, _v)    ((x)->call_rep.eno = htonl((_v))) |  | 
 |  |  | 
 | /* Network BLOB packet - Header */ |  | 
 |  |  | 
 | struct tagBLOBHdr { |  | 
 | rpc_sess_t      hdr_session; |  | 
 | uint8_t         hdr_cmd; |  | 
 | uint32_t        hdr_var; |  | 
 | uint32_t        hdr_len; |  | 
 | uint32_t        hdr_ret; |  | 
 | uint8_t         hdr_pad; |  | 
 | } __packed;                     /* size == 16 bytes */ |  | 
 |  |  | 
 | /* Network RPC client & server elements */ |  | 
 |  |  | 
 | /* RPC function registration element! */ | /* RPC function registration element! */ | 
 | typedef struct tagRPCFunc { | typedef struct tagRPCFunc { | 
 | ait_val_t               func_name; | ait_val_t               func_name; | 
| Line 195  typedef struct tagBLOB { | Line 111  typedef struct tagBLOB { | 
 |  |  | 
 |  |  | 
 | typedef struct { | typedef struct { | 
 | int             cli_id;         /* slot id */ |  | 
 | int             cli_sock;       /* socket fd */ |  | 
 | sockaddr_t      cli_sa;         /* host address */ |  | 
 | ait_val_t       cli_buf;        /* network buffer */ |  | 
 |  |  | 
 | array_t         *cli_vars;      /* function return variables */ |  | 
 |  |  | 
 | void            *cli_parent;    /* pointer to parent rpc_srv_t for server or to rpc_sess_t for client */ |  | 
 | } rpc_cli_t; |  | 
 | #define RPC_RETVARS(x)          ((x)->cli_vars) |  | 
 | #define RPC_SRV_SERVER(x)       ((rpc_srv_t*) (x)->cli_parent) |  | 
 | #define RPC_CLI_SESSION(x)      ((rpc_sess_t*) (x)->cli_parent) |  | 
 |  |  | 
 | typedef struct { |  | 
 | rpc_sess_t                      srv_session;    /* RPC session registration info */ | rpc_sess_t                      srv_session;    /* RPC session registration info */ | 
 | int                             srv_netbuf;     /* size of network buffer */ | int                             srv_netbuf;     /* size of network buffer */ | 
 | int                             srv_proto;      /* Server protocol */ | int                             srv_proto;      /* Server protocol */ | 
| Line 254  typedef int (*rpc_callback_t)(rpc_cli_t *, struct tagR | Line 156  typedef int (*rpc_callback_t)(rpc_cli_t *, struct tagR | 
 |  |  | 
 | /* ----------------------------------------------------------------------- */ | /* ----------------------------------------------------------------------- */ | 
 |  |  | 
 | /* Error support functions */ |  | 
 |  |  | 
 | // rpc_GetErrno() Get error code of last operation |  | 
 | int rpc_GetErrno(); |  | 
 | // rpc_GetError() Get error text of last operation |  | 
 | const char *rpc_GetError(); |  | 
 | // rpc_SetErr() Set error to variables for internal use!!! |  | 
 | void rpc_SetErr(int eno, char *estr, ...); |  | 
 |  |  | 
 |  |  | 
 |  |  | 
 | /* | /* | 
 | * rpc_Read() - RPC read operation |  | 
 | * |  | 
 | * @sock = socket |  | 
 | * @type = type of socket |  | 
 | * @flags = receive flags |  | 
 | * @sa = check client address, if you use udp protocol |  | 
 | * @buf = buffer |  | 
 | * @blen = buffer length |  | 
 | * return: -1 error, 0 EOF or or >0 readed bytes into buffer |  | 
 | */ |  | 
 | ssize_t rpc_Read(int sock, int type, int flags, sockaddr_t * __restrict sa, |  | 
 | unsigned char * __restrict buf, size_t blen); |  | 
 | /* |  | 
 | * rpc_Write() - RPC write operation |  | 
 | * |  | 
 | * @sock = socket |  | 
 | * @type = type of socket |  | 
 | * @flags = send flags |  | 
 | * @sa = send to client address, if you use udp protocol |  | 
 | * @buf = buffer |  | 
 | * @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, |  | 
 | unsigned char * __restrict buf, size_t blen); |  | 
 |  |  | 
 | /* |  | 
 | * rpc_chkPktSession() - Check RPC session |  | 
 | * |  | 
 | * @p = packet session |  | 
 | * @s = active session |  | 
 | * return: -1, 1, 2, 3 are errors or 0 ok |  | 
 | */ |  | 
 | int rpc_chkPktSession(rpc_sess_t *p, rpc_sess_t *s); |  | 
 | /* |  | 
 | * rpc_addPktSession() - Prepare session into network format |  | 
 | * |  | 
 | * @p = packet session |  | 
 | * @s = host session |  | 
 | * return: -1 error or 0 ok |  | 
 | */ |  | 
 | int rpc_addPktSession(rpc_sess_t *p, rpc_sess_t *s); |  | 
 | /* |  | 
 | * rpc_register_srvPing() - Register ping service function | * rpc_register_srvPing() - Register ping service function | 
 | * | * | 
 | * @srv = RPC server instance | * @srv = RPC server instance | 
| Line 360  void rpc_srv_endServer(rpc_srv_t ** __restrict psrv); | Line 208  void rpc_srv_endServer(rpc_srv_t ** __restrict psrv); | 
 | * return: -1 error or 0 ok, infinite loop ... | * return: -1 error or 0 ok, infinite loop ... | 
 | */ | */ | 
 | int rpc_srv_loopServer(rpc_srv_t * __restrict srv); | int rpc_srv_loopServer(rpc_srv_t * __restrict srv); | 
| #define rpc_srv_execServer(_srv, _sync) do { assert((_srv)); \ | #define rpc_srv_execServer(_srv, _sync) \ | 
| if (!(_srv)->srv_kill) { \ | do { assert((_srv)); \ | 
| pthread_create(&(_srv)->srv_tid, NULL, (void*(*)(void*)) \ | if (!(_srv)->srv_kill) { \ | 
| rpc_srv_loopServer, (_srv)); \ | pthread_create(&(_srv)->srv_tid, NULL, (void*(*)(void*)) \ | 
| if ((_sync)) \ | rpc_srv_loopServer, (_srv)); \ | 
| pthread_join((_srv)->srv_tid, (void**) (_sync)); \ | if ((_sync)) \ | 
| else \ | pthread_join((_srv)->srv_tid, (void**) (_sync)); \ | 
| pthread_detach((_srv)->srv_tid); \ | else \ | 
| } } while (0) | pthread_detach((_srv)->srv_tid); \ | 
| #define rpc_srv_killServer(_srv)        (assert((_srv)), (_srv)->srv_blob.kill = 1, (_srv)->srv_kill = 1) | } } while (0) | 
|  | #define rpc_srv_killServer(_srv) \ | 
|  | (assert((_srv)), (_srv)->srv_blob.kill = 1, (_srv)->srv_kill = 1) | 
 |  |  | 
 | /* | /* | 
 | * rpc_srv_initBLOBServer() - Init & create BLOB Server | * rpc_srv_initBLOBServer() - Init & create BLOB Server | 
| Line 394  void rpc_srv_endBLOBServer(rpc_srv_t * __restrict srv) | Line 244  void rpc_srv_endBLOBServer(rpc_srv_t * __restrict srv) | 
 | * return: -1 error or 0 ok, infinite loop ... | * return: -1 error or 0 ok, infinite loop ... | 
 | */ | */ | 
 | int rpc_srv_loopBLOBServer(rpc_srv_t * __restrict srv); | int rpc_srv_loopBLOBServer(rpc_srv_t * __restrict srv); | 
| #define rpc_srv_execBLOBServer(_srv)    do { assert((_srv)); \ | #define rpc_srv_execBLOBServer(_srv) \ | 
| if (!(_srv)->srv_kill && !(_srv)->srv_blob.kill) { \ | do { assert((_srv)); \ | 
| pthread_create(&(_srv)->srv_blob.tid, NULL, \ | if (!(_srv)->srv_kill && !(_srv)->srv_blob.kill) { \ | 
| (void*(*)(void*)) \ | pthread_create(&(_srv)->srv_blob.tid, NULL, \ | 
| rpc_srv_loopBLOBServer, (_srv)); \ | (void*(*)(void*)) rpc_srv_loopBLOBServer, (_srv)); \ | 
| pthread_detach((_srv)->srv_blob.tid); \ | pthread_detach((_srv)->srv_blob.tid); \ | 
| } \ | } \ | 
| } while (0) | } while (0) | 
 |  |  | 
 | /* | /* | 
 |  | * rpc_srv_initServer2() - Init & create layer2 RPC Server | 
 |  | * | 
 |  | * @InstID = Instance for authentication & recognition | 
 |  | * @concurentClients = Concurent clients at same time to this server | 
 |  | * @netBuf = Network buffer length (min:512 bytes), if =0 == BUFSIZ (also meaning max RPC packet) | 
 |  | * @csIface = Interface name for bind server, if NULL first interface on host | 
 |  | * return: NULL == error or !=NULL bind and created RPC server instance | 
 |  | */ | 
 |  | rpc_srv_t *rpc_srv_initServer2(u_char InstID, int concurentClients, int netBuf, | 
 |  | const char *csIface); | 
 |  |  | 
 |  | /* | 
 |  | * rpc_srv_initServerExt() - Init & create pipe RPC Server | 
 |  | * | 
 |  | * @InstID = Instance for authentication & recognition | 
 |  | * @netBuf = Network buffer length (min:512 bytes), if =0 == BUFSIZ (also meaning max RPC packet) | 
 |  | * @fd = File descriptor | 
 |  | * return: NULL == error or !=NULL bind and created RPC server instance | 
 |  | */ | 
 |  | rpc_srv_t *rpc_srv_initServerExt(u_char InstID, int netBuf, int fd); | 
 |  |  | 
 |  | /* | 
 | * rpc_srv_registerCall() - Register call to RPC server | * rpc_srv_registerCall() - Register call to RPC server | 
 | * | * | 
 | * @srv = RPC Server instance | * @srv = RPC Server instance | 
| Line 516  int rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_b | Line 388  int rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_b | 
 | * return: -1 error, 0 ok, >0 unreceived data from client, may be error? | * return: -1 error, 0 ok, >0 unreceived data from client, may be error? | 
 | */ | */ | 
 | int rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob); | int rpc_srv_recvBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob); | 
 |  |  | 
 | /* CLIENT part of functions */ |  | 
 |  |  | 
 | /* |  | 
 | * rpc_cli_sendBLOB() - Send BLOB to server |  | 
 | * |  | 
 | * @cli = Client instance |  | 
 | * @var = BLOB variable |  | 
 | * @data = BLOB data |  | 
 | * @tout = BLOB live on server timeout in seconds, if =0 default timeout |  | 
 | * return: -1 error, 0 ok, 1 remote error |  | 
 | */ |  | 
 | int rpc_cli_sendBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, |  | 
 | void * __restrict data, int tout); |  | 
 | /* |  | 
 | * rpc_cli_recvBLOB() - Receive BLOB from server |  | 
 | * |  | 
 | * @cli = Client instance |  | 
 | * @var = BLOB variable |  | 
 | * @data = BLOB data, must be e_free after use! |  | 
 | * return: -1 error, 0 ok, 1 remote error |  | 
 | */ |  | 
 | int rpc_cli_recvBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, void ** __restrict data); |  | 
 | /* |  | 
 | * rpc_cli_delBLOB() - Delete BLOB from server |  | 
 | * |  | 
 | * @cli = Client instance |  | 
 | * @var = BLOB variable |  | 
 | * return: -1 error, 0 ok, 1 remote error |  | 
 | */ |  | 
 | int rpc_cli_delBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var); |  | 
 | /* |  | 
 | * rpc_cli_getBLOB() - Receive BLOB from server and Delete after that. |  | 
 | * |  | 
 | * @cli = Client instance |  | 
 | * @var = BLOB variable |  | 
 | * @data = BLOB data, must be e_free after use! |  | 
 | * return: -1 error, 0 ok, >0 remote error |  | 
 | */ |  | 
 | int rpc_cli_getBLOB(rpc_cli_t * __restrict cli, ait_val_t * __restrict var, |  | 
 | void ** __restrict data); |  | 
 |  |  | 
 |  |  | 
 | /* RPC Client side functions */ |  | 
 |  |  | 
 | /* |  | 
 | * rpc_cli_openClient() - Connect to RPC Server |  | 
 | * |  | 
 | * @InstID = InstID for RPC session request |  | 
 | * @netBuf = Network buffer length (min:512 bytes), if =0 == BUFSIZ (also meaning max RPC packet) |  | 
 | * @csHost = Host name or IP address for bind server |  | 
 | * @Port = Port for bind server, if Port == 0 default port is selected |  | 
 | * @proto = Protocol, if == 0 choose SOCK_STREAM |  | 
 | * return: NULL == error or !=NULL connection to RPC server established |  | 
 | */ |  | 
 | rpc_cli_t *rpc_cli_openClient(unsigned char InstID, int netBuf, |  | 
 | const char *csHost, unsigned short Port, int proto); |  | 
 | /* |  | 
 | * rpc_cli_reconnectClient() - Reconnecting client to RPC server |  | 
 | * |  | 
 | * @cli = RPC Client session |  | 
 | * return: -1 error or 0 ok |  | 
 | */ |  | 
 | int rpc_cli_reconnectClient(rpc_cli_t * __restrict cli); |  | 
 | /* |  | 
 | * rpc_cli_closeClient() - Close connection to RPC server and free resources |  | 
 | * |  | 
 | * @cli = RPC Client session |  | 
 | * return: none |  | 
 | */ |  | 
 | void rpc_cli_closeClient(rpc_cli_t ** __restrict cli); |  | 
 | /* |  | 
 | * rpc_pkt_Send() - Send RPC packet |  | 
 | * |  | 
 | * @sock = Socket |  | 
 | * @type = Type of socket |  | 
 | * @sa = Server address |  | 
 | * @pkt = RPC packet |  | 
 | * @len = Length of packet |  | 
 | * return: -1 error, 0  EOF or >0 sended bytes |  | 
 | */ |  | 
 | int rpc_pkt_Send(int sock, int type, sockaddr_t * __restrict sa, |  | 
 | ait_val_t * __restrict pkt, int len); |  | 
 | /* |  | 
 | * rpc_pkt_Receive() - Receive RPC packet |  | 
 | * |  | 
 | * @sock = Socket |  | 
 | * @type = Type of socket |  | 
 | * @sa = Server address |  | 
 | * @pkt = RPC packet |  | 
 | * return: -1 error, 0 EOF or >0 received bytes |  | 
 | */ |  | 
 | int rpc_pkt_Receive(int sock, int type, sockaddr_t * __restrict sa, |  | 
 | ait_val_t * __restrict pkt); |  | 
 | /* |  | 
 | * rpc_pkt_Request() - Build RPC Request packet |  | 
 | * |  | 
 | * @pkt = Packet buffer |  | 
 | * @sess = RPC session info |  | 
 | * @tag = Function tag for execution |  | 
 | * @vars = Function argument array of values, may be NULL |  | 
 | * @noreply = We not want RPC reply |  | 
 | * @nocrc = Without CRC calculation |  | 
 | * return: -1 error or != -1 prepared bytes into packet |  | 
 | */ |  | 
 | int rpc_pkt_Request(ait_val_t * __restrict pkt, rpc_sess_t * __restrict sess, |  | 
 | unsigned short tag, array_t * __restrict vars, int noreply, int nocrc); |  | 
 | /* |  | 
 | * rpc_pkt_Replay() - Decode RPC Replay packet |  | 
 | * |  | 
 | * @pkt = Packet buffer |  | 
 | * @sess = RPC session info, if =NULL don't check session |  | 
 | * @tag = Function tag |  | 
 | * @vars = Function argument array of values, may be NULL |  | 
 | * @nocrc = Without CRC calculation |  | 
 | * return: -1 error or != -1 return value from function |  | 
 | */ |  | 
 | int rpc_pkt_Replay(ait_val_t * __restrict pkt, rpc_sess_t * __restrict sess, |  | 
 | unsigned short tag, array_t ** __restrict vars, int nocrc); |  | 
 | /* |  | 
 | * rpc_cli_execCall() - Execute RPC call |  | 
 | * |  | 
 | * @cli = RPC Client session |  | 
 | * @noreply = We not want RPC reply |  | 
 | * @tag = Function tag for execution |  | 
 | * @in_vars = IN function argument array of values, may be NULL |  | 
 | * @out_vars = OUT returned array of rpc values, if !=NULL must be free after use with ait_freeVars() |  | 
 | * return: -1 error, 0 ok result or 1 closed rpc connection |  | 
 | */ |  | 
 | int rpc_cli_execCall(rpc_cli_t *cli, int noreply, unsigned short tag, |  | 
 | array_t * __restrict in_vars, array_t ** __restrict out_vars); |  | 
 | /* |  | 
 | * rpc_cli_freeCall() - Free resouce allocated by RPC call |  | 
 | * |  | 
 | * @out_vars = Returned array with variables from RPC call |  | 
 | * return: none |  | 
 | */ |  | 
 | void rpc_cli_freeCall(array_t ** __restrict out_vars); |  | 
 | /* |  | 
 | * rpc_cli_ping() - Ping RPC server |  | 
 | * |  | 
 | * @cli = connected client |  | 
 | * return: -1 error or !=-1 ping seq id |  | 
 | */ |  | 
 | int rpc_cli_ping(rpc_cli_t *cli); |  | 
 |  |  | 
 |  |  | 
 | /* |  | 
 | * rpc_cli_openBLOBClient() - Connect to BLOB Server |  | 
 | * |  | 
 | * @rpccli = RPC Client session |  | 
 | * @Port = Port for bind server, if Port == 0 default port is selected |  | 
 | * return: NULL == error or !=NULL connection to BLOB server established |  | 
 | */ |  | 
 | rpc_cli_t *rpc_cli_openBLOBClient(rpc_cli_t * __restrict rpccli, unsigned short Port); |  | 
 | /* |  | 
 | * rpc_cli_closeBLOBClient() - Close connection to BLOB server and free resources |  | 
 | * |  | 
 | * @cli = BLOB Client session |  | 
 | * return: none |  | 
 | */ |  | 
 | void rpc_cli_closeBLOBClient(rpc_cli_t ** __restrict cli); |  | 
 |  |  | 
 |  |  | 
 | #endif | #endif |