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