Ejemplo n.º 1
0
RsslRet snapshotSessionInitializeChannel(SnapshotSession *pSession)
{
	RsslInProgInfo inProg;
	RsslRet ret;
	RsslError rsslError;

	ret = rsslInitChannel(pSession->pRsslChannel, &inProg, &rsslError);

	switch(ret)
	{
		case RSSL_RET_SUCCESS: 
			/* Success indicates that initialization is complete. */
			pSession->setWriteFd = RSSL_FALSE;
			printf("<%s> Channel is active!\n\n", pSession->name);
			if ((ret = snapshotSessionProcessChannelActive(pSession)) != RSSL_RET_SUCCESS)
				return ret;
			return RSSL_RET_SUCCESS;

		case RSSL_RET_CHAN_INIT_IN_PROGRESS:

			if (inProg.flags & RSSL_IP_FD_CHANGE)
			{
				/* Indicates that the file descriptor for this channel changed. */
				printf("<%s> Channel FD changed while initializing (from %d to %d)\n\n", pSession->name,
						inProg.oldSocket, inProg.newSocket);

				/* This normally means that the channel was reconnected while initializing,
				 * so trigger ourselves to call rsslInitChannel on write notification
				 * again.  */
				pSession->setWriteFd = RSSL_TRUE;
			}
			else
				pSession->setWriteFd = RSSL_FALSE;

			return RSSL_RET_SUCCESS;

		default:
			printf("<%s> rsslInitChannel() failed: %d(%s).\n\n",
					pSession->name, ret, rsslRetCodeToString(ret));
			return ret;
	}
}
Ejemplo n.º 2
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);
		}
	}
}
Ejemplo n.º 3
0
//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;
			}
		}
	}
}
Ejemplo n.º 4
0
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);
		}
	}
}
Ejemplo n.º 6
0
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);
    }



}