int main(int argc, char **argv)
{
	int i, j;
	struct timeval time_interval;
	fd_set useRead;
	fd_set useExcept;
	int selRet;
	char errTxt[256];
	RsslBuffer errorText = {255, (char*)errTxt};
	RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO;
	RsslRet	retval = 0;
	int iargs;
	RsslErrorInfo rsslErrorInfo;
	RsslBool cacheOption = RSSL_FALSE;

	RsslReactorOMMProviderRole providerRole;

	RsslBindOptions sopts = RSSL_INIT_BIND_OPTS;

	RsslCreateReactorOptions reactorOpts;

	RsslReactorDispatchOptions dispatchOpts;

	time_t nextSendTime;

	/* Initialize RSSL. The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */
	if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &rsslErrorInfo.rsslError) != RSSL_RET_SUCCESS)
	{
		printf("rsslInitialize(): failed <%s>\n",rsslErrorInfo.rsslError.text);
		/* 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);
	}

	rsslClearOMMProviderRole(&providerRole);

	providerRole.base.channelEventCallback = channelEventCallback;
	providerRole.base.defaultMsgCallback = defaultMsgCallback;
	providerRole.loginMsgCallback = loginMsgCallback;
	providerRole.directoryMsgCallback = directoryMsgCallback;
	providerRole.dictionaryMsgCallback = dictionaryMsgCallback;
	providerRole.tunnelStreamListenerCallback = tunnelStreamListenerCallback;

	rsslClearCreateReactorOptions(&reactorOpts);

	if (!(pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo)))
	{
		printf("Reactor creation failed: %s\n", rsslErrorInfo.rsslError.text);
		cleanUpAndExit();
	}

	snprintf(portNo, 128, "%s", defaultPortNo);
	snprintf(serviceName, 128, "%s", defaultServiceName);
	setServiceId(1);
	for(iargs = 1; iargs < argc; ++iargs)
	{
		if (0 == strcmp("-p", argv[iargs]))
		{
			++iargs; if (iargs == argc) exitWithUsage();
			snprintf(portNo, 128, "%s", argv[iargs]);
		}
		else if (0 == strcmp("-s", argv[iargs]))
		{
			++iargs; if (iargs == argc) exitWithUsage();
			snprintf(serviceName, 128, "%s", argv[iargs]);
		}
		else if (0 == strcmp("-id", argv[iargs]))
		{
			long tmpId = 0;
			++iargs; if (iargs == argc) exitWithUsage();
			tmpId = atol(argv[iargs]);
			if (tmpId < 0)
			{
				printf("ServiceId must be positive.\n");
				exitWithUsage();
			}
			setServiceId(tmpId);
		}
		else if (0 == strcmp("-x", argv[iargs]))
		{
			xmlTrace = RSSL_TRUE;
			snprintf(traceOutputFile, 128, "RsslVAProvider\0");
		}
		else if (0 == strcmp("-runtime", argv[iargs]))
		{
			++iargs; if (iargs == argc) exitWithUsage();
			timeToRun = atoi(argv[iargs]);
		}
		else if (0 == strcmp("-cache", argv[iargs]))
		{
			cacheOption = RSSL_TRUE;
		}
		else
		{
			printf("Error: Unrecognized option: %s\n\n", argv[iargs]);
			exitWithUsage();
		}
	}
	printf("portNo: %s\n", portNo);
	printf("serviceName: %s\n", serviceName);
	printf("serviceId: %llu\n", getServiceId());

	/* Initialiize client session information */
	for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
	{
		clearClientSessionInfo(&clientSessions[i]);
	}

	initializeCache(cacheOption);

	/* Initialize login handler */
	initLoginHandler();

	/* Initialize source directory handler */
	initDirectoryHandler();

	/* Initialize dictionary provider */
	initDictionaryProvider();

	/* Initialize market price handler */
	initItemHandler();

	/* Initialize symbol list item list */
	initSymbolListItemList();

	/* Initialize market by order items */
	initMarketByOrderItems();


	/* set service name in directory handler */
	setServiceName(serviceName);

	/* load dictionary */
	if (loadDictionary() != RSSL_RET_SUCCESS)
	{
		/* exit if dictionary cannot be loaded */
		/* 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);
	}

	initializeCacheDictionary();

	/* Initialize run-time */
	initRuntime();

	FD_ZERO(&readFds);
	FD_ZERO(&exceptFds);
	
	sopts.guaranteedOutputBuffers = 500;
	sopts.serviceName = portNo;
	sopts.majorVersion = RSSL_RWF_MAJOR_VERSION;
	sopts.minorVersion = RSSL_RWF_MINOR_VERSION;
	sopts.protocolType = RSSL_RWF_PROTOCOL_TYPE;

	/* Create the server. */
	if (!(rsslSrvr = rsslBind(&sopts, &rsslErrorInfo.rsslError)))
	{
		printf("Unable to bind RSSL server: <%s>\n",rsslErrorInfo.rsslError.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_SET(rsslSrvr->socketId, &readFds);
	FD_SET(pReactor->eventFd, &readFds);
	
	rsslClearReactorDispatchOptions(&dispatchOpts);
	dispatchOpts.maxMessages = MAX_CLIENT_SESSIONS;

	// initialize next send time
	nextSendTime = time(NULL) + UPDATE_INTERVAL;

	/* this is the main loop */
	while(RSSL_TRUE)
	{
		useRead = readFds;
		useExcept = exceptFds;
		time_interval.tv_sec = UPDATE_INTERVAL;
		time_interval.tv_usec = 0;

		/* Call select() to check for any messages */
		selRet = select(FD_SETSIZE,&useRead,
		    NULL,&useExcept,&time_interval);

		if (selRet > 0)
		{
			RsslRet ret;

			/* Accept connection, if one is waiting */
			if (FD_ISSET(rsslSrvr->socketId, &useRead))
			{
				RsslClientSessionInfo *pClientSessionInfo = NULL;
				RsslReactorAcceptOptions aopts;

				rsslClearReactorAcceptOptions(&aopts);

				/* find an available client session */
				for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
				{
					if (!clientSessions[i].isInUse)
					{
						pClientSessionInfo = &clientSessions[i];
						pClientSessionInfo->isInUse = RSSL_TRUE;
						break;
					}
				}

				/* Reject the channel if we are out of client sessions */
				if (!pClientSessionInfo)
					aopts.rsslAcceptOptions.nakMount = RSSL_TRUE;
				else
					aopts.rsslAcceptOptions.userSpecPtr = pClientSessionInfo;


				printf("Accepting new connection...\n");
				if (rsslReactorAccept(pReactor, rsslSrvr, &aopts, (RsslReactorChannelRole*)&providerRole, &rsslErrorInfo) != RSSL_RET_SUCCESS)
				{
					printf("rsslReactorAccept() failed: %s(%s)\n", rsslErrorInfo.rsslError.text, rsslErrorInfo.errorLocation);
					cleanUpAndExit();
				}
			}

			/* Call rsslReactorDispatch().  This will handle any events that have occurred on its channels.
			 * If there are events or messages for the application to process, they will be delivered
			 * through the callback functions given by the providerRole object. 
			 * A return value greater than RSSL_RET_SUCCESS indicates there may be more to process. */
			while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &rsslErrorInfo)) > RSSL_RET_SUCCESS)
				;

			if (ret < RSSL_RET_SUCCESS)
			{
				printf("rsslReactorDispatch() failed: %s\n", rsslErrorInfo.rsslError.text);
				cleanUpAndExit();
			}
		}
		else if (selRet < 0)
		{
#ifdef _WIN32
			if (WSAGetLastError() == WSAEINTR)
				continue;
			printf("Error: select: %d\n", WSAGetLastError());
#else
			if (errno == EINTR)
				continue;
			perror("select");
#endif
			cleanUpAndExit();
		}

		// send any updates at next send time
		if (time(NULL) >= nextSendTime)
		{
			/* Send market price updates for each connected channel */
			updateItemInfo();
			for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
			{
				if (clientSessions[i].clientChannel != NULL)
				{
					if (sendItemUpdates(pReactor, clientSessions[i].clientChannel) != RSSL_RET_SUCCESS)
					{
						removeClientSessionForChannel(pReactor, clientSessions[i].clientChannel);
					}

					// send any tunnel stream messages
					for (j = 0; j < MAX_TUNNEL_STREAMS; j++)
					{
						if (clientSessions[i].simpleTunnelMsgHandler[j].tunnelStreamHandler.pTunnelStream != NULL)
						{
							handleSimpleTunnelMsgHandler(pReactor, clientSessions[i].clientChannel, &clientSessions[i].simpleTunnelMsgHandler[j]);
						}
					}
				}
			}

			nextSendTime += UPDATE_INTERVAL;
		}

		/* Handle run-time */
		handleRuntime();
	}
}
/*** MAIN ***/
int main(int argc, char **argv)
{
	RsslErrorInfo error;
	RsslError rsslErr;
	RsslCreateReactorOptions reactorOpts;
	RsslReactorDispatchOptions dispatchOpts;
	RsslInt32 j;

	RsslReactorOMMNIProviderRole role;
	RsslDataDictionary dictionary = RSSL_INIT_DATA_DICTIONARY;
	
	char err[128];
	RsslBuffer errBuf = {128, &err[0]};
	
	int selRet;

	time_t currentTime = 0;
	RsslRet ret;

	RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS;

	rsslInitNIChannelCommand(&chnlCommand);

	handleConfig(argc, argv, &chnlCommand);

	initializeCache(cacheCommandlineOption);
	
	initOpts.jitOpts.libcryptoName = libcryptoName;
	initOpts.jitOpts.libsslName = libsslName;
	initOpts.jitOpts.libcurlName = libcurlName;
	initOpts.rsslLocking = RSSL_LOCK_GLOBAL_AND_CHANNEL;

	/* Initialize run-time */
	initRuntime();

	rsslInitializeEx(&initOpts, &rsslErr);

	/* Setup role */
	rsslClearOMMNIProviderRole((RsslReactorOMMNIProviderRole*)&role);
	role.pLoginRequest = (RsslRDMLoginRequest*)&chnlCommand.loginRequest;
	role.loginMsgCallback = processLoginResponse;
	role.pDirectoryRefresh = &chnlCommand.directoryRefresh;
	role.base.channelEventCallback = channelEventCallback;
	role.base.defaultMsgCallback = processResponse;

	printf("Connections:\n");

	chnlCommand.pRole = (RsslReactorChannelRole*)&role;
	chnlCommand.cOpts.rsslConnectOptions.guaranteedOutputBuffers = 500;
	chnlCommand.cOpts.rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION;
	chnlCommand.cOpts.rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION;
	chnlCommand.cOpts.rsslConnectOptions.userSpecPtr = (void*)&chnlCommand;

//	printf("	%s:%s:%s\n", chnlCommand.hostName, chnlCommand.port, chnlCommand.serviceName);

	printf("		MarketPriceItems:");
	for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j)
	{
		RsslNIItemInfo *pItem = &chnlCommand.marketPriceItemInfo[j];
		if (pItem->isActive)
		printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname);
	}

	printf("		MarketByOrderItems:");
	for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j)
	{
		RsslNIItemInfo *pItem = &chnlCommand.marketByOrderItemInfo[j];
		if (pItem->isActive)
		printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname);
	}


	printf("\n");

	printf("\n");
	
	/* Load local dictionary */
	if(rsslLoadFieldDictionary("RDMFieldDictionary", &dictionary, &errBuf) < RSSL_RET_SUCCESS)
	{
		printf("Dictionary error: %s\n", errBuf.data);
		exit(-1);
	}
	
	chnlCommand.dictionary = &dictionary;
	
	initializeCacheDictionary(&dictionary);

	rsslClearCreateReactorOptions(&reactorOpts);
	reactorOpts.dispatchDecodeMemoryBufferSize = 1024;

	setupLoginRequest(&chnlCommand, 1);

	setupDirectoryResponseMsg(&chnlCommand, -1);
	
	if (!(pReactor = rsslCreateReactor(&reactorOpts, &error)))
	{
		printf("Error: %s", error.rsslError.text);
		exit(-1);
	}
	
	

	FD_ZERO(&readFds);
	FD_ZERO(&writeFds);
	FD_ZERO(&exceptFds);

	FD_SET(pReactor->eventFd, &readFds);

	if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS)
		printf("Error rsslReactorConnect(): %s\n", error.rsslError.text);
		
	rsslClearReactorDispatchOptions(&dispatchOpts);
	//dispatchOpts.pReactorChannel = &chnlCommand.reactorChannel;

	printf("Connection started!\n");

	while ( RSSL_TRUE )
	{
		struct timeval selectTime;
		int dispatchCount = 0;
		fd_set useReadFds = readFds, useWriteFds = writeFds, useExceptFds = exceptFds;
		selectTime.tv_sec = 1; selectTime.tv_usec = 0;

		handleRuntime();

		selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &selectTime);

		if (selRet == 0 ) /* no messages received, send updates and continue */
		{
			// Update items
			updateItemInfo(&chnlCommand);

			/* Send market price updates for each connected channel */
			if (chnlCommand.startWrite == RSSL_TRUE)
			{
				if ((chnlCommand.reactorChannel != NULL) && (chnlCommand.reactorChannel->socketId != -1))
				{
					if (sendItemUpdates(pReactor,chnlCommand.reactorChannel) != RSSL_RET_SUCCESS)
						recoverConnection(pReactor, chnlCommand.reactorChannel, &chnlCommand);
				}
			}
			else
			{
				if (cacheInfo.useCache)
					cacheItemData(&chnlCommand);
			}
		}
		else if (selRet > 0)
		{
			RsslRet ret;
			while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &error)) > 0);

			if(ret < 0)
			{
				printf("dispatch error! %i\n %s\n %s\n", ret, error.rsslError.text, error.errorLocation);
				/* Reactor has shutdown. Clean up and exit. */
				cleanUpAndExit();
			}
		}
	
		/* get current time */
		if ((currentTime = time(NULL)) < 0)
		{
			printf("time() failed.\n");
		}

		// send login reissue if login reissue time has passed
		if (chnlCommand.canSendLoginReissue == RSSL_TRUE &&
			currentTime >= (RsslInt)chnlCommand.loginReissueTime)
		{
			RsslReactorSubmitMsgOptions submitMsgOpts;
			RsslErrorInfo rsslErrorInfo;

			rsslClearReactorSubmitMsgOptions(&submitMsgOpts);
			submitMsgOpts.pRDMMsg = (RsslRDMMsg*)chnlCommand.pRole->ommNIProviderRole.pLoginRequest;
			if ((ret = rsslReactorSubmitMsg(pReactor,chnlCommand.reactorChannel,&submitMsgOpts,&rsslErrorInfo)) != RSSL_RET_SUCCESS)
			{
				printf("Login reissue failed:  %d(%s)\n", ret, rsslErrorInfo.rsslError.text);
			}
			else
			{
				printf("Login reissue sent\n");
			}
			chnlCommand.canSendLoginReissue = RSSL_FALSE;
		}
	}
}
Example #3
0
RSSL_THREAD_DECLARE(runReactorConnectionHandler, pArg)
{
	ProviderThread *pProvThread = (ProviderThread*)pArg;

	TimeValue nextTickTime;
	RsslInt32 currentTicks = 0;
	TimeValue currentTime;
	RsslRet ret;
	int selRet;
	struct timeval time_interval;
	fd_set useRead;
	fd_set useExcept;
	fd_set useWrt;
	RsslErrorInfo rsslErrorInfo;
	RsslReactorDispatchOptions dispatchOptions;
	RsslCreateReactorOptions reactorOpts;

	rsslClearReactorDispatchOptions(&dispatchOptions);

	if (pProvThread->cpuId >= 0)
	{
		if (bindThread(pProvThread->cpuId) != RSSL_RET_SUCCESS)
		{
			printf("Error: Failed to bind thread to core %d.\n", pProvThread->cpuId);
			exit(-1);
		}
	}

	// create reactor
	rsslClearCreateReactorOptions(&reactorOpts);

	if (!(pProvThread->pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo)))
	{
		printf("Reactor creation failed: %s\n", rsslErrorInfo.rsslError.text);
		cleanUpAndExit();
	}

	FD_ZERO(&pProvThread->readfds);
	FD_ZERO(&pProvThread->wrtfds);
	FD_ZERO(&pProvThread->exceptfds);

	/* Set the reactor's event file descriptor on our descriptor set. This, along with the file descriptors
	 * of RsslReactorChannels, will notify us when we should call rsslReactorDispatch(). */
	FD_SET(pProvThread->pReactor->eventFd, &pProvThread->readfds);

	nextTickTime = getTimeNano() + nsecPerTick;

	/* this is the main loop */
	while(rtrLikely(!signal_shutdown))
	{
		/* Loop on select(), looking for channels with available data, until stopTimeNsec is reached. */
		do
		{
#ifdef WIN32
			/* Windows does not allow select() to be called with empty file descriptor sets. */
			if (pProvThread->readfds.fd_count == 0)
			{
				currentTime = getTimeNano();
				selRet = 0;
				Sleep((DWORD)((currentTime < nextTickTime) ? (nextTickTime - currentTime)/1000000 : 0));
			}
			else
#endif
			{
				useRead = pProvThread->readfds;
				useWrt = pProvThread->wrtfds;
				useExcept = pProvThread->exceptfds;

				currentTime = getTimeNano();
				time_interval.tv_usec = (long)((currentTime < nextTickTime) ? (nextTickTime - currentTime)/1000 : 0);
				time_interval.tv_sec = 0;

				selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval);
			}

			if (selRet == 0)
			{
				break;
			}
			else if (selRet > 0)
			{	
				while ((ret = rsslReactorDispatch(pProvThread->pReactor, &dispatchOptions, &rsslErrorInfo)) > RSSL_RET_SUCCESS) {}
				if (ret < RSSL_RET_SUCCESS)
				{
					printf("rsslReactorDispatch failed with return code: %d error = %s\n", ret,  rsslErrorInfo.rsslError.text);
					exit(-1);
				}
			}
#ifdef WIN32
			else if (WSAGetLastError() != WSAEINTR)
#else 
			else if (errno != EINTR)
#endif
			{
				perror("select");
				exit(-1);
			}
		} while (currentTime < nextTickTime);

		nextTickTime += nsecPerTick;

		providerThreadSendMsgBurst(pProvThread, nextTickTime);
	}

	return RSSL_THREAD_RETURN();
}
/*** MAIN ***/
int main(int argc, char **argv)
{
	RsslRet ret;
	RsslCreateReactorOptions reactorOpts;
	RsslErrorInfo rsslErrorInfo;
	RsslReactorOMMConsumerRole consumerRole;
	RsslRDMLoginRequest loginRequest;
	RsslRDMDirectoryRequest dirRequest;
	RsslReactorDispatchOptions dispatchOpts;
	ChannelStorage *pCommand = &chanCommand;
	RsslReactorConnectOptions *pOpts = &pCommand->cOpts;
	RsslReactorConnectInfo *pInfo = &pCommand->cInfo;
	RsslUInt32 i;

	/* Initialize RSSL. The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */
	if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &rsslErrorInfo.rsslError) != RSSL_RET_SUCCESS)
	{
		printf("rsslInitialize(): failed <%s>\n", rsslErrorInfo.rsslError.text);
		exitApp(-1);
	}
	
	
	initChannelStorage(&chanCommand);

	/* Initialize parameters from config. */
	parseCommandLine(argc, argv);

	/* Initialize run-time */
	initRuntime();

	/* Initialize the default login request(Use 1 as the Login Stream ID). */
	if (rsslInitDefaultRDMLoginRequest(&loginRequest, 1) != RSSL_RET_SUCCESS)
	{
		printf("rsslInitDefaultRDMLoginRequest() failed\n");
		cleanUpAndExit(-1);
	}		

	if (userName.length)
		loginRequest.userName = userName;

	/* Initialize the default directory request(Use 2 as the Directory Stream Id) */
	if (rsslInitDefaultRDMDirectoryRequest(&dirRequest, 2) != RSSL_RET_SUCCESS)
	{
		printf("rsslInitDefaultRDMDirectoryRequest() failed\n");
		cleanUpAndExit(-1);
	}

	/* Setup callback functions and use them on all connections*/
	rsslClearOMMConsumerRole(&consumerRole);
	consumerRole.loginMsgCallback = loginMsgCallback;
	consumerRole.directoryMsgCallback = directoryMsgCallback;
//	consumerRole.dictionaryMsgCallback = dictionaryMsgCallback;
	consumerRole.base.channelEventCallback = channelEventCallback;
	consumerRole.base.defaultMsgCallback = defaultMsgCallback;

	/* Set the messages to send when the channel is up */
	consumerRole.pLoginRequest = &loginRequest;
	consumerRole.pDirectoryRequest = &dirRequest;

	printf("Connections:\n");

	/* Print out a summary of the connections and desired items. */



	printf("	%s:%s\n", pCommand->hostName, pCommand->port);
	printf("    QueueService: %s\n", pCommand->queueServiceName);
	printf("    Source Queue: %s\n", pCommand->sourceName.data);
	printf("	Dest Queues:");
	for (i = 0; i < pCommand->destNameCount; ++i)
		printf(" %s", pCommand->destNames[i].data);
	printf("\n\n");


	/* Initialize connection options and try to load dictionaries. */

	

	pCommand->pRole = (RsslReactorChannelRole*)&consumerRole;
	pInfo->rsslConnectOptions.guaranteedOutputBuffers = 500;
	pInfo->rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION;
	pInfo->rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION;
	pInfo->rsslConnectOptions.userSpecPtr = &chanCommand;
	pInfo->initializationTimeout = 5;
	pOpts->reactorConnectionList = pInfo;
	pOpts->connectionCount = 1;
	pOpts->reconnectAttemptLimit = -1;
	pOpts->reconnectMaxDelay = 5000;
	pOpts->reconnectMinDelay = 1000;


	printf("\n");

	/* Create an RsslReactor which will manage our channels. */

	rsslClearCreateReactorOptions(&reactorOpts);

	if (!(pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo)))
	{
		printf("Error: %s", rsslErrorInfo.rsslError.text);
		exit(-1);
	}

	FD_ZERO(&readFds);
	FD_ZERO(&exceptFds);

	/* Set the reactor's event file descriptor on our descriptor set. This, along with the file descriptors 
	 * of RsslReactorChannels, will notify us when we should call rsslReactorDispatch(). */
	FD_SET(pReactor->eventFd, &readFds);

	printf("Adding connection to %s:%s...\n", pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.address, pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.serviceName );

	if (rsslReactorConnect(pReactor, &pCommand->cOpts, pCommand->pRole, &rsslErrorInfo) != RSSL_RET_SUCCESS)
	{
		printf("Error rsslReactorConnect(): %s\n", rsslErrorInfo.rsslError.text);
	}

	printf("\n");



	rsslClearReactorDispatchOptions(&dispatchOpts);

	/* Main loop. The loop
	 * calls select() to wait for notification, then calls rsslReactorDispatch(). */
	do
	{
		struct timeval selectTime;
		int dispatchCount = 0;
		fd_set useReadFds = readFds, useExceptFds = exceptFds;
		selectTime.tv_sec = 1; selectTime.tv_usec = 0;

		handleRuntime();

		if (!runTimeExpired)
		{
			if (handleQueueMessaging(pReactor, &chanCommand) != RSSL_RET_SUCCESS)
				cleanUpAndExit(-1);
		}
	

		ret = select(FD_SETSIZE, &useReadFds, NULL, &useExceptFds, &selectTime);

		if (ret < 0)
		{
#ifdef _WIN32
			if (WSAGetLastError() == WSAEINTR)
				continue;

			printf("Error: select: %d\n", WSAGetLastError());
#else
			if (errno == EINTR)
				continue;

			perror("select");
#endif
			cleanUpAndExit(-1);
		}

		
		/* Call rsslReactorDispatch().  This will handle any events that have occurred on its channels.
		 * If there are events or messages for the application to process, they will be delivered
		 * through the callback functions given by the consumerRole object. 
		 * A return value greater than RSSL_RET_SUCCESS indicates there may be more to process. */
		while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &rsslErrorInfo)) > RSSL_RET_SUCCESS)
			;

		if (ret < RSSL_RET_SUCCESS)
		{
			printf("rsslReactorDispatch() failed: %s\n", rsslErrorInfo.rsslError.text);
			cleanUpAndExit(-1);
		}

	} while(ret >= RSSL_RET_SUCCESS);

	cleanUpAndExit(-1);
}