/* Sends a basic Login Request on the given streamID, using the RDM package. */ RsslRet sendLoginRequest(ChannelHandler *pChannelHandler, ChannelInfo *pChannelInfo, RsslInt32 streamId, RsslError *error) { RsslRDMLoginRequest loginRequest; RsslRet ret; RsslBuffer *msgBuf; RsslErrorInfo errorInfo; RsslEncodeIterator eIter; RsslChannelInfo chanInfo; RsslChannel *pChannel = pChannelInfo->pChannel; if ((ret = rsslGetChannelInfo(pChannel, &chanInfo, error)) != RSSL_RET_SUCCESS) { printf("rsslGetChannelInfo() failed: %d(%s)\n", ret, error->text); return RSSL_RET_FAILURE; } /* Send Login Request */ if ((ret = rsslInitDefaultRDMLoginRequest(&loginRequest, streamId)) != RSSL_RET_SUCCESS) { printf("rsslInitDefaultRDMLoginRequest() failed: %d\n", ret); return RSSL_RET_FAILURE; } if (strlen(niProvPerfConfig.username)) { loginRequest.userName.data = niProvPerfConfig.username; loginRequest.userName.length = (RsslUInt32)strlen(niProvPerfConfig.username); } loginRequest.flags |= RDM_LG_RQF_HAS_ROLE | RDM_LG_RQF_HAS_APPLICATION_NAME; loginRequest.role = RDM_LOGIN_ROLE_PROV; loginRequest.applicationName = applicationName; if (!(msgBuf = rsslGetBuffer(pChannel, chanInfo.maxFragmentSize, RSSL_FALSE, error))) { printf("rsslGetBuffer() failed: (%d) %s\n", error->rsslErrorId, error->text); return ret; } rsslClearEncodeIterator(&eIter); rsslSetEncodeIteratorRWFVersion(&eIter, pChannel->majorVersion, pChannel->minorVersion); if ( (ret = rsslSetEncodeIteratorBuffer(&eIter, msgBuf)) != RSSL_RET_SUCCESS) { printf("rsslSetEncodeIteratorBuffer() failed: %d(%s)\n", ret, errorInfo.rsslError.text); return ret; } if ((ret = rsslEncodeRDMLoginMsg(&eIter, (RsslRDMLoginMsg*)&loginRequest, &msgBuf->length, &errorInfo)) != RSSL_RET_SUCCESS) { printf("rsslEncodeRDMLoginMsg() failed: %d(%s)\n", ret, errorInfo.rsslError.text); return ret; } return channelHandlerWriteChannel(pChannelHandler, pChannelInfo, msgBuf, 0); }
int main(int argc, char **argv) { /* For this simple training app, only a single channel/connection is used for the entire life of this app. */ /* This example uses Unix I/O contents and basic TCP/IP like file descriptor and socket.*/ /* This example suite uses write descriptor in our client/consumer type examples in mainly 2 areas with * the I/O notification mechanism being used: * Details of those functions could be found in API development guide. * 1) rsslInitChannel() function which exchanges various messages to perform necessary UPA transport * negotiations and handshakes to complete channel initialization. * 2) rsslFlush() calls used throughout the application (after module 1a), together with rsslWrite() calls, such * as in sendMessage() function. The write descriptor can be used to indicate when the socketId has write * availability and help with determining when the network is able to accept additional bytes for writing. * * For the RsslChannel initialization process, if using I/O, a client/consumer application should register the * RsslChannel.socketId with the read, write, and exception file descriptor sets. When the write descriptor * alerts the user that the socketId is ready for writing, rsslInitChannel is called (this sends the * initial connection handshake message). When the read file descriptor alerts the user that the socketId * has data to read, rsslInitChannel is called - this typically reads the next portion of the handshake. * This process would continue until the connection is active. * * Typically, calls to rsslInitChannel are driven by I/O on the connection, however this can also be * accomplished by using a timer to periodically call the function or looping on a call until the channel * transitions to active or a failure occurs. Other than any overhead associated with the function call, * there is no harm in calling rsslInitChannel more frequently than required. If no work is required at * the current time, the function will return and indicate that connection is still in progress. */ /* This example suite also uses a clean FD sets and a dirty FD sets for I/O notification. * select() - a system call for examining the status of file_descriptors. * Tells us that there is data to read on the FDs. * Since select() modifies its file descriptor sets, if the call is being used in a loop, then the fd sets must * be reinitialized before each call. Since they act as input/output parameters for the select() system call; * they are read by and modified by the system call. When select() returns, the values have all been modified * to reflect the set of file descriptors ready. So, every time before you call select(), you have to * (re)initialize the fd_set values. Here we maintain 2 sets FD sets: * a) clean FD sets so that we can repeatedly call select call * b) dirty FD sets used in the actual select call (I/O notification mechanism) * Typically, you reset the dirty FD sets to be equal to the clean FD sets before you call select(). */ /****************************************************************************************************************** DECLARING VARIABLES ******************************************************************************************************************/ char srvrHostname[128], srvrPortNo[128], interfaceName[128]; /* clean FD sets so that we can repeatedly call select call */ fd_set cleanReadFds; fd_set cleanExceptFds; fd_set cleanWriteFds; /* dirty FD sets used in the actual select call (I/O notification mechanism) */ fd_set useReadFds; fd_set useExceptFds; fd_set useWriteFds; struct timeval time_interval; int selRet; RsslRet retval = RSSL_RET_FAILURE; RsslError error; RsslConnectOptions cOpts = RSSL_INIT_CONNECT_OPTS; /* RsslInProgInfo Information for the In Progress Connection State */ RsslInProgInfo inProgInfo = RSSL_INIT_IN_PROG_INFO; /* UPA channel management information */ UpaChannelManagementInfo upaChannelManagementInfo; /* For this simple training app, only a single channel/connection is used for the entire life of this app. */ upaChannelManagementInfo.upaChannel = 0; /* the default option parameters */ /* connect to server running on same machine */ snprintf(srvrHostname, 128, "%s", "localhost"); /* server is running on port number 14002 */ snprintf(srvrPortNo, 128, "%s", "14002"); /* use default NIC network interface card to bind to for all inbound and outbound data */ snprintf(interfaceName, 128, "%s", ""); /* User specifies options such as address, port, and interface from the command line. * User can have the flexibilty of specifying any or all of the parameters in any order. */ if (argc > 1) { int i = 1; while (i < argc) { 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("-i", argv[i]) == 0) { i += 2; snprintf(interfaceName, 128, "%s", argv[i-1]); } else { printf("Error: Unrecognized option: %s\n\n", argv[i]); printf("Usage: %s or\n%s [-h <SrvrHostname>] [-p <SrvrPortNo>] [-i <InterfaceName>] \n", argv[0], argv[0]); exit(RSSL_RET_FAILURE); } } } /****************************************************************************************************************** INITIALIZATION - USING rsslInitialize() ******************************************************************************************************************/ /********************************************************* * Client/Consumer Application Lifecycle Major Step 1: * Initialize UPA Transport using rsslInitialize * The first UPA Transport function that an application should call. This creates and initializes * internal memory and structures, as well as performing any boot strapping for underlying dependencies. * The rsslInitialize function also allows the user to specify the locking model they want applied * to the UPA Transport. *********************************************************/ /* RSSL_LOCK_NONE is used since this is a single threaded application. * For applications with other thread models (RSSL_LOCK_GLOBAL_AND_CHANNEL, RSSL_LOCK_GLOBAL), * see the UPA C developers guide for definitions of other locking models supported by UPA */ if (rsslInitialize(RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslInitialize. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application */ exit(RSSL_RET_FAILURE); } FD_ZERO(&cleanReadFds); FD_ZERO(&cleanExceptFds); FD_ZERO(&cleanWriteFds); /* populate connect options, then pass to rsslConnect function - * UPA Transport should already be initialized */ /* use standard socket connection */ cOpts.connectionType = RSSL_CONN_TYPE_SOCKET; /*!< (0) Channel is a standard TCP socket connection type */ cOpts.connectionInfo.unified.address = srvrHostname; cOpts.connectionInfo.unified.serviceName = srvrPortNo; cOpts.connectionInfo.unified.interfaceName = interfaceName; /* populate version and protocol with RWF information (found in rsslIterators.h) or protocol specific info */ cOpts.protocolType = RSSL_RWF_PROTOCOL_TYPE; /* Protocol type definition for RWF */ cOpts.majorVersion = RSSL_RWF_MAJOR_VERSION; cOpts.minorVersion = RSSL_RWF_MINOR_VERSION; /****************************************************************************************************************** CONNECTION SETUP - USING rsslConnect() ******************************************************************************************************************/ /********************************************************* * Client/Consumer Application Lifecycle Major Step 2: * Connect using rsslConnect (OS connection establishment handshake) * rsslConnect call Establishes an outbound connection, which can leverage standard sockets, HTTP, * or HTTPS. Returns an RsslChannel that represents the connection to the user. In the event of an error, * NULL is returned and additional information can be found in the RsslError structure. * Connection options are passed in via an RsslConnectOptions structure. *********************************************************/ if ((upaChannelManagementInfo.upaChannel = rsslConnect(&cOpts, &error)) == 0) { printf("Error %s (%d) (errno: %d) encountered with rsslConnect. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application, uninitialize to clean up first */ rsslUninitialize(); exit(RSSL_RET_FAILURE); } /* Connection was successful, add socketId to I/O notification mechanism and initialize connection */ /* Typical FD_SET use, this may vary depending on the I/O notification mechanism the application is using */ FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanReadFds); FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanExceptFds); /* for non-blocking I/O (default), write descriptor is set initially in case this end starts the message * handshakes that rsslInitChannel() performs. Once rsslInitChannel() is called for the first time the * channel can wait on the read descriptor for more messages. Without using the write descriptor, we would * have to keep looping and calling rsslInitChannel to complete the channel initialization process, which * can be CPU-intensive. We will set the write descriptor again if a FD_CHANGE event occurs. */ if (!cOpts.blocking) { if (!FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &cleanWriteFds)) FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanWriteFds); } printf("\nChannel IPC descriptor = %d\n", upaChannelManagementInfo.upaChannel->socketId); /****************************************************************************************************************** MAIN LOOP TO SEE IF RESPONSE RECEIVED FROM PROVIDER ******************************************************************************************************************/ /* Main loop for getting connection active and successful completion of the initialization process * The loop calls select() to wait for notification * Currently, the main loop would exit if an error condition is triggered or * RsslChannel.state transitions to RSSL_CH_STATE_ACTIVE. */ /* *If we want a non-blocking read call to the selector, we use select before read as read is a blocking call but select is not *If we want a blocking read call to the selector, such that we want to wait till we get a message, we should use read without select. *In the program below we will use select(), as it is non-blocking */ while (upaChannelManagementInfo.upaChannel->state != RSSL_CH_STATE_ACTIVE) { useReadFds = cleanReadFds; useWriteFds = cleanWriteFds; useExceptFds = cleanExceptFds; /* Set a timeout value if the provider accepts the connection, but does not initialize it */ /* On Linux platform, select() modifies timeout to reflect the amount of time not slept; * most other implementations do not do this. (POSIX.1-2001 permits either behaviour.) * This causes problems both when Linux code which reads timeout is ported to other operating systems, * and when code is ported to Linux that reuses a struct timeval for multiple select()s * in a loop without reinitializing it. Consider timeout to be undefined after select() returns. * * Note: You should reset the values of your timeout before you call select() every time. */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; /* By employing an I/O notification mechanism (e.g. select, poll), an application can leverage a * non-blocking I/O model, using the I/O notification to alert the application when data is available * to read or when output space is available for writing to. The training examples are written from a * non-blocking I/O perspective. Here, we use the select I/O notification mechanism in our examples. */ selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &time_interval); if (selRet == 0) { /* select has timed out, close the channel and exit */ /* On success, select() return zero if the timeout expires before anything interesting happens. */ printf("\nChannel initialization has timed out, exiting...\n"); /* Closes channel, cleans up and exits the application. */ closeChannelCleanUpAndExit(upaChannelManagementInfo.upaChannel, RSSL_RET_FAILURE); } else if (selRet > 0) { /* Received a response from the provider. */ /* On success, select() return the number of file descriptors contained in the three returned descriptor sets * (that is, the total number of bits that are set in readfds, writefds, exceptfds) */ /* Wait for channel to become active. After an RsslChannel is returned from the client's rsslConnect or server's rsslAccept call, * the channel may need to continue the initialization process. This additional initialization is required * as long as the RsslChannel.state is RSSL_CH_STATE_INITIALIZING. When using non-blocking I/O, this is the * typical state that an RsslChannel will start from and it may require multiple initialization calls to * transition to active. rsslInitChannel is typically called based on activity on the socketId, though a timer or * looping can be used - the rsslInitChannel function should continue to be called until the * connection becomes active, at which point reading and writing can begin. */ /* Indicates that an RsslChannel requires additional initialization. This initialization is typically additional * connection handshake messages that need to be exchanged. */ /* rsslInitChannel is called if read or write or except is triggered */ if (FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &useReadFds) || FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &useWriteFds) || FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &useExceptFds)) { /* Write descriptor is set initially in case this end starts the message handshakes that rsslInitChannel() performs. * Once rsslInitChannel() is called for the first time the channel can wait on the read descriptor for more messages. * We will set the write descriptor again if a FD_CHANGE event occurs. */ FD_CLR(upaChannelManagementInfo.upaChannel->socketId, &cleanWriteFds); /********************************************************* * Client/Consumer Application Lifecycle Major Step 3: * Initialize until active using rsslInitChannel (UPA Transport connection establishment handshake) * Continues initialization of an RsslChannel. This channel could originate from rsslConnect or rsslAccept. * This function exchanges various messages to perform necessary UPA negotiations and handshakes to * complete channel initialization. * Requires the use of an RsslInProgInfo structure. * The RsslChannel can be used for all additional transport functionality (e.g. reading, writing) once the * state transitions to RSSL_CH_STATE_ACTIVE. If a connection is rejected or initialization fails, * the state will transition to RSSL_CH_STATE_CLOSED. *********************************************************/ /* Internally, the UPA initialization process includes several actions. The initialization includes * any necessary UPA connection handshake exchanges, including any HTTP or HTTPS negotiation. * Compression, ping timeout, and versioning related negotiations also take place during the * initialization process. This process involves exchanging several messages across the connection, * and once all message exchanges have completed the RsslChannel.state will transition. If the connection * is accepted and all types of negotiations completed properly, the RsslChannel.state will become * RSSL_CH_STATE_ACTIVE. If the connection is rejected, either due to some kind of negotiation failure * or because an RsslServer rejected the connection by setting nakMount to RSSL_TRUE, the RsslChannel.state * will become RSSL_CH_STATE_CLOSED. * * Note: * For both client and server channels, more than one call to rsslInitChannel can be required to complete * the channel initialization process. */ if ((retval = rsslInitChannel(upaChannelManagementInfo.upaChannel, &inProgInfo, &error)) < RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslInitChannel fd=%d. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, upaChannelManagementInfo.upaChannel->socketId, error.text); /* Closes channel, cleans up and exits the application. */ closeChannelCleanUpAndExit(upaChannelManagementInfo.upaChannel, RSSL_RET_FAILURE); break; } else { /* Handle return code appropriately */ switch (retval) { /*!< (2) Transport Success: Channel initialization is In progress, returned from rsslInitChannel. */ case RSSL_RET_CHAN_INIT_IN_PROGRESS: { /* Initialization is still in progress, check the RsslInProgInfo for additional information */ if (inProgInfo.flags & RSSL_IP_FD_CHANGE) { /* The rsslInitChannel function requires the use of an additional parameter, a RsslInProgInfo structure. * Under certain circumstances, the initialization process may be required to create new or additional underlying connections. * If this occurs, the application is required to unregister the previous socketId and register the new socketId with * the I/O notification mechanism being used. When this occurs, the information is conveyed by the RsslInProgInfo and the RsslInProgFlags. * * RSSL_IP_FD_CHANGE indicates that a socketId change has occurred as a result of this call. The previous socketId has been * stored in RsslInProgInfo.oldSocket so it can be unregistered with the I/O notification mechanism. * The new socketId has been stored in RsslInProgInfo.newSocket so it can be registered with the * I/O notification mechanism. The channel initialization is still in progress and subsequent calls * to rsslInitChannel are required to complete it. */ printf("\nChannel In Progress - New FD: %d Old FD: %d\n",upaChannelManagementInfo.upaChannel->socketId, inProgInfo.oldSocket ); /* File descriptor has changed, unregister old and register new */ FD_CLR(inProgInfo.oldSocket, &cleanReadFds); FD_CLR(inProgInfo.oldSocket, &cleanWriteFds); FD_CLR(inProgInfo.oldSocket, &cleanExceptFds); /* newSocket should equal upaChannelManagementInfo.upaChannel->socketId */ FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanReadFds); FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanWriteFds); FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanExceptFds); } else { printf("\nChannel %d In Progress...\n", upaChannelManagementInfo.upaChannel->socketId); } } break; /* channel connection becomes active! * Once a connection is established and transitions to the RSSL_CH_STATE_ACTIVE state, * this RsslChannel can be used for other transport operations. */ case RSSL_RET_SUCCESS: { printf("\nChannel on fd %d is now active - reading and writing can begin.\n", upaChannelManagementInfo.upaChannel->socketId); /********************************************************* * Connection is now active. The RsslChannel can be used for all additional * transport functionality (e.g. reading, writing) now that the state * transitions to RSSL_CH_STATE_ACTIVE *********************************************************/ /* After channel is active, use UPA Transport utility function rsslGetChannelInfo to query RsslChannel negotiated * parameters and settings and retrieve all current settings. This includes maxFragmentSize and negotiated * compression information as well as many other values. */ if ((retval = rsslGetChannelInfo(upaChannelManagementInfo.upaChannel, &upaChannelManagementInfo.upaChannelInfo, &error)) != RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslGetChannelInfo. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* Connection should be closed, return failure */ /* Closes channel, cleans up and exits the application. */ closeChannelCleanUpAndExit(upaChannelManagementInfo.upaChannel, RSSL_RET_FAILURE); } printf( "Channel %d active. Channel Info:\n" " Max Fragment Size: %u\n" " Output Buffers: %u Max, %u Guaranteed\n" " Input Buffers: %u\n" " Send/Recv Buffer Sizes: %u/%u\n" " Ping Timeout: %u\n" " Connected component version: ", upaChannelManagementInfo.upaChannel->socketId, /*!< @brief Socket ID of this UPA channel. */ upaChannelManagementInfo.upaChannelInfo.maxFragmentSize, /*!< @brief This is the max fragment size before fragmentation and reassembly is necessary. */ upaChannelManagementInfo.upaChannelInfo.maxOutputBuffers, /*!< @brief This is the maximum number of output buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.guaranteedOutputBuffers, /*!< @brief This is the guaranteed number of output buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.numInputBuffers, /*!< @brief This is the number of input buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.sysSendBufSize, /*!< @brief This is the systems Send Buffer size. This reports the systems send buffer size respective to the transport type being used (TCP, UDP, etc) */ upaChannelManagementInfo.upaChannelInfo.sysRecvBufSize, /*!< @brief This is the systems Receive Buffer size. This reports the systems receive buffer size respective to the transport type being used (TCP, UDP, etc) */ upaChannelManagementInfo.upaChannelInfo.pingTimeout /*!< @brief This is the value of the negotiated ping timeout */ ); if (upaChannelManagementInfo.upaChannelInfo.componentInfoCount == 0) printf("(No component info)"); else { RsslUInt32 count; for(count = 0; count < upaChannelManagementInfo.upaChannelInfo.componentInfoCount; ++count) { printf("%.*s", upaChannelManagementInfo.upaChannelInfo.componentInfo[count]->componentVersion.length, upaChannelManagementInfo.upaChannelInfo.componentInfo[count]->componentVersion.data); if (count < upaChannelManagementInfo.upaChannelInfo.componentInfoCount - 1) printf(", "); } } printf ("\n\n"); } break; default: /* Error handling */ { printf("\nBad return value fd=%d <%s>\n", upaChannelManagementInfo.upaChannel->socketId, error.text); /* Closes channel, cleans up and exits the application. */ closeChannelCleanUpAndExit(upaChannelManagementInfo.upaChannel, RSSL_RET_FAILURE); } break; } } } } else if (selRet < 0) { /* On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined */ printf("\nSelect error.\n"); /* Closes channel, cleans up and exits the application. */ closeChannelCleanUpAndExit(upaChannelManagementInfo.upaChannel, RSSL_RET_FAILURE); } } }
//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"); }
int main(int argc, char **argv) { /* This example suite uses write descriptor in our server/Interactive Provider type examples in mainly 1 area with * the I/O notification mechanism being used: * 1) rsslFlush() calls used throughout the application (after module 1a), together with rsslWrite() calls, such * as in sendMessage() function. The write descriptor can be used to indicate when the socketId has write * availability and help with determining when the network is able to accept additional bytes for writing. */ /* This example suite also uses a clean FD sets and a dirty FD sets for I/O notification. * select() - a system call for examining the status of file_descriptors. * Tells us that there is data to read on the fds. * Since select() modifies its file descriptor sets, if the call is being used in a loop, then the fd sets must * be reinitialized before each call. Since they act as input/output parameters for the select() system call; * they are read by and modified by the system call. When select() returns, the values have all been modified * to reflect the set of file descriptors ready. So, every time before you call select(), you have to * (re)initialize the fd_set values. Here we maintain 2 sets FD sets: * a) clean FD sets so that we can repeatedly call select call * b) dirty FD sets used in the actual select call (I/O notification mechanism) * Typically, you reset the dirty FD sets to be equal to the clean FD sets before you call select(). */ /************************************************************************************************** DECLARING VARIABLES **************************************************************************************************/ /* UPA Server structure returned via the rsslBind call */ RsslServer* upaSrvr = 0; RsslBool clientAccepted = RSSL_FALSE; char srvrPortNo[128]; /* clean FD sets so that we can repeatedly call select call */ fd_set cleanReadFds; fd_set cleanExceptFds; fd_set cleanWriteFds; /* dirty FD sets used in the actual select call (I/O notification mechanism) */ fd_set useReadFds; fd_set useExceptFds; fd_set useWriteFds; struct timeval time_interval; int selRet; RsslRet retval = RSSL_RET_FAILURE; RsslError error; /* UPA Bind Options used in the rsslBind call. */ RsslBindOptions bindOpts = RSSL_INIT_BIND_OPTS; /* UPA Accept Options used in the rsslAccept call */ RsslAcceptOptions acceptOpts = RSSL_INIT_ACCEPT_OPTS; /* RsslInProgInfo Information for the In Progress Connection State */ RsslInProgInfo inProgInfo = RSSL_INIT_IN_PROG_INFO; /* UPA channel management information */ UpaChannelManagementInfo upaChannelManagementInfo; /* For this simple training app, the interactive provider only supports a single client. If the consumer disconnects, * the interactive provider would simply exit. * * If you want the provider to support multiple client sessions at the same time, you need to implement support * for multiple client sessions feature similar to what rsslProvider example is doing. */ upaChannelManagementInfo.upaChannel = 0; /* the default option parameters */ /* server is running on port number 14002 */ snprintf(srvrPortNo, 128, "%s", "14002"); /* User specifies options such as address, port, and interface from the command line. * User can have the flexibilty of specifying any or all of the parameters in any order. */ if (argc > 1) { int i = 1; while (i < argc) { if (strcmp("-p", argv[i]) == 0) { i += 2; snprintf(srvrPortNo, 128, "%s", argv[i-1]); } else { printf("Error: Unrecognized option: %s\n\n", argv[i]); printf("Usage: %s or\n%s [-p <SrvrPortNo>] \n", argv[0], argv[0]); exit(RSSL_RET_FAILURE); } } } /****************************************************************************************************************** INITIALIZATION - USING rsslInitialize() ******************************************************************************************************************/ /********************************************************* * Server/Provider Application Liefcycle Major Step 1: * Initialize UPA Transport using rsslInitialize * The first UPA Transport function that an application should call. This creates and initializes * internal memory and structures, as well as performing any boot strapping for underlying dependencies. * The rsslInitialize function also allows the user to specify the locking model they want applied * to the UPA Transport. *********************************************************/ /* RSSL_LOCK_NONE is used since this is a single threaded application. * For applications with other thread models (RSSL_LOCK_GLOBAL_AND_CHANNEL, RSSL_LOCK_GLOBAL), * see the UPA C developers guide for definitions of other locking models supported by UPA */ if (rsslInitialize(RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslInitialize. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application */ exit(RSSL_RET_FAILURE); } FD_ZERO(&cleanReadFds); FD_ZERO(&cleanExceptFds); FD_ZERO(&cleanWriteFds); /* populate bind options, then pass to rsslBind function - * UPA Transport should already be initialized */ bindOpts.serviceName = srvrPortNo; /* server is running on default port number 14002 */ bindOpts.pingTimeout = 60; /* servers desired ping timeout is 60 seconds, pings should be sent every 20 */ bindOpts.minPingTimeout = 30; /* min acceptable ping timeout is 30 seconds, pings should be sent every 10 */ /* set up buffering, configure for shared and guaranteed pools */ bindOpts.guaranteedOutputBuffers = 1000; bindOpts.maxOutputBuffers = 2000; bindOpts.sharedPoolSize = 50000; bindOpts.sharedPoolLock = RSSL_TRUE; bindOpts.serverBlocking = RSSL_FALSE; /* perform non-blocking I/O */ bindOpts.channelsBlocking = RSSL_FALSE; /* perform non-blocking I/O */ bindOpts.compressionType = RSSL_COMP_NONE; /* server does not desire compression for this connection */ /* populate version and protocol with RWF information (found in rsslIterators.h) or protocol specific info */ bindOpts.protocolType = RSSL_RWF_PROTOCOL_TYPE; /* Protocol type definition for RWF */ bindOpts.majorVersion = RSSL_RWF_MAJOR_VERSION; bindOpts.minorVersion = RSSL_RWF_MINOR_VERSION; /****************************************************************************************************************** BINDING SETUP - USING rsslBind() ******************************************************************************************************************/ /********************************************************* * Server/Provider Application Liefcycle Major Step 2: * Create listening socket using rsslBind * Establishes a listening socket connection, which supports connections from standard socket and HTTP * rsslConnect users. Returns an RsslServer that represents the listening socket connection to the user. * In the event of an error, NULL is returned and additional information can be found in the RsslError structure. * Options are passed in via an RsslBindOptions structure. Once a listening socket is established, this * RsslServer can begin accepting connections. *********************************************************/ /* Bind UPA server */ if ((upaSrvr = rsslBind(&bindOpts, &error)) != NULL) printf("\nServer IPC descriptor = %d bound on port %d\n", upaSrvr->socketId, upaSrvr->portNumber); else { printf("Error %s (%d) (errno: %d) encountered with rsslBind. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application, uninitialize to clean up first */ rsslUninitialize(); exit(RSSL_RET_FAILURE); } /* rsslBind listening socket connection was successful, add socketId to I/O notification mechanism and * initialize connection */ /* Typical FD_SET use, this may vary depending on the I/O notification mechanism the application is using */ FD_SET(upaSrvr->socketId, &cleanReadFds); FD_SET(upaSrvr->socketId, &cleanExceptFds); /****************************************************************************************************************** MAIN LOOP TO SEE IF CONNECTION RECEIVED FROM CONSUMER ******************************************************************************************************************/ /* Main Loop #1 for detecting incoming client connections. The loop calls select() to wait for notification * when the socketId of the server detects something to be read, this will check for incoming client connections. * When a client successfully connects, a RsslChannel is returned which corresponds to this connection. */ /* *If we want a non-blocking read call to the selector, we use select before read as read is a blocking call but select is not *If we want a blocking read call to the selector, such that we want to wait till we get a message, we should use read without select. *In the program below we will use select(), as it is non-blocking */ while (!clientAccepted) { useReadFds = cleanReadFds; useWriteFds = cleanWriteFds; useExceptFds = cleanExceptFds; /* Set a timeout value for waiting and checking messages received from incoming client connections. */ /* On Linux platform, select() modifies timeout to reflect the amount of time not slept; * most other implementations do not do this. (POSIX.1-2001 permits either behaviour.) * This causes problems both when Linux code which reads timeout is ported to other operating systems, * and when code is ported to Linux that reuses a struct timeval for multiple select()s * in a loop without reinitializing it. Consider timeout to be undefined after select() returns. * * Note: You should reset the values of your timeout before you call select() every time. */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; /* By employing an I/O notification mechanism (e.g. select, poll), an application can leverage a * non-blocking I/O model, using the I/O notification to alert the application when data is available * to read or when output space is available for writing to. The training examples are written from a * non-blocking I/O perspective. Here, we use the select I/O notification mechanism in our examples. */ selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &time_interval); if (selRet == 0) { /* no messages received from incoming connections, continue to wait and check for incoming client connections. */ } else if (selRet > 0) { /* Received a response from the consumer. */ /* On success, select() return the number of file descriptors contained in the three returned descriptor sets * (that is, the total number of bits that are set in readfds, writefds, exceptfds) */ /* rsslInitChannel is called if read is triggered */ if (FD_ISSET(upaSrvr->socketId, &useReadFds)) { /* Use rsslAccept for incoming connections, read and write data to established connections, etc */ /* Accept is typically called when servers socketId indicates activity */ /* After a server is created using the rsslBind call, the rsslAccept call can be made. When the socketId of * the server detects something to be read, this will check for incoming client connections. When a client * successfully connects, a RsslChannel is returned which corresponds to this connection. This channel can * be used to read or write with the connected client. If a clients connect message is not accepted, a * negative acknowledgment is sent to the client and no RsslChannel is returned. * * For this simple training app, the interactive provider only supports a single client. */ /* populate accept options, then pass to rsslAccept function - UPA Transport should already be initialized */ /*!< @brief If RSSL_TRUE, rsslAccept will send a NAK - even if the connection request is valid. */ acceptOpts.nakMount = RSSL_FALSE; /* allow the connection */ /********************************************************* * Server/Provider Application Liefcycle Major Step 3: * Accept connection using rsslAccept * This step is performed per connected client/connection/channel * Uses the RsslServer that represents the listening socket connection and begins the accepting process * for an incoming connection request. Returns an RsslChannel that represents the client connection. * In the event of an error, NULL is returned and additional information can be found in the RsslError * structure. * The rsslAccept function can also begin the rejection process for a connection through the use of the * RsslAcceptOptions structure. * Once a connection is established and transitions to the RSSL_CH_STATE_ACTIVE state, this RsslChannel * can be used for other transport operations. *********************************************************/ /* An OMM Provider application can begin the connection accepting or rejecting process by using the rsslAccept function */ if ((upaChannelManagementInfo.upaChannel = rsslAccept(upaSrvr, &acceptOpts, &error)) == 0) { printf("Error %s (%d) (errno: %d) encountered with rsslAccept. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application, uninitialize to clean up first */ rsslUninitialize(); exit(RSSL_RET_FAILURE); } else { /* For this simple training app, the interactive provider only supports one client session from the consumer. */ printf("\nServer fd=%d: New client on Channel fd=%d\n", upaSrvr->socketId,upaChannelManagementInfo.upaChannel->socketId); /* Connection was successful, add socketId to I/O notification mechanism and initialize connection */ /* Typical FD_SET use, this may vary depending on the I/O notification mechanism the application is using */ FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanReadFds); FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanExceptFds); // set clientAccepted to be TRUE and exit the while Main Loop #1 clientAccepted = RSSL_TRUE; } } } else if (selRet < 0) { /* On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined */ printf("\nSelect error.\n"); /* End application, uninitialize to clean up first */ rsslUninitialize(); exit(RSSL_RET_FAILURE); } } /****************************************************************************************************************** SECOND MAIN LOOP TO CONNECTION ACTIVE - LISTENING/SENDING DATA AMD PING MANAGEMENT ******************************************************************************************************************/ /* Main Loop #2 for getting connection active and successful completion of the initialization process * The loop calls select() to wait for notification * Currently, the main loop would exit if an error condition is triggered or * RsslChannel.state transitions to RSSL_CH_STATE_ACTIVE. */ while (upaChannelManagementInfo.upaChannel->state != RSSL_CH_STATE_ACTIVE) { useReadFds = cleanReadFds; useWriteFds = cleanWriteFds; useExceptFds = cleanExceptFds; /* Set a timeout value for getting connection active and successful completion of the initialization process */ /* On Linux platform, select() modifies timeout to reflect the amount of time not slept; * most other implementations do not do this. (POSIX.1-2001 permits either behaviour.) * This causes problems both when Linux code which reads timeout is ported to other operating systems, * and when code is ported to Linux that reuses a struct timeval for multiple select()s * in a loop without reinitializing it. Consider timeout to be undefined after select() returns. * * Note: You should reset the values of your timeout before you call select() every time. */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; /* By employing an I/O notification mechanism (e.g. select, poll), an application can leverage a * non-blocking I/O model, using the I/O notification to alert the application when data is available * to read or when output space is available for writing to. The training examples are written from a * non-blocking I/O perspective. Here, we use the select I/O notification mechanism in our examples. */ selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &time_interval); if (selRet == 0) { /* select has timed out, close the channel and exit */ /* On success, select() return zero if the timeout expires before anything interesting happens. */ printf("\nChannel initialization has timed out, exiting...\n"); /* Closes channel, closes server, cleans up and exits the application. */ closeChannelServerCleanUpAndExit(upaChannelManagementInfo.upaChannel, upaSrvr, RSSL_RET_FAILURE); } else if (selRet > 0) { /* Received a response from the consumer. */ /* On success, select() return the number of file descriptors contained in the three returned descriptor sets * (that is, the total number of bits that are set in readfds, writefds, exceptfds) */ /* Wait for channel to become active. After an RsslChannel is returned from the client's rsslConnect or server's rsslAccept call, * the channel may need to continue the initialization process. This additional initialization is required * as long as the RsslChannel.state is RSSL_CH_STATE_INITIALIZING. When using non-blocking I/O, this is the * typical state that an RsslChannel will start from and it may require multiple initialization calls to * transition to active. rsslInitChannel is typically called based on activity on the socketId, though a timer or * looping can be used - the rsslInitChannel function should continue to be called until the * connection becomes active, at which point reading and writing can begin. */ /* Indicates that an RsslChannel requires additional initialization. This initialization is typically additional * connection handshake messages that need to be exchanged. */ /* rsslInitChannel is called if read or write or except is triggered */ if (FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &useReadFds) || FD_ISSET(upaChannelManagementInfo.upaChannel->socketId, &useExceptFds)) { /********************************************************* * Server/Provider Application Liefcycle Major Step 4: * Initialize until active using rsslInitChannel (UPA Transport connection establishment handshake) * Continues initialization of an RsslChannel. This channel could originate from rsslConnect or rsslAccept. * This function exchanges various messages to perform necessary UPA negotiations and handshakes to * complete channel initialization. * Requires the use of an RsslInProgInfo structure. * The RsslChannel can be used for all additional transport functionality (e.g. reading, writing) once the * state transitions to RSSL_CH_STATE_ACTIVE. If a connection is rejected or initialization fails, * the state will transition to RSSL_CH_STATE_CLOSED. *********************************************************/ /* Internally, the UPA initialization process includes several actions. The initialization includes * any necessary UPA connection handshake exchanges, including any HTTP or HTTPS negotiation. * Compression, ping timeout, and versioning related negotiations also take place during the * initialization process. This process involves exchanging several messages across the connection, * and once all message exchanges have completed the RsslChannel.state will transition. If the connection * is accepted and all types of negotiations completed properly, the RsslChannel.state will become * RSSL_CH_STATE_ACTIVE. If the connection is rejected, either due to some kind of negotiation failure * or because an RsslServer rejected the connection by setting nakMount to RSSL_TRUE, the RsslChannel.state * will become RSSL_CH_STATE_CLOSED. * * Note: * For both client and server channels, more than one call to rsslInitChannel can be required to complete * the channel initialization process. */ if ((retval = rsslInitChannel(upaChannelManagementInfo.upaChannel, &inProgInfo, &error)) < RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslInitChannel fd=%d. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, upaChannelManagementInfo.upaChannel->socketId, error.text); /* Closes channel, closes server, cleans up and exits the application. */ closeChannelServerCleanUpAndExit(upaChannelManagementInfo.upaChannel, upaSrvr, RSSL_RET_FAILURE); break; } else { /* Handle return code appropriately */ switch (retval) { /*!< (2) Transport Success: Channel initialization is In progress, returned from rsslInitChannel. */ case RSSL_RET_CHAN_INIT_IN_PROGRESS: { /* Initialization is still in progress, check the RsslInProgInfo for additional information */ if (inProgInfo.flags & RSSL_IP_FD_CHANGE) { /* The rsslInitChannel function requires the use of an additional parameter, a RsslInProgInfo structure. * Under certain circumstances, the initialization process may be required to create new or additional underlying connections. * If this occurs, the application is required to unregister the previous socketId and register the new socketId with * the I/O notification mechanism being used. When this occurs, the information is conveyed by the RsslInProgInfo and the RsslInProgFlags. * * RSSL_IP_FD_CHANGE indicates that a socketId change has occurred as a result of this call. The previous socketId has been * stored in RsslInProgInfo.oldSocket so it can be unregistered with the I/O notification mechanism. * The new socketId has been stored in RsslInProgInfo.newSocket so it can be registered with the * I/O notification mechanism. The channel initialization is still in progress and subsequent calls * to rsslInitChannel are required to complete it. */ printf("\nChannel In Progress - New FD: %d Old FD: %d\n",upaChannelManagementInfo.upaChannel->socketId, inProgInfo.oldSocket ); /* File descriptor has changed, unregister old and register new */ FD_CLR(inProgInfo.oldSocket, &cleanReadFds); FD_CLR(inProgInfo.oldSocket, &cleanExceptFds); /* newSocket should equal upaChannelManagementInfo.upaChannel->socketId */ FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanReadFds); FD_SET(upaChannelManagementInfo.upaChannel->socketId, &cleanExceptFds); } else { printf("\nChannel %d In Progress...\n", upaChannelManagementInfo.upaChannel->socketId); } } break; /* channel connection becomes active! * Once a connection is established and transitions to the RSSL_CH_STATE_ACTIVE state, * this RsslChannel can be used for other transport operations. */ case RSSL_RET_SUCCESS: { printf("\nChannel on fd %d is now active - reading and writing can begin.\n", upaChannelManagementInfo.upaChannel->socketId); /********************************************************* * Connection is now active. The RsslChannel can be used for all additional * transport functionality (e.g. reading, writing) now that the state * transitions to RSSL_CH_STATE_ACTIVE *********************************************************/ /* After channel is active, use UPA Transport utility function rsslGetChannelInfo to query RsslChannel negotiated * parameters and settings and retrieve all current settings. This includes maxFragmentSize and negotiated * compression information as well as many other values. */ if ((retval = rsslGetChannelInfo(upaChannelManagementInfo.upaChannel, &upaChannelManagementInfo.upaChannelInfo, &error)) != RSSL_RET_SUCCESS) { printf("Error %s (%d) (errno: %d) encountered with rsslGetChannelInfo. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* Connection should be closed, return failure */ /* Closes channel, closes server, cleans up and exits the application. */ closeChannelServerCleanUpAndExit(upaChannelManagementInfo.upaChannel, upaSrvr, RSSL_RET_FAILURE); } printf( "Channel %d active. Channel Info:\n" " Max Fragment Size: %u\n" " Output Buffers: %u Max, %u Guaranteed\n" " Input Buffers: %u\n" " Send/Recv Buffer Sizes: %u/%u\n" " Ping Timeout: %u\n" " Connected component version: ", upaChannelManagementInfo.upaChannel->socketId, /*!< @brief Socket ID of this UPA channel. */ upaChannelManagementInfo.upaChannelInfo.maxFragmentSize, /*!< @brief This is the max fragment size before fragmentation and reassembly is necessary. */ upaChannelManagementInfo.upaChannelInfo.maxOutputBuffers, /*!< @brief This is the maximum number of output buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.guaranteedOutputBuffers, /*!< @brief This is the guaranteed number of output buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.numInputBuffers, /*!< @brief This is the number of input buffers available to the channel. */ upaChannelManagementInfo.upaChannelInfo.sysSendBufSize, /*!< @brief This is the systems Send Buffer size. This reports the systems send buffer size respective to the transport type being used (TCP, UDP, etc) */ upaChannelManagementInfo.upaChannelInfo.sysRecvBufSize, /*!< @brief This is the systems Receive Buffer size. This reports the systems receive buffer size respective to the transport type being used (TCP, UDP, etc) */ upaChannelManagementInfo.upaChannelInfo.pingTimeout /*!< @brief This is the value of the negotiated ping timeout */ ); if (upaChannelManagementInfo.upaChannelInfo.componentInfoCount == 0) printf("(No component info)"); else { RsslUInt32 count; for(count = 0; count < upaChannelManagementInfo.upaChannelInfo.componentInfoCount; ++count) { printf("%.*s", upaChannelManagementInfo.upaChannelInfo.componentInfo[count]->componentVersion.length, upaChannelManagementInfo.upaChannelInfo.componentInfo[count]->componentVersion.data); if (count < upaChannelManagementInfo.upaChannelInfo.componentInfoCount - 1) printf(", "); } } printf ("\n\n"); /* do not allow new client to connect */ /* For this simple training app, the interactive provider only supports a single client. Once a client * successfully connects, we call rsslCloseServer function to close the listening socket associated with the * RsslServer. The connected RsslChannels will remain open. This allows the established connection to continue * to send and receive data, while preventing new clients from connecting. */ /* clean up server */ FD_CLR(upaSrvr->socketId, &cleanReadFds); FD_CLR(upaSrvr->socketId, &cleanExceptFds); /********************************************************* * Server/Provider Application Liefcycle Major Step 7: * Closes a listening socket associated with an RsslServer. This will release any pool based resources * back to their respective pools, close the listening socket, and perform any additional necessary cleanup. * Any established connections will remain open, allowing for continued information exchange. *********************************************************/ /* clean up server using rsslCloseServer call. * If a server is being shut down, the rsslCloseServer function should be used to close the listening socket and perform * any necessary cleanup. All currently connected RsslChannels will remain open. This allows applications to continue * to send and receive data, while preventing new applications from connecting. The server has the option of calling * rsslCloseChannel to shut down any currently connected applications. * When shutting down the UPA Transport, the application should release any unwritten pool buffers. * The listening socket can be closed by calling rsslCloseServer. This prevents any new connection attempts. * If shutting down connections for all connected clients, the provider should call rsslCloseChannel for each connection client. */ if ((upaSrvr) && (rsslCloseServer(upaSrvr, &error) < RSSL_RET_SUCCESS)) { printf("Error %s (%d) (errno: %d) encountered with rsslCloseServer. Error Text: %s\n", rsslRetCodeToString(error.rsslErrorId), error.rsslErrorId, error.sysError, error.text); /* End application, uninitialize to clean up first */ rsslUninitialize(); exit(RSSL_RET_FAILURE); } // set upaSrvr to be NULL upaSrvr = 0; } break; default: /* Error handling */ { printf("\nBad return value fd=%d <%s>\n", upaChannelManagementInfo.upaChannel->socketId, error.text); /* Closes channel, closes server, cleans up and exits the application. */ closeChannelServerCleanUpAndExit(upaChannelManagementInfo.upaChannel, upaSrvr, RSSL_RET_FAILURE); } break; } } } } else if (selRet < 0) { /* On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined */ printf("\nSelect error.\n"); /* Closes channel, closes server, cleans up and exits the application. */ closeChannelServerCleanUpAndExit(upaChannelManagementInfo.upaChannel, upaSrvr, RSSL_RET_FAILURE); } } }
RsslRet processActiveChannel(ChannelHandler *pChanHandler, ChannelInfo *pChannelInfo) { ProviderThread *pProvThread = (ProviderThread*)pChanHandler->pUserSpec; ProviderSession *pProvSession = (ProviderSession*)pChannelInfo->pUserSpec; RsslError error; RsslRet ret; RsslChannelInfo channelInfo; RsslUInt32 count; #ifdef ENABLE_XML_TRACE RsslTraceOptions traceOptions; rsslClearTraceOptions(&traceOptions); traceOptions.traceMsgFileName = "upacProvPerf"; traceOptions.traceMsgMaxFileSize = 1000000000; traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_WRITE | RSSL_TRACE_READ; rsslIoctl(pChannelInfo->pChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &error); #endif if (provPerfConfig.highWaterMark > 0) { if (rsslIoctl(pChannelInfo->pChannel, RSSL_HIGH_WATER_MARK, &provPerfConfig.highWaterMark, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl() of RSSL_HIGH_WATER_MARK failed <%s>\n", error.text); exit(-1); } } if ((ret = rsslGetChannelInfo(pChannelInfo->pChannel, &channelInfo, &error)) != RSSL_RET_SUCCESS) { printf("rsslGetChannelInfo() failed: %d\n", ret); return 0; } printf( "Channel %d active. Channel Info:\n" " maxFragmentSize: %u\n" " maxOutputBuffers: %u\n" " guaranteedOutputBuffers: %u\n" " numInputBuffers: %u\n" " pingTimeout: %u\n" " clientToServerPings: %s\n" " serverToClientPings: %s\n" " sysSendBufSize: %u\n" " sysSendBufSize: %u\n" " compressionType: %s\n" " compressionThreshold: %u\n" " ComponentInfo: ", pChannelInfo->pChannel->socketId, channelInfo.maxFragmentSize, channelInfo.maxOutputBuffers, channelInfo.guaranteedOutputBuffers, channelInfo.numInputBuffers, channelInfo.pingTimeout, channelInfo.clientToServerPings == RSSL_TRUE ? "true" : "false", channelInfo.serverToClientPings == RSSL_TRUE ? "true" : "false", channelInfo.sysSendBufSize, channelInfo.sysRecvBufSize, channelInfo.compressionType == RSSL_COMP_ZLIB ? "zlib" : "none", channelInfo.compressionThreshold ); if (channelInfo.componentInfoCount == 0) printf("(No component info)"); else for(count = 0; count < channelInfo.componentInfoCount; ++count) { printf("%.*s", channelInfo.componentInfo[count]->componentVersion.length, channelInfo.componentInfo[count]->componentVersion.data); if (count < channelInfo.componentInfoCount - 1) printf(", "); } printf ("\n\n"); /* Check that we can successfully pack, if packing messages. */ if (providerThreadConfig.totalBuffersPerPack > 1 && providerThreadConfig.packingBufferLength > channelInfo.maxFragmentSize) { printf("Error(Channel %d): MaxFragmentSize %u is too small for packing buffer size %u\n", pChannelInfo->pChannel->socketId, channelInfo.maxFragmentSize, providerThreadConfig.packingBufferLength); exit(-1); } if (ret = (printEstimatedMsgSizes(pProvThread, pProvSession)) != RSSL_RET_SUCCESS) return RSSL_RET_FAILURE; pProvSession->timeActivated = getTimeNano(); return RSSL_RET_SUCCESS; }
RsslRet processActiveChannel(ChannelHandler *pChanHandler, ChannelInfo *pChannelInfo) { ProviderThread *pProviderThread = (ProviderThread*)pChanHandler->pUserSpec; ProviderSession *pProvSession = (ProviderSession*)pChannelInfo->pUserSpec; RsslRet ret; RsslError error; RsslChannelInfo channelInfo; RsslUInt32 count; if (niProvPerfConfig.highWaterMark > 0) { if (rsslIoctl(pChannelInfo->pChannel, RSSL_HIGH_WATER_MARK, &niProvPerfConfig.highWaterMark, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl() of RSSL_HIGH_WATER_MARK failed <%s>\n", error.text); exit(-1); } } if ((ret = rsslGetChannelInfo(pChannelInfo->pChannel, &channelInfo, &error)) != RSSL_RET_SUCCESS) { printf("rsslGetChannelInfo() failed: %d\n", ret); return 0; } printf( "Channel %d active. Channel Info:\n" " maxFragmentSize: %u\n" " maxOutputBuffers: %u\n" " guaranteedOutputBuffers: %u\n" " numInputBuffers: %u\n" " pingTimeout: %u\n" " clientToServerPings: %s\n" " serverToClientPings: %s\n" " sysSendBufSize: %u\n" " sysSendBufSize: %u\n" " compressionType: %s\n" " compressionThreshold: %u\n" " ComponentInfo: ", pChannelInfo->pChannel->socketId, channelInfo.maxFragmentSize, channelInfo.maxOutputBuffers, channelInfo.guaranteedOutputBuffers, channelInfo.numInputBuffers, channelInfo.pingTimeout, channelInfo.clientToServerPings == RSSL_TRUE ? "true" : "false", channelInfo.serverToClientPings == RSSL_TRUE ? "true" : "false", channelInfo.sysSendBufSize, channelInfo.sysRecvBufSize, channelInfo.compressionType == RSSL_COMP_ZLIB ? "zlib" : "none", channelInfo.compressionThreshold ); if (channelInfo.componentInfoCount == 0) printf("(No component info)"); else for(count = 0; count < channelInfo.componentInfoCount; ++count) { printf("%.*s", channelInfo.componentInfo[count]->componentVersion.length, channelInfo.componentInfo[count]->componentVersion.data); if (count < channelInfo.componentInfoCount - 1) printf(", "); } printf ("\n\n"); /* Check that we can successfully pack, if packing messages. */ if (providerThreadConfig.totalBuffersPerPack > 1 && providerThreadConfig.packingBufferLength > channelInfo.maxFragmentSize) { printf("Error(Channel %d): MaxFragmentSize %u is too small for packing buffer size %u\n", pChannelInfo->pChannel->socketId, channelInfo.maxFragmentSize, providerThreadConfig.packingBufferLength); exit(-1); } if (ret = (printEstimatedMsgSizes(pProviderThread, pProvSession)) != RSSL_RET_SUCCESS) return RSSL_RET_FAILURE; pProvSession->timeActivated = getTimeNano(); /* Send Login Request */ ret = sendLoginRequest(pChanHandler, pChannelInfo, 1, &error); if (ret < RSSL_RET_SUCCESS) { printf("sendLoginRequest() failed: %d\n", ret); exit(-1); } else if (ret > RSSL_RET_SUCCESS) { /* Need to flush */ providerThreadRequestChannelFlush(pProviderThread, pChannelInfo); } return RSSL_RET_SUCCESS; }
void UPAProvider::ReadFromChannel(RsslChannel* chnl) { // first, handle state change int retval; RsslError error; if (chnl->socketId != -1 && chnl->state == RSSL_CH_STATE_INITIALIZING) { RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO; // its initialising if ((retval = rsslInitChannel(chnl, &inProg, &error)) < RSSL_RET_SUCCESS) { // we fail to init the channel so just shut it down t42log_warn("sessionInactive fd=%d <%s>\n", chnl->socketId,error.text); RemoveChannelConnection(chnl); } else { switch (retval) { case RSSL_RET_CHAN_INIT_IN_PROGRESS: if (inProg.flags & RSSL_IP_FD_CHANGE) { // the FDs have changed t42log_info("Channel In Progress - New FD: %d Old FD: %d\n",chnl->socketId, inProg.oldSocket ); FD_CLR(inProg.oldSocket,&readfds_); FD_CLR(inProg.oldSocket,&exceptfds_); FD_SET(chnl->socketId,&readfds_); FD_SET(chnl->socketId,&exceptfds_); } else { t42log_debug("Channel %d connection in progress\n", chnl->socketId); } break; case RSSL_RET_SUCCESS: { // initialization is complete t42log_info("Client Channel fd=%d is now ACTIVE\n" ,chnl->socketId); #ifdef _WIN32 // WINDOWS: change size of send/receive buffer since it's small by default int rcvBfrSize = 65535; int sendBfrSize = 65535; if (rsslIoctl(chnl, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &error) != RSSL_RET_SUCCESS) { t42log_warn("rsslIoctl(): failed <%s>\n", error.text); } if (rsslIoctl(chnl, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &error) != RSSL_RET_SUCCESS) { t42log_warn("rsslIoctl(): failed <%s>\n", error.text); } #endif /* if device we connect to supports connected component versioning, * also display the product version of what this connection is to */ RsslChannelInfo chanInfo; if ((retval = rsslGetChannelInfo(chnl, &chanInfo, &error)) >= RSSL_RET_SUCCESS) { RsslUInt32 i; for (i = 0; i < chanInfo.componentInfoCount; i++) { t42log_info("Connection is from %s device.\n", chanInfo.componentInfo[i]->componentVersion.data); } } } break; default: t42log_error("Bad return value fd=%d <%s>\n", chnl->socketId,error.text); RemoveChannelConnection(chnl); break; } } } // the channel is active so read whatver there is to read if (chnl->socketId != -1 && chnl->state == RSSL_CH_STATE_ACTIVE) { RsslRet readret = 1; while (readret > 0) /* read until no more to read */ { RsslBuffer *msgBuf = 0 ; if ((msgBuf = rsslRead(chnl,&readret,&error)) != 0) { if (ProcessRequest(chnl, msgBuf) == RSSL_RET_SUCCESS) { /* set flag for client message received */ SetChannelReceivedClientMsg(chnl); } } if (msgBuf == 0) { switch (readret) { case RSSL_RET_CONGESTION_DETECTED: case RSSL_RET_SLOW_READER: case RSSL_RET_PACKET_GAP_DETECTED: if (chnl->state != RSSL_CH_STATE_CLOSED) { // disconnectOnGaps must be false. Connection is not closed t42log_warn("Read Error: %s <%d>\n", error.text, readret); /* break out of switch */ break; } /// if channel is closed, we want to fall through case RSSL_RET_FAILURE: { t42log_info("channelInactive fd=%d <%s>\n", chnl->socketId,error.text); RemoveChannelConnection(chnl); } break; case RSSL_RET_READ_FD_CHANGE: { t42log_info("rsslRead() FD Change - Old FD: %d New FD: %d\n", chnl->oldSocketId, chnl->socketId); FD_CLR(chnl->oldSocketId, &readfds_); FD_CLR(chnl->oldSocketId, &exceptfds_); FD_SET(chnl->socketId, &readfds_); FD_SET(chnl->socketId, &exceptfds_); } break; case RSSL_RET_READ_PING: { /* set flag for client message received */ SetChannelReceivedClientMsg(chnl); } break; default: if (readret < 0 && readret != RSSL_RET_READ_WOULD_BLOCK) { t42log_warn("Read Error: %s <%d>\n", error.text, readret); } break; } } } } else if (chnl->state == RSSL_CH_STATE_CLOSED) { t42log_info("Channel fd=%d Closed.\n", chnl->socketId); RemoveChannelConnection(chnl); } }