void queueMsgHandlerInit(QueueMsgHandler *pQueueMsgHandler, char *consumerName, RsslUInt8 domainType,
		RsslBool useAuthentication)
{
	int i;
	tunnelStreamHandlerInit(&pQueueMsgHandler->tunnelStreamHandler,
			consumerName, domainType, useAuthentication, RSSL_TRUE /* Queue messaging */,
			queueMsgHandlerProcessTunnelOpened,
			queueMsgHandlerProcessTunnelClosed,
			queueMsgHandlerDefaultMsgCallback,
			queueMsgHandlerQueueMsgCallback);

	rsslClearBuffer(&pQueueMsgHandler->sourceName);
	for (i = 0; i < MAX_DEST_NAMES; ++i)
		rsslClearBuffer(&pQueueMsgHandler->destNames[i]);
	pQueueMsgHandler->destNameCount = 0;
	pQueueMsgHandler->isQueueStreamOpen = RSSL_FALSE;
	pQueueMsgHandler->identifier = 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);
	}
}
/*
 * Encode and send a queue message ACK through the ReactorChannel.
 * This message will contain an field list as its payload.
 */
static void ackQueueMsg(QueueMsgHandler *pQueueMsgHandler, RsslBuffer *pDestName, RsslInt32 streamId)
{
	RsslRet ret;
	RsslErrorInfo rsslErrorInfo;
	RsslEnum enumVal;
	RsslUInt uIntVal;
	RsslReal realVal;
	RsslTunnelStreamSubmitMsgOptions submitMsgOpts;
	RsslRDMQueueData queueData;
	RsslEncodeIterator eIter;
	RsslFieldList fieldList;
	RsslFieldEntry fieldEntry;
	RsslBuffer fieldBuffer;
	RsslBuffer ackBuffer;
	char ackBufferMemory[1024];
	RsslTunnelStream *pTunnelStream = pQueueMsgHandler->tunnelStreamHandler.pTunnelStream;

	ackBuffer.data = ackBufferMemory;
	ackBuffer.length = sizeof(ackBufferMemory);

    // encode content into ackBuffer
	rsslClearEncodeIterator(&eIter);
	rsslSetEncodeIteratorRWFVersion(&eIter, pTunnelStream->classOfService.common.protocolMajorVersion, 
			pTunnelStream->classOfService.common.protocolMajorVersion);
	rsslSetEncodeIteratorBuffer(&eIter, &ackBuffer);

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

	/* MsgType */
	rsslClearFieldEntry(&fieldEntry);
	rsslClearBuffer(&fieldBuffer);
	fieldEntry.fieldId = 35;
	fieldEntry.dataType = RSSL_DT_BUFFER;
	fieldBuffer.length = 1;
	fieldBuffer.data = (char*)"8";  // 8 for execution report
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		return;
	}

	/* OrderId */
	rsslClearFieldEntry(&fieldEntry);
	rsslClearBuffer(&fieldBuffer);
	fieldEntry.fieldId = 37;
	fieldEntry.dataType = RSSL_DT_BUFFER;
	fieldBuffer.length = 18;
	fieldBuffer.data = (char*)"BATS-3456789-98765";
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		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);
		return;
	}

	/* ExecID */
	rsslClearFieldEntry(&fieldEntry);
	rsslClearBuffer(&fieldBuffer);
	fieldEntry.fieldId = 17;
	fieldEntry.dataType = RSSL_DT_BUFFER;
	fieldBuffer.length = 10;
	fieldBuffer.data = (char*)"7654689076";
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &fieldBuffer)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		return;
	}

	/* ExecType */
	rsslClearFieldEntry(&fieldEntry);
	fieldEntry.fieldId = 150;
	fieldEntry.dataType = RSSL_DT_ENUM;
	enumVal = 0;  // 0 for New, 1 for partial fill, 2 for fill, 3 for Done
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &enumVal)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		return;
	}

	/* Order Status */
	rsslClearFieldEntry(&fieldEntry);
	fieldEntry.fieldId = 39;
	fieldEntry.dataType = RSSL_DT_ENUM;
	enumVal = 0;  // 0 for new, 1 for partial fill, 2 for fill, 3 for done
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &enumVal)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		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);
		return;
	}
	
	/* LeavesQty */
	rsslClearFieldEntry(&fieldEntry);
	fieldEntry.fieldId = 151;
	fieldEntry.dataType = RSSL_DT_UINT;
	uIntVal = 1000;  
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &uIntVal)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		return;
	}
	
	/* CumQty */
	rsslClearFieldEntry(&fieldEntry);
	fieldEntry.fieldId = 14;
	fieldEntry.dataType = RSSL_DT_UINT;
	uIntVal = 0;  
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &uIntVal)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		return;
	}

	/* AvgPx */
	rsslClearFieldEntry(&fieldEntry);
	fieldEntry.fieldId = 6;
	fieldEntry.dataType = RSSL_DT_REAL;
	rsslClearReal(&realVal);
	realVal.value = 0;  
	realVal.hint = RSSL_RH_EXPONENT0;
	if ((ret = rsslEncodeFieldEntry(&eIter, &fieldEntry, &realVal)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldEntry(): Failed <%d>\n", ret);
		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);
		return;
	}
	
	if ((ret = rsslEncodeFieldListComplete(&eIter, RSSL_TRUE)) != RSSL_RET_SUCCESS)
	{
		printf("rsslEncodeFieldListComplete(): Failed <%d>\n", ret);
		return;
	}
    //// End Content Encoding ////

	// set ackBuffer encoded length
	ackBuffer.length = rsslGetEncodedBufferLength(&eIter);

    // initialize the QueueData with the ackBuffer set as the encodedDataBody
	rsslClearRDMQueueData(&queueData);
	queueData.rdmMsgBase.streamId = streamId;
	queueData.identifier = ++pQueueMsgHandler->identifier;
	queueData.rdmMsgBase.domainType = QUEUE_MSG_DOMAIN;
	queueData.sourceName = pQueueMsgHandler->sourceName;
	queueData.destName = *pDestName;
	queueData.timeout = RDM_QMSG_TC_INFINITE;
	queueData.containerType = RSSL_DT_FIELD_LIST;
	queueData.encDataBody = ackBuffer;

	// submit QueueData message with the encodedDataBody to the tunnel stream
	rsslClearTunnelStreamSubmitMsgOptions(&submitMsgOpts);
	submitMsgOpts.pRDMMsg = (RsslRDMMsg *)&queueData;
	if ((ret = rsslTunnelStreamSubmitMsg(pQueueMsgHandler->tunnelStreamHandler.pTunnelStream, &submitMsgOpts, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
	{
		printf("rsslTunnelStreamSubmitMsg(): Failed <%s>\n", rsslErrorInfo.rsslError.text);
		return;
	}

	printf("Submitted Exec Report message with ID %lld to %.*s.\n\n", pQueueMsgHandler->identifier, pDestName->length, pDestName->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; 
}