/*
 * IPRPC - Inter Process Remote Procedure Call
 *
 * Copyright (C) 2012-2013 by Hiroyuki KAJIURA. 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:Neither the name of copyright owner 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 THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
 *
 */

#define	IPC_MARSHAL_MAIN

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include	"ipcInfo.h"
#include	"ipcLog.h"
#include	"ipcType.h"
#include	"ipcSyscall.h"
#include	"rpcMsg.h"
#include	"ipcShm.h"
#include	"ipcShmDB.h"
#include	"ipcQue.h"
#include	"ipcStub.h"
#include	"ipcMarshal.h"

#define	IPC_NO_RESTRICTION_LENGTH			0xFFFFFFFF
#define	IPC_ENABLE_UNKNOWN_TYPE_LENGTH			0x00000000
#define	IPC_ENABLE_INT_TYPE_LENGTH			0x0000000F
#define	IPC_ENABLE_UINT_TYPE_LENGTH			0x0000000F
#ifdef	IEEE754_LONG_DOUBLE_BIAS
#define	IPC_ENABLE_FLOAT_TYPE_LENGTH			0x0000001C
#else	/* IEEE754_LONG_DOUBLE_BIAS */
#define	IPC_ENABLE_FLOAT_TYPE_LENGTH			0x0000000C
#endif	/* IEEE754_LONG_DOUBLE_BIAS */
#define	IPC_ENABLE_ENUM_TYPE_LENGTH			0x00000004
#define	IPC_ENABLE_STRING_TYPE_LENGTH			IPC_NO_RESTRICTION_LENGTH
#define	IPC_ENABLE_OCTET_ARRAY_TYPE_LENGTH		IPC_NO_RESTRICTION_LENGTH
#define	IPC_ENABLE_BOOLEAN_TYPE_LENGTH			0x00000001
#ifndef	USE_IDC
#define	IPC_ENABLE_REFERENCE_TYPE_LENGTH		0x00000008
#else	/* USE_IDC */
#define	IPC_ENABLE_REFERENCE_TYPE_LENGTH		0x00000018
#endif	/* USE_IDC */

#define	IPC_LENGTH_OF_BOOLEAN_TYPE			0x00000001
#define	IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE		0x00000008
#ifdef	USE_IDC
#define	IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE		0x00000008
#endif	/* USE_IDC */

#define	IPC_TRUE_VAL_OF_BOOLEAN_TYPE			(1)
#define	IPC_FALSE_VAL_OF_BOOLEAN_TYPE			(0)

static int32_t IpcMarshalDataSharedMemId = -1;

static RpcResult_t IPC_parseOneData(RpcParamData_t *inData,uint32_t *useSize);
static RpcResult_t IPC_checkParamLength(uint32_t paramLeng,uint32_t enableLeng);
static RpcResult_t IPC_putOneData(RpcParamData_t *inData,void *outData,uint32_t outSize,uint32_t *useSize);
static RpcResult_t IPC_parseMarshaledData(void *inData,uint32_t inSize,uint32_t *needSize,RpcParamData_t *pData);
static RpcResult_t IPC_putMarshalledData(RpcParamData_t *pData,void *outP,uint32_t *leng);

#ifdef	RPC_CHECK_BYTEORDER
static void IPC_convertNetworkByteOrder(void *inData,void *outData,uint32_t size);
static void IPC_convertHostByteOrder(void *inData,void *outData,uint32_t size);
#endif	/* RPC_CHECK_BYTEORDER */

void IPC_DumpParamData(RpcParamData_t *pData);
uint8_t *IPC_ConvertTypeToString(RpcParamType_t type);

/*--- MARSHAL LIBRARY ---*/

extern RpcResult_t IPC_InitMarshal(RpcBool_t masterProcess) {
	RpcResult_t ret = RPC_SUCCESS;

	if(IpcMarshalDataSharedMemId == -1) {
		if((ret = IPC_GetShmInfo(IPC_MARSHAL_DATA_SHARED_MEM_NAME, &IpcMarshalDataSharedMemId,(void**)NULL, (uint32_t*)NULL)) != RPC_SUCCESS) {
			return ret;
		}
		if(masterProcess) {
			if((ret = IPC_InitShmGapArea(IpcMarshalDataSharedMemId,IPC_SHM_MARSHAL_GAP_SIZE)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN INIT SHM GAP AREA ret:%s;",RPC_LogConvertResultCode(ret));
				return ret;		
			}
			if((ret = IPC_InitShmAllocArea(IpcMarshalDataSharedMemId, IPC_MARSHAL_SHARED_MEM_REAL_SIZE, IPC_SHM_MARSHAL_NUM_OF_DEV, IPC_SHM_MARSHAL_MIN_SIZE, IPC_SHM_MARSHAL_RATE_OF_MAGNIFY)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN INIT SHM ALLOC AREA ret:%s;",RPC_LogConvertResultCode(ret));
				return ret;		
			}
		}
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG1, "SHM MEM ID:0x%x;",IpcMarshalDataSharedMemId);
	return ret;
}

extern RpcResult_t IPC_Marshal(RpcParamData_t *inData, void **outData, uint32_t *outSize) {
	RpcParamData_t *p;uint32_t useSize;RpcResult_t ret;
	uint32_t oneSize,tmpSize;void *outP;RpcParamHeader_t *header;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG1,"IN IPC_Marshal inData:0x%x; outData:0x%x; outSize:0x%x",inData,outData,outSize);
	if(IpcMarshalDataSharedMemId == -1) {
		*outSize = 0;*outData = NULL;
		return RPC_FATAL_ERROR;
	}
	if((inData == NULL)||(outData == NULL)||(outSize == NULL)) {
		return RPC_PARAM_ERROR;
	}
	*outSize = 0;
	for(p = inData;p->paramSpec.paramType != RPC_TYPE_UNKNOWN;p++) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG3,"  TYPE:%s; LENG:%d; DATA:0x%x;",
//			IPC_ConvertTypeToString(p->paramSpec.paramType),p->paramSpec.paramLeng,p->paramData);
		if((ret = IPC_parseOneData(p,&oneSize)) != RPC_SUCCESS) {
			*outSize = 0;*outData = NULL;
			return ret;
		}
		*outSize += oneSize;
	}
	*outSize += (sizeof(RpcParamSpec_t)+sizeof(RpcParamHeader_t));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG2," NOW 2nd Stage, outSize:%d;",*outSize);
	if((*outData = outP = IPC_AllocShmMem(IpcMarshalDataSharedMemId, *outSize)) == NULL) {
		*outSize = 0;*outData = NULL;
		return RPC_NO_MORE_RESOURCE;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG2," NOW 3rd Stage, outData:0x%x;",*outData);
	header = (RpcParamHeader_t*)outP;
#ifndef	RPC_CHECK_BYTEORDER
	header->paramLength = *outSize;
#else	/* RPC_CHECK_BYTEORDER */
	IPC_convertNetworkByteOrder((void*)outSize,(void*)&(header->paramLength),sizeof(header->paramLength));
#endif	/* RPC_CHECK_BYTEORDER */
	header->reserved = 0;
	tmpSize = *outSize - sizeof(RpcParamHeader_t);
	outP = (void*)&(((uint8_t*)outP)[sizeof(RpcParamHeader_t)]);
	for(p = inData;p->paramSpec.paramType != RPC_TYPE_UNKNOWN;p++) {
		if((ret = IPC_putOneData(p,outP,tmpSize,&useSize)) != RPC_SUCCESS) {
			IPC_FreeShmMem(IpcMarshalDataSharedMemId, *outData);
			*outSize = 0;*outData = NULL;
			return ret;
		}
		tmpSize -= useSize;
		outP = (void*)&(((uint8_t*)outP)[useSize]);
	}
	if((ret = IPC_putOneData(p,outP,tmpSize,&useSize)) != RPC_SUCCESS) {
		IPC_FreeShmMem(IpcMarshalDataSharedMemId, *outData);
		*outSize = 0;*outData = NULL;
		return ret;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_Marshal outData:0x%x;outSize:%d;",*outData,*outSize);
	return RPC_SUCCESS;
}

extern RpcResult_t IPC_Unmarshal(void *inData, uint32_t inSize, void *outData, uint32_t outSize) {
	RpcParamData_t *pData;void *inP,*outP;int32_t size,needSize,oSize;
	RpcResult_t ret;RpcParamHeader_t *header; uint32_t leng;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG1,"IN IPC_Unmarshal inData:0x%x; inSize:%d; outData:0x%x; outSize:%d;",
//		inData, inSize, outData, outSize);
	if(IpcMarshalDataSharedMemId == -1) {
		return RPC_FATAL_ERROR;
	}
	if((inData == NULL)||(inSize == 0)||(outData == NULL)||(outSize == 0)) {
		return RPC_PARAM_ERROR;
	}
//	inP = inData; size = inSize;
	header = (RpcParamHeader_t*)inData;
#ifdef	RPC_CHECK_BYTEORDER
	IPC_convertHostByteOrder((void*)&(header->paramLength),(void*)&leng,sizeof(header->paramLength));
	header->paramLength = leng;
#endif	/* RPC_CHECK_BYTEORDER */
	if(header->paramLength != inSize) {
		return RPC_PARAM_ERROR;
	}
	size = inSize- sizeof(RpcParamHeader_t);
	inP = (void*)&(((uint8_t*)inData)[sizeof(RpcParamHeader_t)]);
	pData = (RpcParamData_t*)outData;
	oSize = outSize;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2," STEP 1");
	for(;;) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "    inP:0x%x; size:%d; pData:0x%x;oSize:%d;",inP,size,pData,oSize);
		if(size < 0) {
			return RPC_PARAM_ERROR;		
		}
		if(oSize < sizeof(RpcParamData_t)) {
			return RPC_NO_MORE_RESOURCE;
		}
		if((ret = IPC_parseMarshaledData(inP,size,&needSize,pData)) != RPC_SUCCESS) {
			return ret;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "        PARSE TYPE:%s; LENG:%d;",IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng);
		oSize -= sizeof(RpcParamData_t);
		inP = (void*)&(((uint8_t*)inP)[needSize]);
		size -= needSize;
		if(pData->paramSpec.paramType == RPC_TYPE_UNKNOWN)
			break;
		pData++;
//		outP = (void*)pData;
	}
	pData++;
	outP = (void*)pData;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2," STEP 2");
	for(pData = (RpcParamData_t*)outData;pData->paramSpec.paramType != RPC_TYPE_UNKNOWN;pData++) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "    PUT:pData:0x%x TYPE:%s; LENG:%d; outP:0x%x; oSize:%d;",pData,IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng,outP,oSize);
		if(oSize < IPC_ALIGNMENT(pData->paramSpec.paramLeng)) {
			return RPC_NO_MORE_RESOURCE;
		}
		if((ret = IPC_putMarshalledData(pData,outP,&leng)) != RPC_SUCCESS) {
			IPC_FreeShmMem(IpcMarshalDataSharedMemId, inData);
			(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_ERROR,"FAIL IN IPC_Unmarshal");
			return ret;
		}
		if(leng > 0)
			pData->paramData = outP;
		else
			pData->paramData = (uint8_t*)NULL;
		outP = (void*)&(((uint8_t*)outP)[IPC_ALIGNMENT(leng)]);
		oSize -= IPC_ALIGNMENT(leng);
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "  FREE MEM inData:0x%x;",inData);
	IPC_FreeShmMem(IpcMarshalDataSharedMemId, inData);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_Unmarshal ");
	return RPC_SUCCESS;
}

extern void IPC_FreeMarshaledSharedData(void *data) {
	if(data == (void*)NULL)
		return;
	if(IpcMarshalDataSharedMemId != -1) {
		IPC_FreeShmMem(IpcMarshalDataSharedMemId, data);
	}
}

extern uint32_t IPC_GetMarshaledDataSize(void *data) {
	uint32_t size;RpcParamHeader_t *header;

	if(data == (void*)NULL)
		return (uint32_t)0;
	header = (RpcParamHeader_t*)data;
#ifndef	RPC_CHECK_BYTEORDER
	size = header->paramLength;
#else	/* RPC_CHECK_BYTEORDER */
	IPC_convertHostByteOrder((void*)&(header->paramLength),(void*)&size,sizeof(header->paramLength));
#endif	/* RPC_CHECK_BYTEORDER */
	return size;
}

extern void *IPC_DuplicateMarshaledData(void *marshaledData,uint32_t marshaledDataSize) {
	void *ret;

	if((marshaledData == (void*)NULL)||(marshaledDataSize == (uint32_t)0))
		return (void*)NULL;
	if((ret = IPC_AllocShmMem(IpcMarshalDataSharedMemId, marshaledDataSize)) == NULL) {
		return ret;
	}
	(void)memcpy(ret,marshaledData,marshaledDataSize);
	return ret;
}

/* --- OTHER LIBRARY --- */

extern void IPC_SetMsgParam(RpcMsgParam_t *msgParam,uint32_t funcId,uint32_t pId,uint32_t queId,uint32_t seqNum,uint32_t extData,void* extParam) {
	msgParam->u.msgParam.funcId = funcId;
	msgParam->u.msgParam.srcPid = pId;
	msgParam->u.msgParam.srcQueId = queId;
	msgParam->u.msgParam.seqNum = seqNum;
	msgParam->u.msgParam.extData = extData;
	msgParam->u.msgParam.extParam = extParam;
}

/* ----- Internal Functions ----- */

static RpcResult_t IPC_parseOneData(RpcParamData_t *inData,uint32_t *useSize) {
	uint32_t enableLength;uint32_t leng;

	*useSize = sizeof(RpcParamSpec_t);
	leng = inData->paramSpec.paramLeng;
	switch(inData->paramSpec.paramType) {
	case RPC_INT_TYPE:
		enableLength = IPC_ENABLE_INT_TYPE_LENGTH;
		break;
	case RPC_UINT_TYPE:
		enableLength = IPC_ENABLE_UINT_TYPE_LENGTH;
		break;
	case RPC_FLOAT_TYPE:
		enableLength = IPC_ENABLE_FLOAT_TYPE_LENGTH;
		break;
	case RPC_STRING_TYPE:
		enableLength = IPC_ENABLE_STRING_TYPE_LENGTH;
		if(strlen(inData->paramData) != inData->paramSpec.paramLeng) {
			*useSize = 0;
			return (RPC_PARAM_ERROR);
		}
		break;
	case RPC_ENUM_TYPE:
		enableLength = IPC_ENABLE_ENUM_TYPE_LENGTH;
		break;
	case RPC_OCTET_ARRAY_TYPE:
		enableLength = IPC_ENABLE_OCTET_ARRAY_TYPE_LENGTH;
		break;
	case RPC_TYPE_UNKNOWN:
		enableLength = IPC_ENABLE_UNKNOWN_TYPE_LENGTH;
		break;
	case RPC_BOOLEAN_TYPE:
		enableLength = IPC_ENABLE_BOOLEAN_TYPE_LENGTH;
		leng = IPC_LENGTH_OF_BOOLEAN_TYPE;
		break;
	case RPC_REFERENCE_TYPE:
#ifndef	USE_IDC
		if(sizeof(uint8_t*) != inData->paramSpec.paramLeng) {
			*useSize = 0;
			return (RPC_PARAM_ERROR);
		}
		leng = IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE;
#else	/* USE_IDC */
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_WARNING,"THIS SYSTEM DOES STILL NOT SUPPORT DEVICE ID IN MARSHALLING REFERENCE TYPE");
		if(sizeof(uint8_t*) != inData->paramSpec.paramLeng) {
			*useSize = 0;
			return (RPC_PARAM_ERROR);
		}
		leng = IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE+IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE;
#endif	/*USE_IDC */
		break;
	default:
		*useSize = 0;
		return (RPC_PARAM_ERROR);
	}
	if(IPC_checkParamLength(leng,enableLength) != RPC_SUCCESS) {
		*useSize = 0;
		return RPC_PARAM_ERROR;
	}
	*useSize += IPC_ALIGNMENT(leng);
	return RPC_SUCCESS;
}

static RpcResult_t IPC_checkParamLength(uint32_t paramLeng,uint32_t enableLeng) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "IN IPC_checkParamLength paramLeng:0x%x; enableLeng:0x%x;",paramLeng,enableLeng);
	if(enableLeng == IPC_NO_RESTRICTION_LENGTH)
		return RPC_SUCCESS;
	else if((enableLeng == 0)&&(paramLeng == 0))
		return RPC_SUCCESS;
	else if(paramLeng & enableLeng)
		return RPC_SUCCESS;
	else
		return RPC_PARAM_ERROR;
}

static RpcResult_t IPC_putOneData(RpcParamData_t *inData,void *outData,uint32_t outSize,uint32_t *useSize) {
	RpcResult_t ret = RPC_SUCCESS;
	RpcParamSpec_t *paramSpec;void *dataP;int rest;uint32_t leng;
	uint8_t tempVal;uint64_t tempRef;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG2,"IN IPC_putOneData inData:0x%x;(TYPE:0x%x; LENG:%d; DATA:0x%x;) outData:0x%x;, outSize:%d; useSize:0x%x;",
//		     inData,inData->paramSpec.paramType,inData->paramSpec.paramLeng,inData->paramData,outData,outSize,useSize);
	*useSize = 0;
	if(outSize < sizeof(RpcParamSpec_t)) {
		ret = RPC_NO_MORE_RESOURCE;
		goto errOut;
	}
	paramSpec = (RpcParamSpec_t*)outData;
	*useSize = sizeof(RpcParamSpec_t);
	dataP = (void*)&(((uint8_t*)outData)[*useSize]);
	leng = inData->paramSpec.paramLeng;
	switch(inData->paramSpec.paramType) {
	case RPC_INT_TYPE:
	case RPC_UINT_TYPE:
	case RPC_FLOAT_TYPE:
	case RPC_STRING_TYPE:
	case RPC_ENUM_TYPE:
	case RPC_OCTET_ARRAY_TYPE:
	case RPC_TYPE_UNKNOWN:
#ifndef	RPC_CHECK_BYTEORDER
		paramSpec->paramType = inData->paramSpec.paramType;
		paramSpec->paramLeng = leng;
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertNetworkByteOrder((void*)&(inData->paramSpec.paramType),(void*)&(paramSpec->paramType),sizeof(inData->paramSpec.paramType));
		IPC_convertNetworkByteOrder((void*)&(leng),(void*)&(paramSpec->paramLeng),sizeof(leng));
#endif	/* RPC_CHECK_BYTEORDER */
		break;
	case RPC_BOOLEAN_TYPE:
		leng = IPC_LENGTH_OF_BOOLEAN_TYPE;
#ifndef	RPC_CHECK_BYTEORDER
		paramSpec->paramType = inData->paramSpec.paramType;
		paramSpec->paramLeng = leng;
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertNetworkByteOrder((void*)&(inData->paramSpec.paramType),(void*)&(paramSpec->paramType),sizeof(inData->paramSpec.paramType));
		IPC_convertNetworkByteOrder((void*)&(leng),(void*)&(paramSpec->paramLeng),sizeof(leng));
#endif	/* RPC_CHECK_BYTEORDER */
		break;
	case RPC_REFERENCE_TYPE:
#ifndef	USE_IDC
		leng = IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE;
#ifndef	RPC_CHECK_BYTEORDER
		paramSpec->paramType = inData->paramSpec.paramType;
		paramSpec->paramLeng = leng;
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertNetworkByteOrder((void*)&(inData->paramSpec.paramType),(void*)&(paramSpec->paramType),sizeof(inData->paramSpec.paramType));
		IPC_convertNetworkByteOrder((void*)&(leng),(void*)&(paramSpec->paramLeng),sizeof(leng));
#endif	/* RPC_CHECK_BYTEORDER */
#else	/* USE_IDC */
		leng = IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE+IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE;
#ifndef	RPC_CHECK_BYTEORDER
		paramSpec->paramType = inData->paramSpec.paramType;
		paramSpec->paramLeng = leng;
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertNetworkByteOrder((void*)&(inData->paramSpec.paramType),(void*)&(paramSpec->paramType),sizeof(inData->paramSpec.paramType));
		IPC_convertNetworkByteOrder((void*)&(leng),(void*)&(paramSpec->paramLeng),sizeof(leng));
#endif	/* RPC_CHECK_BYTEORDER */
#endif	/* USE_IDC */
		break;
	default:
		ret = RPC_PARAM_ERROR;
		goto errOut;
	}
	if((leng > 0)&&(outSize < (*useSize + IPC_ALIGNMENT(leng)))) {
		ret = RPC_NO_MORE_RESOURCE;
		goto errOut;
	}
	if(leng > 0) {
		*useSize += leng;
		switch(inData->paramSpec.paramType) {
		case RPC_INT_TYPE:
		case RPC_UINT_TYPE:
		case RPC_FLOAT_TYPE:
		case RPC_ENUM_TYPE:
#ifndef	RPC_CHECK_BYTEORDER
			(void)memcpy(dataP,(void*)inData->paramData,leng);
#else	/* RPC_CHECK_BYTEORDER */
			IPC_convertNetworkByteOrder((void*)inData->paramData,(void*)dataP,leng);
#endif	/* RPC_CHECK_BYTEORDER */
			break;
		case RPC_STRING_TYPE:
		case RPC_OCTET_ARRAY_TYPE:
			(void)memcpy(dataP,(void*)inData->paramData,leng);
			break;
		case RPC_BOOLEAN_TYPE:
			switch(*(RpcBool_t*)(inData->paramData)) {
			case RPC_TRUE:
				tempVal = IPC_TRUE_VAL_OF_BOOLEAN_TYPE; break;
			case RPC_FALSE:
				tempVal = IPC_FALSE_VAL_OF_BOOLEAN_TYPE; break;
			default:
				ret = RPC_PARAM_ERROR;
				goto errOut;
			}
#ifndef	RPC_CHECK_BYTEORDER
			(void)memcpy(dataP,(void*)&tempVal,leng);
#else	/* RPC_CHECK_BYTEORDER */
			IPC_convertNetworkByteOrder((void*)&tempVal,(void*)dataP,leng);
#endif	/* RPC_CHECK_BYTEORDER */
			break;
		case RPC_REFERENCE_TYPE:
			switch(sizeof(uint8_t*)) {
			case 4:
				tempRef = ((uint64_t)(*((uint32_t*)(inData->paramData)))&0x00000000FFFFFFFF);
				break;
			case 8:
				tempRef = (uint64_t)(*((uint64_t*)(inData->paramData)));
				break;
			}
//			(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG3,"  INDATA:0x%x; OUTDATA:0x%Lx",
//				*((uint32_t*)inData->paramData),tempRef);
#ifdef	USE_IDC
			(void)memset((void*)dataP,0,IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE);
#ifndef	RPC_CHECK_BYTEORDER
			(void)memcpy((void*)((uint8_t*)dataP+IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE),(void*)&tempRef,leng-IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE);
#else	/* RPC_CHECK_BYTEORDER */
			IPC_convertNetworkByteOrder((void*)&tempRef,(void*)((uint8_t*)dataP+IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE),leng-IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE);
#endif	/* RPC_CHECK_BYTEORDER */
#else	/* USE_IDC */
#ifndef	RPC_CHECK_BYTEORDER
			(void)memcpy(dataP,(void*)&tempRef,leng);
#else	/* RPC_CHECK_BYTEORDER */
			IPC_convertNetworkByteOrder((void*)&tempRef,(void*)dataP,leng);
#endif	/* RPC_CHECK_BYTEORDER */
#endif	/* USE_IDC */
			break;
		default:
			break;
		}
		rest = IPC_ALIGNMENT(leng) - leng;
		if(rest > 0) {
			dataP = (void*)&(((uint8_t*)outData)[*useSize]);
			(void)memset(dataP,0,rest);
			*useSize += rest;
		}
	}

errOut:
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_putOneData useSize:%d; RET:0x%x;",*useSize,ret);
	return ret;
}

static RpcResult_t IPC_parseMarshaledData(void *inData,uint32_t inSize,uint32_t *needSize,RpcParamData_t *pData) {
	RpcResult_t ret = RPC_SUCCESS;RpcParamSpec_t *pSpec;
	uint32_t enableLength;uint32_t temp;
//	uint32_t leng;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "IN IPC_parseMarshaledData inData:0x%x; inSize:%d;",
//		inData,inSize);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "STEP1");
	if(inSize < sizeof(RpcParamSpec_t)) {
		*needSize = 0;
		return RPC_PARAM_ERROR;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "STEP2");
	pSpec = (RpcParamSpec_t*)inData;
#ifdef	RPC_CHECK_BYTEORDER
	IPC_convertHostByteOrder((void*)&(pSpec->paramType),(void*)&temp,sizeof(pSpec->paramType));
	pSpec->paramType = temp;
	IPC_convertHostByteOrder((void*)&(pSpec->paramLeng),(void*)&temp,sizeof(pSpec->paramLeng));
	pSpec->paramLeng = temp;
#endif	/* RPC_CHECK_BYTEORDER */
//	leng = pSpec->paramLeng;
	switch(pSpec->paramType) {
	case RPC_INT_TYPE:
		enableLength = IPC_ENABLE_INT_TYPE_LENGTH;
		break;
	case RPC_UINT_TYPE:
		enableLength = IPC_ENABLE_UINT_TYPE_LENGTH;
		break;
	case RPC_FLOAT_TYPE:
		enableLength = IPC_ENABLE_FLOAT_TYPE_LENGTH;
		break;
	case RPC_STRING_TYPE:
		enableLength = IPC_ENABLE_STRING_TYPE_LENGTH;
//		leng = pSpec->paramLeng+1;
		break;
	case RPC_ENUM_TYPE:
		enableLength = IPC_ENABLE_ENUM_TYPE_LENGTH;
		break;
	case RPC_OCTET_ARRAY_TYPE:
		enableLength = IPC_ENABLE_OCTET_ARRAY_TYPE_LENGTH;
		break;
	case RPC_TYPE_UNKNOWN:
		enableLength = IPC_ENABLE_UNKNOWN_TYPE_LENGTH;
		break;
	case RPC_BOOLEAN_TYPE:
		enableLength = IPC_ENABLE_BOOLEAN_TYPE_LENGTH;
//		leng = sizeof(RpcBool_t);
		break;
	case RPC_REFERENCE_TYPE:
		enableLength = IPC_ENABLE_REFERENCE_TYPE_LENGTH;
//		leng = sizeof(uint8_t*);
		break;
	default:
		*needSize = 0;
		return RPC_PARAM_ERROR;
	}
	if(IPC_checkParamLength(pSpec->paramLeng,enableLength) != RPC_SUCCESS) {
		*needSize = 0;
		return RPC_PARAM_ERROR;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "  TYPE:%s",IPC_ConvertTypeToString(pSpec->paramType));
	(void)memcpy((void*)pData,(void*)pSpec,sizeof(RpcParamSpec_t));
	*needSize = sizeof(RpcParamSpec_t) + IPC_ALIGNMENT(pSpec->paramLeng);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "  inSize:%d; NeedSize:%d TYPE:%s; LENG:%d;",inSize,*needSize,IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng);
	if(inSize < *needSize) {
		*needSize = 0;
		return RPC_PARAM_ERROR;
	}
	pData->paramData = (void*)&(((uint8_t*)inData)[sizeof(RpcParamSpec_t)]);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG2, "OUT IPC_parseMarshaledData paramData:0x%x",pData->paramData);
	return ret;
}

static RpcResult_t IPC_putMarshalledData(RpcParamData_t *pData,void *outP,uint32_t *leng) {
	RpcBool_t tempVal;uint8_t *tempP;

	*leng = 0;
	switch(pData->paramSpec.paramType) {
	case RPC_INT_TYPE:
	case RPC_UINT_TYPE:
	case RPC_ENUM_TYPE:
	case RPC_FLOAT_TYPE:
#ifndef	RPC_CHECK_BYTEORDER
		(void)memcpy(outP,pData->paramData,pData->paramSpec.paramLeng);
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertHostByteOrder((void*)pData->paramData,(void*)outP,pData->paramSpec.paramLeng);
#endif	/* RPC_CHECK_BYTEORDER */
		*leng = pData->paramSpec.paramLeng;
		break;
	case RPC_OCTET_ARRAY_TYPE:
		(void)memcpy(outP,pData->paramData,pData->paramSpec.paramLeng);
		*leng = pData->paramSpec.paramLeng;
		break;
	case RPC_STRING_TYPE:
		(void)memcpy(outP,pData->paramData,pData->paramSpec.paramLeng);
		((uint8_t*)outP)[pData->paramSpec.paramLeng] = 0;
		*leng = pData->paramSpec.paramLeng+1;
		break;
	case RPC_TYPE_UNKNOWN:
		*leng = pData->paramSpec.paramLeng;
		break;
	case RPC_BOOLEAN_TYPE:
		pData->paramSpec.paramLeng = *leng = sizeof(RpcBool_t);
		switch(*(uint8_t*)(pData->paramData)) {
		case IPC_TRUE_VAL_OF_BOOLEAN_TYPE:
			tempVal = RPC_TRUE; break;
		case IPC_FALSE_VAL_OF_BOOLEAN_TYPE:
			tempVal = RPC_FALSE; break;
		}
		(void)memcpy(outP,(void*)&tempVal,*leng);
		break;
	case RPC_REFERENCE_TYPE:
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_WARNING,"THIS SYSTEM DOES STILL NOT SUPPORT DEVICE ID IN UNMARSHALLING REFERENCE TYPE");
		pData->paramSpec.paramLeng = *leng = sizeof(uint8_t*);
#ifndef	USE_IDC
		tempP = (uint8_t*)((uint8_t*)(pData->paramData)+(IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE-*leng));
#else	/* USE_IDC */
		tempP = (uint8_t*)((uint8_t*)(pData->paramData)+(IPC_LENGTH_OF_DEVID_OF_REFERENCE_TYPE+IPC_LENGTH_OF_ADDR_OF_REFERENCE_TYPE-*leng));
#endif	/* USE_IDC */
#ifndef	RPC_CHECK_BYTEORDER
		(void)memcpy(outP,tempP,*leng);
#else	/* RPC_CHECK_BYTEORDER */
		IPC_convertHostByteOrder((void*)tempP,(void*)outP,*leng);
#endif	/* RPC_CHECK_BYTEORDER */
		break;
	default:
		break;
	}
	return RPC_SUCCESS;
}

#ifdef	RPC_CHECK_BYTEORDER
static void IPC_convertNetworkByteOrder(void *inData,void *outData,uint32_t size) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "IN IPC_convertNetworkByteOrder inData:0x%x; outData:0x%x; size:%d;",inData,outData,size);
#ifdef	__BIG_ENDIAN__
	if(size > 0) {
		(void)memcpy((void*)outData,(void*)inData,size);
	}
#else	/* __BIG_ENDIAN__ */
	{int i;
	switch(size) {
	case 0:
		break;
	case 1:
		*((uint8_t*)outData) = *((uint8_t*)inData);
		break;
	case 2:
		*((uint16_t*)outData) = htons(*((uint16_t*)inData));
		break;
	case 4:
		*((uint32_t*)outData) = htonl(*((uint32_t*)inData));
		break;
	case 8:
		for(i = 0;i<8;i++) {
			((uint8_t*)outData)[i] = ((uint8_t*)inData)[7-i];
		}
		break;
	case 16:
		for(i = 0;i<16;i++) {
			((uint8_t*)outData)[i] = ((uint8_t*)inData)[15-i];
		}
		break;
	default:
		break;
	}
	}
#endif	/* __BIG_ENDIAN__ */
//	RPC_MemDump(inData,size," -- IN DUMP --");
//	RPC_MemDump(outData,size," --OUT DUMP --");
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "OUT IPC_convertNetworkByteOrder ");
}

static void IPC_convertHostByteOrder(void *inData,void *outData,uint32_t size) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "IN IPC_convertHostByteOrder inData:0x%x; outData:0x%x; size:%d;",inData,outData,size);
#ifdef	__BIG_ENDIAN__
	if(size > 0) {
		(void)memcpy((void*)outData,(void*)inData,size);
	}
#else	/* __BIG_ENDIAN__ */
	{int i;
	switch(size) {
	case 0:
		break;
	case 1:
		*((uint8_t*)outData) = *((uint8_t*)inData);
		break;
	case 2:
		*((uint16_t*)outData) = ntohs(*((uint16_t*)inData));
		break;
	case 4:
		*((uint32_t*)outData) = ntohl(*((uint32_t*)inData));
		break;
	case 8:
		for(i = 0;i<8;i++) {
			((uint8_t*)outData)[i] = ((uint8_t*)inData)[7-i];
		}
		break;
	case 16:
		for(i = 0;i<16;i++) {
			((uint8_t*)outData)[i] = ((uint8_t*)inData)[15-i];
		}
		break;
	default:
		(void)memcpy((void*)outData,(void*)inData,size);
		break;
	}
	}
#endif	/* __BIG_ENDIAN__ */
//	RPC_MemDump(inData,size," -- IN DUMP --");
//	RPC_MemDump(outData,size," --OUT DUMP --");
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL, RPC_LOG_LEVEL_DEBUG3, "OUT IPC_convertHostByteOrder ");
}
#endif	/* RPC_CHECK_BYTEORDER */

/* ----- TEST Functions ----- */

uint8_t *IPC_ConvertTypeToString(RpcParamType_t type) {
	switch(type) {
	case RPC_INT_TYPE:
		return (uint8_t*)"INT   ";
	case RPC_UINT_TYPE:
		return (uint8_t*)"UINT  ";
	case RPC_FLOAT_TYPE:
		return (uint8_t*)"FLOAT ";
	case RPC_STRING_TYPE:
		return (uint8_t*)"STRING";
	case RPC_ENUM_TYPE:
		return (uint8_t*)"ENUM  ";
	case RPC_OCTET_ARRAY_TYPE:
		return (uint8_t*)"OCTARY";
	case RPC_TYPE_UNKNOWN:
		return (uint8_t*)"UNKNWN";
	case RPC_BOOLEAN_TYPE:
		return (uint8_t*)"BOOLEN";
	case RPC_REFERENCE_TYPE:
		return (uint8_t*)"REFRNC";
	default:
		return (uint8_t*)"ERROR ";
	}
}

void IPC_DumpParamData(RpcParamData_t *pData) {
	int i;char lData[128];

#if	__WORDSIZE == 64
	fprintf(stdout,"--- PARAM DATA DATA:0x%Lx ---\n",(uint64_t)pData);
#else	/* __WORDSIZE */
	fprintf(stdout,"--- PARAM DATA DATA:0x%x ---\n",(uint32_t)pData);
#endif	/* __WORDSIZE */
	i = 1;
	while(pData->paramSpec.paramType != RPC_TYPE_UNKNOWN) {
#if	__WORDSIZE == 64
		fprintf(stdout," TYPE:%s LENG:%d DATA-P:0x%Lx\n",(char*)IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng,(uint64_t)pData->paramData);
#else	/* __WORDSIZE */
		fprintf(stdout," TYPE:%s LENG:%d DATA-P:0x%x\n",(char*)IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng,(uint32_t)pData->paramData);
#endif	/* __WORDSIZE */
		sprintf(lData,"NUM:%d; TYPE:%s",i,IPC_ConvertTypeToString(pData->paramSpec.paramType));
		RPC_MemDump(pData->paramData,pData->paramSpec.paramLeng,lData);
		switch(pData->paramSpec.paramType) {
		case RPC_INT_TYPE:
			switch(pData->paramSpec.paramLeng) {
			case 1:
				fprintf(stdout,"  VAL:%d;\n",*((int8_t*)(pData->paramData)));
				break;
			case 2:
				fprintf(stdout,"  VAL:%d;\n",*((int16_t*)(pData->paramData)));
				break;
			case 4:
				fprintf(stdout,"  VAL:%d;\n",*((int32_t*)(pData->paramData)));
				break;
			case 8:
				fprintf(stdout,"  VAL:%Ld;\n",*((int64_t*)(pData->paramData)));
				break;
			}
			break;
		case RPC_UINT_TYPE:
			switch(pData->paramSpec.paramLeng) {
			case 1:
				fprintf(stdout,"  VAL:%d;\n",*((uint8_t*)(pData->paramData)));
				break;
			case 2:
				fprintf(stdout,"  VAL:%d;\n",*((uint16_t*)(pData->paramData)));
				break;
			case 4:
				fprintf(stdout,"  VAL:%d;\n",*((uint32_t*)(pData->paramData)));
				break;
			case 8:
				fprintf(stdout,"  VAL:%Ld;\n",*((uint64_t*)(pData->paramData)));
				break;
			}
			break;
		case RPC_FLOAT_TYPE:
			switch(pData->paramSpec.paramLeng) {
			case 4:
				fprintf(stdout,"  VAL:%e;\n",*((float*)(pData->paramData)));
				break;
			case 8:
				fprintf(stdout,"  VAL:%le;\n",*((double*)(pData->paramData)));
				break;
			case 16:
				fprintf(stdout,"  VAL:%Le;\n",*((long double*)(pData->paramData)));
				break;
			}
			break;
		case RPC_ENUM_TYPE:
			fprintf(stdout,"  VAL:0x%x;\n",*((uint32_t*)(pData->paramData)));
			break;
		case RPC_BOOLEAN_TYPE:
			fprintf(stdout,"  VAL:%s;\n", (*((uint8_t*)(pData->paramData)))?"TRUE":"FALSE");
			break;
		case RPC_REFERENCE_TYPE:
			switch(pData->paramSpec.paramLeng) {
			case 8:
				fprintf(stdout,"  VAL:0:%Lx;\n",(uint64_t)(*((uint64_t*)(pData->paramData))));
				break;
			case 16:
				fprintf(stdout,"  VAL:%Lx:%Lx;\n",(uint64_t)(*((uint32_t*)(pData->paramData))),(uint64_t)(*(((uint64_t*)(pData->paramData))+1)));
				break;
			}
			break;
		default:
			break;
		}
		pData++;i++;
	}
#if	__WORDSIZE == 64
	fprintf(stdout," TYPE:%s LENG:%d DATA-P:0x%Lx\n",(char*)IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng,(uint64_t)pData->paramData);
#else	/* __WORDSIZE */
	fprintf(stdout," TYPE:%s LENG:%d DATA-P:0x%x\n",(char*)IPC_ConvertTypeToString(pData->paramSpec.paramType),pData->paramSpec.paramLeng,(uint32_t)pData->paramData);
#endif	/* __WORDSIZE */
	sprintf(lData,"NUM:%d; TYPE:%s",i,IPC_ConvertTypeToString(pData->paramSpec.paramType));
	RPC_MemDump(pData->paramData,pData->paramSpec.paramLeng,lData);
}

#ifdef	DEBUG

RpcResult_t marshalTest(void);

RpcResult_t marshalTest(void) {
	RpcResult_t ret;RpcParamData_t pData[14];
	RpcParamData_t *oData;
	int i;
	uint8_t *marshalData;void *shmData;uint32_t marshalSize;
	int8_t data0 = 1;uint16_t data1 = 2;
	int32_t data2 = -1;uint64_t data3 = 3;
	float data4 = -118.625;double data5 = 118.625;
	char *data6 = "abcdefghijklmn";
	RpcParamType_t data7 = RPC_ENUM_TYPE;
	uint8_t data8[128] = {0};
	uint8_t *data9;
	uint32_t unmarshalData[10*1024];
	RpcBool_t data10 = RPC_TRUE;
	RpcBool_t data11 = RPC_FALSE;
	long double data12 = -118.625L;
	double data12X = (double)data12;

	fprintf(stdout,"@@@@@ NOW START MARSHAL TEST @@@@\n");
#if	0
	if((ret = IPC_InitSharedMem(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitSharedMem ret:%s;",RPC_LogConvertResultCode(ret));
		return ret;
	}
//	fprintf(stdout,"STEP2\n");
	if((ret = IPC_AttachSharedMem()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_AttachSharedMem ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DestroySharedMem();
		return ret;
	}
//	fprintf(stdout,"STEP3\n");
	if((ret = IPC_InitMarshal(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitMarshal ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;		
	}
#endif	/* 0 */
#if	0
//	fprintf(stdout,"STEP4\n");
	if((ret = IPC_InitShmGapArea(IpcMarshalDataSharedMemId, 1024)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN INIT SHM GAP AREA ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;		
	}
//	fprintf(stdout,"STEP5\n");
	if((ret = IPC_InitShmAllocArea(IpcMarshalDataSharedMemId, IPC_MARSHAL_SHARED_MEM_REAL_SIZE, 6, 64, 2)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN INIT SHM ALLOC AREA ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;		
	}
#endif	/* 0 */
//	fprintf(stdout,"STEP6\n");
	if((shmData = IPC_AllocShmMem(IpcMarshalDataSharedMemId, 2000)) == NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN SHM ALLOCATION ");
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return RPC_FATAL_ERROR;			
	}
#if	__WORDSIZE == 64
	fprintf(stdout,"@@@ SET DATA0 shmData:0x%Lx; @@@\n",(uint64_t)shmData);
#else	/* __WORDSIZE */
	fprintf(stdout,"@@@ SET DATA0 shmData:0x%x; @@@\n",(uint32_t)shmData);
#endif	/* __WORDSIZE */
	for(i = 0;i < 128;i++) {
		data8[i] = 128 -i;
	}
	data9 = (uint8_t*)shmData;
	for(i = 0;i < 2000;i++) {
		data9[i] = (uint8_t)i;
	}
	fprintf(stdout,"@@@ SET DATA @@\n");
	pData[0].paramSpec.paramType = RPC_INT_TYPE;pData[0].paramSpec.paramLeng = 1;pData[0].paramData = (uint8_t*)&data0;
	pData[1].paramSpec.paramType = RPC_UINT_TYPE;pData[1].paramSpec.paramLeng = 2;pData[1].paramData = (uint8_t*)&data1;
	pData[2].paramSpec.paramType = RPC_INT_TYPE;pData[2].paramSpec.paramLeng = 4;pData[2].paramData = (uint8_t*)&data2;
	pData[3].paramSpec.paramType = RPC_UINT_TYPE;pData[3].paramSpec.paramLeng = 8;pData[3].paramData = (uint8_t*)&data3;
	pData[4].paramSpec.paramType = RPC_FLOAT_TYPE;pData[4].paramSpec.paramLeng = 4;pData[4].paramData = (uint8_t*)&data4;
	pData[5].paramSpec.paramType = RPC_FLOAT_TYPE;pData[5].paramSpec.paramLeng = 8;pData[5].paramData = (uint8_t*)&data5;
	pData[6].paramSpec.paramType = RPC_STRING_TYPE;pData[6].paramSpec.paramLeng = strlen(data6);;pData[6].paramData = (uint8_t*)data6;
	pData[7].paramSpec.paramType = RPC_ENUM_TYPE;pData[7].paramSpec.paramLeng = 4;pData[7].paramData = (uint8_t*)&data7;
	pData[8].paramSpec.paramType = RPC_OCTET_ARRAY_TYPE;pData[8].paramSpec.paramLeng = 128;pData[8].paramData = (uint8_t*)data8;
	pData[9].paramSpec.paramType = RPC_REFERENCE_TYPE;pData[9].paramSpec.paramLeng = sizeof(uint8_t*);pData[9].paramData = (uint8_t*)&data9;
	pData[10].paramSpec.paramType = RPC_BOOLEAN_TYPE;pData[10].paramSpec.paramLeng = sizeof(RpcBool_t);pData[10].paramData = (uint8_t*)&data10;
	pData[11].paramSpec.paramType = RPC_BOOLEAN_TYPE;pData[11].paramSpec.paramLeng = sizeof(RpcBool_t);pData[11].paramData = (uint8_t*)&data11;
#ifdef	IEEE754_LONG_DOUBLE_BIAS
	pData[12].paramSpec.paramType = RPC_FLOAT_TYPE;pData[12].paramSpec.paramLeng = 16;
	pData[12].paramData = (uint8_t*)&data12;
#else	/* IEEE754_LONG_DOUBLE_BIAS */
	pData[12].paramSpec.paramType = RPC_FLOAT_TYPE;pData[12].paramSpec.paramLeng = 8;
	pData[12].paramData = (uint8_t*)&data12X;
#endif	/* IEEE754_LONG_DOUBLE_BIAS */
	pData[13].paramSpec.paramType = RPC_TYPE_UNKNOWN;pData[13].paramSpec.paramLeng = 0;pData[13].paramData = (uint8_t*)NULL;
	fprintf(stdout,"\n\n@@@ BEFORE MARSHAL DATA @@@\n");
	IPC_DumpParamData(pData);
//	RPC_MemDump((uint8_t*)(*((uint32_t*)(pData[9].paramData))),2000,"## SHM MEM DATA ##");

	if((ret = IPC_Marshal(pData, (void**)&marshalData, &marshalSize)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN MARSHAL ret:%s;",RPC_LogConvertResultCode(ret));
		IPC_FreeShmMem(IpcMarshalDataSharedMemId, shmData);
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;					
	}
	fprintf(stdout,"\n\n@@@ AFTER MARSHAL DATA @@@\n");
	RPC_MemDump(marshalData,marshalSize,"PACKED DATA");


	if((ret = IPC_Unmarshal(marshalData, marshalSize, unmarshalData, 10*1024)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MARSHAL,RPC_LOG_LEVEL_FATAL,"ERROR IN UNMARSHAL ret:%s;",RPC_LogConvertResultCode(ret));
		IPC_FreeShmMem(IpcMarshalDataSharedMemId, marshalData);
		IPC_FreeShmMem(IpcMarshalDataSharedMemId, shmData);
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;							
	}
	fprintf(stdout,"\n\n@@@ AFTER UNMARSHAL DATA @@@\n");
//	oData = (RpcParamData_t*)unmarshalData;
	IPC_DumpParamData((RpcParamData_t*)unmarshalData);
//	RPC_MemDump((uint8_t*)(*((uint32_t*)((RpcParamData_t*)unmarshalData)[9].paramData)),2000,"## SHM MEM DATA ##");
	IPC_FreeShmMem(IpcMarshalDataSharedMemId, shmData);
	(void)IPC_DettachSharedMem();
	(void)IPC_DestroySharedMem();
	return RPC_SUCCESS;
}

#endif	/* DEBUG */

