File:  [ELWIX - Embedded LightWeight unIX -] / libaitrpc / src / lists.c
Revision 1.1.2.7: download - view: text, annotated - select for diffs - revision graph
Thu Jul 8 07:16:36 2010 UTC (14 years ago) by misho
Branches: rpc1_0
fix ret arguments and it means!

#include "global.h"


/*
 * rpc_srv_retValsCall() Declare return variables for RPC call and zeroed values
					(for safe handling return values, use this!)
 * @call = RPC function call
 * @return_vals = Number of return variables
 * return: NULL error, !=NULL array with return values for RPC call with return_vals items
 */
inline rpc_val_t *
rpc_srv_retValsCall(rpc_func_t * __restrict call, int return_vals)
{
	rpc_val_t *v = NULL;

	if (rpc_srv_declValsCall(call, return_vals) == -1)
		return NULL;
	else
		rpc_srv_zeroValsCall(call);
	if (rpc_srv_getValsCall(call, &v) == -1)
		return NULL;

	return v;
}

/*
 * rpc_srv_freeValsCall() Free return variables for RPC call
 * @call = RPC function call
 * return: none
 */
inline void
rpc_srv_freeValsCall(rpc_func_t * __restrict call)
{
	rpc_srv_declValsCall(call, 0);
}

/*
 * rpc_srv_declValsCall() Declare return variables for RPC call, 
				if already allocated memory for RPC call return values 
				function reallocate used space with return_vals count elements
 * @call = RPC function call
 * @return_vals = Number of return variables
 * return: -1 error, !=-1 ok
 */
inline int
rpc_srv_declValsCall(rpc_func_t * __restrict call, int return_vals)
{
	void *ptr;

	if (!call || return_vals < 0) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t declare return variables for RPC call...\n");
		return -1;
	} else
		call->func_args = return_vals;

	if (!return_vals) {
		if (call->func_vals) {
			free(call->func_vals);
			call->func_vals = NULL;
		}
	} else {
		ptr = realloc(call->func_vals, return_vals * sizeof(rpc_val_t));
		if (!ptr) {
			LOGERR;
			return -1;
		} else
			call->func_vals = ptr;
	}

	return return_vals;
}

/*
 * rpc_srv_zeroValsCall() Clean values from return variables of RPC call
 * @call = RPC function call
 * return: -1 error, !=-1 Returned number of cleaned RPC variables
 */
inline int
rpc_srv_zeroValsCall(rpc_func_t * __restrict call)
{
	if (!call) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t delete return variables ...\n");
		return -1;
	}

	memset(call->func_vals, 0, call->func_args * sizeof(rpc_val_t));
	return call->func_args;
}

/*
 * rpc_srv_copyValsCall() Copy return variables for RPC call to new variable
 * @call = RPC function call
 * @newvals = New allocated variables array, must be free after use
 * return: -1 error, !=-1 Returned number of copied RPC variables
 */
inline int
rpc_srv_copyValsCall(rpc_func_t * __restrict call, rpc_val_t ** __restrict newvals)
{
	if (!call || !newvals) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t copy return variables to new array\n");
		return -1;
	}

	*newvals = calloc(call->func_args, sizeof(rpc_val_t));
	if (!*newvals) {
		LOGERR;
		return -1;
	} else
		memcpy(*newvals, call->func_vals, call->func_args * sizeof(rpc_val_t));

	return call->func_args;
}

/*
 * rpc_srv_getValsCall() Get return variables for RPC call
 * @call = RPC function call
 * @vals = Returned variables, may be NULL
 * return: -1 error, !=-1 Number of returned variables
 */
inline int
rpc_srv_getValsCall(rpc_func_t * __restrict call, rpc_val_t ** __restrict vals)
{
	if (!call) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get return variables ...\n");
		return -1;
	}

	if (vals)
		*vals = call->func_vals;
	return call->func_args;
}

// ---------------------------------------------------------

/*
 * rpc_srv_registerCall() Register call to RPC server
 * @srv = RPC Server instance
 * @csModule = Module name, if NULL self binary
 * @csFunc = Function name
 * @args = Number of return function arguments, use for restriction case!
 * return: -1 error or 0 register ok
 */
int
rpc_srv_registerCall(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc, u_char args)
{
	rpc_func_t *func;
	u_char str[MAXPATHLEN + UCHAR_MAX + 1];

	memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
	if (!srv || !csFunc) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t register function to RPC server ...\n");
		return -1;
	}
	if (!(func = malloc(sizeof(rpc_func_t)))) {
		LOGERR;
		return -1;
	} else {
		memset(func, 0, sizeof(rpc_func_t));
		strlcpy((char*) func->func_name, csFunc, UCHAR_MAX + 1);
	}
	if (csModule) {
		strlcpy((char*) func->func_file, csModule, MAXPATHLEN);
		strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
	}
	strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
	strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);

	func->func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
	func->func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);

	func->func_parent = srv;

	if (args > 0 && rpc_srv_declValsCall(func, args) == -1) {
		free(func);
		return -1;
	}

	pthread_mutex_lock(&srv->srv_mtx);
	func->func_next = srv->srv_funcs;
	srv->srv_funcs = func;
	pthread_mutex_unlock(&srv->srv_mtx);
	return 0;
}

/*
 * rpc_srv_unregisterCall() Unregister call from RPC server
 * @srv = RPC Server instance
 * @csModule = Module name, if NULL self binary
 * @csFunc = Function name
 * return: -1 error, 0 not found call, 1 unregister ok
 */
int
rpc_srv_unregisterCall(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc)
{
	rpc_func_t func, *f, *curr;
	u_char str[MAXPATHLEN + UCHAR_MAX + 1];

	memset(&func, 0, sizeof(rpc_func_t));
	memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
	if (!srv || !csFunc) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t unregister function from RPC server ...\n");
		return -1;
	} else
		strlcpy((char*) func.func_name, csFunc, UCHAR_MAX + 1);
	if (csModule) {
		strlcpy((char*) func.func_file, csModule, MAXPATHLEN);
		strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
	}
	strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
	strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);

	func.func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
	func.func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);

	f = rpc_srv_getCall(srv, func.func_tag, func.func_hash);
	if (!f)		// not found element for unregister
		return 0;

	pthread_mutex_lock(&srv->srv_mtx);
	if (srv->srv_funcs == f) {	// if is 1st element
		srv->srv_funcs = srv->srv_funcs->func_next;

		if (f->func_args && f->func_vals)
			free(f->func_vals);
		free(f);
	} else {
		for (curr = srv->srv_funcs; curr->func_next != f; curr = curr->func_next);
		curr->func_next = curr->func_next->func_next;

		if (f->func_args && f->func_vals)
			free(f->func_vals);
		free(f);
	}
	pthread_mutex_unlock(&srv->srv_mtx);

	return 1;
}

/*
 * rpc_srv_getCall() Get registered call from RPC server
 * @srv = RPC Server instance
 * @tag = tag for function
 * @hash = hash for function
 * return: NULL not found call, !=NULL return call
 */
inline rpc_func_t *
rpc_srv_getCall(rpc_srv_t * __restrict srv, uint16_t tag, uint32_t hash)
{
	rpc_func_t *f;

	if (!srv) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get function from RPC server ...\n");
		return NULL;
	}

	for (f = srv->srv_funcs; f; f = f->func_next)
		if (f->func_tag == tag && f->func_hash == hash)
			break;

	return f;
}

/*
 * rpc_srv_getFunc() Get registered call from RPC server by Name
 * @srv = RPC Server instance
 * @csModule = Module name, if NULL self binary
 * @csFunc = Function name
 * return: NULL not found call, !=NULL return call
 */
rpc_func_t *
rpc_srv_getFunc(rpc_srv_t * __restrict srv, const char *csModule, const char *csFunc)
{
	rpc_func_t func;
	u_char str[MAXPATHLEN + UCHAR_MAX + 1];

	memset(&func, 0, sizeof(rpc_func_t));
	memset(str, 0, MAXPATHLEN + UCHAR_MAX + 1);
	if (!srv || !csFunc) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get function from RPC server ...\n");
		return NULL;
	} else
		strlcpy((char*) func.func_name, csFunc, UCHAR_MAX + 1);
	if (csModule) {
		strlcpy((char*) func.func_file, csModule, MAXPATHLEN);
		strlcpy((char*) str, csModule, MAXPATHLEN + UCHAR_MAX + 1);
	}
	strlcat((char*) str, "__", MAXPATHLEN + UCHAR_MAX + 1);
	strlcat((char*) str, csFunc, MAXPATHLEN + UCHAR_MAX + 1);

	func.func_tag = crcFletcher16((u_short*) str, (MAXPATHLEN + UCHAR_MAX + 1) / 2);
	func.func_hash = hash_fnv((char*) str, MAXPATHLEN + UCHAR_MAX + 1);

	return rpc_srv_getCall(srv, func.func_tag, func.func_hash);
}

// ---------------------------------------------------------

/*
 * rpc_srv_getBLOB() Get registered BLOB 
 * @srv = RPC Server instance
 * @var = hash for variable
 * return: NULL not found, !=NULL return blob var
 */
inline rpc_blob_t *
rpc_srv_getBLOB(rpc_srv_t * __restrict srv, uint32_t var)
{
	rpc_blob_t *b;

	if (!srv) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t get variable from BLOB server ...\n");
		return NULL;
	}

	for (b = srv->srv_blob.blobs; b; b = b->blob_next) {
		if (b->blob_var == var)
			break;
	}

	return b;
}

/*
 * rpc_srv_registerBLOB() Register new BLOB to server
 * @srv = RPC Server instance
 * @len = BLOB length
 * return: NULL error or new registered BLOB
 */
rpc_blob_t *
rpc_srv_registerBLOB(rpc_srv_t * __restrict srv, size_t len)
{
	rpc_blob_t *blob = NULL;

	if (!srv || !len) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t register BLOB to server ...\n");
		return blob;
	}

	blob = rpc_srv_blobCreate(srv, len);
	if (blob) {
		pthread_mutex_lock(&srv->srv_blob.mtx);
		blob->blob_next = srv->srv_blob.blobs;
		srv->srv_blob.blobs = blob;
		pthread_mutex_unlock(&srv->srv_blob.mtx);
	}

	return blob;
}

/*
 * 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_blob_t *b, *curr;

	if (!srv) {
		rpc_SetErr(EINVAL, "Error:: Invalid parameter can`t unregister BLOB from server ...\n");
		return -1;
	}

	b = rpc_srv_getBLOB(srv, var);
	if (!b)		// not found element for unregister
		return 0;

	pthread_mutex_lock(&srv->srv_blob.mtx);
	if (srv->srv_blob.blobs == b) {	// if is 1st element
		srv->srv_blob.blobs = srv->srv_blob.blobs->blob_next;
	} else {
		for (curr = srv->srv_blob.blobs; curr->blob_next != b; curr = curr->blob_next);
		curr->blob_next = curr->blob_next->blob_next;
	}
	rpc_srv_blobFree(srv, b);
	free(b);
	pthread_mutex_unlock(&srv->srv_blob.mtx);

	return 1;
}

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