static void handleRuntime() { RsslErrorInfo error; time_t currentTime = 0; RsslRet retval = 0; /* get current time */ time(¤tTime); if(chnlCommand.reconnect == RSSL_TRUE) { chnlCommand.reconnect = RSSL_FALSE; printf("Reconnecting in 10 seconds...\n"); chnlCommand.timeToReconnect = 10; } if (chnlCommand.timeToReconnect > 0) { --chnlCommand.timeToReconnect; if (chnlCommand.timeToReconnect == 0) { if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS) { printf("Error rsslReactorConnect(): %s\n", error.rsslError.text); chnlCommand.reconnect = RSSL_TRUE; } } } if(currentTime > rsslProviderRuntime) { if( chnlCommand.reactorChannel != NULL && rsslReactorCloseChannel(pReactor, chnlCommand.reactorChannel, &error) != RSSL_RET_SUCCESS) { printf("Error rsslReactorCloseChannel(): %s\n", error.rsslError.text); } cleanUpAndExit(); } }
/*** MAIN ***/ int main(int argc, char **argv) { RsslErrorInfo error; RsslError rsslErr; RsslCreateReactorOptions reactorOpts; RsslReactorDispatchOptions dispatchOpts; RsslInt32 j; RsslReactorOMMNIProviderRole role; RsslDataDictionary dictionary = RSSL_INIT_DATA_DICTIONARY; char err[128]; RsslBuffer errBuf = {128, &err[0]}; int selRet; time_t currentTime = 0; RsslRet ret; RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS; rsslInitNIChannelCommand(&chnlCommand); handleConfig(argc, argv, &chnlCommand); initializeCache(cacheCommandlineOption); initOpts.jitOpts.libcryptoName = libcryptoName; initOpts.jitOpts.libsslName = libsslName; initOpts.jitOpts.libcurlName = libcurlName; initOpts.rsslLocking = RSSL_LOCK_GLOBAL_AND_CHANNEL; /* Initialize run-time */ initRuntime(); rsslInitializeEx(&initOpts, &rsslErr); /* Setup role */ rsslClearOMMNIProviderRole((RsslReactorOMMNIProviderRole*)&role); role.pLoginRequest = (RsslRDMLoginRequest*)&chnlCommand.loginRequest; role.loginMsgCallback = processLoginResponse; role.pDirectoryRefresh = &chnlCommand.directoryRefresh; role.base.channelEventCallback = channelEventCallback; role.base.defaultMsgCallback = processResponse; printf("Connections:\n"); chnlCommand.pRole = (RsslReactorChannelRole*)&role; chnlCommand.cOpts.rsslConnectOptions.guaranteedOutputBuffers = 500; chnlCommand.cOpts.rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION; chnlCommand.cOpts.rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION; chnlCommand.cOpts.rsslConnectOptions.userSpecPtr = (void*)&chnlCommand; // printf(" %s:%s:%s\n", chnlCommand.hostName, chnlCommand.port, chnlCommand.serviceName); printf(" MarketPriceItems:"); for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j) { RsslNIItemInfo *pItem = &chnlCommand.marketPriceItemInfo[j]; if (pItem->isActive) printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname); } printf(" MarketByOrderItems:"); for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j) { RsslNIItemInfo *pItem = &chnlCommand.marketByOrderItemInfo[j]; if (pItem->isActive) printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname); } printf("\n"); printf("\n"); /* Load local dictionary */ if(rsslLoadFieldDictionary("RDMFieldDictionary", &dictionary, &errBuf) < RSSL_RET_SUCCESS) { printf("Dictionary error: %s\n", errBuf.data); exit(-1); } chnlCommand.dictionary = &dictionary; initializeCacheDictionary(&dictionary); rsslClearCreateReactorOptions(&reactorOpts); reactorOpts.dispatchDecodeMemoryBufferSize = 1024; setupLoginRequest(&chnlCommand, 1); setupDirectoryResponseMsg(&chnlCommand, -1); if (!(pReactor = rsslCreateReactor(&reactorOpts, &error))) { printf("Error: %s", error.rsslError.text); exit(-1); } FD_ZERO(&readFds); FD_ZERO(&writeFds); FD_ZERO(&exceptFds); FD_SET(pReactor->eventFd, &readFds); if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS) printf("Error rsslReactorConnect(): %s\n", error.rsslError.text); rsslClearReactorDispatchOptions(&dispatchOpts); //dispatchOpts.pReactorChannel = &chnlCommand.reactorChannel; printf("Connection started!\n"); while ( RSSL_TRUE ) { struct timeval selectTime; int dispatchCount = 0; fd_set useReadFds = readFds, useWriteFds = writeFds, useExceptFds = exceptFds; selectTime.tv_sec = 1; selectTime.tv_usec = 0; handleRuntime(); selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &selectTime); if (selRet == 0 ) /* no messages received, send updates and continue */ { // Update items updateItemInfo(&chnlCommand); /* Send market price updates for each connected channel */ if (chnlCommand.startWrite == RSSL_TRUE) { if ((chnlCommand.reactorChannel != NULL) && (chnlCommand.reactorChannel->socketId != -1)) { if (sendItemUpdates(pReactor,chnlCommand.reactorChannel) != RSSL_RET_SUCCESS) recoverConnection(pReactor, chnlCommand.reactorChannel, &chnlCommand); } } else { if (cacheInfo.useCache) cacheItemData(&chnlCommand); } } else if (selRet > 0) { RsslRet ret; while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &error)) > 0); if(ret < 0) { printf("dispatch error! %i\n %s\n %s\n", ret, error.rsslError.text, error.errorLocation); /* Reactor has shutdown. Clean up and exit. */ cleanUpAndExit(); } } /* get current time */ if ((currentTime = time(NULL)) < 0) { printf("time() failed.\n"); } // send login reissue if login reissue time has passed if (chnlCommand.canSendLoginReissue == RSSL_TRUE && currentTime >= (RsslInt)chnlCommand.loginReissueTime) { RsslReactorSubmitMsgOptions submitMsgOpts; RsslErrorInfo rsslErrorInfo; rsslClearReactorSubmitMsgOptions(&submitMsgOpts); submitMsgOpts.pRDMMsg = (RsslRDMMsg*)chnlCommand.pRole->ommNIProviderRole.pLoginRequest; if ((ret = rsslReactorSubmitMsg(pReactor,chnlCommand.reactorChannel,&submitMsgOpts,&rsslErrorInfo)) != RSSL_RET_SUCCESS) { printf("Login reissue failed: %d(%s)\n", ret, rsslErrorInfo.rsslError.text); } else { printf("Login reissue sent\n"); } chnlCommand.canSendLoginReissue = RSSL_FALSE; } } }
/*** MAIN ***/ int main(int argc, char **argv) { RsslRet ret; RsslCreateReactorOptions reactorOpts; RsslErrorInfo rsslErrorInfo; RsslReactorOMMConsumerRole consumerRole; RsslRDMLoginRequest loginRequest; RsslRDMDirectoryRequest dirRequest; RsslReactorDispatchOptions dispatchOpts; ChannelStorage *pCommand = &chanCommand; RsslReactorConnectOptions *pOpts = &pCommand->cOpts; RsslReactorConnectInfo *pInfo = &pCommand->cInfo; RsslUInt32 i; /* Initialize RSSL. The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */ if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &rsslErrorInfo.rsslError) != RSSL_RET_SUCCESS) { printf("rsslInitialize(): failed <%s>\n", rsslErrorInfo.rsslError.text); exitApp(-1); } initChannelStorage(&chanCommand); /* Initialize parameters from config. */ parseCommandLine(argc, argv); /* Initialize run-time */ initRuntime(); /* Initialize the default login request(Use 1 as the Login Stream ID). */ if (rsslInitDefaultRDMLoginRequest(&loginRequest, 1) != RSSL_RET_SUCCESS) { printf("rsslInitDefaultRDMLoginRequest() failed\n"); cleanUpAndExit(-1); } if (userName.length) loginRequest.userName = userName; /* Initialize the default directory request(Use 2 as the Directory Stream Id) */ if (rsslInitDefaultRDMDirectoryRequest(&dirRequest, 2) != RSSL_RET_SUCCESS) { printf("rsslInitDefaultRDMDirectoryRequest() failed\n"); cleanUpAndExit(-1); } /* Setup callback functions and use them on all connections*/ rsslClearOMMConsumerRole(&consumerRole); consumerRole.loginMsgCallback = loginMsgCallback; consumerRole.directoryMsgCallback = directoryMsgCallback; // consumerRole.dictionaryMsgCallback = dictionaryMsgCallback; consumerRole.base.channelEventCallback = channelEventCallback; consumerRole.base.defaultMsgCallback = defaultMsgCallback; /* Set the messages to send when the channel is up */ consumerRole.pLoginRequest = &loginRequest; consumerRole.pDirectoryRequest = &dirRequest; printf("Connections:\n"); /* Print out a summary of the connections and desired items. */ printf(" %s:%s\n", pCommand->hostName, pCommand->port); printf(" QueueService: %s\n", pCommand->queueServiceName); printf(" Source Queue: %s\n", pCommand->sourceName.data); printf(" Dest Queues:"); for (i = 0; i < pCommand->destNameCount; ++i) printf(" %s", pCommand->destNames[i].data); printf("\n\n"); /* Initialize connection options and try to load dictionaries. */ pCommand->pRole = (RsslReactorChannelRole*)&consumerRole; pInfo->rsslConnectOptions.guaranteedOutputBuffers = 500; pInfo->rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION; pInfo->rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION; pInfo->rsslConnectOptions.userSpecPtr = &chanCommand; pInfo->initializationTimeout = 5; pOpts->reactorConnectionList = pInfo; pOpts->connectionCount = 1; pOpts->reconnectAttemptLimit = -1; pOpts->reconnectMaxDelay = 5000; pOpts->reconnectMinDelay = 1000; printf("\n"); /* Create an RsslReactor which will manage our channels. */ rsslClearCreateReactorOptions(&reactorOpts); if (!(pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo))) { printf("Error: %s", rsslErrorInfo.rsslError.text); exit(-1); } FD_ZERO(&readFds); FD_ZERO(&exceptFds); /* Set the reactor's event file descriptor on our descriptor set. This, along with the file descriptors * of RsslReactorChannels, will notify us when we should call rsslReactorDispatch(). */ FD_SET(pReactor->eventFd, &readFds); printf("Adding connection to %s:%s...\n", pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.address, pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.serviceName ); if (rsslReactorConnect(pReactor, &pCommand->cOpts, pCommand->pRole, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("Error rsslReactorConnect(): %s\n", rsslErrorInfo.rsslError.text); } printf("\n"); rsslClearReactorDispatchOptions(&dispatchOpts); /* Main loop. The loop * calls select() to wait for notification, then calls rsslReactorDispatch(). */ do { struct timeval selectTime; int dispatchCount = 0; fd_set useReadFds = readFds, useExceptFds = exceptFds; selectTime.tv_sec = 1; selectTime.tv_usec = 0; handleRuntime(); if (!runTimeExpired) { if (handleQueueMessaging(pReactor, &chanCommand) != RSSL_RET_SUCCESS) cleanUpAndExit(-1); } ret = select(FD_SETSIZE, &useReadFds, NULL, &useExceptFds, &selectTime); if (ret < 0) { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; printf("Error: select: %d\n", WSAGetLastError()); #else if (errno == EINTR) continue; perror("select"); #endif cleanUpAndExit(-1); } /* Call rsslReactorDispatch(). This will handle any events that have occurred on its channels. * If there are events or messages for the application to process, they will be delivered * through the callback functions given by the consumerRole object. * A return value greater than RSSL_RET_SUCCESS indicates there may be more to process. */ while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &rsslErrorInfo)) > RSSL_RET_SUCCESS) ; if (ret < RSSL_RET_SUCCESS) { printf("rsslReactorDispatch() failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(-1); } } while(ret >= RSSL_RET_SUCCESS); cleanUpAndExit(-1); }