예제 #1
0
RsslRet RTR_C_INLINE decodePayload(RsslDecodeIterator* dIter, RsslMsg *msg, ProviderThread* pProviderThread)
{
	RsslRet ret;
	RsslErrorInfo errorInfo;

	switch(msg->msgBase.domainType)
	{
		case RSSL_DMT_MARKET_PRICE:
			if ((ret = decodeMPUpdate(dIter, msg, pProviderThread)) != RSSL_RET_SUCCESS)
			{
				rsslSetErrorInfo(&errorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
						(char*)"decodeMPUpdate() failed: %d(%s)", ret, rsslRetCodeToString(ret));
				return ret;
			}
			return RSSL_RET_SUCCESS;
		case RSSL_DMT_MARKET_BY_ORDER:
			if ((ret = decodeMBOUpdate(dIter, msg, pProviderThread) != RSSL_RET_SUCCESS))
			{
				rsslSetErrorInfo(&errorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
						(char*)"decodeMBOUpdate() failed: %d(%s)", ret, rsslRetCodeToString(ret));
				return ret;
			}
			return RSSL_RET_SUCCESS;
		default:
			rsslSetErrorInfo(&errorInfo, RSSL_EIC_FAILURE, RSSL_RET_FAILURE, __FILE__, __LINE__,
					(char*)"decodePayload(): Unhandled domain type %s(%d)", 
					rsslDomainTypeToString(msg->msgBase.domainType), msg->msgBase.domainType);
			return RSSL_RET_FAILURE;
	}
}
예제 #2
0
RsslReactorCallbackRet queueMsgHandlerDefaultMsgCallback(RsslTunnelStream *pTunnelStream, RsslTunnelStreamMsgEvent *pEvent)
{
	RsslMsg *pRsslMsg = pEvent->pRsslMsg;

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

	return RSSL_RC_CRET_SUCCESS; 
}
예제 #3
0
static RsslRet processSymbolListResponse(SnapshotSession* pSession, RsslMsg* msg, RsslDecodeIterator* dIter)
{
	RsslRet ret = 0;

	RsslMsgKey* key = 0;
	RsslMap rsslMap;
	RsslMapEntry mapEntry;
	RsslVector rsslVector;
	RsslVectorEntry vectorEntry;
	char tempData[1024];
	char mapKeyData[32];
	RsslBuffer tempBuffer;
	RsslBuffer fidBufferValue;
	RsslLocalFieldSetDefDb fieldSetDefDb;
	RsslLocalElementSetDefDb elemSetDefDb;
	RsslElementList elemList;
	RsslElementEntry elemEntry;
	RsslFieldEntry fieldEntry;
	RsslFieldList fieldList;
	RsslBuffer stringBuf;
	char data[24];

	tempBuffer.data = tempData;
	tempBuffer.length = 1024;

	switch(msg->msgBase.msgClass)
	{
	case RSSL_MC_REFRESH:

		printf("\n<%s> Received symbol list refresh.\n\n", pSession->name);
	case RSSL_MC_UPDATE:

		/* decode symbol list response */
		/* get key*/
		key = (RsslMsgKey *)rsslGetMsgKey(msg);

		if(msg->msgBase.msgClass == RSSL_MC_REFRESH)
		{
			rsslStateToString(&tempBuffer, &msg->refreshMsg.state);
			printf("%.*s\n", tempBuffer.length, tempBuffer.data);
		}

		rsslClearMap(&rsslMap);

		if ((ret = rsslDecodeMap(dIter, &rsslMap)) != RSSL_RET_SUCCESS)
		{
			printf("<%s> rsslDecodeMap() failed with return code: %d\n", pSession->name, ret);
			return RSSL_RET_FAILURE;
		}

		if (rsslMap.flags & RSSL_MPF_HAS_SET_DEFS)
		{
			/* must ensure it is the correct type - if map contents are element list, this is a field set definition db */
			if (rsslMap.containerType == RSSL_DT_FIELD_LIST)
			{
				rsslClearLocalFieldSetDefDb(&fieldSetDefDb);
				if ((ret = rsslDecodeLocalFieldSetDefDb(dIter, &fieldSetDefDb)) < RSSL_RET_SUCCESS)
				{
					/* decoding failures tend to be unrecoverable */
					printf("<%s> Error %s (%d) encountered with rsslDecodeLocalElementSetDefDb().  Error Text: %s\n",
						pSession->name,
						rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
					return ret;
				}
			}
		}

		/* decode the map */
		while ((ret = rsslDecodeMapEntry(dIter, &mapEntry, mapKeyData)) != RSSL_RET_END_OF_CONTAINER)
		{
			if(ret != RSSL_RET_SUCCESS)
			{
				printf("<%s> rsslDecodeMapEntry() failed with return code: %d\n", pSession->name, ret);
				return RSSL_RET_FAILURE;
			}

			stringBuf.data = data;
			stringBuf.length = 24;
			rsslPrimitiveToString(&mapKeyData,rsslMap.keyPrimitiveType,&stringBuf);

			printf("\nID: %s, ", stringBuf.data);
			pSession->symbolListEntry[SymbolListCounter] = (SymbolListEntry*)malloc(sizeof(SymbolListEntry));
			pSession->symbolListEntry[SymbolListCounter]->id = atoi(stringBuf.data);

			if ((ret = rsslDecodeFieldList(dIter, &fieldList, &fieldSetDefDb)) != RSSL_RET_SUCCESS)
			{
				printf("<%s> rsslDecodeMap() failed with return code: %d\n", pSession->name, ret);
				return RSSL_RET_FAILURE;
			}


			/* The following fields are needed to uniquely identify a symbol on the realtime and gap fill streams:
			FID		Name						Type
			3422	Provider Symbol				RMTES_STRING
			8746	Provider Symbol 2			RMTES_STRING
			32639	Multicast channel(RT)		Vector of Element Lists
			32640	Multicast Channel(Gapfill)	Vector of Element Lists
			*/


			while ((ret = rsslDecodeFieldEntry(dIter, &fieldEntry)) != RSSL_RET_END_OF_CONTAINER)
			{
				if (ret != RSSL_RET_SUCCESS)
				{
					printf("<%s> rsslDecodeFieldEntry() failed with return code: %d\n", pSession->name, ret);
					return RSSL_RET_FAILURE;
				}

				if(fieldEntry.fieldId == 8746)
				{
					if ((ret = rsslDecodeBuffer(dIter, &fidBufferValue)) == RSSL_RET_SUCCESS)
					{
						//snprintf(&pSession->symbolListEntry[SymbolListCounter]->name[0], 128, "%.*s", fidBufferValue.length, fidBufferValue.data);
						printf("SYMBOL2: %s", fidBufferValue.data);
					}
					else if (ret != RSSL_RET_BLANK_DATA)
					{
						printf("<%s> Error: %s (%d) encountered with rsslDecodeBuffer(). Error Text: %s\n",
							pSession->name,
							rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
						return ret;
					}
				}
				else if (fieldEntry.fieldId == 3422)
				{
					if ((ret = rsslDecodeBuffer(dIter, &fidBufferValue)) == RSSL_RET_SUCCESS)
					{
						snprintf(&pSession->symbolListEntry[SymbolListCounter]->name[0], 128, "%.*s", fidBufferValue.length, fidBufferValue.data);
						printf("SYMBOL: %s", pSession->symbolListEntry[SymbolListCounter]->name);
					}
					else if (ret != RSSL_RET_BLANK_DATA)
					{
						printf("<%s> Error: %s (%d) encountered with rsslDecodeBuffer(). Error Text: %s\n",
							pSession->name,
							rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
						return ret;
					}
				}
				else if (fieldEntry.fieldId == 32639)
				{

					int countStreamingChan = 0;

					rsslClearVector(&rsslVector);
					if ((ret = rsslDecodeVector(dIter, &rsslVector)) != RSSL_RET_SUCCESS)
					{
						printf("<%s> rsslDecodeVector() failed with return code: %d\n", pSession->name, ret);
						return RSSL_RET_FAILURE;
					}

					if (rsslVector.flags & RSSL_VTF_HAS_SET_DEFS)
					{
						/* must ensure it is the correct type - if map contents are element list, this is a field set definition db */
						if (rsslVector.containerType == RSSL_DT_ELEMENT_LIST)
						{
							rsslClearLocalElementSetDefDb(&elemSetDefDb);
							if ((ret = rsslDecodeLocalElementSetDefDb(dIter, &elemSetDefDb)) < RSSL_RET_SUCCESS)
							{
								/* decoding failures tend to be unrecoverable */
								printf("<%s> Error %s (%d) encountered with rsslDecodeLocalElementSetDefDb().  Error Text: %s\n",
									pSession->name,
									rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
								return ret;
							}
						}
					}

					/* decode the vector */
					while ((ret = rsslDecodeVectorEntry(dIter, &vectorEntry)) != RSSL_RET_END_OF_CONTAINER)
					{
						if(ret != RSSL_RET_SUCCESS)
						{
							printf("<%s> rsslDecodeVectorEntry() failed with return code: %d\n", pSession->name, ret);
							return RSSL_RET_FAILURE;
						}

						rsslClearElementList(&elemList);
						if ((ret = rsslDecodeElementList(dIter, &elemList, &elemSetDefDb)) != RSSL_RET_SUCCESS)
						{
							printf("<%s> rsslDecodeElementList() failed with return code: %d\n", pSession->name, ret);
							return RSSL_RET_FAILURE;
						}

						while ((ret = rsslDecodeElementEntry(dIter, &elemEntry)) != RSSL_RET_END_OF_CONTAINER)
						{
							if (ret != RSSL_RET_SUCCESS)
							{
								printf("<%s> rsslDecodeElementEntry() failed with return code: %d\n", pSession->name, ret);
								return RSSL_RET_FAILURE;
							}

							if (rsslBufferIsEqual(&elemEntry.name, &RSSL_ENAME_CHANNEL_ID))
							{
								if ((ret = rsslDecodeUInt(dIter, &pSession->symbolListEntry[SymbolListCounter]->streamingChannels[countStreamingChan].channelId)) == RSSL_RET_SUCCESS)
								{	
									printf(" StreamingChanId: %d", pSession->symbolListEntry[SymbolListCounter]->streamingChannels[countStreamingChan].channelId);
								}
								else
								{
									printf("<%s> Error: %s (%d) encountered with rsslDecodeUInt(). Error Text: %s\n",
										pSession->name,
										rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
									return ret;
								}
							}
							else if (rsslBufferIsEqual(&elemEntry.name, &RSSL_ENAME_DOMAIN))
							{
								if ((ret = rsslDecodeUInt(dIter, &pSession->symbolListEntry[SymbolListCounter]->streamingChannels[countStreamingChan].domain)) == RSSL_RET_SUCCESS)
								{	
									printf(" StreamingChanDom: %d", pSession->symbolListEntry[SymbolListCounter]->streamingChannels[countStreamingChan].domain);
								}
								else
								{
									printf("<%s> Error: %s (%d) encountered with rsslDecodeUInt(). Error Text: %s\n",
										pSession->name,
										rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
									return ret;
								}
							}

						}
						countStreamingChan++;

					}
				}
				else if (fieldEntry.fieldId == 32640)
				{
					int countGapChan = 0;

					rsslClearVector(&rsslVector);
					if ((ret = rsslDecodeVector(dIter, &rsslVector)) != RSSL_RET_SUCCESS)
					{
						printf("<%s> rsslDecodeVector() failed with return code: %d\n", pSession->name, ret);
						return RSSL_RET_FAILURE;
					}

					if (rsslVector.flags & RSSL_VTF_HAS_SET_DEFS)
					{
						/* must ensure it is the correct type - if map contents are element list, this is a field set definition db */
						if (rsslVector.containerType == RSSL_DT_ELEMENT_LIST)
						{
							rsslClearLocalElementSetDefDb(&elemSetDefDb);
							if ((ret = rsslDecodeLocalElementSetDefDb(dIter, &elemSetDefDb)) < RSSL_RET_SUCCESS)
							{
								/* decoding failures tend to be unrecoverable */
								printf("<%s> Error %s (%d) encountered with rsslDecodeLocalElementSetDefDb().  Error Text: %s\n",
									pSession->name,
									rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
								return ret;
							}

						}
					}

					/* decode the vector */
					while ((ret = rsslDecodeVectorEntry(dIter, &vectorEntry)) != RSSL_RET_END_OF_CONTAINER)
					{
						if(ret != RSSL_RET_SUCCESS)
						{
							printf("<%s> rsslDecodeVectorEntry() failed with return code: %d\n", pSession->name, ret);
							return RSSL_RET_FAILURE;
						}

						rsslClearElementList(&elemList);
						if ((ret = rsslDecodeElementList(dIter, &elemList, &elemSetDefDb)) != RSSL_RET_SUCCESS)
						{
							printf("<%s> rsslDecodeElementList() failed with return code: %d\n", pSession->name, ret);
							return RSSL_RET_FAILURE;
						}

						while ((ret = rsslDecodeElementEntry(dIter, &elemEntry)) != RSSL_RET_END_OF_CONTAINER)
						{
							if (ret != RSSL_RET_SUCCESS)
							{
								printf("<%s> rsslDecodeElementEntry() failed with return code: %d\n", pSession->name, ret);
								return RSSL_RET_FAILURE;
							}
							if (rsslBufferIsEqual(&elemEntry.name, &RSSL_ENAME_CHANNEL_ID))
							{
								if ((ret = rsslDecodeUInt(dIter, &pSession->symbolListEntry[SymbolListCounter]->gapChannels[countGapChan].channelId)) == RSSL_RET_SUCCESS)
								{	
									printf(" GapChanId: %d", pSession->symbolListEntry[SymbolListCounter]->gapChannels[countGapChan].channelId);
								}
								else
								{
									printf("<%s> Error: %s (%d) encountered with rsslDecodeUInt(). Error Text: %s\n",
										pSession->name,
										rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
									return ret;
								}
							}
							else if (rsslBufferIsEqual(&elemEntry.name, &RSSL_ENAME_DOMAIN))
							{
								if ((ret = rsslDecodeUInt(dIter, &pSession->symbolListEntry[SymbolListCounter]->gapChannels[countGapChan].domain)) == RSSL_RET_SUCCESS)
								{	
									printf(" GapChanlDom: %d", pSession->symbolListEntry[SymbolListCounter]->gapChannels[countGapChan].domain);
								}
								else
								{
									printf("<%s> Error: %s (%d) encountered with rsslDecodeUInt(). Error Text: %s\n",
										pSession->name,
										rsslRetCodeToString(ret), ret, rsslRetCodeInfo(ret));
									return ret;
								}
							}
						}
					}
					countGapChan++;
				}
			}
			SymbolListCounter++;
		}



		break;

	case RSSL_MC_STATUS:
		printf("\n<%s> Received Item StatusMsg for stream %i \n", pSession->name, msg->statusMsg.msgBase.streamId);
		if (msg->statusMsg.flags & RSSL_STMF_HAS_STATE)
		{
			rsslStateToString(&tempBuffer, &msg->statusMsg.state);
			printf("        %.*s\n\n", tempBuffer.length, tempBuffer.data);
		}

		break;

	case RSSL_MC_ACK:
		/* although this application only posts on MP (Market Price), 
		* ACK handler is provided for other domains to allow user to extend 
		* and post on MBO (Market By Order), MBP (Market By Price), SymbolList, and Yield Curve domains */
		printf("\n<%s> Received AckMsg for stream %i \n", pSession->name, msg->msgBase.streamId);

		/* get key */
		key = (RsslMsgKey *)rsslGetMsgKey(msg);

		/* print out item name from key if it has it */
		if (key)
		{
			printf("%.*s\nDOMAIN: %s\n", key->name.length, key->name.data, rsslDomainTypeToString(msg->msgBase.domainType));
		}
		printf("\tackId=%u\n", msg->ackMsg.ackId);
		if (msg->ackMsg.flags & RSSL_AKMF_HAS_SEQ_NUM)
			printf("\tseqNum=%u\n", msg->ackMsg.seqNum);
		if (msg->ackMsg.flags & RSSL_AKMF_HAS_NAK_CODE)
			printf("\tnakCode=%u\n", msg->ackMsg.nakCode);
		if (msg->ackMsg.flags & RSSL_AKMF_HAS_TEXT)
			printf("\ttext=%.*s\n", msg->ackMsg.text.length, msg->ackMsg.text.data);

		break;

	default:
		printf("\n<%s> Recieved Unhandled Item Msg Class: %d\n", pSession->name, msg->msgBase.msgClass);
		break;
	}

	return RSSL_RET_SUCCESS;
}
예제 #4
0
RsslRet snapshotSessionRequestItems(SnapshotSession *pSession)
{
	RsslUInt32 i;
	RsslEncodeIterator encodeIter;
	RsslRequestMsg requestMsg;
	RsslBuffer *pBuffer;
	RsslError rsslError;
	RsslRet ret;

	for (i = 0; i < itemList.itemCount; ++i)
	{
		Item *pItem = &itemList.items[i];

		if (!(pBuffer = rsslGetBuffer(pSession->pRsslChannel, 128, RSSL_FALSE, &rsslError)))
		{
			printf("<%s> rsslGetBuffer() failed while sending item request: %d (%s -- %s).\n\n",
					pSession->name,
					rsslError.rsslErrorId, rsslRetCodeToString(rsslError.rsslErrorId), rsslError.text);
			return ret;
		}

		rsslClearRequestMsg(&requestMsg);
		requestMsg.flags = RSSL_RQMF_HAS_QOS;
		requestMsg.msgBase.streamId = pItem->snapshotServerStreamId;
		requestMsg.msgBase.domainType = pItem->domainType;
		requestMsg.msgBase.containerType = RSSL_DT_NO_DATA;
		requestMsg.qos.rate = RSSL_QOS_RATE_TICK_BY_TICK;
		requestMsg.qos.timeliness = RSSL_QOS_TIME_REALTIME;

		/* This system uses the real-time feed's stream ID as the name. */
		requestMsg.msgBase.msgKey.flags = RSSL_MKF_HAS_SERVICE_ID | RSSL_MKF_HAS_IDENTIFIER;
		requestMsg.msgBase.msgKey.identifier = pItem->feedStreamId;
		requestMsg.msgBase.msgKey.serviceId = exampleConfig.serviceId;

		rsslClearEncodeIterator(&encodeIter);
		rsslSetEncodeIteratorRWFVersion(&encodeIter, pSession->pRsslChannel->majorVersion,
				pSession->pRsslChannel->minorVersion);
		rsslSetEncodeIteratorBuffer(&encodeIter, pBuffer);
		if ((ret = rsslEncodeMsg(&encodeIter, (RsslMsg*)&requestMsg)) != RSSL_RET_SUCCESS)
		{
			printf("<%s> rsslEncodeMsg() failed while sending item request: %d (%s).\n\n",
					pSession->name,
					ret, rsslRetCodeToString(ret));
			rsslReleaseBuffer(pBuffer, &rsslError);
			return ret;
		}

		pBuffer->length = rsslGetEncodedBufferLength(&encodeIter);

		/* Write the message. */
		if ((ret = snapshotSessionWrite(pSession, pBuffer)) != RSSL_RET_SUCCESS)
			return ret;

		printf("<%s> Sent request for item %s, %s on stream %d.\n\n",
				pSession->name, pItem->symbolName,
				rsslDomainTypeToString(pItem->domainType), pItem->snapshotServerStreamId);

	}

	return RSSL_RET_SUCCESS;
}
예제 #5
0
static RsslRet snapshotSessionProcessMessage(SnapshotSession *pSession, RsslBuffer *pBuffer)
{
	RsslDecodeIterator decodeIter;
	RsslRet ret;
	RsslErrorInfo rsslErrorInfo;
	RsslMsg rsslMsg;
	char tempMem[1024];
	RsslBuffer tempBuffer;
	Item *pItem;

	printf("<%s> Received message:\n", pSession->name);

	/* Decode the message header. */
	rsslClearDecodeIterator(&decodeIter);
	rsslSetDecodeIteratorRWFVersion(&decodeIter, pSession->pRsslChannel->majorVersion,
			pSession->pRsslChannel->minorVersion);
	rsslSetDecodeIteratorBuffer(&decodeIter, pBuffer);
	if ((ret = rsslDecodeMsg(&decodeIter, &rsslMsg)) != RSSL_RET_SUCCESS)
	{
		printf("<%s> rsslDecodeMsg() failed: %d(%s).\n\n", 
				pSession->name, ret, rsslRetCodeToString(ret));
		return ret;
	}

	switch(rsslMsg.msgBase.domainType)
	{
		case RSSL_DMT_LOGIN:
		{
			/* Decode the message using the RDM package decoder utility. */
			RsslRDMLoginMsg loginMsg;

			tempBuffer.data = tempMem;
			tempBuffer.length = sizeof(tempMem);

			if ((ret = rsslDecodeRDMLoginMsg(&decodeIter, &rsslMsg, &loginMsg, &tempBuffer, 
							&rsslErrorInfo)) != RSSL_RET_SUCCESS)
			{
				printf(	"<%s> rsslDecodeRDMLoginMsg() failed: %d (%s -- %s)\n"
						"  at %s.\n\n",
						pSession->name,
						ret, rsslRetCodeToString(ret), rsslErrorInfo.rsslError.text,
						rsslErrorInfo.errorLocation);
				return ret;
			}

			switch(loginMsg.rdmMsgBase.rdmMsgType)
			{
				case RDM_LG_MT_REFRESH:
					printf("<%s> Received login refresh.\n\n",
							pSession->name,
							ret, rsslRetCodeToString(ret), rsslErrorInfo.rsslError.text);

					if (pSession->state == SNAPSHOT_STATE_LOGIN_REQUESTED)
					{
						if (snapshotSessionSendSymbolListRequest(pSession) != RSSL_RET_SUCCESS)
							return ret;
					}

					break;

				default:
					printf("<%s> Received unhandled RDM Login Message Type %d.\n\n",
							pSession->name, loginMsg.rdmMsgBase.rdmMsgType);
					return RSSL_RET_FAILURE;
			}
			return RSSL_RET_SUCCESS;
		}

		case RSSL_DMT_SYMBOL_LIST:
		{
			processSymbolListResponse(pSession, &rsslMsg, &decodeIter);

			if (rsslMsg.refreshMsg.flags & RSSL_RFMF_REFRESH_COMPLETE)
			{
				pSession->state = SNAPSHOT_STATE_SYMBOL_LIST_RECEIVED;
			}
		}
		break;

		default:
		{
			if ((pItem = itemListGetItemBySnapStreamID(&itemList, rsslMsg.msgBase.streamId, rsslMsg.msgBase.domainType))
					== NULL)
			{
				printf("<%s> Received unhandled message with snapshot stream ID %d, and domain %d(%s).\n\n",
						pSession->name,
						rsslMsg.msgBase.streamId,
						rsslMsg.msgBase.domainType,
						rsslDomainTypeToString(rsslMsg.msgBase.domainType));

				return RSSL_RET_SUCCESS;
			}

			return itemProcessMsg(pItem, &decodeIter, &rsslMsg, RSSL_TRUE);
		}

	}

	return RSSL_RET_SUCCESS;
}
예제 #6
0
static RsslRet sendItemRequestReject(ProviderThread *pProvThread, ProviderSession* pProvSession, RsslInt32 streamId, RsslUInt8 domainType, ItemRejectReason reason)
{
	RsslRet ret;

	if ((ret = getItemMsgBuffer(pProvThread, pProvSession, 128) < RSSL_RET_SUCCESS))
		return ret;

	/* encode request reject status */
	if ((ret = encodeItemRequestReject(pProvSession->pChannelInfo->pChannel, streamId, reason, pProvSession->pWritingBuffer, domainType)) < RSSL_RET_SUCCESS)
	{
		printf("\nencodeItemRequestReject() failed: %d\n", ret);
		return RSSL_RET_FAILURE;
	}

	printf("\nRejecting Item Request with streamId=%d and domain %s.  Reason: %s\n", streamId,  rsslDomainTypeToString(domainType), itemRejectReasonToString(reason));

	/* send request reject status */
	return sendItemMsgBuffer(pProvThread, pProvSession, RSSL_TRUE);
}
/*
 * Processes a market price response.
 */
RsslRet processMarketPriceResponse(RsslMsg* msg, RsslDecodeIterator* dIter)
{
	RsslMsgKey* key = 0;
	RsslFieldList fList = RSSL_INIT_FIELD_LIST;
	RsslFieldEntry fEntry = RSSL_INIT_FIELD_ENTRY;
	RsslRet ret = 0;
	char tempData[1024];
	RsslBuffer tempBuffer;
	RsslBool isBatchRequest = RSSL_FALSE;
	
	tempBuffer.data = tempData;
	tempBuffer.length = 1024;

	switch(msg->msgBase.msgClass)
	{
		case RSSL_MC_REFRESH:
			printf("Received RefreshMsg for stream %i\n", msg->refreshMsg.msgBase.streamId);

			if (msg->refreshMsg.flags & RSSL_RFMF_HAS_SEQ_NUM)
				printf("SEQ. NO.: %u\n", msg->refreshMsg.seqNum);

			/* process just like update */
		case RSSL_MC_UPDATE:
			/* decode market price response */
			
			/* get key */
			key = (RsslMsgKey *)rsslGetMsgKey(msg);

			/* print out item name from key if it has it */
			if (key)
			{
				printf("%.*s\n", key->name.length, key->name.data);
			}
			if (msg->msgBase.msgClass == RSSL_MC_UPDATE)
			{
				printf("Received UpdateMsg for stream %i\n", msg->updateMsg.msgBase.streamId);
				/* When displaying update information, we should also display the updateType information. */
				printf("UPDATE TYPE: %u\n", msg->updateMsg.updateType);	

				if (msg->updateMsg.flags & RSSL_UPMF_HAS_SEQ_NUM)
					printf("SEQ. NO.: %u\n", msg->updateMsg.seqNum);
			}
			printf("DOMAIN: %s\n", rsslDomainTypeToString(msg->msgBase.domainType));

			if (msg->msgBase.msgClass == RSSL_MC_REFRESH)
			{
				rsslStateToString(&tempBuffer, &msg->refreshMsg.state);
				printf("%.*s\n", tempBuffer.length, tempBuffer.data);
			}

			/* decode field list */
			if ((ret = rsslDecodeFieldList(dIter, &fList, 0)) == RSSL_RET_SUCCESS)
			{
				/* decode each field entry in list */
				while ((ret = rsslDecodeFieldEntry(dIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER)
				{
					if (ret == RSSL_RET_SUCCESS)
					{
						if ((ret = decodeFieldEntry(&fEntry, dIter)) != RSSL_RET_SUCCESS)
						{
							return ret;
						}
					}
					else
					{
						printf("rsslDecodeFieldEntry() failed with return code: %d\n", ret);
						return RSSL_RET_FAILURE;
					}
				}
			}
			else
			{
				printf("rsslDecodeFieldList() failed with return code: %d\n", ret);
				return RSSL_RET_FAILURE;
			}
			break;
		case RSSL_MC_STATUS:
			if (msg->statusMsg.flags & RSSL_STMF_HAS_STATE)
    		{
				printf("Received StatusMsg for stream %i\n", msg->statusMsg.msgBase.streamId);
    			rsslStateToString(&tempBuffer, &msg->statusMsg.state);
				printf("	%.*s\n\n", tempBuffer.length, tempBuffer.data);
			}
			break;
		default:
			printf("\nReceived Unhandled Item Msg Class: %d\n", msg->msgBase.msgClass);
   			break;
	}

	return RSSL_RET_SUCCESS;
}
/*
 * Publically visable symbol list response handler 
 *
 * Processes a symbol list response.  This consists of extracting the
 * key, printing out the item name contained in the key, decoding the
 * map and map entries.
 * pReactor - RsslReactor associated with the application
 * pReactorChannel - The channel to get the symbol list response from
 * msg - The partially decoded message
 * dIter - The decode iterator
 */
RsslRet processSymbolListResponse(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslMsgEvent* pMsgEvent, RsslMsg* msg, RsslDecodeIterator* dIter)
{
	RsslRet ret = 0;

	RsslMsgKey* key = 0;
	RsslMap rsslMap = RSSL_INIT_MAP;
	RsslMapEntry mapEntry = RSSL_INIT_MAP_ENTRY;
	RsslBuffer mapKey = RSSL_INIT_BUFFER;
	char tempData[1024];
	RsslBuffer tempBuffer;
	ChannelCommand *pCommand = (ChannelCommand*)pReactorChannel->userSpecPtr;
	ItemRequest *pRequest = &pCommand->symbolListRequest;

	tempBuffer.data = tempData;
	tempBuffer.length = 1024;

	switch(msg->msgBase.msgClass)
	{
		case RSSL_MC_REFRESH:
			/* update our item state list if its a refresh, then process just like update */

			pRequest->itemState.dataState = msg->refreshMsg.state.dataState;
			pRequest->itemState.streamState = msg->refreshMsg.state.streamState;

			/* refresh continued - process just like update */

		case RSSL_MC_UPDATE:
			/* decode symbol list response */
			/* get key*/
			key = (RsslMsgKey *)rsslGetMsgKey(msg);

			/* Print descriptor of the channel this message was received from. */
			printf("\n(Channel %d): ", pReactorChannel->socketId);

			/* print the name of the symbolist and the domain */
			printf("\n%.*s\nDOMAIN: %s\n", pRequest->itemName.length, pRequest->itemName.data, rsslDomainTypeToString(msg->msgBase.domainType));
	
			if (msg->msgBase.msgClass == RSSL_MC_UPDATE)
			{
				/* When displaying update information, we should also display the updateType information. */
				printf("UPDATE TYPE: %u\n", msg->updateMsg.updateType);	
			}

			if(msg->msgBase.msgClass == RSSL_MC_REFRESH)
			{
				rsslStateToString(&tempBuffer, &msg->refreshMsg.state);
				printf("%.*s\n", tempBuffer.length, tempBuffer.data);
			}

			if ((ret = rsslDecodeMap(dIter, &rsslMap)) == RSSL_RET_SUCCESS)
			{
				/* decode the map */
				while ((ret = rsslDecodeMapEntry(dIter, &mapEntry, &mapKey)) != RSSL_RET_END_OF_CONTAINER)
				{
					if(ret == RSSL_RET_SUCCESS)
					{
						/* print the name and action for this symbol list entry */
						printf("%.*s\t%s\n", mapEntry.encKey.length, mapEntry.encKey.data, mapEntryActionToString(mapEntry.action));
					}
					else
					{
						printf("rsslDecodeMapEntry() failed with return code: %d\n", ret);
						return RSSL_RET_FAILURE;
					}
				}
			}
			else
			{
				printf("rsslDecodeMap() failed with return code: %d\n", ret);
				return RSSL_RET_FAILURE;
			}

			break;

		case RSSL_MC_STATUS:
			printf("\nReceived Item StatusMsg for stream %i \n", msg->statusMsg.msgBase.streamId);
			if (msg->statusMsg.flags & RSSL_STMF_HAS_STATE)
			{
				rsslStateToString(&tempBuffer, &msg->statusMsg.state);
				printf("	%.*s\n\n", tempBuffer.length, tempBuffer.data);

				/* update our state table for posting */
				pRequest->itemState.dataState = msg->statusMsg.state.dataState;
				pRequest->itemState.streamState = msg->statusMsg.state.streamState;
			}

			break;

		case RSSL_MC_ACK:
			/* although this application only posts on MP (Market Price), 
			   ACK handler is provided for other domains to allow user to extend 
			   and post on MBO (Market By Order), MBP (Market By Price), SymbolList, and Yield Curve domains */
			printf("\nReceived AckMsg for stream %i \n", msg->msgBase.streamId);

			/* get key */
			key = (RsslMsgKey *)rsslGetMsgKey(msg);

			/* print out item name from key if it has it */
			if (key)
			{
				printf("%.*s\nDOMAIN: %s\n", key->name.length, key->name.data, rsslDomainTypeToString(msg->msgBase.domainType));
			}
			printf("\tackId=%u\n", msg->ackMsg.ackId);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_SEQ_NUM)
				printf("\tseqNum=%u\n", msg->ackMsg.seqNum);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_NAK_CODE)
				printf("\tnakCode=%u\n", msg->ackMsg.nakCode);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_TEXT)
				printf("\ttext=%.*s\n", msg->ackMsg.text.length, msg->ackMsg.text.data);

			break;

		default:
			printf("\nRecieved Unhandled Item Msg Class: %d\n", msg->msgBase.msgClass);
			break;
	}

	return RSSL_RET_SUCCESS;
}
/*
 * Publically visable market price response handler 
 *
 * Processes a market price response.  This consists of extracting the
 * key, printing out the item name contained in the key, decoding the
 * field list and field entry, and calling decodeFieldEntry() to decode
 * the field entry data.
 * msg - The partially decoded message
 * dIter - The decode iterator
 */
RsslRet processMarketPriceResponse(RsslChannel *chnl, RsslMsg* msg, RsslDecodeIterator* dIter)
{
	RsslMsgKey* key;
	RsslFieldList fList = RSSL_INIT_FIELD_LIST;
	RsslFieldEntry fEntry = RSSL_INIT_FIELD_ENTRY;
	RsslRet ret = 0;
	char tempData[1024];
	RsslBuffer tempBuffer;
	RsslBool isBatchRequest = RSSL_FALSE;
	RsslBool isPrivateStream = RSSL_FALSE;
	MarketPriceItemInfo *itemInfo = NULL;
	char postUserAddrString[16];

	tempBuffer.data = tempData;
	tempBuffer.length = sizeof(tempData);

	key = (RsslMsgKey *)rsslGetMsgKey(msg);

	// determine which item in the info list we received a response for
	if (msg->msgBase.streamId == MARKETPRICE_BATCH_STREAM_ID_START ||
		msg->msgBase.streamId == MARKETPRICE_BATCH_PRIVATE_STREAM_ID_START)
	{
		isBatchRequest = RSSL_TRUE;	// we dont have info list entries for a status response to a batch request
	}
	else if (msg->msgBase.streamId >= MARKETPRICE_PRIVATE_STREAM_ID_START)
	{
		isPrivateStream = RSSL_TRUE;
		itemInfo = &marketPricePSItemInfoList[msg->msgBase.streamId - MARKETPRICE_PRIVATE_STREAM_ID_START];
	}
	else if (msg->msgBase.streamId >= MARKETPRICE_STREAM_ID_START)
	{
		itemInfo = &marketPriceItemInfoList[msg->msgBase.streamId - MARKETPRICE_STREAM_ID_START];
	}

	switch(msg->msgBase.msgClass)
	{
		case RSSL_MC_REFRESH:
			if (!(msg->refreshMsg.flags & RSSL_RFMF_PRIVATE_STREAM)) /* non-private stream */
			{
				/* check if this response should be on private stream but is not */
				/* if this is the case, close the stream */
				if (isPrivateStream)
				{
					printf("\nReceived non-private response for stream %i that should be private - closing stream\n", msg->msgBase.streamId);
					/* close stream */
					if (closeMPItemStream(chnl, itemInfo->streamId) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;
					/* remove private stream entry from list */
					removeMarketPriceItemEntry(chnl, itemInfo->streamId, RSSL_TRUE);
					return RSSL_RET_SUCCESS;
				}
			}

			/* update our item state list if its a refresh, then process just like update */
			itemInfo->itemState.dataState = msg->refreshMsg.state.dataState;
			itemInfo->itemState.streamState = msg->refreshMsg.state.streamState;

			/* refresh continued - process just like update */

		case RSSL_MC_UPDATE:

			/* print out item name from key if it has it */
			if (key && (key->flags & RSSL_MKF_HAS_NAME))
				printf("\n%.*s", key->name.length, key->name.data);
			else
				printf("\n%s", itemInfo->itemname);

			if (isPrivateStream) printf(" (PRIVATE STREAM)");
			printf("\n");

			printf("DOMAIN: %s\n", rsslDomainTypeToString(msg->msgBase.domainType));

			if (msg->msgBase.msgClass == RSSL_MC_UPDATE)
			{
				/* When displaying update information, we should also display the updateType information. */
				printf("UPDATE TYPE: %u\n", msg->updateMsg.updateType);	

				/* The Visible Publisher Identity (VPI) can be found within the RsslPostUserInfo. 
				 * This will provide both the publisher ID and publisher address. Consumer can obtain the information from the msg - The partially decoded message.
				 */
				if (msg->updateMsg.flags & RSSL_UPMF_HAS_POST_USER_INFO)
				{
					rsslIPAddrUIntToString(msg->updateMsg.postUserInfo.postUserAddr, postUserAddrString);
					printf("Received UpdateMsg for stream %i ", itemInfo->streamId);
					printf("from publisher with user ID: \"%u\" at user address: \"%s\"\n", msg->updateMsg.postUserInfo.postUserId, postUserAddrString);
				}
			}
			else if (msg->msgBase.msgClass == RSSL_MC_REFRESH)
			{
				rsslStateToString(&tempBuffer, &msg->refreshMsg.state);
				printf("%.*s\n", tempBuffer.length, tempBuffer.data);

				/* The Visible Publisher Identity (VPI) can be found within the RsslPostUserInfo. 
				 * This will provide both the publisher ID and publisher address. Consumer can obtain the information from the msg - The partially decoded message.
				 */
				if (msg->refreshMsg.flags & RSSL_RFMF_HAS_POST_USER_INFO)
				{
					rsslIPAddrUIntToString(msg->refreshMsg.postUserInfo.postUserAddr, postUserAddrString);
					printf("\nReceived RefreshMsg for stream %i ", itemInfo->streamId);
					printf("from publisher with user ID: \"%u\" at user address: \"%s\"\n", msg->refreshMsg.postUserInfo.postUserId, postUserAddrString);
				}
			}


			/* decode market price response */
			/* decode field list */
			if ((ret = rsslDecodeFieldList(dIter, &fList, 0)) != RSSL_RET_SUCCESS)
			{
				printf("rsslDecodeFieldList() failed with return code: %d\n", ret);
				return RSSL_RET_FAILURE;
			}
			/* decode each field entry in list */
			while ((ret = rsslDecodeFieldEntry(dIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER)
			{
				if (ret != RSSL_RET_SUCCESS)
				{
					printf("rsslDecodeFieldEntry() failed with return code: %d\n", ret);
					return RSSL_RET_FAILURE;
				}
				/* decode field entry info */
				if (decodeFieldEntry(&fEntry, dIter) != RSSL_RET_SUCCESS)
				{
					printf("\ndecodeFieldEntry() failed\n");
					return RSSL_RET_FAILURE;
				}
			}
			break;

		case RSSL_MC_STATUS:
			if (isBatchRequest)
				printf("\nReceived Batch StatusMsg for stream %i \n", msg->statusMsg.msgBase.streamId);
			else
				printf("\nReceived Item StatusMsg for stream %i \n", itemInfo->streamId);

			if (!(msg->statusMsg.flags & RSSL_STMF_PRIVATE_STREAM)) /* non-private stream */
			{
				/* check if this response should be on private stream but is not */
				/* if this is the case, close the stream */
				if (isPrivateStream)
				{
					printf("\nReceived non-private response for stream %i that should be private - closing stream\n", itemInfo->streamId);
					if (closeMPItemStream(chnl, itemInfo->streamId) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;
					/* remove private stream entry from list */
					removeMarketPriceItemEntry(chnl, itemInfo->streamId, RSSL_TRUE);
					return RSSL_RET_SUCCESS;
				}
			}

			if (msg->statusMsg.flags & RSSL_STMF_HAS_STATE)
    		{
    			rsslStateToString(&tempBuffer, &msg->statusMsg.state);
				printf("	%.*s\n\n", tempBuffer.length, tempBuffer.data);

				if (itemInfo)
				{
					/* update our state table with the new state */
					itemInfo->itemState.dataState = msg->statusMsg.state.dataState;
					itemInfo->itemState.streamState = msg->statusMsg.state.streamState;
				}
				/* The Visible Publisher Identity (VPI) can be found within the RsslPostUserInfo. 
				 * This will provide both the publisher ID and publisher address. Consumer can obtain the information from the msg - The partially decoded message.
				 */
				if (msg->statusMsg.flags & RSSL_STMF_HAS_POST_USER_INFO)
				{
					rsslIPAddrUIntToString(msg->statusMsg.postUserInfo.postUserAddr, postUserAddrString);
					printf("Received StatusMsg for stream %i ", itemInfo->streamId);
					printf("from publisher with user ID: \"%u\" at user address: \"%s\"\n", msg->statusMsg.postUserInfo.postUserId, postUserAddrString);
				}

				/* redirect to private stream if indicated */
				if (msg->statusMsg.state.streamState == RSSL_STREAM_REDIRECTED &&
					(msg->statusMsg.flags & RSSL_STMF_PRIVATE_STREAM))
				{
    				if (redirectToMarketPricePrivateStream(chnl, itemInfo->streamId) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;
				}
			}
			break;

		case RSSL_MC_ACK:
			printf("\nReceived AckMsg for stream %i \n", msg->msgBase.streamId);

			/* print out item name from key if it has it */
			/* if we sent an off stream post, we may not have created an itemInfo for it */
			if (key && (key->flags & RSSL_MKF_HAS_NAME))
				printf("\n%.*s", key->name.length, key->name.data);
			else if(itemInfo)	
				printf("\n%s", itemInfo->itemname);

			if (isPrivateStream) printf(" (PRIVATE STREAM)");
			printf("\n");

			printf("DOMAIN: %s\n", rsslDomainTypeToString(msg->msgBase.domainType));

			printf("\tackId=%u\n", msg->ackMsg.ackId);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_SEQ_NUM)
				printf("\tseqNum=%u\n", msg->ackMsg.seqNum);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_NAK_CODE)
				printf("\tnakCode=%u\n", msg->ackMsg.nakCode);
			if (msg->ackMsg.flags & RSSL_AKMF_HAS_TEXT)
				printf("\ttext=%.*s\n", msg->ackMsg.text.length, msg->ackMsg.text.data);

			break;

		default:
			printf("\nReceived Unhandled Item Msg Class: %d\n", msg->msgBase.msgClass);
   			break;
	}

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