File:  [ELWIX - Embedded LightWeight unIX -] / libaitrpc / inc / aitrpc.h
Revision 1.29: download - view: text, annotated - select for diffs - revision graph
Wed Mar 20 17:32:30 2024 UTC (2 months, 1 week ago) by misho
Branches: MAIN
CVS tags: rpc9_6, RPC9_5, HEAD
Version 9.5

/*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
*  by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: aitrpc.h,v 1.29 2024/03/20 17:32:30 misho Exp $
*
**************************************************************************
The ELWIX and AITNET software is distributed under the following
terms:

All of the documentation and software included in the ELWIX and AITNET
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>

Copyright 2004 - 2024
	by Michael Pounov <misho@elwix.org>.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
   must display the following acknowledgement:
This product includes software developed by Michael Pounov <misho@elwix.org>
ELWIX - Embedded LightWeight unIX and its contributors.
4. Neither the name of AITNET nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef __AITRPC_H
#define __AITRPC_H


#include <assert.h>
#include <pthread.h>
#include <sys/queue.h>
#include <aitrpc_pkt.h>
#include <aitrpc_cli.h>
#include <aitsched.h>


#define RPC_CALLBACK_CHECK_INPUT(x)	do { \
						assert((x)); \
						if (!(x)) { \
							rpc_SetErr(EINVAL, \
									"Invalid callback parameters ..."); \
							return -1; \
						} \
					} while (0)


/* Network RPC server elements */

/* RPC function registration element! */
typedef struct tagRPCFunc {
	ait_val_t		func_name;

	void			*func_parent;

	SLIST_ENTRY(tagRPCFunc)	func_next;
	AVL_ENTRY(tagRPCFunc)	func_node;
} rpc_func_t;
#define RPC_FUNC_SERVER(x)	((rpc_srv_t*) (x)->func_parent)

/* Tree root node */
typedef struct tagRPCFuncs {
	pthread_mutex_t		mtx;

	struct tagRPCFunc	*slh_first;
	struct tagRPCFunc	*avlh_root;
} rpc_funcs_t;
#define RPC_FUNCS_LOCK(x)	pthread_mutex_lock(&(x)->mtx)
#define RPC_FUNCS_UNLOCK(x)	pthread_mutex_unlock(&(x)->mtx)
#define RPC_FUNCS_ISEMPTY(x)	AVL_EMPTY((x))


/* BLOB register element */
typedef struct tagBLOB {
	uint32_t		blob_var;	/* BLOB id */

	size_t			blob_len;	/* size of allocated BLOB data */
	void			*blob_data;	/* mapped BLOB data */

	TAILQ_ENTRY(tagBLOB)	blob_node;
} rpc_blob_t;


typedef struct {
	rpc_sess_t			srv_session;	/* RPC session registration info */
	int				srv_netbuf;	/* size of network buffer */
	int				srv_proto;	/* Server protocol */

	pthread_t			srv_tid;	/* RPC exec pthread */
	sched_root_task_t		*srv_root;	/* RPC server scheduler */
	intptr_t			srv_kill;	/* Scheduler condition variable */

	rpc_cli_t			srv_server;	/* RPC server socket */
	array_t				*srv_clients;	/* connected rpc client sockets */

	rpc_funcs_t			srv_funcs;	/* RPC functions */

	struct {
		pthread_t			tid;		/* BLOB exec pthread */
		sched_root_task_t		*root;		/* BLOB server scheduler */
		intptr_t			kill;		/* BLOB server state: ==0 disable | !=0 enable */

		ait_val_t			dir;		/* BLOB states directory */

		rpc_cli_t			server;		/* BLOB server socket */
		array_t				*clients;	/* connected blob client sockets */

		TAILQ_HEAD(, tagBLOB)		blobs;		/* registered blob variables list */
	} 				srv_blob;
} rpc_srv_t;


/* 
 * (*rpc_callback_t)() - Callback type definition for RPC call in server process
 *
 * @arg1 = RPC client
 * @arg2 = RPC packet header
 * @arg3 = input array with values from RPC call execution request
 * return: -1 error or >-1 success execution
 */
typedef int (*rpc_callback_t)(rpc_cli_t *, struct tagRPCCall *, array_t *);

#define RPC_CALL_DEFINE(x)	int (x)(rpc_cli_t*, struct tagRPCCall*, array_t*)
#define RPC_CALL_ARGS(arg1, arg2, arg3)	rpc_cli_t* arg1, struct tagRPCCall* arg2, array_t* arg3
#define RPC_CALL_STDARGS	RPC_CALL_ARGS(cli, rpc, iv)


/*
 * rpc_srv_DispatchSignal() - Enable/Disable Signal dispatcher for RPC scheduler
 *
 * @x = RPC server instance
 * @y = Enable or =0 Disable
 * return: 0 enabled signal dispatcher. See schedSignalDispatch() in libaitsched
 */
#define rpc_srv_DispatchSignal(x, y)	schedSignalDispatch((x)->srv_root, (y))

/* ----------------------------------------------------------------------- */

/*
 * rpc_register_srvPing() - Register ping service function
 *
 * @srv = RPC server instance
 * return: -1 error or 0 ok
 */
int rpc_register_srvPing(rpc_srv_t * __restrict srv);
/*
 * rpc_register_srvServices() - Register internal service functions
 *
 * @srv = RPC server instance
 * return: -1 error or 0 ok
 */
int rpc_register_srvServices(rpc_srv_t * __restrict srv);
/*
 * rpc_register_blobServices() - Register internal service functions
 *
 * @srv = RPC server instance
 * return: -1 error or 0 ok
 */
int rpc_register_blobServices(rpc_srv_t * __restrict srv);


/* RPC Server side functions */

/*
 * rpc_srv_initServer() - Init & create 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)
 * @csHost = Host name or address for bind server, if NULL any address
 * @Port = Port for bind server, if Port == 0 default port is selected
 * @proto = Protocol, if == 0 choose SOCK_STREAM
 * return: NULL == error or !=NULL bind and created RPC server instance
 */
rpc_srv_t *rpc_srv_initServer(unsigned char InstID, int concurentClients, int netBuf, 
		const char *csHost, unsigned short Port, int proto);
/*
 * rpc_srv_endServer() - Destroy RPC server, close all opened sockets and free resources
 *
 * @psrv = RPC Server instance
 * return: none
 */
void rpc_srv_endServer(rpc_srv_t ** __restrict psrv);
/*
 * rpc_srv_loopServer() - Execute Main server loop and wait for clients requests
 *
 * @srv = RPC Server instance
 * return: -1 error or 0 ok, infinite loop ...
 */
int rpc_srv_loopServer(rpc_srv_t * __restrict srv);
#define rpc_srv_execServer(_srv, _sync) \
	do { assert((_srv)); \
		if (!(_srv)->srv_kill) { \
			pthread_create(&(_srv)->srv_tid, NULL, (void*(*)(void*)) \
					rpc_srv_loopServer, (_srv)); \
			if ((_sync)) \
				pthread_join((_srv)->srv_tid, (void**) (_sync)); \
			else \
				pthread_detach((_srv)->srv_tid); \
	} } 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
 *
 * @srv = RPC server instance
 * @Port = Port for bind server, if Port == 0 default port is selected
 * @diskDir = Disk place for BLOB file objects
 * return: -1 == error or 0 bind and created BLOB server instance
 */
int rpc_srv_initBLOBServer(rpc_srv_t * __restrict srv, unsigned short Port, const char *diskDir);
/*
 * rpc_srv_endBLOBServer() - Destroy BLOB server, close all opened sockets and free resources
 *
 * @srv = RPC Server instance
 * return: none
 */
void rpc_srv_endBLOBServer(rpc_srv_t * __restrict srv);
/*
 * rpc_srv_loopBLOB() - Execute Main BLOB server loop and wait for clients requests
 *
 * @srv = RPC Server instance
 * return: -1 error or 0 ok, infinite loop ...
 */
int rpc_srv_loopBLOBServer(rpc_srv_t * __restrict srv);
#define rpc_srv_execBLOBServer(_srv) \
	do { assert((_srv)); \
		if (!(_srv)->srv_kill && !(_srv)->srv_blob.kill) { \
			pthread_create(&(_srv)->srv_blob.tid, NULL, \
					(void*(*)(void*)) rpc_srv_loopBLOBServer, (_srv)); \
			pthread_detach((_srv)->srv_blob.tid); \
		} \
	} 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
 *
 * @srv = RPC Server instance
 * @tag = Function tag
 * @funcaddr = Function address
 * return: -1 error, 0 already registered tag or 1 register ok
 */
int rpc_srv_registerCall(rpc_srv_t * __restrict srv, unsigned short tag, void *funcaddr);
/*
 * rpc_srv_unregisterCall() - Unregister call from RPC server
 *
 * @srv = RPC Server instance
 * @tag = Function tag
 * return: -1 error, 0 not found call, 1 unregister ok
 */
int rpc_srv_unregisterCall(rpc_srv_t * __restrict srv, unsigned short tag);
/*
 * rpc_srv_getCall()  - Get registered call from RPC server
 *
 * @srv = RPC Server instance
 * @tag = tag for function
 * return: NULL not found call, !=NULL return call
 */
rpc_func_t *rpc_srv_getCall(rpc_srv_t * __restrict srv, uint16_t tag);
/*
 * rpc_srv_execCall() Execute registered call from RPC server
 *
 * @cli = RPC client
 * @rpc = IN RPC call structure
 * @funcname = Execute RPC function
 * @args = IN RPC calling arguments from RPC client
 * return: -1 error, !=-1 ok
 */
int rpc_srv_execCall(rpc_cli_t * __restrict cli, struct tagRPCCall * __restrict rpc, 
		ait_val_t funcname, array_t * __restrict args);


/*
 * rpc_srv_blobCreate() - Create and map blob to memory region and return object
 *
 * @srv = RPC Server instance
 * @len = BLOB length object
 * @tout = BLOB live timeout in seconds
 * return: NULL error or !=NULL allocated BLOB object
 */
rpc_blob_t *rpc_srv_blobCreate(rpc_srv_t * __restrict srv, int len, int tout);
/*
 * rpc_srv_blobMap() - Map blob to memory region 
 *
 * @srv = RPC Server instance
 * @blob = Map to this BLOB element
 * return: -1 error or 0 ok
 */
int rpc_srv_blobMap(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob);
/*
 * rpc_srv_blobUnmap() - Unmap blob memory region 
 *
 * @blob = Mapped BLOB element
 * return: none
 */
void rpc_srv_blobUnmap(rpc_blob_t * __restrict blob);
/*
 * rpc_srv_blobFree() - Free blob from disk & memory
 *
 * @srv = RPC Server instance
 * @blob = Mapped BLOB element
 * return: -1 error or 0 ok
 */
int rpc_srv_blobFree(rpc_srv_t * __restrict srv, rpc_blob_t * __restrict blob);

/*
 * rpc_srv_registerBLOB() - Register new BLOB to server
 *
 * @srv = RPC Server instance
 * @len = BLOB length
 * @tout = BLOB live timeout in seconds
 * return: NULL error or new registered BLOB
 */
rpc_blob_t *rpc_srv_registerBLOB(rpc_srv_t * __restrict srv, size_t len, int tout);
/*
 * rpc_srv_unregisterBLOB() - Unregister BLOB from server
 *
 * @srv = RPC Server instance
 * @var = BLOB Variable for unregister
 * return: -1 error, 0 not found call, 1 unregister ok
 */
int rpc_srv_unregisterBLOB(rpc_srv_t * __restrict srv, uint32_t var);
/*
 * rpc_srv_getBLOB() - Get registered BLOB 
 *
 * @srv = RPC Server instance
 * @var = hash for variable
 * return: NULL not found, !=NULL return blob var
 */
rpc_blob_t *rpc_srv_getBLOB(rpc_srv_t * __restrict srv, uint32_t var);

/*
 * rpc_srv_sendBLOB() - Send mapped BLOB to client
 *
 * @cli = Client instance
 * @blob = Mapped BLOB element
 * return: -1 error, 0 ok
 */
int rpc_srv_sendBLOB(rpc_cli_t * __restrict cli, rpc_blob_t * __restrict blob);
/*
 * rpc_srv_recvBLOB() - Receive BLOB from client
 *
 * @cli = Client instance
 * @blob = Mapped BLOB element
 * 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);


/*
 * rpc_srv_Return() - Prepare IPC return answer to RPC client
 *
 * @c = RPC client 
 * return: number of arguments in response
 */
int rpc_srv_Return(rpc_cli_t *c);


#endif

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