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