static void simpleTunnelMsgHandlerSendMessage(SimpleTunnelMsgHandler *pSimpleTunnelMsgHandler)
{
	RsslTunnelStream *pTunnelStream = pSimpleTunnelMsgHandler->tunnelStreamHandler.pTunnelStream;
	RsslReactorChannel *pReactorChannel = pTunnelStream->pReactorChannel;

	RsslTunnelStreamSubmitOptions submitOpts;
	RsslTunnelStreamGetBufferOptions bufferOpts;
	RsslEncodeIterator eIter;
	RsslBuffer *pBuffer;
	RsslRet ret, ret2;
	RsslErrorInfo errorInfo;

	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);
		return;
	}

	rsslClearEncodeIterator(&eIter);
	rsslSetEncodeIteratorRWFVersion(&eIter, pTunnelStream->classOfService.common.protocolMajorVersion,
			pTunnelStream->classOfService.common.protocolMinorVersion);
	rsslSetEncodeIteratorBuffer(&eIter, pBuffer);

	/* Write text as the data body. */
	pBuffer->length = snprintf(pBuffer->data, pBuffer->length, "TunnelStream Message: %d", pSimpleTunnelMsgHandler->msgCount + 1);

	/* Message encoding complete; submit it. */
	rsslClearTunnelStreamSubmitOptions(&submitOpts);
	submitOpts.containerType = RSSL_DT_OPAQUE;
	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);
		return;
	}

	++pSimpleTunnelMsgHandler->msgCount;
}
예제 #2
0
/*
 * Encode and send a queue message through the ReactorChannel.
 * This message will contain an field list as its payload.
 */
static void sendQueueMsg(QueueMsgHandler *pQueueMsgHandler)
{
	int i;
	RsslErrorInfo rsslErrorInfo;
	RsslRet ret, ret2;
	RsslFieldList fieldList;
	RsslFieldEntry fieldEntry;

	for(i = 0; i < pQueueMsgHandler->destNameCount; i++)
	{
		RsslBuffer *pBuffer;
		RsslTunnelStreamSubmitOptions submitOpts;
		RsslTunnelStreamGetBufferOptions bufferOpts;
		RsslRDMQueueData queueData;
		RsslEncodeIterator eIter;
		RsslBuffer fieldBuffer;
		RsslDateTime dateTime;
		RsslReal real;
		RsslEnum enumVal;
		RsslUInt uintVal;
		RsslTunnelStream *pTunnelStream = pQueueMsgHandler->tunnelStreamHandler.pTunnelStream;

		rsslClearTunnelStreamGetBufferOptions(&bufferOpts);
		bufferOpts.size = 1024;
		if ((pBuffer = rsslTunnelStreamGetBuffer(pQueueMsgHandler->tunnelStreamHandler.pTunnelStream, 
						&bufferOpts, &rsslErrorInfo)) == NULL)
		{
			printf("rsslTunnelStreamGetBuffer(): Failed <%s>\n", rsslErrorInfo.rsslError.text);
			return;
		}

        // initialize the QueueData encoding
		rsslClearRDMQueueData(&queueData);
		queueData.rdmMsgBase.streamId = QUEUE_MSG_STREAM_ID;
		queueData.identifier = ++pQueueMsgHandler->identifier;
		queueData.rdmMsgBase.domainType = QUEUE_MSG_DOMAIN;
		queueData.sourceName = pQueueMsgHandler->sourceName;
		queueData.destName = pQueueMsgHandler->destNames[i];
		queueData.timeout = RDM_QMSG_TC_INFINITE;
		queueData.containerType = RSSL_DT_FIELD_LIST;

		rsslClearEncodeIterator(&eIter);
		rsslSetEncodeIteratorRWFVersion(&eIter, pTunnelStream->classOfService.common.protocolMajorVersion, 
				pTunnelStream->classOfService.common.protocolMinorVersion);
		rsslSetEncodeIteratorBuffer(&eIter, pBuffer);

		if ((ret = rsslEncodeRDMQueueMsgInit(&eIter, (RsslRDMQueueMsg*)&queueData, &rsslErrorInfo)) != RSSL_RET_ENCODE_CONTAINER)
		{
			printf("rsslEncodeRDMQueueMsgInit(): Failed <%s>\n", rsslErrorInfo.rsslError.text);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		//// Start Content Encoding ////
		rsslClearFieldList(&fieldList);
		fieldList.flags = RSSL_FLF_HAS_STANDARD_DATA;
		if ((ret = rsslEncodeFieldListInit(&eIter, &fieldList, NULL, 0)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldListInit(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* MsgType */
		rsslClearFieldEntry(&fieldEntry);
		rsslClearBuffer(&fieldBuffer);
		fieldEntry.fieldId = 35;
		fieldEntry.dataType = RSSL_DT_BUFFER;
		fieldBuffer.length = 1;
		fieldBuffer.data = (char*)"D";  // D for new single order
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* ClOrderId */
		rsslClearFieldEntry(&fieldEntry);
		rsslClearBuffer(&fieldBuffer);
		fieldEntry.fieldId = 11;
		fieldEntry.dataType = RSSL_DT_BUFFER;
		fieldBuffer.length = 12;
		fieldBuffer.data = (char*)"100000020998";
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* Account */
		rsslClearFieldEntry(&fieldEntry);
		rsslClearBuffer(&fieldBuffer);
		fieldEntry.fieldId = 1;
		fieldEntry.dataType = RSSL_DT_BUFFER;
		fieldBuffer.length = 10;
		fieldBuffer.data = (char*)"D6789-3456";
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* Handle instruction */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 21;
		fieldEntry.dataType = RSSL_DT_ENUM;
		
		enumVal = 1;  // 1 = automated, 2 = semi automated, 3 = manual
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &enumVal)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* Symbol */
		rsslClearFieldEntry(&fieldEntry);
		rsslClearBuffer(&fieldBuffer);
		fieldEntry.fieldId = 55;
		fieldEntry.dataType = RSSL_DT_BUFFER;
		fieldBuffer.length = 3;
		fieldBuffer.data = (char*)"TRI";
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* Side */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 54;
		fieldEntry.dataType = RSSL_DT_ENUM;
		
		enumVal = 1;  // 1 for Buy
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &enumVal)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* TransactTime */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 60;
		fieldEntry.dataType = RSSL_DT_DATETIME;

		if ((ret = rsslDateTimeGmtTime(&dateTime)) != RSSL_RET_SUCCESS)
		{
			printf("rsslDateTimeGmtTime(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &dateTime)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* OrderQty */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 38;
		fieldEntry.dataType = RSSL_DT_UINT;
		uintVal = 1000;
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &uintVal)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		/* OrderType */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 40;
		fieldEntry.dataType = RSSL_DT_ENUM;		
		enumVal = 1;  // 2 for Limit Order
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &enumVal)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}
		
		
		/* Price */
		rsslClearFieldEntry(&fieldEntry);
		fieldEntry.fieldId = 44;
		fieldEntry.dataType = RSSL_DT_REAL;		
		rsslClearReal(&real);
		real.value = 3835;    //38.35
		real.hint = RSSL_RH_EXPONENT_2;
		if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &real)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}


		if ((ret = rsslEncodeFieldListComplete(&eIter, RSSL_TRUE)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeFieldListComplete(): Failed <%d>\n", ret);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}
        //// End Content Encoding ////

		// complete the QueueData encoding
		if ((ret = rsslEncodeRDMQueueMsgComplete(&eIter, RSSL_TRUE, &pBuffer->length, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
		{
			printf("rsslEncodeRDMQueueMsgComplete(): Failed <%s>\n", rsslErrorInfo.rsslError.text);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		// submit the encoded data buffer of QueueData to the tunnel stream
		rsslClearTunnelStreamSubmitOptions(&submitOpts);
		submitOpts.containerType = RSSL_DT_MSG;
		if ((ret = rsslTunnelStreamSubmit(pQueueMsgHandler->tunnelStreamHandler.pTunnelStream, pBuffer, &submitOpts, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
		{
			printf("rsslTunnelStreamSubmit(): Failed <%s>\n", rsslErrorInfo.rsslError.text);
			if ((ret2 = rsslTunnelStreamReleaseBuffer(pBuffer, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
				printf("rsslTunnelStreamReleaseBuffer(): Failed <%d:%s>\n", ret2, rsslErrorInfo.rsslError.text);
			return;
		}

		printf("Submitted Single Order message with ID %lld to %.*s.\n\n", pQueueMsgHandler->identifier, pQueueMsgHandler->destNames[i].length, pQueueMsgHandler->destNames[i].data);
	}
}
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; 
}
static void simpleTunnelMsgHandlerSendMessage(SimpleTunnelMsgHandler *pSimpleTunnelMsgHandler)
{
	RsslTunnelStream *pTunnelStream = pSimpleTunnelMsgHandler->tunnelStreamHandler.pTunnelStream;
	RsslReactorChannel *pReactorChannel = pTunnelStream->pReactorChannel;

	RsslTunnelStreamSubmitOptions submitOpts;
	RsslTunnelStreamGetBufferOptions bufferOpts;
	RsslEncodeIterator eIter;
	RsslBuffer *pBuffer;
	RsslRet ret, ret2;
	RsslErrorInfo errorInfo;
	RsslInt32 pos;

	for ( pos = 0; pos < MAX_STREAMID; ++pos )
	{
		if ( !_domainType[pos] ) continue;

		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);
			return;
		}

		rsslClearEncodeIterator(&eIter);
		rsslSetEncodeIteratorRWFVersion(&eIter, pTunnelStream->classOfService.common.protocolMajorVersion,
				pTunnelStream->classOfService.common.protocolMinorVersion);
		rsslSetEncodeIteratorBuffer(&eIter, pBuffer);

		switch ( _msgClass[pos] )
		{
		case RSSL_MC_REFRESH :
			encodeRefreshMsg( _domainType[pos], pos, pBuffer );
			_msgClass[pos] = RSSL_MC_UPDATE;
			break;
		case RSSL_MC_UPDATE :
			encodeUpdateMsg( _domainType[pos], pos, pBuffer );
			if ( ++_updateCount[pos] > 10 )
			{
				_msgClass[pos] = RSSL_MC_STATUS;
				_updateCount[pos] = 0;
			}
			break;
		case RSSL_MC_STATUS :
			encodeStatusMsg( _domainType[pos], pos, pBuffer );
			_domainType[pos] = 0;
			break;
		default :
			continue;
		}

		/* 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);
			return;
		}

		++pSimpleTunnelMsgHandler->msgCount;
	}
}