Esempio n. 1
0
/*
 * Processes all RSSL messages that aren't processed by 
 * any domain-specific callback functions.  
 * Item requests are handled here.
 */
RsslReactorCallbackRet defaultMsgCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslMsgEvent *pRsslMsgEvent)
{
	RsslDecodeIterator dIter;
	RsslMsg *pRsslMsg = pRsslMsgEvent->pRsslMsg;

	if (!pRsslMsg)
	{
		RsslErrorInfo *pError = pRsslMsgEvent->pErrorInfo;
		printf("defaultMsgCallback() received error: %s(%s)\n", pError->rsslError.text, pError->errorLocation);
		removeClientSessionForChannel(pReactor, pReactorChannel);
		return RSSL_RC_CRET_SUCCESS;
	}
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	rsslSetDecodeIteratorRWFVersion(&dIter, pReactorChannel->majorVersion, pReactorChannel->minorVersion);
	rsslSetDecodeIteratorBuffer(&dIter, &pRsslMsg->msgBase.encDataBody);

	switch ( pRsslMsg->msgBase.domainType )
	{
		case RSSL_DMT_MARKET_PRICE:
		case RSSL_DMT_MARKET_BY_ORDER:
		case RSSL_DMT_MARKET_BY_PRICE:
		case RSSL_DMT_YIELD_CURVE:
		case RSSL_DMT_SYMBOL_LIST:
			if (processItemRequest(pReactor, pReactorChannel, pRsslMsg, &dIter) != RSSL_RET_SUCCESS)
			{
				removeClientSessionForChannel(pReactor, pReactorChannel);
				return RSSL_RC_CRET_SUCCESS;
			}
			break;
		default:
			switch(pRsslMsg->msgBase.msgClass)
			{
				case RSSL_MC_REQUEST:
					if (sendNotSupportedStatus(pReactor, pReactorChannel, pRsslMsg) != RSSL_RET_SUCCESS)
					{
						removeClientSessionForChannel(pReactor, pReactorChannel);
						return RSSL_RC_CRET_SUCCESS;
					}
					break;

				case RSSL_MC_CLOSE:
					printf("Received Close message with StreamId %d and unsupported domain %u\n\n",
							pRsslMsg->msgBase.streamId, pRsslMsg->msgBase.domainType);
					break;

				default:
					printf("Received unhandled message with MsgClass %u, StreamId %d and unsupported domain %u\n\n",
							pRsslMsg->msgBase.msgClass, pRsslMsg->msgBase.streamId, pRsslMsg->msgBase.domainType);
					break;
			}
			break;
	}

	return RSSL_RC_CRET_SUCCESS;
}
RSSL_VA_API RsslRet rsslTunnelStreamRequestGetCos(RsslTunnelStreamRequestEvent *pEvent, RsslClassOfService *pCos, RsslErrorInfo *pError)
{
	NewTunnelStreamRequest *pRequest = (NewTunnelStreamRequest*)pEvent;

	if (pEvent == NULL)
	{
		rsslSetErrorInfo(pError, RSSL_EIC_FAILURE, RSSL_RET_INVALID_ARGUMENT, __FILE__, __LINE__, "RsslTunnelStreamRequestEvent not provided.");
		return RSSL_RET_INVALID_ARGUMENT;
	}

	if (pCos == NULL)
	{
		rsslSetErrorInfo(pError, RSSL_EIC_FAILURE, RSSL_RET_INVALID_ARGUMENT, __FILE__, __LINE__, "RsslClassOfService not provided.");
		return RSSL_RET_INVALID_ARGUMENT;
	}

	if (pError == NULL)
		return RSSL_RET_INVALID_ARGUMENT;

	if (!pRequest->eventCosDecoded)
	{
		rsslClearClassOfService(pCos);

		switch(pRequest->pReqMsg->msgBase.containerType)
		{
			case RSSL_DT_FILTER_LIST:
			{
				RsslDecodeIterator dIter;
				RsslRet ret;

				rsslClearDecodeIterator(&dIter);
				rsslSetDecodeIteratorRWFVersion(&dIter, pRequest->event.pReactorChannel->majorVersion, pRequest->event.pReactorChannel->minorVersion);
				rsslSetDecodeIteratorBuffer(&dIter, &pRequest->pReqMsg->msgBase.encDataBody);

				if ((ret = rsslDecodeClassOfService(&dIter, &pRequest->classOfService, NULL, pError)) != RSSL_RET_SUCCESS)
					return ret;

				break;
			}

			default:
				break;
		}

		pRequest->eventCosDecoded = RSSL_TRUE;
	}

	*pCos = pRequest->classOfService;
	return RSSL_RET_SUCCESS;
}
/*
 * Apply buffer containing full encoded message to cache
 */
RsslRet applyMsgBufferToCache(RsslUInt8 majorVersion, RsslUInt8 minorVersion, RsslPayloadEntryHandle* pCacheEntryHandle, RsslVACacheInfo* pCacheInfo, RsslBuffer *pBuffer)
{
    RsslDecodeIterator dIter;
    RsslMsg msg;
    RsslRet ret;

    if (*pCacheEntryHandle == 0)
    {
        /* allocate cache entry */
        *pCacheEntryHandle = rsslPayloadEntryCreate(pCacheInfo->cacheHandle, &pCacheInfo->cacheErrorInfo);
        if (*pCacheEntryHandle == 0)
        {
            printf("Failed to create cache entry.\n\tError (%d): %s\n",
                   pCacheInfo->cacheErrorInfo.rsslErrorId, pCacheInfo->cacheErrorInfo.text);

            return RSSL_RET_FAILURE;
        }
    }

    rsslClearDecodeIterator(&dIter);
    rsslSetDecodeIteratorRWFVersion(&dIter, majorVersion, minorVersion);

    if((ret = rsslSetDecodeIteratorBuffer(&dIter, pBuffer)) != RSSL_RET_SUCCESS)
    {
        printf("Failed to set iterator on data buffer: Error (%d)", ret);
        return ret;
    }

    rsslClearMsg(&msg);
    if ((ret = rsslDecodeMsg(&dIter, &msg)) != RSSL_RET_SUCCESS)
    {
        printf("Failed to decode message: Error (%d)", ret);
        return ret;
    }

    if ((ret = rsslPayloadEntryApply(*pCacheEntryHandle,
                                     &dIter,
                                     &msg,
                                     &pCacheInfo->cacheErrorInfo)) != RSSL_RET_SUCCESS)
    {
        printf("Failed to apply payload data to cache.\n\tError (%d): %s\n",
               pCacheInfo->cacheErrorInfo.rsslErrorId, pCacheInfo->cacheErrorInfo.text);

        return ret;
    }

    return RSSL_RET_SUCCESS;
}
Esempio n. 4
0
RsslReactorCallbackRet defaultMsgCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslMsgEvent* pMsgEvent)
{
	ProviderSession *pProvSession = (ProviderSession *)pReactorChannel->userSpecPtr;
	ProviderThread *pProvThread = pProvSession->pProviderThread;
	RsslMsg *pMsg = pMsgEvent->pRsslMsg;
	RsslDecodeIterator dIter;

	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, pReactorChannel->majorVersion, pReactorChannel->minorVersion);

	rsslSetDecodeIteratorBuffer(&dIter, &pMsg->msgBase.encDataBody);

	switch (pMsg->msgBase.domainType)
	{
		case RSSL_DMT_MARKET_PRICE:
			if (xmlMsgDataHasMarketPrice)
				processItemRequest(pProvThread, pProvSession, pMsg, &dIter);
			else
				sendItemRequestReject(pProvThread, pProvSession, 
						pMsg->msgBase.streamId, pMsg->msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		case RSSL_DMT_MARKET_BY_ORDER:
			if (xmlMsgDataHasMarketByOrder)
				processItemRequest(pProvThread, pProvSession, pMsg, &dIter);
			else
				sendItemRequestReject(pProvThread, pProvSession, 
						pMsg->msgBase.streamId, pMsg->msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		default:
			sendItemRequestReject(pProvThread, pProvSession, 
					pMsg->msgBase.streamId, pMsg->msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
	}

	return RSSL_RC_CRET_SUCCESS;
}
/*
 * Apply partially decoded message to cache
 */
RsslRet applyMsgToCache(RsslPayloadEntryHandle *pCacheEntryHandle, RsslVACacheInfo* pCacheInfo, RsslMsg *pMsg, RsslDecodeIterator *dIter)
{
    RsslRet ret;
    RsslDecodeIterator cacheDecodeIter;

    if (*pCacheEntryHandle == 0)
    {
        /* allocate cache entry */
        *pCacheEntryHandle = rsslPayloadEntryCreate(pCacheInfo->cacheHandle, &pCacheInfo->cacheErrorInfo);
        if (*pCacheEntryHandle == 0)
        {
            printf("Failed to create cache entry.\n\tError (%d): %s\n",
                   pCacheInfo->cacheErrorInfo.rsslErrorId, pCacheInfo->cacheErrorInfo.text);

            return RSSL_RET_FAILURE;
        }
    }

    rsslClearDecodeIterator(&cacheDecodeIter);
    rsslSetDecodeIteratorRWFVersion(&cacheDecodeIter, dIter->_majorVersion, dIter->_minorVersion);
    rsslSetDecodeIteratorBuffer(&cacheDecodeIter, &pMsg->msgBase.encDataBody);

    if ((ret = rsslPayloadEntryApply(*pCacheEntryHandle,
                                     &cacheDecodeIter,
                                     pMsg,
                                     &pCacheInfo->cacheErrorInfo)) != RSSL_RET_SUCCESS)
    {
        printf("Failed to apply payload data to cache.\n\tError (%d): %s\n",
               pCacheInfo->cacheErrorInfo.rsslErrorId, pCacheInfo->cacheErrorInfo.text);

        return ret;
    }


    return RSSL_RET_SUCCESS;
}
Esempio n. 6
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;
}
Esempio n. 7
0
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer)
{
	RsslRet ret = RSSL_RET_SUCCESS; RsslMsg msg = RSSL_INIT_MSG;
	RsslDecodeIterator dIter;
	ProviderThread *pProvThread = (ProviderThread*)pChannelHandler->pUserSpec;
	RsslChannel *pChannel = pChannelInfo->pChannel;
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, pChannel->majorVersion, pChannel->minorVersion);

	rsslSetDecodeIteratorBuffer(&dIter, pBuffer);

	ret = rsslDecodeMsg(&dIter, &msg);				
	if (ret != RSSL_RET_SUCCESS)
	{
		printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d  Size %d \n", ret, pChannel->socketId, pBuffer->length);
		cleanUpAndExit();
	}

	switch ( msg.msgBase.domainType )
	{
		case RSSL_DMT_LOGIN:
			ret = processLoginRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_SOURCE:
			ret = processDirectoryRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_DICTIONARY:
			ret = processDictionaryRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_MARKET_PRICE:
			if (xmlMsgDataHasMarketPrice)
				ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter);
			else
				ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
						msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		case RSSL_DMT_MARKET_BY_ORDER:
			if (xmlMsgDataHasMarketByOrder)
				ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter);
			else
				ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
						msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		default:
			ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
					msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
	}


	if (ret < RSSL_RET_SUCCESS) 
	{
		printf("Failed to process request from domain %d: %d\n", msg.msgBase.domainType, ret);
	}
	else if (ret > RSSL_RET_SUCCESS)
	{
		/* The function sent a message and indicated that we need to flush. */
		providerThreadRequestChannelFlush(pProvThread, pChannelInfo);
	}

	return ret;
}
Esempio n. 8
0
static RsslRet wlExtractSymbolListFromMsg(WlBase *pBase, RsslRequestMsg *pRequestMsg,
		RsslUInt32 majorVersion, RsslUInt32 minorVersion, RsslBool *pHasBehaviors,
		RsslUInt *pSymbolListFlags, RsslErrorInfo *pErrorInfo)
{
	RsslDecodeIterator dIter;

	RsslRet ret = 0;
	RsslElementList elementList;
	RsslElementEntry elementEntry;

	/* setup decode iterator */
	rsslClearDecodeIterator(&dIter);
	rsslSetDecodeIteratorRWFVersion(&dIter, majorVersion, minorVersion);
	rsslSetDecodeIteratorBuffer(&dIter, &pRequestMsg->msgBase.encDataBody);

	rsslClearElementList(&elementList);

	*pSymbolListFlags = 0;
	*pHasBehaviors = RSSL_FALSE;

	if (pRequestMsg->msgBase.containerType != RSSL_DT_ELEMENT_LIST)
		return RSSL_RET_SUCCESS; /* Nothing to extract. */

	/* check the container type and decode element list */ 
	if ((ret = rsslDecodeElementList(&dIter, &elementList, 0)) == RSSL_RET_SUCCESS)
	{
		rsslClearElementEntry(&elementEntry);

		/* find and decode the :SymbolListBehaviors */
		while ((ret = rsslDecodeElementEntry(&dIter, &elementEntry)) != RSSL_RET_END_OF_CONTAINER)
		{
			if (ret < RSSL_RET_SUCCESS)
			{
				rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
						"Error decoding element entry in Request Msg -- %d.", ret);
				return ret;
			}
			else
			{
				if (rsslBufferIsEqual(&elementEntry.name, &RSSL_ENAME_SYMBOL_LIST_BEHAVIORS))
				{
					RsslElementList behaviorsElementList;

					*pHasBehaviors = RSSL_TRUE;

					if (elementEntry.dataType != RSSL_DT_ELEMENT_LIST)
					{
						rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__,
								"Error decoding Symbol List behaviors -- Element has wrong data type.");
						return ret;
					}

					if ((ret = rsslDecodeElementList(&dIter, &behaviorsElementList, 0)) == RSSL_RET_SUCCESS)
					{
						RsslElementEntry behaviorsEntry;
						rsslClearElementEntry(&behaviorsEntry);

						/* find and decode the :DataStreams */
						while ((ret = rsslDecodeElementEntry(&dIter, &behaviorsEntry)) != RSSL_RET_END_OF_CONTAINER)
						{
							if (ret < RSSL_RET_SUCCESS)
							{
								rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
										"Error decoding element entry in Request Msg -- %d.", ret);
								return ret;
							}
							else
							{
								if (rsslBufferIsEqual(&behaviorsEntry.name, &RSSL_ENAME_DATA_STREAMS))
								{
									if (behaviorsEntry.dataType != RSSL_DT_UINT)
									{
										rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__,
												"Error decoding Symbol List Data Streams -- Element has wrong data type.");
										return ret;
									}

									if ((ret = rsslDecodeUInt(&dIter, pSymbolListFlags)) != RSSL_RET_SUCCESS)
									{
										rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
												"Error decoding Symbol List Data Streams -- %d.", ret);
										return ret;
									}

									if (((*pSymbolListFlags) & (RDM_SYMBOL_LIST_DATA_STREAMS | RDM_SYMBOL_LIST_DATA_SNAPSHOTS))
											== (RDM_SYMBOL_LIST_DATA_STREAMS | RDM_SYMBOL_LIST_DATA_SNAPSHOTS))
									{
										rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__,
												"Symbol list request specifies both data streams and data snapshots.");
										return RSSL_RET_INVALID_DATA;
									}

									return RSSL_RET_SUCCESS;
								}
							}
						}
					}
					else
					{
						rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__,
								"Error decoding Symbol List Behaviors Element List -- %d.", ret);
						return ret;
					}

					return RSSL_RET_SUCCESS;
				}
			}
		}
	}
	else
	{
		rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__,
				"Unexpected container type: -- %d, or decoding error -- %d.", pRequestMsg->msgBase.containerType, ret);
		return RSSL_RET_INVALID_DATA;
	}

	return RSSL_RET_SUCCESS;
}
RsslRet tunnelManagerReadMsg(TunnelManager *pManager, RsslMsg *pMsg, RsslErrorInfo *pErrorInfo)
{
	TunnelManagerImpl *pManagerImpl = (TunnelManagerImpl*)pManager;
	RsslRet ret;
	RsslHashLink *pHashLink;
	RsslTunnelStream *pTunnelStream;

	if ((pHashLink = rsslHashTableFind(&pManagerImpl->_streamIdToTunnelStreamTable, &pMsg->msgBase.streamId, NULL)) != NULL)
	{
		pTunnelStream = (RsslTunnelStream*)RSSL_HASH_LINK_TO_OBJECT(TunnelStreamImpl, _managerHashLink, pHashLink);

		if ((ret = tunnelStreamRead(pTunnelStream, pMsg, pErrorInfo)) != RSSL_RET_SUCCESS)
			return tunnelManagerHandleStreamError(pManager, pTunnelStream, ret, pErrorInfo);
	}
	else if (pManagerImpl->_listenerCallback != NULL)
	{
		switch(pMsg->msgBase.msgClass)
		{
			case RSSL_MC_REQUEST:
			{
				RsslReactorCallbackRet cret;
				NewTunnelStreamRequest newRequest;

				if (!rsslRequestMsgCheckQualifiedStream(&pMsg->requestMsg))
					return RSSL_RET_NO_TUNNEL_STREAM;

				memset(&newRequest, 0, sizeof(NewTunnelStreamRequest));

				newRequest.event.pReactorChannel = (RsslReactorChannel*)pManagerImpl->base._pReactorChannel;
				newRequest.event.streamId = pMsg->msgBase.streamId;
				newRequest.event.domainType = pMsg->msgBase.domainType;
				newRequest.pReqMsg = &pMsg->requestMsg;
				newRequest.streamVersion = COS_CURRENT_STREAM_VERSION;

				if (rsslMsgKeyCheckHasFilter(&pMsg->msgBase.msgKey))
					newRequest.event.classOfServiceFilter = pMsg->msgBase.msgKey.filter;
				else
				{
					if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
								(char*)"Rejected a consumer's tunnel stream due to missing msgKey.filter.",
								(char*)"Request is missing msgKey.filter", 32,
								RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;

					return RSSL_RET_SUCCESS;
				}

				newRequest.state = TSR_WAIT_ACCEPT;


				if (rsslMsgKeyCheckHasServiceId(&pMsg->msgBase.msgKey))
					newRequest.event.serviceId = pMsg->msgBase.msgKey.serviceId;
				else
				{
					if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
								(char*)"Rejected a consumer's tunnel stream due to missing msgKey.serviceId.",
								(char*)"Request is missing msgKey.serviceId", 35,
								RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;

					return RSSL_RET_SUCCESS;
				}


				if (rsslMsgKeyCheckHasName(&pMsg->msgBase.msgKey))
				{
					if ((newRequest.event.name = (char*)malloc(pMsg->msgBase.msgKey.name.length + 1))
							== NULL)
					{
						rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_ARGUMENT, __FILE__, __LINE__,
								"Failed to allocate memory.");
						return RSSL_RET_FAILURE;
					}

					strncpy(newRequest.event.name, pMsg->msgBase.msgKey.name.data,
							pMsg->msgBase.msgKey.name.length);
					newRequest.event.name[pMsg->msgBase.msgKey.name.length] = '\0';
				}
				else
				{
					if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
								(char*)"Rejected a consumer's tunnel stream due to missing msgKey.name.",
								(char*)"Request is missing msgKey.name", 30,
								RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
						return RSSL_RET_FAILURE;

					return RSSL_RET_SUCCESS;
				}


				/* If filter list provided, get stream version. If not (though that shouldn't happen), assume defaults. */
				if (pMsg->msgBase.containerType == RSSL_DT_FILTER_LIST)
				{
					RsslDecodeIterator dIter;
					RsslRet ret;
					RsslUInt streamVersion;

					rsslClearDecodeIterator(&dIter);
					rsslSetDecodeIteratorRWFVersion(&dIter, newRequest.event.pReactorChannel->majorVersion, newRequest.event.pReactorChannel->minorVersion);
					rsslSetDecodeIteratorBuffer(&dIter, &newRequest.pReqMsg->msgBase.encDataBody);

					if ((ret = rsslGetClassOfServiceStreamVersion(&dIter, &streamVersion, pErrorInfo))
						!= RSSL_RET_SUCCESS)
					{
						if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
									(char*)"Rejected a consumer's tunnel stream due to failure to get the stream version.",
									(char*)"Failed to decode ClassOfService filter list.", 44,
									RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
								return RSSL_RET_FAILURE;


						return RSSL_RET_SUCCESS;
					}

					if (streamVersion > COS_CURRENT_STREAM_VERSION)
					{
						if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
									(char*)"Rejected a consumer's tunnel stream due to an unrecognized stream version.",
									(char*)"Unknown stream version requested.", 32,
									RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;


						return RSSL_RET_SUCCESS;
					}
					newRequest.streamVersion = streamVersion;
				}

				if ((cret = (*pManagerImpl->_listenerCallback)(&newRequest.event, pErrorInfo))
						!= RSSL_RC_CRET_SUCCESS)
				{
					rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_ARGUMENT, __FILE__, __LINE__,
							"Unexpected return code %d from tunnel stream listener callback", cret);
					return RSSL_RET_FAILURE;
				}

				/* Application should have accepted or rejected the tunnel stream. */
				if (newRequest.state == TSR_WAIT_ACCEPT)
				{
					if (tunnelManagerAutoReject(pManagerImpl, &newRequest.event,
								(char*)"A tunnel stream request was not accepted or rejected within the listener callback.",
								(char*)"Provider did not accept or reject this stream.", 46,
								RSSL_STREAM_CLOSED, pErrorInfo) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;


				}
				break;
			}

			default:
				return RSSL_RET_NO_TUNNEL_STREAM;
		}

	}
	else
		return RSSL_RET_NO_TUNNEL_STREAM;

	tunnelManagerSetNeedsDispatchNow(pManagerImpl, 
			pManagerImpl->_tunnelStreamDispatchList.count > 0);

	return RSSL_RET_SUCCESS;
}
Esempio n. 10
0
/* Processes a queue message event. */
RsslReactorCallbackRet queueMsgHandlerQueueMsgCallback(RsslTunnelStream *pTunnelStream, RsslTunnelStreamQueueMsgEvent *pEvent)
{
	RsslState *pState;
	RsslBuffer tempBuffer;
	char tempData[1024];
	QueueMsgHandler *pQueueMsgHandler = (QueueMsgHandler*)pTunnelStream->userSpecPtr;
	RsslReactorChannel *pReactorChannel = pTunnelStream->pReactorChannel;

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

	switch (pEvent->pQueueMsg->rdmMsgBase.rdmMsgType)
	{
		case RDM_QMSG_MT_DATA:
        {
			RsslBool sendAck = RSSL_FALSE;
			RsslRDMQueueData *pQueueData = (RsslRDMQueueData *)pEvent->pQueueMsg;
			RsslDecodeIterator dIter;

			printf("Received Msg on stream %d from %.*s to %.*s, ID: %lld\n",
					pQueueData->rdmMsgBase.streamId, pQueueData->sourceName.length, pQueueData->sourceName.data, pQueueData->destName.length, pQueueData->destName.data, pQueueData->identifier);

			if (rsslRDMQueueDataCheckIsPossibleDuplicate(pQueueData))
				printf("  (Message may be a duplicate of a previous message.)\n");


			printf("  Queue Depth: %u\n", pQueueData->queueDepth);
                

            switch (pQueueData->containerType)
            {

				case RSSL_DT_FIELD_LIST:
				{
                    // Received a buffer; decode it.
					rsslClearDecodeIterator(&dIter);
					rsslSetDecodeIteratorRWFVersion(&dIter, pTunnelStream->classOfService.common.protocolMajorVersion, 
							pTunnelStream->classOfService.common.protocolMajorVersion);
					rsslSetDecodeIteratorBuffer(&dIter, &pQueueData->encDataBody);

					/* If queueMsgHandlerDecodeQueueData, this message is an order message so we will acknowledge it. */
					if (queueMsgHandlerDecodeQueueData(&dIter))
						ackQueueMsg(pQueueMsgHandler, &pQueueData->sourceName, pQueueData->rdmMsgBase.streamId);
    
                }
                default:
                    break;
            }                
            break;
        }

		case RDM_QMSG_MT_DATA_EXPIRED:
        {
			RsslBool sendAck = RSSL_FALSE;
			RsslRDMQueueDataExpired *pQueueDataExpired = (RsslRDMQueueDataExpired *)pEvent->pQueueMsg;
			RsslDecodeIterator dIter;

			printf("Received Msg on stream %d from %.*s to %.*s, ID: %lld (Undeliverable Message with code: %d(%s))\n",
					pQueueDataExpired->rdmMsgBase.streamId, 
					pQueueDataExpired->sourceName.length, pQueueDataExpired->sourceName.data, 
					pQueueDataExpired->destName.length, pQueueDataExpired->destName.data, 
					pQueueDataExpired->identifier, 
					pQueueDataExpired->undeliverableCode,
					rsslRDMQueueUndeliverableCodeToString(pQueueDataExpired->undeliverableCode));

			if (rsslRDMQueueDataExpiredCheckIsPossibleDuplicate(pQueueDataExpired))
				printf("  (Message may be a duplicate of a previous message.)");


			printf("  Queue Depth: %u\n", pQueueDataExpired->queueDepth);
                

            switch (pQueueDataExpired->containerType)
            {

				case RSSL_DT_FIELD_LIST:
				{
                    // Received a buffer; decode it.
					rsslClearDecodeIterator(&dIter);
					rsslSetDecodeIteratorRWFVersion(&dIter, pTunnelStream->classOfService.common.protocolMajorVersion, 
							pTunnelStream->classOfService.common.protocolMajorVersion);
					rsslSetDecodeIteratorBuffer(&dIter, &pQueueDataExpired->encDataBody);
					queueMsgHandlerDecodeQueueData(&dIter);
    
                }
                default:
                    break;
            }                
            break;
        }
		case RDM_QMSG_MT_ACK:
		{
			RsslRDMQueueAck *pQueueAck = (RsslRDMQueueAck *)pEvent->pQueueMsg;
			printf("Received persistence Ack for submitted message with ID: %lld\n\n", pQueueAck->identifier);
			break;
		}
		case RDM_QMSG_MT_REFRESH:
		{
			RsslRDMQueueRefresh *pQueueRefresh = (RsslRDMQueueRefresh *)pEvent->pQueueMsg;
			pState = &pQueueRefresh->state;

			if (pState->streamState == RSSL_STREAM_OPEN
					&& pState->dataState == RSSL_DATA_OK)
				pQueueMsgHandler->isQueueStreamOpen = RSSL_TRUE;
			else
				pQueueMsgHandler->isQueueStreamOpen = RSSL_FALSE;

			rsslStateToString(&tempBuffer, pState);
			printf("Received QueueRefresh on stream %d for sourceName %.*s with %.*s\n  Queue Depth: %u\n\n", pQueueRefresh->rdmMsgBase.streamId, pQueueRefresh->sourceName.length, pQueueRefresh->sourceName.data, tempBuffer.length, tempBuffer.data, pQueueRefresh->queueDepth);

			time(&pQueueMsgHandler->nextMsgTime);
			pQueueMsgHandler->nextMsgTime += QUEUE_MSG_FREQUENCY;

			break;
		}
		case RDM_QMSG_MT_STATUS:
		{
			RsslRDMQueueStatus *pQueueStatus = (RsslRDMQueueStatus *)pEvent->pQueueMsg;
			if (pQueueStatus->flags & RDM_QMSG_STF_HAS_STATE)
			{
				pState = &pQueueStatus->state;

				if (pState->streamState == RSSL_STREAM_OPEN
						&& pState->dataState == RSSL_DATA_OK)
					pQueueMsgHandler->isQueueStreamOpen = RSSL_TRUE;
				else
					pQueueMsgHandler->isQueueStreamOpen = RSSL_FALSE;

				rsslStateToString(&tempBuffer, pState);
				printf("Received QueueStatus on stream %d with %.*s\n\n", pQueueStatus->rdmMsgBase.streamId, tempBuffer.length, tempBuffer.data);
			}
			else
			{
				printf("Received QueueStatus on stream %d\n\n", pQueueStatus->rdmMsgBase.streamId);
			}
			break;
		}
	}

	return RSSL_RC_CRET_SUCCESS;
}
/*
 * Processes information contained in Dictionary responses.
 * Takes the payload of the messages and caches them
 * using the RSSL utilities for decoding dictionary info.
 */
RsslReactorCallbackRet dictionaryMsgCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslRDMDictionaryMsgEvent *pDictionaryMsgEvent)
{
	char	errTxt[256];
	RsslBuffer errorText = {255, (char*)errTxt};
	char tempData[1024];
	RsslBuffer tempBuffer;
	RsslDecodeIterator dIter;
	ChannelCommand *pCommand = (ChannelCommand*)pReactorChannel->userSpecPtr;
	RsslRDMDictionaryMsg *pDictionaryMsg = pDictionaryMsgEvent->pRDMDictionaryMsg;


	if (!pDictionaryMsg)
	{
		RsslErrorInfo *pError = pDictionaryMsgEvent->baseMsgEvent.pErrorInfo;
		printf("dictionaryResponseCallback: %s(%s)\n", pError->rsslError.text, pError->errorLocation);
		closeConnection(pReactor, pReactorChannel, pCommand);
		return RSSL_RC_CRET_SUCCESS;
	}


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

	switch(pDictionaryMsg->rdmMsgBase.rdmMsgType)
	{
	case RDM_DC_MT_REFRESH:
	{
		RsslRDMDictionaryRefresh *pRefresh = &pDictionaryMsg->refresh;

		if (pRefresh->flags & RDM_DC_RFF_HAS_INFO)
		{
			/* The first part of a dictionary refresh should contain information about its type.
			 * Save this information and use it as subsequent parts arrive. */

			switch(pRefresh->type)
			{
				case RDM_DICTIONARY_FIELD_DEFINITIONS: pCommand->fieldDictionaryStreamId = pRefresh->rdmMsgBase.streamId; break;
				case RDM_DICTIONARY_ENUM_TABLES: pCommand->enumDictionaryStreamId = pRefresh->rdmMsgBase.streamId; break;
				default: 
					printf("Unknown dictionary type %llu from message on stream %d\n", pRefresh->type, pRefresh->rdmMsgBase.streamId);
					closeConnection(pReactor, pReactorChannel, pCommand);
					return RSSL_RC_CRET_SUCCESS;
			}
		}

		/* decode dictionary response */
		rsslClearDecodeIterator(&dIter);
		rsslSetDecodeIteratorRWFVersion(&dIter, pReactorChannel->majorVersion, pReactorChannel->minorVersion);

		/* Set the iterator to the payload of the response and pass it to
		 * the appropriate dictionary decoder. */
		rsslSetDecodeIteratorBuffer(&dIter, &pRefresh->dataBody);

		printf("\nReceived Dictionary Response: %.*s\n", pRefresh->dictionaryName.length, pRefresh->dictionaryName.length ? pRefresh->dictionaryName.data : "");

		if (pRefresh->rdmMsgBase.streamId == pCommand->fieldDictionaryStreamId)
		{
    		if (rsslDecodeFieldDictionary(&dIter, &pCommand->dictionary, RDM_DICTIONARY_VERBOSE, &errorText) == RSSL_RET_SUCCESS)
			{
				if (pRefresh->flags & RDM_DC_RFF_IS_COMPLETE)
				{
					printf("Field Dictionary complete.\n");

					if (pCommand->cacheInfo.useCache == RSSL_TRUE)
					{
						if ( RSSL_RET_SUCCESS != rsslPayloadCacheSetDictionary( pCommand->cacheInfo.cacheHandle,
													&pCommand->dictionary,
													pCommand->cacheInfo.cacheDictionaryKey,
													&pCommand->cacheInfo.cacheErrorInfo) )
						{
							pCommand->cacheInfo.useCache = RSSL_FALSE;
							printf("\nUnable to bind dictionary to cache. Disabling cache for this connection.\n\tError (%d): %s\n",
									pCommand->cacheInfo.cacheErrorInfo.rsslErrorId, pCommand->cacheInfo.cacheErrorInfo.text);
						}
					}
				}
			}
			else
    		{
    			printf("Decoding Dictionary failed: %.*s\n", errorText.length, errorText.data);
				closeConnection(pReactor, pReactorChannel, pCommand);
    		}
		}
		else if (pRefresh->rdmMsgBase.streamId == pCommand->enumDictionaryStreamId)
		{
    		if (rsslDecodeEnumTypeDictionary(&dIter, &pCommand->dictionary, RDM_DICTIONARY_VERBOSE, &errorText) == RSSL_RET_SUCCESS)
			{
				if (pRefresh->flags & RDM_DC_RFF_IS_COMPLETE)
					printf("Enumerated Types Dictionary complete.\n");
			}
			else
    		{
    			printf("Decoding Dictionary failed: %.*s\n", errorText.length, errorText.data);
    			closeConnection(pReactor, pReactorChannel, pCommand);
    		}

		}
		else
		{
			printf("Received unexpected dictionary message on stream %d\n", pDictionaryMsg->rdmMsgBase.streamId);
		}
		return RSSL_RC_CRET_SUCCESS;
	}

	case RDM_DC_MT_STATUS:
		printf("\nReceived StatusMsg for dictionary\n");
		return RSSL_RC_CRET_SUCCESS;

	default:
		printf("\nReceived Unhandled Dictionary Msg Type: %d\n", pDictionaryMsg->rdmMsgBase.rdmMsgType);
		return RSSL_RC_CRET_SUCCESS;
	}

}
Esempio n. 12
0
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer)
{
	RsslRet ret = RSSL_RET_SUCCESS;
	RsslMsg msg = RSSL_INIT_MSG;
	RsslDecodeIterator dIter;
	RsslChannel *chnl = pChannelInfo->pChannel;
	ProviderThread *pProviderThread = (ProviderThread*)pChannelHandler->pUserSpec;
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion);

	rsslSetDecodeIteratorBuffer(&dIter, pBuffer);

	ret = rsslDecodeMsg(&dIter, &msg);				
	if (ret != RSSL_RET_SUCCESS)
	{
		printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d  Size %d \n", ret, chnl->socketId, pBuffer->length);
		cleanUpAndExit();
	}

	switch ( msg.msgBase.domainType )
	{
		case RSSL_DMT_LOGIN:
		{
			RsslRDMLoginMsg loginMsg;
			char memoryChar[1024];
			RsslBuffer memoryBuffer = { sizeof(memoryChar), memoryChar };
			RsslErrorInfo errorInfo;
			RsslState *pState = NULL;

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

			switch(loginMsg.rdmMsgBase.rdmMsgType)
			{
				case RDM_LG_MT_REFRESH:
					pState = &loginMsg.refresh.state;

					printf(	"Received login refresh.\n");
					if (loginMsg.refresh.flags &
							RDM_LG_RFF_HAS_APPLICATION_NAME)
						printf( "  ApplicationName: %.*s\n",
								loginMsg.refresh.applicationName.length,
								loginMsg.refresh.applicationName.data);
					printf("\n");

					break;

				case RDM_LG_MT_STATUS:
					printf("Received login status message.\n");
					if (loginMsg.status.flags & RDM_LG_STF_HAS_STATE)
						pState = &loginMsg.status.state;
					break;

				default:
					printf("Received unhandled login message class: %d.\n", msg.msgBase.msgClass);
					break;
			}

			if (pState)
			{
				if (pState->streamState == RSSL_STREAM_OPEN)
				{
					ProviderSession *pProvSession = (ProviderSession*)pChannelInfo->pUserSpec;

					ret = publishDirectoryRefresh(pChannelHandler, pChannelInfo, -1);

					if (ret < RSSL_RET_SUCCESS)
					{
						printf("publishDirectoryRefresh() failed: %d.\n", ret);
						return ret;
					}

					if (niProvPerfConfig.itemPublishCount > 0)
					{
						RsslInt32 itemListUniqueIndex;
						RsslInt32 itemListCount;
						RsslInt32 itemListCountRemainder;

						/* If there are multiple connections, determine which items are
						 * to be published on this connection.
						 * If any items are common to all connections, they are taken from the first
						 * items in the item list.  The rest of the list is then divided to provide a unique
						 * item list for each connection. */

						/* Determine where items unique to this connection start. */
						itemListUniqueIndex = niProvPerfConfig.commonItemCount;
						itemListUniqueIndex += ((niProvPerfConfig.itemPublishCount - niProvPerfConfig.commonItemCount)
							/ providerThreadConfig.threadCount) * (pProviderThread->providerIndex);

						/* Account for remainder. */
						itemListCount = niProvPerfConfig.itemPublishCount / providerThreadConfig.threadCount;
						itemListCountRemainder = niProvPerfConfig.itemPublishCount % providerThreadConfig.threadCount;

						if (pProviderThread->providerIndex < itemListCountRemainder)
						{
							/* This provider publishes an extra item */
							itemListCount += 1;

							/* Shift index by one for each provider before this one, since they publish extra items too. */
							itemListUniqueIndex += pProviderThread->providerIndex;
						}
						else
							/* Shift index by one for each provider that publishes an extra item. */
							itemListUniqueIndex += itemListCountRemainder;

						if ((ret = providerSessionAddPublishingItems(pProviderThread, (ProviderSession*)pChannelInfo->pUserSpec, 
									niProvPerfConfig.commonItemCount, itemListUniqueIndex, itemListCount - niProvPerfConfig.commonItemCount, 
									(RsslUInt16)directoryConfig.serviceId)) != RSSL_RET_SUCCESS)
						{
							printf("providerSessionAddPublishingItems() failed\n");
							return ret;
						}
						else
						{
							printf("Created publishing list.\n");
							ret = RSSL_RET_SUCCESS;
						}

						/* send the first burst of refreshes */
						if (rotatingQueueGetCount(&pProvSession->refreshItemList) != 0)
							ret = sendRefreshBurst(pProviderThread, pProvSession);
						else
							ret = RSSL_RET_SUCCESS;

						if (ret < RSSL_RET_SUCCESS)
							return ret;
					}

					if (ret > RSSL_RET_SUCCESS)
					{
						/* Need to flush */
						providerThreadRequestChannelFlush(pProviderThread, pChannelInfo);
					}

				}
				else
				{
					printf("Login stream closed.\n");
					ret = RSSL_RET_FAILURE;
				}
			}
			else 
				ret = RSSL_RET_SUCCESS;
			break;
		}
		default:
			printf("Received message with unhandled domain: %d\n", msg.msgBase.domainType);
			break;
	}


	if (ret < RSSL_RET_SUCCESS) 
	{
		signal_shutdown = RSSL_TRUE;
		return ret;
	}
	else
	{
		/* Typically these requests result in a response, so call for a flush to make sure it gets out.*/
		providerThreadRequestChannelFlush(pProviderThread, pChannelInfo);
		return ret;
	}
}
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; 
}
Esempio n. 14
0
RsslRet UPAProvider::ProcessRequest(RsslChannel* chnl, RsslBuffer* buffer)
{
    RsslRet ret = 0;
    RsslMsg msg = RSSL_INIT_MSG;
    RsslDecodeIterator dIter;

    // set up an iterator to decode the message
    rsslClearDecodeIterator(&dIter);
    rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion);
    // and attach it top the message buffer
    rsslSetDecodeIteratorBuffer(&dIter, buffer);

    ret = rsslDecodeMsg(&dIter, &msg);				
    if (ret != RSSL_RET_SUCCESS)
    {
        t42log_error("UPAProvider::ProcessRequest - rsslDecodeMsg(): Error %d on channel fd=%d  Size %d \n", ret, chnl->socketId, buffer->length);
        RemoveChannelConnection(chnl);
        return RSSL_RET_FAILURE;
    }

    switch ( msg.msgBase.domainType )
    {
    case RSSL_DMT_LOGIN:
        if (ProcessLoginRequest(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
        {

            RemoveChannelConnection(chnl);
            return RSSL_RET_FAILURE;
        }
        break;
    case RSSL_DMT_SOURCE:

        if (ProcessSourceDirectoryRequest(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
        {
            RemoveChannelConnection(chnl);
            return RSSL_RET_FAILURE;
        }
        break;
    case RSSL_DMT_DICTIONARY:
        if (ProcessDictionaryRequest(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
        {
            RemoveChannelConnection(chnl);
            return RSSL_RET_FAILURE;
        }
        break;
    case RSSL_DMT_MARKET_PRICE:
    case RSSL_DMT_MARKET_BY_ORDER:
    case RSSL_DMT_SYMBOL_LIST:
    case RSSL_DMT_MARKET_BY_PRICE:
    case RSSL_DMT_YIELD_CURVE:
        if (ProcessItemRequest(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
        {
            RemoveChannelConnection(chnl);
            return RSSL_RET_FAILURE;
        }
        break;
    default:
          break;
    }


    return RSSL_RET_SUCCESS;
}
Esempio n. 15
0
// Process a channel response
// Decode the higher level message elements that when we have determined the message type
// pass to the appropriate handler
RsslRet UPAConsumer::ProcessResponse(RsslChannel* chnl, RsslBuffer* buffer)
{
   RsslRet ret = 0;
   RsslMsg msg = RSSL_INIT_MSG;
   RsslDecodeIterator dIter;
   UPALogin::RsslLoginResponseInfo *loginRespInfo = NULL;

   // bump counter
   //++incomingMessageCount_;
   statsLogger_->IncIncomingMessageCount();

   // reset the decode iterator
   rsslClearDecodeIterator(&dIter);

   // set version info 
   rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion);

   if ((ret = rsslSetDecodeIteratorBuffer(&dIter, buffer)) != RSSL_RET_SUCCESS)
   {
      t42log_error("rsslSetDecodeIteratorBuffer() failed with return code: %d\n", ret);
      return RSSL_RET_FAILURE;
   }

   // Decode the message - note this only decode the outer parts of the message
   ret = rsslDecodeMsg(&dIter, &msg);				
   if (ret != RSSL_RET_SUCCESS)
   {
      t42log_error("rsslDecodeMsg(): Error %d on SessionData fd=%d  Size %d \n", ret, chnl->socketId, buffer->length);
      return RSSL_RET_FAILURE;
   }

   switch ( msg.msgBase.domainType )
   {
   case RSSL_DMT_LOGIN:
      if (login_->processLoginResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
      {
		 t42log_info("ProcessResponse: cl=%d, rec=%d sus=%d notentitled=%d",
		 	login_->IsClosed(), login_->IsClosedRecoverable(), login_->IsSuspect(), login_->IsNotEntitled());
         if (login_->IsNotEntitled())
         {
		 	shouldRecoverConnection_ = RSSL_FALSE;
            return RSSL_RET_FAILURE;
         }
         else if (login_->IsClosed())
         {
            return RSSL_RET_FAILURE;
         }
         else if (login_->IsClosedRecoverable())
         {
            RecoverConnection();
         }
         else if (login_->IsSuspect())
         {
            isInLoginSuspectState_ = RSSL_TRUE;
         }
      }
      else
      {
         if (isInLoginSuspectState_)
         {
            isInLoginSuspectState_ = RSSL_FALSE;
         }
      }
      break;
   case RSSL_DMT_SOURCE:
      //			if (processSourceDirectoryResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
      if (sourceDirectory_->ProcessSourceDirectoryResponse( &msg, &dIter) != RSSL_RET_SUCCESS)
         return RSSL_RET_FAILURE;

      break;
   case RSSL_DMT_DICTIONARY:
      if (upaDictionary_->ProcessDictionaryResponse(&msg, &dIter) != RSSL_RET_SUCCESS)
         return RSSL_RET_FAILURE;

      //TODO check that dictionary processing failure results in connection failure notification



      break;
   case RSSL_DMT_MARKET_PRICE:
      if (!isInLoginSuspectState_)
      {

         // lookup the subscription from the stream id
         RsslUInt32 streamId = msg.msgBase.streamId;


         if (streamId >= 16)
            // its either a regular mp update or an onstream ack
         {
            UPAItem_ptr_t item = streamManager_.GetItem(streamId); 	
            if (item.get() == 0)
            {
               // the item has been released - just ignore the update
               return RSSL_RET_SUCCESS;
            }

            if (item->Subscription()->ProcessMarketPriceResponse(&msg, &dIter) != RSSL_RET_SUCCESS)

               return RSSL_RET_FAILURE;
         }

         // otherwise is an ack or nak to an offstream post
         if (streamId == login_->StreamId())
         {
            // this isnt associated with a subscription so just have to process it here
            if (ProcessOffStreamResponse(&msg, &dIter) != RSSL_RET_SUCCESS)
            {
               return RSSL_RET_FAILURE;
            }
         }


      }
      break;
   case RSSL_DMT_MARKET_BY_ORDER:
      if (!isInLoginSuspectState_)
      {
         // lookup the subscription from the stream id
         RsslUInt32 streamId = msg.msgBase.streamId;

         UPAItem_ptr_t item = streamManager_.GetItem(streamId); 


         if (item.get() == 0)
         {
            // the item has been released - just ignore the update
            return RSSL_RET_SUCCESS;
         }

         if (item->Subscription()->ProcessMarketByOrderResponse(&msg, &dIter) != RSSL_RET_SUCCESS)
            return RSSL_RET_FAILURE;
      }
      break;
   case RSSL_DMT_MARKET_BY_PRICE:
      if (!isInLoginSuspectState_)
      {
         // lookup the subscription from the stream id
         RsslUInt32 streamId = msg.msgBase.streamId;

         UPAItem_ptr_t item = streamManager_.GetItem(streamId); 


         if (item.get() == 0)
         {
            // the item has been released - just ignore the update
            return RSSL_RET_SUCCESS;
         }

         if (item->Subscription()->ProcessMarketByPriceResponse(&msg, &dIter) != RSSL_RET_SUCCESS)
            return RSSL_RET_FAILURE;
      }
      break;
   case RSSL_DMT_YIELD_CURVE:

      break;
   case RSSL_DMT_SYMBOL_LIST:

      break;
   default:
      t42log_warn("Unhandled Domain Type: %d\n", msg.msgBase.domainType);
      break;
   }

   return RSSL_RET_SUCCESS;
}
Esempio n. 16
0
/*
 * Processes a response from a channel.  This consists of
 * performing a high level decode of the message and then
 * calling the applicable specific function for further
 * processing.
 * chnl - The channel of the response
 * buffer - The message buffer containing the response
 */
static RsslRet processResponse(RsslChannel* chnl, RsslBuffer* buffer)
{
	RsslRet ret = 0;
	RsslMsg msg = RSSL_INIT_MSG;
	RsslDecodeIterator dIter;
	RsslLoginResponseInfo *loginRespInfo = NULL;
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion);

	if((ret = rsslSetDecodeIteratorBuffer(&dIter, buffer)) != RSSL_RET_SUCCESS)
	{
		printf("\nrsslSetDecodeIteratorBuffer() failed with return code: %d\n", ret);
		return RSSL_RET_FAILURE;
	}
	ret = rsslDecodeMsg(&dIter, &msg);				
	if (ret != RSSL_RET_SUCCESS)
	{
		printf("\nrsslDecodeMsg(): Error %d on SessionData fd="SOCKET_PRINT_TYPE" Size %d \n", ret, chnl->socketId, buffer->length);	
		return RSSL_RET_FAILURE;
	}

	switch ( msg.msgBase.domainType )
	{
		case RSSL_DMT_LOGIN:
			if (processLoginResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
			{
				if (isLoginStreamClosed())
				{
					return RSSL_RET_FAILURE;
				}
				else if (isLoginStreamClosedRecoverable())
				{
					recoverConnection();
				}
				else if (isLoginStreamSuspect())
				{
					loginRespInfo = getLoginResponseInfo();
					/* if not single open provider, close source directory stream and item streams */
					if (!loginRespInfo->SingleOpen)
					{
						if (closeSourceDirectoryStream(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;

						if (closeSymbolListStream(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;

						if (closeYieldCurveItemStreams(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;

						if (closeMarketPriceItemStreams(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;

						if (closeMarketByOrderItemStreams(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;

						if (closeMarketByPriceItemStreams(rsslConsumerChannel) != RSSL_RET_SUCCESS)
							return RSSL_RET_FAILURE;
					}
					isInLoginSuspectState = RSSL_TRUE;
				}
			}
			else
			{
				if (isInLoginSuspectState)
				{
					isInLoginSuspectState = RSSL_FALSE;
				}
			}
			break;
		case RSSL_DMT_SOURCE:
			if (processSourceDirectoryResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
				return RSSL_RET_FAILURE;

			/* if we have loaded the dictionaries, now that we have the directory, set up posting if its enabled */
			if ((isFieldDictionaryLoaded() || isEnumTypeDictionaryLoaded()) && ((onPostEnabled || offPostEnabled) && !postInit))
			{
				/* Initialize Post Processing after sending the login request message */
				/* ensure that provider supports posting - if not, disable posting */
				RsslLoginResponseInfo* loginInfo = getLoginResponseInfo();
					
				if (loginInfo->SupportOMMPost == RSSL_TRUE)
				{
					/* This sets up our basic timing so post messages will be sent periodically */
					initPostHandler();
					/* posting has been initialized */
					postInit = RSSL_TRUE;
				}
				else
				{
					/* provider does not support posting, disable it */
					onPostEnabled = RSSL_FALSE;
					offPostEnabled = RSSL_FALSE;
					disableOnstreamPost();
					disableOffstreamPost();
					printf("\nConnected Provider does not support OMM Posting.  Disabling Post functionality.\n");
				}
			}

			break;
		case RSSL_DMT_DICTIONARY:
			if (processDictionaryResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
				return RSSL_RET_FAILURE;

			/* Now that we have downloaded dictionaries and directory set up posting if its enabled */
			if ((onPostEnabled || offPostEnabled) && !postInit)
			{
				/* Initialize Post Processing after sending the login request message */
				/* ensure that provider supports posting - if not, disable posting */
				RsslLoginResponseInfo* loginInfo = getLoginResponseInfo();
					
				if (loginInfo->SupportOMMPost == RSSL_TRUE)
				{
					/* This sets up our basic timing so post messages will be sent periodically */
					initPostHandler();
					/* posting has been initialized */
					postInit = RSSL_TRUE;
				}
				else
				{
					/* provider does not support posting, disable it */
					onPostEnabled = RSSL_FALSE;
					offPostEnabled = RSSL_FALSE;
					disableOnstreamPost();
					disableOffstreamPost();
					printf("\nConnected Provider does not support OMM Posting.  Disabling Post functionality.\n");
				}
			}

			break;
		case RSSL_DMT_MARKET_PRICE:
			if (!isInLoginSuspectState)
			{
				if (processMarketPriceResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
					return RSSL_RET_FAILURE;
			}
			break;
		case RSSL_DMT_MARKET_BY_ORDER:
			if (!isInLoginSuspectState)
			{
				if (processMarketByOrderResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
					return RSSL_RET_FAILURE;
			}
			break;
		case RSSL_DMT_MARKET_BY_PRICE:
			if (!isInLoginSuspectState)
			{
				if (processMarketByPriceResponse(chnl, &msg, &dIter)  != RSSL_RET_SUCCESS)
					return RSSL_RET_FAILURE;
			}
			break;
		case RSSL_DMT_YIELD_CURVE:
			if(!isInLoginSuspectState)
			{
				if (processYieldCurveResponse(chnl, &msg, &dIter) != RSSL_RET_SUCCESS)
					return RSSL_RET_FAILURE;
			}
			break;
		case RSSL_DMT_SYMBOL_LIST:
			if(!isInLoginSuspectState)
			{
				if (processSymbolListResponse(&msg, &dIter) != RSSL_RET_SUCCESS)
					return RSSL_RET_FAILURE;
			}
			break;
		default:
			printf("Unhandled Domain Type: %d\n", msg.msgBase.domainType);
			break;
	}

	return RSSL_RET_SUCCESS;
}
Esempio n. 17
0
RsslRet wlProcessSymbolListMsg(WlBase *pBase, WlItems *pItems, RsslMsg *pRsslMsg,
		WlSymbolListRequest *pRequest, RsslErrorInfo *pErrorInfo)
{
	if (!(pRequest->flags & (RDM_SYMBOL_LIST_DATA_STREAMS | RDM_SYMBOL_LIST_DATA_SNAPSHOTS)))
		return RSSL_RET_SUCCESS;

	switch(pRsslMsg->msgBase.msgClass)
	{
		case RSSL_MC_REFRESH:
		case RSSL_MC_UPDATE:
		{
			RsslDecodeIterator dIter;
			RsslRet ret;
			RsslMap map;
			RsslMapEntry mapEntry;
			RsslRequestMsg requestMsg;
			WlItemRequest matchRequest;
			RsslQos itemQos;
			WlService *pWlService = pRequest->itemBase.pRequestedService->pMatchingService;
			RDMCachedService *pCachedService = pWlService->pService;

			/* Data streams are requested by service name, so need the service's name. */
			if (!pCachedService->hasServiceName)
			{
				rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_FAILURE, __FILE__, __LINE__, 
						"Service for Symbol List stream is missing name. Cannot create data streams.");
				return RSSL_RET_FAILURE;
			}

			if (pRsslMsg->msgBase.containerType != RSSL_DT_MAP)
				return RSSL_RET_SUCCESS;

			rsslClearDecodeIterator(&dIter);
			rsslSetDecodeIteratorRWFVersion(&dIter, pBase->pRsslChannel->majorVersion,
					pBase->pRsslChannel->minorVersion);
			rsslSetDecodeIteratorBuffer(&dIter, &pRsslMsg->msgBase.encDataBody);

			rsslClearRequestMsg(&requestMsg);

			requestMsg.msgBase.domainType = RSSL_DMT_MARKET_PRICE;
			requestMsg.msgBase.containerType = RSSL_DT_NO_DATA;
			requestMsg.flags = RSSL_RQMF_HAS_QOS;

			/* Use best QoS available from service. */
			if (pWlService->pService->rdm.info.qosCount)
				itemQos = pWlService->pService->rdm.info.qosList[0];
			else
			{
				rsslClearQos(&itemQos);
				itemQos.timeliness = RSSL_QOS_TIME_REALTIME;
				itemQos.rate = RSSL_QOS_RATE_TICK_BY_TICK;
			}

			if (pRequest->flags & RDM_SYMBOL_LIST_DATA_STREAMS)
				requestMsg.flags |= RSSL_RQMF_STREAMING;

			/* Create a request structure for searching the table of open provider streams
			 * If we find a match, we don't want to request the item again. */
			rsslClearQos(&matchRequest.qos);
			matchRequest.requestMsgFlags = RSSL_RQMF_HAS_QOS;
			matchRequest.qos = itemQos;
			rsslClearQos(&requestMsg.qos);
			requestMsg.qos = itemQos;

			matchRequest.base.domainType = RSSL_DMT_MARKET_PRICE;
			rsslClearMsgKey(&matchRequest.msgKey);
			matchRequest.msgKey.flags = RSSL_MKF_HAS_NAME | RSSL_MKF_HAS_SERVICE_ID;
			matchRequest.msgKey.serviceId = (RsslUInt16)pWlService->pService->rdm.serviceId;

			if (pRequest->itemBase.pRequestedService->flags & WL_RSVC_HAS_NAME)
			{
				matchRequest.msgKey.flags &= ~RSSL_MKF_HAS_SERVICE_ID;
				matchRequest.pRequestedService = pRequest->itemBase.pRequestedService;
			}

			if ((ret = rsslDecodeMap(&dIter, &map)) != RSSL_RET_SUCCESS)
			{
				rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__, 
						"Error decoding symbol list map -- %d.", ret);
				return ret;
			}

			if (map.keyPrimitiveType != RSSL_DT_BUFFER
					&& map.keyPrimitiveType != RSSL_DT_ASCII_STRING
					&& map.keyPrimitiveType != RSSL_DT_RMTES_STRING)
			{
				rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__, 
						"Incorrect Symbol List map key type %u.", map.keyPrimitiveType);
				return RSSL_RET_INVALID_DATA;
			}

			while ((ret = rsslDecodeMapEntry(&dIter, &mapEntry, &matchRequest.msgKey.name)) !=
					RSSL_RET_END_OF_CONTAINER)
			{
				if (ret != RSSL_RET_SUCCESS)
				{
					rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, ret, __FILE__, __LINE__, 
							"Error decoding symbol list map entry -- %d.", ret);
					return ret;
				}

				switch(mapEntry.action)
				{
					case RSSL_MPEA_ADD_ENTRY:
					case RSSL_MPEA_UPDATE_ENTRY:
					{
						WlItemRequestCreateOpts opts;
						RsslUInt32 hashSum;
						RsslHashLink *pHashLink;

						hashSum = wlProviderRequestHashSum(&matchRequest);

						/* If streaming items were requested, check that a provider-driven
						 * stream is not already open before requesting. */
						if (pRequest->flags & RDM_SYMBOL_LIST_DATA_STREAMS)
						{
							pHashLink = rsslHashTableFind(&pItems->providerRequestsByAttrib,
									(void*)&matchRequest, &hashSum);

							if (pHashLink)
								continue;

						}

						requestMsg.msgBase.streamId = wlBaseTakeProviderStreamId(pBase);

						requestMsg.msgBase.msgKey = matchRequest.msgKey;
						requestMsg.msgBase.msgKey.flags &= ~RSSL_MKF_HAS_SERVICE_ID;

						wlClearItemRequestCreateOptions(&opts);
						opts.pRequestMsg = &requestMsg;
						opts.pUserSpec = NULL;
						opts.slDataStreamFlags = pRequest->flags;
						opts.majorVersion = pBase->pRsslChannel->majorVersion;
						opts.minorVersion = pBase->pRsslChannel->minorVersion;
						opts.pServiceName = &pCachedService->rdm.info.serviceName;


						if ((ret = wlItemRequestCreate(pBase, pItems, &opts, pErrorInfo))
									!= RSSL_RET_SUCCESS)
							return ret;

						break;
					}

					case RSSL_MPEA_DELETE_ENTRY:
						/* No action (delete action does not close streams). */
						break;
					default:
						rsslSetErrorInfo(pErrorInfo, RSSL_EIC_FAILURE, RSSL_RET_INVALID_DATA, __FILE__, __LINE__, 
								"Unknown mapEntry action %u.", mapEntry.action);
						return RSSL_RET_INVALID_DATA;
						break;
				}
			}

			return RSSL_RET_SUCCESS;
		}

		default:
			return RSSL_RET_SUCCESS;
	}
}