RsslReactorCallbackRet simpleTunnelMsgHandlerConsumerMsgCallback(RsslTunnelStream *pTunnelStream, RsslTunnelStreamMsgEvent *pEvent)
{
	switch(pEvent->containerType)
	{
		case RSSL_DT_OPAQUE:
		{
			/* Read the text contained. */
			printf("Tunnel Stream %d received OPAQUE data: %.*s\n\n", 
					pTunnelStream->streamId, pEvent->pRsslBuffer->length, pEvent->pRsslBuffer->data);
			break;
		}


		default:
		{
			printf("Received unhandled buffer containerType %d(%s) in tunnel stream %d\n\n", 
				pEvent->containerType, rsslDataTypeToString(pEvent->containerType), pTunnelStream->streamId);
			break;
		}
	}	

	return RSSL_RC_CRET_SUCCESS; 
}
Beispiel #2
0
RsslRet decodeMBOUpdate(RsslDecodeIterator* pIter, RsslMsg* msg, ProviderThread* pProviderThread)
{
	RsslFieldList fList = RSSL_INIT_FIELD_LIST;
	RsslFieldEntry fEntry = RSSL_INIT_FIELD_ENTRY;
	RsslMap Map = RSSL_INIT_MAP;
	RsslMapEntry mEntry = RSSL_INIT_MAP_ENTRY;
	RsslRet ret = 0;
	
	RsslPrimitive key;
	RsslDataType dataType;
	RsslPrimitive primitive;
	RsslDictionaryEntry* dictionaryEntry = NULL;

	RsslUInt genMsgTimeTracker = 0;
	
	/* decode field list */
			
	if((ret = rsslDecodeMap(pIter, &Map)) == RSSL_RET_SUCCESS)
	{
		if(rsslMapCheckHasSetDefs(&Map) == RSSL_TRUE)
		{
			rsslClearLocalFieldSetDefDb(&pProviderThread->fListSetDef);
			pProviderThread->fListSetDef.entries.data = pProviderThread->setDefMemory;
			pProviderThread->fListSetDef.entries.length = sizeof(pProviderThread->setDefMemory);
			if((ret = rsslDecodeLocalFieldSetDefDb(pIter, &pProviderThread->fListSetDef)) != RSSL_RET_SUCCESS)
				return ret;
		}
		
		if(rsslMapCheckHasSummaryData(&Map) == RSSL_TRUE)
		{
			if((ret = rsslDecodeFieldList(pIter, &fList, &pProviderThread->fListSetDef)) == RSSL_RET_SUCCESS)
			{
				while ((ret = rsslDecodeFieldEntry(pIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER)
				{	
					if (ret != RSSL_RET_SUCCESS) return ret;

					/* get dictionary entry */
					dictionaryEntry = getDictionaryEntry(pProviderThread->pDictionary,
							fEntry.fieldId);

					if  (!dictionaryEntry)
					{
						printf("Error: Decoded field ID %d not present in dictionary.\n", fEntry.fieldId);
						return RSSL_RET_FAILURE;
					}

					/* decode and print out fid value */
					dataType = dictionaryEntry->rwfType;

					switch (dataType)
					{
						case RSSL_DT_INT:
							if((ret = rsslDecodeInt(pIter, &primitive.intType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_UINT:
							if((ret = rsslDecodeUInt(pIter, &primitive.uintType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_FLOAT:
							if ((ret = rsslDecodeFloat(pIter, &primitive.floatType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_DOUBLE:
							if ((ret = rsslDecodeDouble(pIter, &primitive.doubleType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_REAL:
							if ((ret = rsslDecodeReal(pIter, &primitive.realType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_DATE:
							if ((ret = rsslDecodeDate(pIter, &primitive.dateType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_TIME:
							if ((ret = rsslDecodeTime(pIter, &primitive.timeType)) < RSSL_RET_SUCCESS )
								return ret;
							break;
						case RSSL_DT_DATETIME:
							if ((ret = rsslDecodeDateTime(pIter, &primitive.dateTimeType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_QOS:
							if ((ret = rsslDecodeQos(pIter, &primitive.qosType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_STATE:
							if ((ret = rsslDecodeState(pIter, &primitive.stateType)) < RSSL_RET_SUCCESS)
								return ret;
							break;
						case RSSL_DT_ENUM:
							{
								RsslEnumType *pEnumTypeInfo;
								if ((ret = rsslDecodeEnum(pIter, &primitive.enumType)) < RSSL_RET_SUCCESS )
									return ret;

								if (ret == RSSL_RET_BLANK_DATA)
									break;

								pEnumTypeInfo = getFieldEntryEnumType(dictionaryEntry, primitive.enumType);
								if (pEnumTypeInfo)
									primitive.bufferType = pEnumTypeInfo->display;
								break;
							}
						case RSSL_DT_BUFFER:
						case RSSL_DT_ASCII_STRING:
						case RSSL_DT_UTF8_STRING:
						case RSSL_DT_RMTES_STRING:
							if ((ret = rsslDecodeBuffer(pIter, &primitive.bufferType)) < RSSL_RET_SUCCESS )
								return ret;
							break;
						default:
							printf("Error: Unhandled data type %s(%u) in field with ID %u.\n", 
									rsslDataTypeToString(dataType), dataType, fEntry.fieldId);
							return RSSL_RET_FAILURE;
					}

					if (msg->msgBase.msgClass == RSSL_MC_GENERIC && ret != RSSL_RET_BLANK_DATA)
					{
						if(fEntry.fieldId == TIM_TRK_3_FID)
							genMsgTimeTracker = primitive.uintType;
					}
				}
			}
			else
			{
				return ret;
			}
		}

		while((ret = rsslDecodeMapEntry(pIter, &mEntry, &key)) != RSSL_RET_END_OF_CONTAINER)
		{
			if (mEntry.action != RSSL_MPEA_DELETE_ENTRY)
			{
				if((ret = rsslDecodeFieldList(pIter, &fList, &pProviderThread->fListSetDef)) == RSSL_RET_SUCCESS)
				{
					while ((ret = rsslDecodeFieldEntry(pIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER)
					{	
						if (ret != RSSL_RET_SUCCESS) return ret;

						/* get dictionary entry */
						dictionaryEntry = getDictionaryEntry(pProviderThread->pDictionary,
								fEntry.fieldId);

						if  (!dictionaryEntry)
						{
							printf("Error: Decoded field ID %d not present in dictionary.\n", fEntry.fieldId);
							return RSSL_RET_FAILURE;
						}

						/* decode and print out fid value */
						dataType = dictionaryEntry->rwfType;
						
						switch (dataType)
						{
							case RSSL_DT_INT:
								if((ret = rsslDecodeInt(pIter, &primitive.intType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_UINT:
								if((ret = rsslDecodeUInt(pIter, &primitive.uintType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_FLOAT:
								if ((ret = rsslDecodeFloat(pIter, &primitive.floatType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_DOUBLE:
								if ((ret = rsslDecodeDouble(pIter, &primitive.doubleType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_REAL:
								if ((ret = rsslDecodeReal(pIter, &primitive.realType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_DATE:
								if ((ret = rsslDecodeDate(pIter, &primitive.dateType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_TIME:
								if ((ret = rsslDecodeTime(pIter, &primitive.timeType)) < RSSL_RET_SUCCESS )
									return ret;
								break;
							case RSSL_DT_DATETIME:
								if ((ret = rsslDecodeDateTime(pIter, &primitive.dateTimeType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_QOS:
								if ((ret = rsslDecodeQos(pIter, &primitive.qosType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_STATE:
								if ((ret = rsslDecodeState(pIter, &primitive.stateType)) < RSSL_RET_SUCCESS)
									return ret;
								break;
							case RSSL_DT_ENUM:
								{
									RsslEnumType *pEnumTypeInfo;
									if ((ret = rsslDecodeEnum(pIter, &primitive.enumType)) < RSSL_RET_SUCCESS )
										return ret;

									if (ret == RSSL_RET_BLANK_DATA)
										break;

									pEnumTypeInfo = getFieldEntryEnumType(dictionaryEntry, primitive.enumType);
									if (pEnumTypeInfo)
										primitive.bufferType = pEnumTypeInfo->display;
									break;
								}
							case RSSL_DT_BUFFER:
							case RSSL_DT_ASCII_STRING:
							case RSSL_DT_UTF8_STRING:
							case RSSL_DT_RMTES_STRING:
								if ((ret = rsslDecodeBuffer(pIter, &primitive.bufferType)) < RSSL_RET_SUCCESS )
									return ret;
								break;
							default:
								printf("Error: Unhandled data type %s(%u) in field with ID %u.\n", 
										rsslDataTypeToString(dataType), dataType, fEntry.fieldId);
								return RSSL_RET_FAILURE;
						}
					}
				}
				else
				{
					return ret;
				}
			}
		}
	}
	else
	{
		return ret;
	}
	
	if(genMsgTimeTracker)
		updateLatencyStats(pProviderThread, genMsgTimeTracker);

	return RSSL_RET_SUCCESS;
}
RsslRet decodeMPUpdate(RsslDecodeIterator *pIter, RsslMsg *msg, ConsumerThread* pConsumerThread)
{
	RsslFieldList fList = RSSL_INIT_FIELD_LIST;
	RsslFieldEntry fEntry = RSSL_INIT_FIELD_ENTRY;
	RsslRet ret = 0;

	RsslDataType dataType;
	RsslPrimitive primitive;
	RsslDictionaryEntry* dictionaryEntry = NULL;

	RsslUInt timeTracker = 0;
	RsslUInt postTimeTracker = 0;
	RsslUInt genMsgTimeTracker = 0;

	/* decode field list */
	if ((ret = rsslDecodeFieldList(pIter, &fList, 0)) == RSSL_RET_SUCCESS)
	{
		while ((ret = rsslDecodeFieldEntry(pIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER)
		{	
			if (ret != RSSL_RET_SUCCESS) return ret;

			/* get dictionary entry */
			dictionaryEntry = getDictionaryEntry(pConsumerThread->pDictionary,
					fEntry.fieldId);

			if  (!dictionaryEntry)
			{
				printf("Error: Decoded field ID %d not present in dictionary.\n", fEntry.fieldId);
				return RSSL_RET_FAILURE;
			}

			/* decode and print out fid value */
			dataType = dictionaryEntry->rwfType;
			switch (dataType)
			{
				case RSSL_DT_INT:
					if((ret = rsslDecodeInt(pIter, &primitive.intType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_UINT:
					if((ret = rsslDecodeUInt(pIter, &primitive.uintType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_FLOAT:
					if ((ret = rsslDecodeFloat(pIter, &primitive.floatType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_DOUBLE:
					if ((ret = rsslDecodeDouble(pIter, &primitive.doubleType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_REAL:
					if ((ret = rsslDecodeReal(pIter, &primitive.realType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_DATE:
					if ((ret = rsslDecodeDate(pIter, &primitive.dateType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_TIME:
					if ((ret = rsslDecodeTime(pIter, &primitive.timeType)) < RSSL_RET_SUCCESS )
						return ret;
					break;
				case RSSL_DT_DATETIME:
					if ((ret = rsslDecodeDateTime(pIter, &primitive.dateTimeType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_QOS:
					if ((ret = rsslDecodeQos(pIter, &primitive.qosType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_STATE:
					if ((ret = rsslDecodeState(pIter, &primitive.stateType)) < RSSL_RET_SUCCESS)
						return ret;
					break;
				case RSSL_DT_ENUM:
				{
					RsslEnumType *pEnumTypeInfo;
					if ((ret = rsslDecodeEnum(pIter, &primitive.enumType)) < RSSL_RET_SUCCESS )
						return ret;

					if (ret == RSSL_RET_BLANK_DATA)
						break;

					pEnumTypeInfo = getFieldEntryEnumType(dictionaryEntry, primitive.enumType);
					if (pEnumTypeInfo)
						primitive.bufferType = pEnumTypeInfo->display;
					break;
				}
				case RSSL_DT_BUFFER:
				case RSSL_DT_ASCII_STRING:
				case RSSL_DT_UTF8_STRING:
				case RSSL_DT_RMTES_STRING:
					if ((ret = rsslDecodeBuffer(pIter, &primitive.bufferType)) < RSSL_RET_SUCCESS )
						return ret;
					break;
				default:
					printf("Error: Unhandled data type %s(%u) in field with ID %u.\n", 
							rsslDataTypeToString(dataType), dataType, fEntry.fieldId);
					return RSSL_RET_FAILURE;
			}

			if (msg->msgBase.msgClass == RSSL_MC_UPDATE && ret != RSSL_RET_BLANK_DATA)
			{
				if(fEntry.fieldId == TIM_TRK_1_FID)
					timeTracker = primitive.uintType;
				if(fEntry.fieldId == TIM_TRK_2_FID)
					postTimeTracker = primitive.uintType;
			}
			else if (msg->msgBase.msgClass == RSSL_MC_GENERIC && ret != RSSL_RET_BLANK_DATA)
			{
				if(fEntry.fieldId == TIM_TRK_3_FID)
					genMsgTimeTracker = primitive.uintType;
			}
		}
	}
	else
	{
		return ret;
	}
	
	if (timeTracker)
		updateLatencyStats(pConsumerThread, timeTracker, RSSL_MC_UPDATE);
	if(postTimeTracker && checkPostUserInfo(msg))
		updateLatencyStats(pConsumerThread, postTimeTracker, RSSL_MC_POST);
	if(genMsgTimeTracker)
		updateLatencyStats(pConsumerThread, genMsgTimeTracker, RSSL_MC_GENERIC);

	return RSSL_RET_SUCCESS;
}
RsslReactorCallbackRet simpleTunnelMsgHandlerProviderMsgCallback(RsslTunnelStream *pTunnelStream, RsslTunnelStreamMsgEvent *pEvent)
{
	RsslMsg *pRsslMsg = pEvent->pRsslMsg;
	RsslReactorChannel *pReactorChannel = pTunnelStream->pReactorChannel;
	SimpleTunnelMsgHandler *pSimpleTunnelMsgHandler = (SimpleTunnelMsgHandler*)pTunnelStream->userSpecPtr;

	/* Inspect the message and handle it accordingly. This is basically
	 * the same as the consumer's message callback but will respond to the
	 * client's authentication login message if one is received. */

	switch(pEvent->containerType)
	{
		case RSSL_DT_OPAQUE:
		{
			/* Read the text contained. */
			printf("Tunnel Stream %d received OPAQUE data: %.*s\n\n", 
					pTunnelStream->streamId, pEvent->pRsslBuffer->length, pEvent->pRsslBuffer->data);
			break;

		}

		case RSSL_DT_MSG:
		{

			switch(pRsslMsg->msgBase.domainType)
			{
				case RSSL_DMT_LOGIN:
				{
					RsslDecodeIterator dIter;
					RsslRDMLoginMsg loginMsg;
					char tmpMemory[1024];
					RsslBuffer memoryBuffer;
					RsslRet ret;
					RsslErrorInfo errorInfo;

					/* Use the ValueAdd RDM Decoder to decode the login message. */
					rsslClearDecodeIterator(&dIter);
					rsslSetDecodeIteratorRWFVersion(&dIter, pTunnelStream->classOfService.common.protocolMajorVersion,
						pTunnelStream->classOfService.common.protocolMinorVersion);
					rsslSetDecodeIteratorBuffer(&dIter, &pRsslMsg->msgBase.encDataBody);

					rsslClearBuffer(&memoryBuffer);
					memoryBuffer.length = sizeof(tmpMemory);
					memoryBuffer.data = tmpMemory;

					if ((ret = rsslDecodeRDMLoginMsg(&dIter, pRsslMsg, &loginMsg, &memoryBuffer, &errorInfo))
						!= RSSL_RET_SUCCESS)
					{
						printf("rsslDecodeRDMLoginMsg() failed: %s(%s)\n", rsslRetCodeToString(ret), errorInfo.rsslError.text);
						break;
					}

					switch(loginMsg.rdmMsgBase.rdmMsgType)
					{
					case RDM_LG_MT_REQUEST:
						{
							/* This is a login request, likely the client's authentication
							* request. Send a response to establish the tunnel stream. */

							RsslRDMLoginRefresh loginRefresh;
							RsslTunnelStreamSubmitOptions submitOpts;
							RsslTunnelStreamGetBufferOptions bufferOpts;
							RsslBuffer *pBuffer;
							RsslEncodeIterator eIter;
							RsslRet ret, ret2;
							RsslRDMLoginRequest *pLoginRequest = &loginMsg.request;

							printf("Received login request on tunnel stream(ID %d) with stream ID %d.\n", 
								pTunnelStream->streamId, pLoginRequest->rdmMsgBase.streamId);

							if (pLoginRequest->flags & RDM_LG_RQF_NO_REFRESH)
								break;

							rsslClearTunnelStreamGetBufferOptions(&bufferOpts);
							bufferOpts.size = 1024;
							if ((pBuffer = rsslTunnelStreamGetBuffer(pTunnelStream, &bufferOpts, &errorInfo))
								== NULL)
							{
								printf("rsslTunnelStreamGetBuffer failed: %s(%s)\n", rsslRetCodeToString(errorInfo.rsslError.rsslErrorId), &errorInfo.rsslError.text);
								break;
							}

							rsslClearRDMLoginRefresh(&loginRefresh);

							/* Set state information */
							loginRefresh.state.streamState = RSSL_STREAM_OPEN;
							loginRefresh.state.dataState = RSSL_DATA_OK;
							loginRefresh.state.code = RSSL_SC_NONE;
							loginRefresh.state.text.data = (char*)"Tunnel login accepted.";
							loginRefresh.state.text.length = (RsslUInt32)strlen(loginRefresh.state.text.data);

							/* Set stream ID */
							loginRefresh.rdmMsgBase.streamId = pLoginRequest->rdmMsgBase.streamId;

							/* Mark refresh as solicited since it is a response to a request. */
							loginRefresh.flags = RDM_LG_RFF_SOLICITED;

							/* Echo the userName, applicationId, applicationName, and position */
							loginRefresh.flags |= RDM_LG_RFF_HAS_USERNAME;
							loginRefresh.userName = pLoginRequest->userName;
							if (pLoginRequest->flags & RDM_LG_RQF_HAS_USERNAME_TYPE)
							{
								loginRefresh.flags |= RDM_LG_RFF_HAS_USERNAME_TYPE;
								loginRefresh.userNameType = pLoginRequest->userNameType;
							}

							loginRefresh.flags |= RDM_LG_RFF_HAS_APPLICATION_ID;
							loginRefresh.applicationId = pLoginRequest->applicationId;

							loginRefresh.flags |= RDM_LG_RFF_HAS_APPLICATION_NAME;
							loginRefresh.applicationName = pLoginRequest->applicationName;

							loginRefresh.flags |= RDM_LG_RFF_HAS_POSITION;
							loginRefresh.position = pLoginRequest->position;

							/* This provider does not support Single-Open behavior. */
							loginRefresh.flags |= RDM_LG_RFF_HAS_SINGLE_OPEN;
							loginRefresh.singleOpen = 0; 

							/* set the clear cache flag */
							loginRefresh.flags |= RDM_LG_RFF_CLEAR_CACHE;

							/* Leave all other parameters as default values. */

							/* Encode the refresh. */
							rsslClearEncodeIterator(&eIter);
							rsslSetEncodeIteratorRWFVersion(&eIter, pTunnelStream->classOfService.common.protocolMajorVersion,
								pTunnelStream->classOfService.common.protocolMinorVersion);
							if((ret = rsslSetEncodeIteratorBuffer(&eIter, pBuffer)) < RSSL_RET_SUCCESS)
							{
								printf("rsslSetEncodeIteratorBuffer(): Failed <%s>\n", errorInfo.rsslError.text);
								if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &errorInfo)) != RSSL_RET_SUCCESS)
									printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, errorInfo.rsslError.text);
								break;
							}

							if (rsslEncodeRDMLoginMsg(&eIter, (RsslRDMLoginMsg*)&loginRefresh, &pBuffer->length, &errorInfo) != RSSL_RET_SUCCESS)
							{
								printf("rsslEncodeRDMLoginMsg(): Failed <%s>\n", errorInfo.rsslError.text);
								if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &errorInfo)) != RSSL_RET_SUCCESS)
									printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, errorInfo.rsslError.text);
								break;
							}

							/* Message encoding complete; submit it. */
							rsslClearTunnelStreamSubmitOptions(&submitOpts);
							submitOpts.containerType = RSSL_DT_MSG;
							if ((ret = rsslTunnelStreamSubmit(pTunnelStream, pBuffer, &submitOpts, &errorInfo)) != RSSL_RET_SUCCESS)
							{
								printf("rsslTunnelStreamSubmit(): Failed <%s>\n", errorInfo.rsslError.text);
								if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &errorInfo)) != RSSL_RET_SUCCESS)
									printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, errorInfo.rsslError.text);
								break;
							}

							printf("Sent response to tunnel login request.\n\n");

							pSimpleTunnelMsgHandler->waitingForAuthenticationRequest = RSSL_FALSE;

							break;
						}

					case RDM_LG_MT_CLOSE:
						{
							/* Login close message. */
							RsslRDMLoginClose *pLoginClose = &loginMsg.close;

							printf("Received login close on tunnel stream(ID %d) with stream ID %d.\n", 
								pTunnelStream->streamId, pLoginClose->rdmMsgBase.streamId);
							break;
						}
					}


					break;
				}

				default:
				{
					/* Don't recognize this message. */
					printf("Received unhandled message in TunnelStream with stream ID %d, class %u(%s) and domainType %u(%s)\n\n",
						pRsslMsg->msgBase.streamId, 
						pRsslMsg->msgBase.msgClass, rsslMsgClassToString(pRsslMsg->msgBase.msgClass),
						pRsslMsg->msgBase.domainType, rsslDomainTypeToString(pRsslMsg->msgBase.domainType));
					break;
				}
			}
			break;
		}

		default:
		{
			printf("Received unhandled buffer containerType %d(%s) in tunnel stream %d\n\n", 
				pEvent->containerType, rsslDataTypeToString(pEvent->containerType), pTunnelStream->streamId);
			break;
		}
	}


	return RSSL_RC_CRET_SUCCESS; 
}