示例#1
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;
	}
}
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;
}
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; 
}