RsslRet snapshotSessionProcessWriteReady(SnapshotSession *pSession) { RsslRet ret = RSSL_RET_FAILURE; RsslError rsslError; switch(pSession->pRsslChannel->state) { case RSSL_CH_STATE_ACTIVE: ret = rsslFlush(pSession->pRsslChannel, &rsslError); /* Read values less than RSSL_RET_SUCCESS are codes to handle. */ if (ret < RSSL_RET_SUCCESS) { /* Flush failed; close the channel. */ printf("<%s> rsslFlush() failed: %d(%s).\n\n", pSession->name, ret, rsslRetCodeToString(ret)); rsslCloseChannel(pSession->pRsslChannel, &rsslError); pSession->pRsslChannel = NULL; return ret; } else if (ret == 0) pSession->setWriteFd = RSSL_FALSE; /* Done flushing. */ return RSSL_RET_SUCCESS; case RSSL_CH_STATE_INITIALIZING: return snapshotSessionInitializeChannel(pSession); default: printf("<%s> Unhandled channel state %u.\n\n", pSession->name, ret, rsslRetCodeToString(ret)); exit(-1); return RSSL_RET_FAILURE; } }
/* * Handles the run-time for the rsslConsumer. Closes all streams * for the consumer after run-time has elapsed. */ static void handleRuntime() { time_t currentTime = 0; RsslRet retval = 0; RsslError error; /* get current time */ time(¤tTime); if (currentTime >= rsslConsumerRuntime) { if (rsslConsumerChannel != NULL && rsslConsumerChannel->socketId != -1 && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) { /* close all streams */ closeOffstreamPost(rsslConsumerChannel); /* close all item streams */ closeSymbolListStream(rsslConsumerChannel); closeMarketPriceItemStreams(rsslConsumerChannel); closeMarketByOrderItemStreams(rsslConsumerChannel); closeMarketByPriceItemStreams(rsslConsumerChannel); closeYieldCurveItemStreams(rsslConsumerChannel); /* close dictionary stream */ if (!isFieldDictionaryLoadedFromFile()) closeDictionaryStream(rsslConsumerChannel, FIELD_DICTIONARY_STREAM_ID); if (!isEnumTypeDictionaryLoadedFromFile()) closeDictionaryStream(rsslConsumerChannel, ENUM_TYPE_DICTIONARY_STREAM_ID); /* close source directory stream */ closeSourceDirectoryStream(rsslConsumerChannel); /* close login stream */ /* note that closing login stream will automatically close all other streams at the provider */ if (closeLoginStream(rsslConsumerChannel) != RSSL_RET_SUCCESS) { cleanUpAndExit(); } /* flush before exiting */ if (FD_ISSET(rsslConsumerChannel->socketId, &wrtfds)) { retval = 1; while (retval > RSSL_RET_SUCCESS) { retval = rsslFlush(rsslConsumerChannel, &error); } if (retval < RSSL_RET_SUCCESS) { printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } } } printf("\nrsslConsumer run-time expired...\n"); cleanUpAndExit(); } }
// Send a message on a channel RsslRet SendUPAMessage(RsslChannel* UPAChannel, RsslBuffer* msgBuffer) { RsslError error; RsslRet retval = 0; RsslUInt32 bytesWritten = 0; RsslUInt32 uncompressedBytesWritten = 0; RsslUInt8 writeFlags = RSSL_WRITE_NO_FLAGS; /* send the request */ if ((retval = rsslWrite(UPAChannel, msgBuffer, RSSL_HIGH_PRIORITY, writeFlags, &bytesWritten, &uncompressedBytesWritten, &error)) > RSSL_RET_FAILURE) { // set write fd if there's still data queued // flush is done by application if (retval > RSSL_RET_SUCCESS) { FD_SET(UPAChannel->socketId, &wrtfds); } } else { if (retval == RSSL_RET_WRITE_CALL_AGAIN) { // call flush and write again while (retval == RSSL_RET_WRITE_CALL_AGAIN) { if ((retval = rsslFlush(UPAChannel, &error)) < RSSL_RET_SUCCESS) { t42log_error("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } retval = rsslWrite(UPAChannel, msgBuffer, RSSL_HIGH_PRIORITY, writeFlags, &bytesWritten, &uncompressedBytesWritten, &error); } //set write fd if there's still data queued //flush is done by application if (retval > RSSL_RET_SUCCESS) { FD_SET(UPAChannel->socketId, &wrtfds); } } else if (retval == RSSL_RET_WRITE_FLUSH_FAILED && UPAChannel->state != RSSL_CH_STATE_CLOSED) { // set write fd if flush failed // flush is done by application FD_SET(UPAChannel->socketId, &wrtfds); } else // close the connection and return { // rsslWrite failed, release buffer t42log_error("rsslWrite() failed with return code %d - <%s>\n", retval, error.text); rsslReleaseBuffer(msgBuffer, &error); return RSSL_RET_FAILURE; } } t42log_debug("SendMessage - %lu bytes written, %lu bytes uncompressed \n", bytesWritten, uncompressedBytesWritten); if ((retval = rsslFlush(UPAChannel, &error)) < RSSL_RET_SUCCESS) { //printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } else if (retval == RSSL_RET_SUCCESS) { //clear write fd FD_CLR(UPAChannel->socketId, &wrtfds); } return RSSL_RET_SUCCESS; }
//END APIQA int main(int argc, char **argv) { struct timeval time_interval; RsslError error; fd_set useRead; fd_set useExcept; fd_set useWrt; int selRet; char errTxt[256]; RsslBuffer errorText = {255, (char*)errTxt}; RsslRet retval = 0; RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO; int i; RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS; time_t currentTime; #ifdef _WIN32 int rcvBfrSize = 65535; int sendBfrSize = 65535; #endif snprintf(srvrHostname, 128, "%s", defaultSrvrHostname); snprintf(srvrPortNo, 128, "%s", defaultSrvrPortNo); snprintf(serviceName, 128, "%s", defaultServiceName); snprintf(interfaceName, 128, "%s", defaultInterface); setUsername((char *)""); setAuthenticationToken((char *)""); setAuthenticationExtended((char *)""); setApplicationId((char *)""); snprintf(proxyHostname, 128, "%s", defaultProxyHost); snprintf(proxyPort, 128, "%s", defaultProxyPort); /* Check usage and retrieve operating parameters */ if (argc == 1) /* use default operating parameters */ { snprintf(itemName, 128, "%s", defaultItemName); /* add item name in market price handler */ addMarketPriceItemName(itemName, RSSL_FALSE); mpItemReq = RSSL_TRUE; printf("\nUsing default operating parameters...\n\n"); printf("srvrHostname: %s\n", srvrHostname); printf("srvrPortNo: %s\n", srvrPortNo); printf("serviceName: %s\n", serviceName); printf("itemName: %s\n", itemName); printf("connType: %d\n", connType); } else if (argc > 1) /* all operating parameters entered by user */ { i = 1; while(i < argc) { if(strcmp("-libsslName", argv[i]) == 0) { i += 2; snprintf(libsslName, 128, "%s", argv[i-1]); initOpts.jitOpts.libsslName = libsslName; } //APIQA else if (strcmp("-reissueDir", argv[i]) == 0) { printf("Found -reissueDir "); _initialDirFilter = atoi(argv[++i]); printf("%d ", _initialDirFilter); _reissueDirFilter = atoi(argv[++i]); printf("%d\n", _reissueDirFilter); setDirectoryFilter(_initialDirFilter, _reissueDirFilter); break; } else if (strcmp("-reissueDict", argv[i]) == 0) { printf("Found -reissueDict "); _initialDictFilter = atoi(argv[++i]); printf("%d ", _initialDictFilter); _reissueDictFilter = atoi(argv[++i]); printf("%d\n", _reissueDictFilter); setDictionaryFilter(_initialDictFilter, _reissueDictFilter); break; } else if (strcmp("-xmlTrace", argv[i]) == 0) { xmlTrace = RSSL_TRUE; ++i; } else if (strcmp("-loadDictFromFile", argv[i]) == 0) { _loadDictFromFile = RSSL_TRUE; ++i; } else if (strcmp("-reissueQos", argv[i]) == 0) { _reissueQos = RSSL_TRUE; _qosRate = atoi(argv[++i]); _qosTimeliness = atoi(argv[++i]); printf("\nReissueQoS for rate = %d and timeline = %d\n", _qosRate, _qosTimeliness); setReissueQos(_qosRate, _qosTimeliness); break; } else if (strcmp("-reissueQosAndWorstQos", argv[i]) == 0) { _reissueQosAndWorstQos = RSSL_TRUE; _qosRate = atoi(argv[++i]); _qosTimeliness = atoi(argv[++i]); _worstQosRate = atoi(argv[++i]); _worstQosTimeliness = atoi(argv[++i]); printf("\nReissueQoS for rate = %d and timeline = %d\n", _qosRate, _qosTimeliness); printf("ReissueWorstQos QoS for worstRate = %d and worstTimeliness = %d\n", _worstQosRate, _worstQosTimeliness); setReissueQosAndWorstQos(_qosRate, _qosTimeliness, _worstQosRate, _worstQosTimeliness); break; } else if (strcmp("-sendGenericMsgOnLogin", argv[i]) == 0) { _sendGenMsgOnLogin = RSSL_TRUE; break; } else if (strcmp("-sendGenericMsgOnDirectory", argv[i]) == 0) { _sendGenMsgOnDirectory = RSSL_TRUE; break; } else if (strcmp("-requestDict", argv[i]) == 0) { _initialDictFilter = atoi(argv[++i]); break; } else if (strcmp("-requestDir", argv[i]) == 0) { _initialDirFilter = atoi(argv[++i]); break; } else if (strcmp("-reissueServiceId", argv[i]) == 0) { _changeServiceId = atoi(argv[++i]); printf("\nReissueServiceId to service ID = %d\n", _changeServiceId); setReissueChangeServiceName(_changeServiceId); break; } else if (strcmp("-privateStreamForItemReq", argv[i]) == 0) { setPriviateStream(); ++i; } else if (strcmp("-requestSameKeyWithDiffStreamId", argv[i]) == 0) { setReqSameKeyWithDiffStreamId(); snprintf(itemName, 128, "%s", defaultItemName); addMarketPriceItemName(itemName, RSSL_FALSE); break; } else if (strcmp("-specificServiceId", argv[i]) == 0) { setSpecificServiceId(atoi(argv[++i])); ++i; } else if (strcmp("-sendDirReqWithoutLogin", argv[i]) == 0) { _sendDirReqWithoutLogin = RSSL_TRUE; ++i; } else if (strcmp("-sendDictReqWithoutLogin", argv[i]) == 0) { _sendDictReqWithoutLogin = RSSL_TRUE; ++i; } else if (strcmp("-sendItemReqWithoutLogin", argv[i]) == 0) { _sendItemReqWithoutLogin = RSSL_TRUE; ++i; } //END APIQA else if(strcmp("-libcryptoName", argv[i]) == 0) { i += 2; snprintf(libcryptoName, 128, "%s", argv[i-1]); initOpts.jitOpts.libcryptoName = libcryptoName; } else if(strcmp("-uname", argv[i]) == 0) { i += 2; setUsername(argv[i-1]); } else if(strcmp("-at", argv[i]) == 0) { i += 2; setAuthenticationToken(argv[i-1]); } else if(strcmp("-ax", argv[i]) == 0) { i += 2; setAuthenticationExtended(argv[i-1]); } else if(strcmp("-aid", argv[i]) == 0) { i += 2; setApplicationId(argv[i-1]); } else if(strcmp("-h", argv[i]) == 0) { i += 2; snprintf(srvrHostname, 128, "%s", argv[i-1]); } else if(strcmp("-p", argv[i]) == 0) { i += 2; snprintf(srvrPortNo, 128, "%s", argv[i-1]); } else if(strcmp("-ph", argv[i]) == 0) { i += 2; snprintf(proxyHostname, 128, "%s", argv[i-1]); } else if(strcmp("-pp", argv[i]) == 0) { i += 2; snprintf(proxyPort, 128, "%s", argv[i-1]); } else if(strcmp("-s", argv[i]) == 0) { i += 2; snprintf(serviceName, 128, "%s", argv[i-1]); } else if (strcmp("-c", argv[i]) == 0) { i += 1; if (0 == strcmp(argv[i], "socket") || 0 == strcmp(argv[i], "0")) connType = RSSL_CONN_TYPE_SOCKET; else if (0 == strcmp(argv[i], "http") || 0 == strcmp(argv[i], "2")) connType = RSSL_CONN_TYPE_HTTP; else if (0 == strcmp(argv[i], "encrypted") || 0 == strcmp(argv[i], "1")) connType = RSSL_CONN_TYPE_ENCRYPTED; else if (0 == strcmp(argv[i], "reliableMCast") || 0 == strcmp(argv[i], "4")) connType = RSSL_CONN_TYPE_RELIABLE_MCAST; else { connType = (RsslConnectionTypes)atoi(argv[i]); } i += 1; } else if (strcmp("-yc", argv[i]) == 0) { i += 2; /* add item name in yield curve handler */ addYieldCurveItemName(argv[i-1], RSSL_FALSE); ycItemReq = RSSL_TRUE; } else if(strcmp("-mp", argv[i]) == 0) { i += 2; /* add item name in market price handler */ addMarketPriceItemName(argv[i-1], RSSL_FALSE); mpItemReq = RSSL_TRUE; } else if(strcmp("-mbo", argv[i]) == 0) { i += 2; /* add item name in market by order handler */ addMarketByOrderItemName(argv[i-1], RSSL_FALSE); mboItemReq = RSSL_TRUE; } else if(strcmp("-mbp", argv[i]) == 0) { i += 2; /* add item name in market by price handler */ addMarketByPriceItemName(argv[i-1], RSSL_FALSE); mbpItemReq = RSSL_TRUE; } else if(strcmp("-sl", argv[i]) == 0) { i++; slReq = RSSL_TRUE; /* check the rest of the command line arguments */ if(i != argc) { /* check to see if next strings is the symbol list name */ if(!(strncmp("-", argv[i], 1))) { /* user didn't specifiy name */ setSymbolListInfo(RSSL_FALSE, slReq); } else { i++; setSymbolListName(argv[i-1]); setSymbolListInfo(RSSL_TRUE, slReq); } } else { /* no more command line arguments, so user didn't specifiy SL name */ setSymbolListInfo(RSSL_FALSE, slReq); } } else if(strcmp("-view", argv[i]) == 0) { i++; setViewRequest(); } else if (strcmp("-post", argv[i]) == 0) { i++; onPostEnabled = RSSL_TRUE; enableOnstreamPost(); } else if (strcmp("-x", argv[i]) == 0) { i++; xmlTrace = RSSL_TRUE; snprintf(traceOutputFile, 128, "RsslConsumer\0"); } else if (strcmp("-td", argv[i]) == 0) { i++; showTransportDetails = RSSL_TRUE; } else if (strcmp("-offpost", argv[i]) == 0) { i++; offPostEnabled = RSSL_TRUE; } else if(strcmp("-snapshot", argv[i]) == 0) { i++; setMPSnapshotRequest(); setMBOSnapshotRequest(); setMBPSnapshotRequest(); setSLSnapshotRequest(); setYCSnapshotRequest(); } else if(strcmp("-mpps", argv[i]) == 0) { i += 2; /* add item name in market price handler */ addMarketPriceItemName(argv[i-1], RSSL_TRUE); mpItemReq = RSSL_TRUE; } else if(strcmp("-mbops", argv[i]) == 0) { i += 2; /* add item name in market by order handler */ addMarketByOrderItemName(argv[i-1], RSSL_TRUE); mboItemReq = RSSL_TRUE; } else if(strcmp("-mbpps", argv[i]) == 0) { i += 2; /* add item name in market by price handler */ addMarketByPriceItemName(argv[i-1], RSSL_TRUE); mbpItemReq = RSSL_TRUE; } else if (strcmp("-ycps", argv[i]) == 0) { i += 2; /* add item name in yield curve handler */ addYieldCurveItemName(argv[i-1], RSSL_TRUE); ycItemReq = RSSL_TRUE; } else if(strcmp("-runtime", argv[i]) == 0) { i += 2; timeToRun = atoi(argv[i-1]); } else { printf("Error: Unrecognized option: %s\n\n", argv[i]); printf("Usage: %s or\n%s [-uname <LoginUsername>] [-h <SrvrHostname>] [-p <SrvrPortNo>] [-c <ConnType>] [-s <ServiceName>] [-view] [-post] [-offpost] [-snapshot] [-sl [<SymbolList Name>]] [-mp|-mpps <MarketPrice ItemName>] [-mbo|-mbops <MarketByOrder ItemName>] [-mbp|-mbpps <MarketByPrice ItemName>] [-runtime <seconds>] [-td]\n", argv[0], argv[0]); printf("\n -mp or -mpps For each occurance, requests item using Market Price domain. (-mpps for private stream)\n"); printf("\n -mbo or -mbops For each occurance, requests item using Market By Order domain. (-mbops for private stream)\n"); printf("\n -mbp or -mbpps For each occurance, requests item using Market By Price domain. (-mbpps for private stream)\n"); printf("\n -yc or -ycps For each occurance, requests item using Yield Curve domain. (-ycps for private stream)\n"); printf("\n -view specifies each request using a basic dynamic view.\n"); printf("\n -post specifies that the application should attempt to send post messages on the first requested Market Price item (i.e., on-stream)\n"); printf("\n -offpost specifies that the application should attempt to send post messages on the login stream (i.e., off-stream)\n"); printf("\n -snapshot specifies each request using non-streaming.\n"); printf("\n -sl requests symbol list using Symbol List domain. (symbol list name optional)\n"); printf("\n -td prints out additional transport details from rsslReadEx() and rsslWriteEx() function calls \n"); printf("\n -x provides an XML trace of messages.\n"); printf("\n -at Specifies the Authentication Token. If this is present, the login user name type will be RDM_LOGIN_USER_AUTHN_TOKEN.\n"); printf("\n -ax Specifies the Authentication Extended information.\n"); printf("\n -aid Specifies the Application ID.\n"); printf("\n -runtime adjusts the time the application runs.\n"); //APIQA printf("-sendGenericMsgOnLogin\n"); printf("-sendGenericMsgOnDirectory\n"); printf("-requestDict <verbosity>\n"); printf("-requestDir <filters>\n"); printf("-reissueServiceId <service ID>\n"); printf("-reissueDir <initial filter> <reissue filter>\n"); printf("-reissueDict <initial filter> <reissue filter>\n"); printf("-reissueQos <rate> <timeliness>\n"); printf("-reissueQosAndWorstQos <rate> <timeliness> <worstRate> <worstTimeliness>\n"); printf("\nRate value definition\n\t- rate == 0 then RSSL_QOS_RATE_TICK_BY_TICK\n\t- rate == -1 then RSSL_QOS_RATE_JIT_CONFLATED\n\t- if 0 < rate <= 65535, RSSL_QOS_RATE_TIME_CONFLATED using the rate for rateInfo\n"); printf("\nTimeliness value definition\n\t- timeliness == 0 then RSSL_QOS_TIME_REALTIME\n\t- timeliness == -1 then RSSL_QOS_TIME_DELAYED_UNKNOWN\n\t- if 0 < timeliness <= 65535, RSSL_QOS_TIME_DELAYED using the timelines for timeInfo"); //END APIQA #ifdef _WIN32 /* WINDOWS: wait for user to enter something before exiting */ printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } } //APIQA setDirectoryFilter(_initialDirFilter, _reissueDirFilter); setDictionaryFilter(_initialDictFilter, _reissueDictFilter); //END APIQA printf("Proxy host: %s\n", proxyHostname); printf("Proxy port: %s\n", proxyPort); printf("\nInput arguments...\n\n"); printf("Using Connection Type = %d\n", connType); printf("srvrHostname: %s\n", srvrHostname); printf("srvrPortNo: %s\n", srvrPortNo); printf("serviceName: %s\n", serviceName); /* if no items were requested but a command line was specified, use the default item */ if (!mpItemReq && !mboItemReq && !mbpItemReq && !slReq && !ycItemReq) { snprintf(itemName, 128, "%s", defaultItemName); /* add item name in market price handler */ addMarketPriceItemName(itemName, RSSL_FALSE); mpItemReq = RSSL_TRUE; } /* this application requires at least one market price item to be requested for on-stream posting to be performed */ if (onPostEnabled && !mpItemReq) { printf("\nPosting will not be performed as no Market Price items were requested\n"); onPostEnabled = RSSL_FALSE; } } /* set service name in directory handler */ setServiceName(serviceName); /* load dictionary */ //APIQA //loadDictionary(); if (_loadDictFromFile) { loadDictionary(); } //APIQA /* Initialize RSSL */ /* RSSL_LOCK_NONE is used since this is a single threaded application. */ if (rsslInitializeEx(&initOpts, &error) != RSSL_RET_SUCCESS) { printf("rsslInitialize(): failed <%s>\n", error.text); /* WINDOWS: wait for user to enter something before exiting */ #ifdef _WIN32 printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } FD_ZERO(&readfds); FD_ZERO(&exceptfds); FD_ZERO(&wrtfds); /* Initialize run-time */ initRuntime(); /* this is the main loop */ while(1) { /* this is the connection recovery loop */ while(shouldRecoverConnection) { /* Connect to RSSL server */ printf("\nAttempting to connect to server %s:%s...\n", srvrHostname, srvrPortNo); if ((rsslConsumerChannel = connectToRsslServer(connType, &error)) == NULL) { printf("Unable to connect to RSSL server: <%s>\n",error.text); } else { FD_SET(rsslConsumerChannel->socketId, &readfds); FD_SET(rsslConsumerChannel->socketId, &wrtfds); FD_SET(rsslConsumerChannel->socketId, &exceptfds); } if (rsslConsumerChannel != NULL && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) shouldRecoverConnection = RSSL_FALSE; /* Wait for channel to become active. This finalizes the three-way handshake. */ while (rsslConsumerChannel != NULL && rsslConsumerChannel->state != RSSL_CH_STATE_ACTIVE) { useRead = readfds; useWrt = wrtfds; useExcept = exceptfds; /* Set a timeout value if the provider accepts the connection, but does not initialize it */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval); /* select has timed out, close the channel and attempt to reconnect */ if(selRet == 0) { printf("\nChannel initialization has timed out, attempting to reconnect...\n"); FD_CLR(rsslConsumerChannel->socketId, &readfds); FD_CLR(rsslConsumerChannel->socketId, &exceptfds); if (FD_ISSET(rsslConsumerChannel->socketId, &wrtfds)) FD_CLR(rsslConsumerChannel->socketId, &wrtfds); recoverConnection(); } else /* Received a response from the provider. */ if(selRet > 0 && (FD_ISSET(rsslConsumerChannel->socketId, &useRead) || FD_ISSET(rsslConsumerChannel->socketId, &useWrt) || FD_ISSET(rsslConsumerChannel->socketId, &useExcept))) { if (rsslConsumerChannel->state == RSSL_CH_STATE_INITIALIZING) { FD_CLR(rsslConsumerChannel->socketId,&wrtfds); if ((retval = rsslInitChannel(rsslConsumerChannel, &inProg, &error)) < RSSL_RET_SUCCESS) { printf("\nchannelInactive fd="SOCKET_PRINT_TYPE" <%s>\n", rsslConsumerChannel->socketId,error.text); recoverConnection(); break; } else { switch (retval) { case RSSL_RET_CHAN_INIT_IN_PROGRESS: if (inProg.flags & RSSL_IP_FD_CHANGE) { printf("\nChannel In Progress - New FD: "SOCKET_PRINT_TYPE" Old FD: "SOCKET_PRINT_TYPE"\n",rsslConsumerChannel->socketId, inProg.oldSocket ); FD_CLR(inProg.oldSocket,&readfds); FD_CLR(inProg.oldSocket,&exceptfds); FD_SET(rsslConsumerChannel->socketId,&readfds); FD_SET(rsslConsumerChannel->socketId,&exceptfds); FD_SET(rsslConsumerChannel->socketId,&wrtfds); } else { printf("\nChannel "SOCKET_PRINT_TYPE" In Progress...\n", rsslConsumerChannel->socketId); //Sleep(1000); } break; case RSSL_RET_SUCCESS: { RsslChannelInfo chanInfo; printf("\nChannel "SOCKET_PRINT_TYPE" Is Active\n" ,rsslConsumerChannel->socketId); /* reset should recover connection flag */ shouldRecoverConnection = RSSL_FALSE; /* if device we connect to supports connected component versioning, * also display the product version of what this connection is to */ if ((retval = rsslGetChannelInfo(rsslConsumerChannel, &chanInfo, &error)) >= RSSL_RET_SUCCESS) { RsslUInt32 i; for (i = 0; i < chanInfo.componentInfoCount; i++) { printf("Connected to %s device.\n", chanInfo.componentInfo[i]->componentVersion.data); } } } break; default: printf("\nBad return value fd="SOCKET_PRINT_TYPE" <%s>\n", rsslConsumerChannel->socketId,error.text); cleanUpAndExit(); break; } } } } else if(selRet < 0) { printf("\nSelect error.\n"); cleanUpAndExit(); } handleRuntime(); } /* sleep before trying again */ if (shouldRecoverConnection) { for(i = 0; i < CONSUMER_CONNECTION_RETRY_TIME; ++i) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif handleRuntime(); } } } /* WINDOWS: change size of send/receive buffer since it's small by default */ #ifdef _WIN32 if (rsslIoctl(rsslConsumerChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl(): failed <%s>\n", error.text); } if (rsslIoctl(rsslConsumerChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl(): failed <%s>\n", error.text); } #endif /* Initialize ping handler */ initPingHandler(rsslConsumerChannel); /* Send login request message */ isLoginReissue = RSSL_FALSE; //APIQA /*if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { cleanUpAndExit(); }*/ if (!_sendDirReqWithoutLogin && !_sendDictReqWithoutLogin && !_sendItemReqWithoutLogin) { if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { cleanUpAndExit(); } } else { printf("FALSE\n"); if (_sendDirReqWithoutLogin) { sendSourceDirectoryRequest(rsslConsumerChannel, _sendGenMsgOnDirectory); } else if (_sendDictReqWithoutLogin) { sendDictionaryRequest(rsslConsumerChannel, "RWFFld", FIELD_DICTIONARY_STREAM_ID, _initialDictFilter); sendDictionaryRequest(rsslConsumerChannel, "RWFEnum", ENUM_TYPE_DICTIONARY_STREAM_ID, _initialDictFilter); } else if (_sendItemReqWithoutLogin) { printf("Sending MP REQUEST\n"); sendMarketPriceItemRequests(rsslConsumerChannel); } } //END APIQA /* this is the message processing loop */ while(1) { useRead = readfds; useExcept = exceptfds; useWrt = wrtfds; time_interval.tv_sec = 1; time_interval.tv_usec = 0; /* Call select() to check for any messages */ selRet = select(FD_SETSIZE,&useRead, &useWrt,&useExcept,&time_interval); if (selRet < 0) /* no messages received, continue */ { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; #else if (errno == EINTR) { continue; } #endif } else if (selRet > 0) /* messages received, read from channel */ { if ((rsslConsumerChannel != NULL) && (rsslConsumerChannel->socketId != -1)) { if ((FD_ISSET(rsslConsumerChannel->socketId, &useRead)) || (FD_ISSET(rsslConsumerChannel->socketId, &useExcept))) { if (readFromChannel(rsslConsumerChannel) != RSSL_RET_SUCCESS) recoverConnection(); } /* flush for write file descriptor and active state */ if (rsslConsumerChannel != NULL && FD_ISSET(rsslConsumerChannel->socketId, &useWrt) && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) { if ((retval = rsslFlush(rsslConsumerChannel, &error)) < RSSL_RET_SUCCESS) { printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } else if (retval == RSSL_RET_SUCCESS) { /* clear write fd */ FD_CLR(rsslConsumerChannel->socketId, &wrtfds); } } } } /* break out of message processing loop if should recover connection */ if (shouldRecoverConnection == RSSL_TRUE) { printf("Recovering connection in 5 seconds\n"); connectionRecovery = RSSL_TRUE; #ifdef _WIN32 Sleep(5000); #else sleep(5); #endif break; } /* Handle pings */ handlePings(rsslConsumerChannel); /* Handle run-time */ handleRuntime(); if (onPostEnabled || offPostEnabled) { /* if configured to post, send post messages if its time */ /* Handle Post */ if (handlePosts(rsslConsumerChannel, connectionRecovery) != RSSL_RET_SUCCESS) recoverConnection(); connectionRecovery = RSSL_FALSE; } if ((currentTime = time(NULL)) < 0) { printf("time() failed.\n"); } // send login reissue if login reissue time has passed if (canSendLoginReissue == RSSL_TRUE && currentTime >= (RsslInt)loginReissueTime) { isLoginReissue = RSSL_TRUE; if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { printf("Login reissue failed\n"); } else { printf("Login reissue sent\n"); } canSendLoginReissue = RSSL_FALSE; } } } }
void UPAConsumer::Run() { RsslError error; struct timeval time_interval; RsslRet retval = 0; fd_set useRead; fd_set useExcept; fd_set useWrt; // get hold of the statistics logger statsLogger_ = StatisticsLogger::GetStatisticsLogger(); // todo might want to make these configurable #ifdef _WIN32 int rcvBfrSize = 65535; int sendBfrSize = 65535; #endif int selRet; FD_ZERO(&readfds_); FD_ZERO(&exceptfds_); FD_ZERO(&wrtfds_); // The outer thread loop attempts to make / remake a connection to the rssl server // // Inner loop dispatches requests from the mama queue and reads the socket for incoming responses while (runThread_) { // attempt to make connection while(shouldRecoverConnection_ && runThread_) { login_->UPAChannel(0); sourceDirectory_->UPAChannel(0); upaDictionary_->UPAChannel(0); // connect to server t42log_info("Attempting to connect to server %s:%s...\n", connectionConfig_.Host().c_str(), connectionConfig_.Port().c_str()); if ((rsslConsumerChannel_ = ConnectToRsslServer(connectionConfig_.Host(), connectionConfig_.Port(), interfaceName_, connType_, &error)) == NULL) { t42log_error("Unable to connect to RSSL server: <%s>\n",error.text); } else { if (rsslConsumerChannel_) { // connected - set up socket fds RsslSocket s = rsslConsumerChannel_->socketId; FD_SET(rsslConsumerChannel_->socketId, &readfds_); FD_SET(rsslConsumerChannel_->socketId, &wrtfds_); FD_SET(rsslConsumerChannel_->socketId, &exceptfds_); } } if (rsslConsumerChannel_ != NULL && rsslConsumerChannel_->state == RSSL_CH_STATE_ACTIVE) shouldRecoverConnection_ = RSSL_FALSE; //Wait for channel to become active. while (rsslConsumerChannel_ != NULL && rsslConsumerChannel_->state != RSSL_CH_STATE_ACTIVE && runThread_) { useRead = readfds_; useWrt = wrtfds_; useExcept = exceptfds_; /* Set a timeout value if the provider accepts the connection, but does not initialize it */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval); // select has timed out, close the channel and attempt to reconnect if (selRet == 0) { t42log_warn("Channel initialization has timed out, attempting to reconnect...\n"); if (rsslConsumerChannel_) { FD_CLR(rsslConsumerChannel_->socketId, &readfds_); FD_CLR(rsslConsumerChannel_->socketId, &exceptfds_); if (FD_ISSET(rsslConsumerChannel_->socketId, &wrtfds_)) FD_CLR(rsslConsumerChannel_->socketId, &wrtfds_); } RecoverConnection(); } else // Received a response from the provider. if (rsslConsumerChannel_ && selRet > 0 && (FD_ISSET(rsslConsumerChannel_->socketId, &useRead) || FD_ISSET(rsslConsumerChannel_->socketId, &useWrt) || FD_ISSET(rsslConsumerChannel_->socketId, &useExcept))) { if (rsslConsumerChannel_->state == RSSL_CH_STATE_INITIALIZING) { RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO; FD_CLR(rsslConsumerChannel_->socketId,&wrtfds_); if ((retval = rsslInitChannel(rsslConsumerChannel_, &inProg, &error)) < RSSL_RET_SUCCESS) { // channel init failed, try again t42log_warn("channelInactive fd=%d <%s>\n", rsslConsumerChannel_->socketId,error.text); RecoverConnection(); break; } else { switch ((int)retval) { case RSSL_RET_CHAN_INIT_IN_PROGRESS: if (inProg.flags & RSSL_IP_FD_CHANGE) { t42log_info("Channel In Progress - New FD: %d Old FD: %d\n",rsslConsumerChannel_->socketId, inProg.oldSocket ); FD_CLR(inProg.oldSocket,&readfds_); FD_CLR(inProg.oldSocket,&exceptfds_); FD_SET(rsslConsumerChannel_->socketId,&readfds_); FD_SET(rsslConsumerChannel_->socketId,&exceptfds_); FD_SET(rsslConsumerChannel_->socketId,&wrtfds_); } else { t42log_info("Channel %d In Progress...\n", rsslConsumerChannel_->socketId); } break; case RSSL_RET_SUCCESS: { // connected t42log_info("Channel %d Is Active\n" ,rsslConsumerChannel_->socketId); shouldRecoverConnection_ = RSSL_FALSE; RsslChannelInfo chanInfo; // log channel info if ((retval = rsslGetChannelInfo(rsslConsumerChannel_, &chanInfo, &error)) >= RSSL_RET_SUCCESS) { RsslUInt32 i; for (i = 0; i < chanInfo.componentInfoCount; i++) { t42log_info("Connected to %s device.\n", chanInfo.componentInfo[i]->componentVersion.data); } } login_->UPAChannel(rsslConsumerChannel_); sourceDirectory_->UPAChannel(rsslConsumerChannel_); upaDictionary_->UPAChannel(rsslConsumerChannel_); mama_log (MAMA_LOG_LEVEL_FINEST, "Provider returned \"Connection Successful\""); NotifyListeners(true, "Provider returned \"Connection Successful\""); } break; default: { // Connection has failed char buff[256]={0}; memset(buff,0,sizeof(buff)); sprintf(buff, "Bad return value on connection fd=%d <%s>\n", rsslConsumerChannel_->socketId,error.text); t42log_error("%s\n", buff); NotifyListeners(false, buff); runThread_ = false; } break; } } } } else if (selRet < 0) { t42log_error("Select error.\n"); runThread_ = false; break; } } // wait a while before retry if (shouldRecoverConnection_) { LogReconnection(); WaitReconnectionDelay(); } } // WINDOWS: change size of send/receive buffer since it's small by default #ifdef _WIN32 if (rsslConsumerChannel_ && rsslIoctl(rsslConsumerChannel_, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &error) != RSSL_RET_SUCCESS) { t42log_error("rsslIoctl(): failed <%s>\n", error.text); } if (rsslConsumerChannel_ && rsslIoctl(rsslConsumerChannel_, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &error) != RSSL_RET_SUCCESS) { t42log_error("rsslIoctl(): failed <%s>\n", error.text); } #endif /* Initialize ping handler */ if (rsslConsumerChannel_) InitPingHandler(rsslConsumerChannel_); int64_t queueCount = 0; /* this is the message processing loop */ while (runThread_) { // first dispatch some events off the event queue if (!PumpQueueEvents()) { break; } if ((rsslConsumerChannel_ != NULL) && (rsslConsumerChannel_->socketId != -1)) { // if we have a connection useRead = readfds_; useExcept = exceptfds_; useWrt = wrtfds_; time_interval.tv_sec = 0; time_interval.tv_usec = 100000; // look at the socket state selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval); } else { // no connection, just sleep for 1s #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif continue; } if (!runThread_) { // thread is stopped break; } if (selRet < 0) // no messages received, continue { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; #else if (errno == EINTR) { continue; } #endif } else if (selRet > 0) // messages received { if ((rsslConsumerChannel_ != NULL) && (rsslConsumerChannel_->socketId != -1)) { if ((FD_ISSET(rsslConsumerChannel_->socketId, &useRead)) || (FD_ISSET(rsslConsumerChannel_->socketId, &useExcept))) { // This will empty the read buffer and dispatch incoming events if (ReadFromChannel(rsslConsumerChannel_) != RSSL_RET_SUCCESS) { // the read failed so attempt to recover if required if(RSSL_TRUE == shouldRecoverConnection_) { RecoverConnection(); } else { // otherwise just run out of the thread runThread_ = false; } } } // If there's anything to be written flush the write socket if (rsslConsumerChannel_ != NULL && FD_ISSET(rsslConsumerChannel_->socketId, &useWrt) && rsslConsumerChannel_->state == RSSL_CH_STATE_ACTIVE) { if ((retval = rsslFlush(rsslConsumerChannel_, &error)) < RSSL_RET_SUCCESS) { t42log_error("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } else if (retval == RSSL_RET_SUCCESS) { // and clear the fd FD_CLR(rsslConsumerChannel_->socketId, &wrtfds_); } } } } // break out of message processing loop if should recover connection if (shouldRecoverConnection_ == RSSL_TRUE) { LogReconnection(); WaitReconnectionDelay(); break; } // check if its time to process pings if (rsslConsumerChannel_) { ProcessPings(rsslConsumerChannel_); } } } // thread has stopped RemoveChannel(rsslConsumerChannel_); t42log_debug("Exit UPAConsumer thread\n"); }
void UPAProvider::Run() { struct timeval time_interval; RsslRet retval = 0; fd_set useRead; fd_set useExcept; fd_set useWrt; // prime the counter for ping checking lastPingCheck_ = utils::time::GetMilliCount(); FD_ZERO(&readfds_); FD_ZERO(&exceptfds_); FD_ZERO(&wrtfds_); RsslError error; if (!Bind(portno_, &error)) { t42log_error("Unable to start provider thread, bind return error %d ('%s') \n",error.sysError, error.text); return; } while(runThread_ == true) { useRead = readfds_; useExcept = exceptfds_; useWrt = wrtfds_; time_interval.tv_sec = selTimeoutSec; time_interval.tv_usec = selTimeoutUSec; // now process any queued publish events size_t numEvents = 0; size_t maxDispatchesPerCycle = 50; size_t maxPendingOpens = 500; mama_status status = mamaQueue_getEventCount(requestQueue_, &numEvents); if ((status == MAMA_STATUS_OK) && (numEvents > 0)) { // although we only really want to throttle subscriptions, for simplicity throttle everything here. size_t eventsDispatched = 0; // so keep dispatching while there are events on the queue, we haven t hit the mac per cycle and we havent hit the max pending limit while (numEvents > eventsDispatched && eventsDispatched < maxDispatchesPerCycle ) { mamaQueue_dispatchEvent(requestQueue_); ++eventsDispatched; } t42log_info("dispatched %d requests \n", eventsDispatched); } int selRet = select(FD_SETSIZE,&useRead, &useWrt,&useExcept,&time_interval); if (selRet == 0) { // timed out, no messages received so publish from queue } else if ( selRet > 0) { // read from the socket if ((rsslServer_ != NULL) && (rsslServer_->socketId != -1) && (FD_ISSET(rsslServer_->socketId,&useRead))) { // this is on the listening socket (rsslServer_->socketId) CreateNewClientConnection(); } // so now read on all the channels for( int index = 0; index < maxClientConnections; index ++) { if ((clientConnections_[index].clientChannel != NULL) && (clientConnections_[index].clientChannel->socketId != -1)) { // theres a connection on this index so check the FDs if ((FD_ISSET(clientConnections_[index].clientChannel->socketId, &useRead)) || (FD_ISSET(clientConnections_[index].clientChannel->socketId, &useExcept))) { // Theres something to read ReadFromChannel(clientConnections_[index].clientChannel); } // The UPA provider sample ties these 2 conditions together but the problem then is that the // ping initialization does happen until there is something to write (the write fd is set) and // there is no guarantee when that will happen. So here we check for active state on the channel // and whether the ping settings have been initialized before we check the write fd. Seems safer. if (clientConnections_[index].clientChannel != NULL && clientConnections_[index].clientChannel->state == RSSL_CH_STATE_ACTIVE) { // if we havent set the ping times already (and the channel is now active) set them from the channel settings if (clientConnections_[index].pingsInitialized != RSSL_TRUE) { InitChannelPingTimes(&clientConnections_[index]); t42log_debug("Using %d as pingTimeout for Channel %d\n", clientConnections_[index].clientChannel->pingTimeout,clientConnections_[index].clientChannel->socketId); } // if there is something to write and the channel is active thne flush the write socket if (clientConnections_[index].clientChannel != NULL && FD_ISSET(clientConnections_[index].clientChannel->socketId, &useWrt)) { if ((retval = rsslFlush(clientConnections_[index].clientChannel, &error)) < RSSL_RET_SUCCESS) { // the write failed. Kill the connection t42log_error("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); RemoveChannelConnection(clientConnections_[index].clientChannel); } else if (retval == RSSL_RET_SUCCESS) { // clear the write fd FD_CLR(clientConnections_[index].clientChannel->socketId, &wrtfds_); } } } // if there is something to write and the channel is active thne flush the write socket if (clientConnections_[index].clientChannel != NULL && FD_ISSET(clientConnections_[index].clientChannel->socketId, &useWrt) && clientConnections_[index].clientChannel->state == RSSL_CH_STATE_ACTIVE) { // if we havent set the ping times already (and the channel is now active) set them from the channel settings if (clientConnections_[index].pingsInitialized != RSSL_TRUE) { InitChannelPingTimes(&clientConnections_[index]); t42log_debug("Using %d as pingTimeout for Channel %d\n", clientConnections_[index].clientChannel->pingTimeout,clientConnections_[index].clientChannel->socketId); } if ((retval = rsslFlush(clientConnections_[index].clientChannel, &error)) < RSSL_RET_SUCCESS) { // the write failed. Kill the connection t42log_error("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); RemoveChannelConnection(clientConnections_[index].clientChannel); } else if (retval == RSSL_RET_SUCCESS) { // clear the write fd FD_CLR(clientConnections_[index].clientChannel->socketId, &wrtfds_); } } } } } else { // handle error #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) { continue; } else { t42log_error("select() failed with error code %d\n", WSAGetLastError()); break; } #else if (errno == EINTR) { continue; } else { t42log_error("select() failed with error code %d\n", errno); break; } #endif } HandlePings(); } }