/*
 * Handles the run-time for the rsslConsumer.  Closes all streams
 * for the consumer after run-time has elapsed.
 */
static void handleRuntime()
{
	time_t currentTime = 0;
	RsslRet	retval = 0;
	RsslError error;

	/* get current time */
	time(&currentTime);

	if (currentTime >= rsslConsumerRuntime)
	{
		if (rsslConsumerChannel != NULL && rsslConsumerChannel->socketId != -1 && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE)
		{
			/* close all streams */
			closeOffstreamPost(rsslConsumerChannel);
			
			/* close all item streams */
			closeSymbolListStream(rsslConsumerChannel);
			closeMarketPriceItemStreams(rsslConsumerChannel);
			closeMarketByOrderItemStreams(rsslConsumerChannel);
			closeMarketByPriceItemStreams(rsslConsumerChannel);
			closeYieldCurveItemStreams(rsslConsumerChannel);

			/* close dictionary stream */
			if (!isFieldDictionaryLoadedFromFile())
    			closeDictionaryStream(rsslConsumerChannel, FIELD_DICTIONARY_STREAM_ID);
			if (!isEnumTypeDictionaryLoadedFromFile())
    			closeDictionaryStream(rsslConsumerChannel, ENUM_TYPE_DICTIONARY_STREAM_ID);

			/* close source directory stream */
			closeSourceDirectoryStream(rsslConsumerChannel);

			/* close login stream */
			/* note that closing login stream will automatically
			   close all other streams at the provider */
			if (closeLoginStream(rsslConsumerChannel) != RSSL_RET_SUCCESS)
			{
				cleanUpAndExit();
			}

			/* flush before exiting */
			if (FD_ISSET(rsslConsumerChannel->socketId, &wrtfds))
			{
				retval = 1;
				while (retval > RSSL_RET_SUCCESS)
				{
					retval = rsslFlush(rsslConsumerChannel, &error);
				}
				if (retval < RSSL_RET_SUCCESS)
				{
					printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text);
				}
			}
		}

		printf("\nrsslConsumer run-time expired...\n");
		cleanUpAndExit();
	}
}
/*
 * Handles the ping processing for a channel.  Sends a ping to the
 * server if the next send ping time has arrived and checks if a
 * ping has been received from the server within the next receive
 * ping time.
 * chnl - The channel to handle pings for
 */
static void handlePings(RsslChannel* chnl)
{
	time_t currentTime = 0;

	/* get current time */
	time(&currentTime);

	/* handle client pings */
	if (currentTime >= nextSendPingTime)
	{
		/* send ping to server */
		if (sendPing(chnl) != RSSL_RET_SUCCESS)
		{
			cleanUpAndExit();
		}

		/* set time to send next ping from client */
		nextSendPingTime = currentTime + (time_t)pingTimeoutClient;
	}

	/* handle server pings */
	if (currentTime >= nextReceivePingTime)
	{
		/* check if client received message from server since last time */
		if (receivedServerMsg)
		{
			/* reset flag for server message received */
			receivedServerMsg = RSSL_FALSE;

			/* set time client should receive next message/ping from server */
			nextReceivePingTime = currentTime + (time_t)pingTimeoutServer;
		}
		else /* lost contact with server */
		{
			printf("\nLost contact with server...\n");
			cleanUpAndExit();
		}
	}
}
static void handleRuntime()
{
	RsslErrorInfo error;
	time_t currentTime = 0;
	RsslRet	retval = 0;

	/* get current time */
	time(&currentTime); 

	if(chnlCommand.reconnect == RSSL_TRUE)
	{
		chnlCommand.reconnect = RSSL_FALSE;
		printf("Reconnecting in 10 seconds...\n");
		chnlCommand.timeToReconnect = 10;
	}

	if (chnlCommand.timeToReconnect > 0)
	{
		--chnlCommand.timeToReconnect;

		if (chnlCommand.timeToReconnect == 0)
		{
			if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS)
			{
				printf("Error rsslReactorConnect(): %s\n", error.rsslError.text);
				chnlCommand.reconnect = RSSL_TRUE;
			}
		}
	}

	if(currentTime > rsslProviderRuntime)
	{
		if( chnlCommand.reactorChannel != NULL && rsslReactorCloseChannel(pReactor, chnlCommand.reactorChannel, &error) != RSSL_RET_SUCCESS)
		{
			printf("Error rsslReactorCloseChannel(): %s\n", error.rsslError.text);
		}

		cleanUpAndExit();
	}

}
/*
 * Handles time-related events.
 * Calls rsslReactorConnect() for any channels that we want to recover.
 * Exits the application if the run-time has expired.
 */
static void handleRuntime()
{
	time_t currentTime = 0;
	RsslRet	retval = 0;
	RsslErrorInfo rsslErrorInfo;

	/* get current time */
	time(&currentTime); 


	if (currentTime >= rsslConsumerRuntime)
	{
		if (!runTimeExpired)
		{
			runTimeExpired = RSSL_TRUE;
			printf("Run time expired.\n\n");
			
			if (chanCommand.pHandlerTunnelStream != NULL)
				printf("Waiting for tunnel stream to close...\n");


			/* Close tunnel streams if any are open. */
			closeTunnelStreams(chanCommand.reactorChannel, &rsslErrorInfo);		
		}
		else
		{
			if (chanCommand.pHandlerTunnelStream == NULL
					|| currentTime >= rsslConsumerRuntime + 10)
			{
				if (chanCommand.pHandlerTunnelStream != NULL)
					printf("Tunnel stream still open after ten seconds, giving up.\n");
				cleanUpAndExit(-1);
			}
		}
	}
}
/*
 * Removes a client session for a channel.
 * pReactorChannel - The channel to remove the client session for
 */
void removeClientSessionForChannel(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel)
{
	RsslErrorInfo rsslErrorInfo;
	int i;

	for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
	{
		if (clientSessions[i].clientChannel == pReactorChannel)
		{
			removeClientSession(&clientSessions[i]);
			break;
		}
	}

	FD_CLR(pReactorChannel->socketId, &readFds);
	FD_CLR(pReactorChannel->socketId, &exceptFds);


	if (rsslReactorCloseChannel(pReactor, pReactorChannel, &rsslErrorInfo) != RSSL_RET_SUCCESS)
	{
		printf("rsslReactorCloseChannel() failed: %s\n", rsslErrorInfo.rsslError.text);
		cleanUpAndExit();
	}
}
Beispiel #6
0
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer)
{
	RsslRet ret = RSSL_RET_SUCCESS; RsslMsg msg = RSSL_INIT_MSG;
	RsslDecodeIterator dIter;
	ProviderThread *pProvThread = (ProviderThread*)pChannelHandler->pUserSpec;
	RsslChannel *pChannel = pChannelInfo->pChannel;
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, pChannel->majorVersion, pChannel->minorVersion);

	rsslSetDecodeIteratorBuffer(&dIter, pBuffer);

	ret = rsslDecodeMsg(&dIter, &msg);				
	if (ret != RSSL_RET_SUCCESS)
	{
		printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d  Size %d \n", ret, pChannel->socketId, pBuffer->length);
		cleanUpAndExit();
	}

	switch ( msg.msgBase.domainType )
	{
		case RSSL_DMT_LOGIN:
			ret = processLoginRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_SOURCE:
			ret = processDirectoryRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_DICTIONARY:
			ret = processDictionaryRequest(pChannelHandler, pChannelInfo, &msg, &dIter);
			break;
		case RSSL_DMT_MARKET_PRICE:
			if (xmlMsgDataHasMarketPrice)
				ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter);
			else
				ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
						msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		case RSSL_DMT_MARKET_BY_ORDER:
			if (xmlMsgDataHasMarketByOrder)
				ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter);
			else
				ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
						msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
		default:
			ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, 
					msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED);
			break;
	}


	if (ret < RSSL_RET_SUCCESS) 
	{
		printf("Failed to process request from domain %d: %d\n", msg.msgBase.domainType, ret);
	}
	else if (ret > RSSL_RET_SUCCESS)
	{
		/* The function sent a message and indicated that we need to flush. */
		providerThreadRequestChannelFlush(pProvThread, pChannelInfo);
	}

	return ret;
}
RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pChannelEvent)
{
	RsslBool clientSessionFound = RSSL_FALSE;
	RsslClientSessionInfo *pClientSessionInfo = (RsslClientSessionInfo*)pReactorChannel->userSpecPtr;
	

	switch(pChannelEvent->channelEventType)
	{
		case RSSL_RC_CET_CHANNEL_UP:
		{
			/* A channel that we have requested via rsslReactorAccept() has come up.  Set our
			 * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for
			 * this channel. */
#ifdef _WIN32
			int rcvBfrSize = 65535;
			int sendBfrSize = 65535;
			RsslErrorInfo rsslErrorInfo;
#endif
			printf("Connection up!\n");
			pClientSessionInfo->clientChannel = pReactorChannel;
			printf("\nServer fd="SOCKET_PRINT_TYPE": New client on Channel fd="SOCKET_PRINT_TYPE"\n",
					pReactorChannel->pRsslServer->socketId, pReactorChannel->socketId);
			FD_SET(pReactorChannel->socketId, &readFds);
			FD_SET(pReactorChannel->socketId, &exceptFds);

#ifdef _WIN32
			/* WINDOWS: change size of send/receive buffer since it's small by default */
			if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text);
			}
			if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text);
			}
#endif
			if (xmlTrace) 
			{
				RsslErrorInfo rsslErrorInfo;
				RsslTraceOptions traceOptions;

				rsslClearTraceOptions(&traceOptions);
				traceOptions.traceMsgFileName = traceOutputFile;
				traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_TO_STDOUT | RSSL_TRACE_TO_MULTIPLE_FILES | RSSL_TRACE_WRITE | RSSL_TRACE_READ;
				traceOptions.traceMsgMaxFileSize = 100000000;

				rsslReactorChannelIoctl(pReactorChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &rsslErrorInfo);
			}
	
			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_READY:
			/* The channel has exchanged the messages necessary to setup the connection
			 * and is now ready for general use. For an RDM Provider, this normally immediately
			 * follows the CHANNEL_UP event. */
			return RSSL_RC_CRET_SUCCESS;
		case RSSL_RC_CET_FD_CHANGE:
			/* The file descriptor representing the RsslReactorChannel has been changed.
			 * Update our file descriptor sets. */
			printf("Fd change: "SOCKET_PRINT_TYPE" to "SOCKET_PRINT_TYPE"\n", pReactorChannel->oldSocketId, pReactorChannel->socketId);
			FD_CLR(pReactorChannel->oldSocketId, &readFds);
			FD_CLR(pReactorChannel->oldSocketId, &exceptFds);
			FD_SET(pReactorChannel->socketId, &readFds);
			FD_SET(pReactorChannel->socketId, &exceptFds);
			return RSSL_RC_CRET_SUCCESS;
		case RSSL_RC_CET_WARNING:
			/* We have received a warning event for this channel. Print the information and continue. */
			printf("Received warning for Channel fd="SOCKET_PRINT_TYPE".\n", pReactorChannel->socketId);
			printf("	Error text: %s\n", pChannelEvent->pError->rsslError.text);
			return RSSL_RC_CRET_SUCCESS;
		case RSSL_RC_CET_CHANNEL_DOWN:
		{
			/* The channel has failed and has gone down.  Print the error, close the channel, and reconnect later. */
			printf("Connection down!\n");

			if (pChannelEvent->pError)
				printf("	Error text: %s\n", pChannelEvent->pError->rsslError.text);

			closeItemChnlStreams(pReactor, pReactorChannel);
			closeDictionaryChnlStreams(pReactorChannel);
			closeDirectoryStreamForChannel(pReactorChannel);
			closeLoginStreamForChannel(pReactorChannel);

			if(pClientSessionInfo->clientChannel == NULL)
			{
				pClientSessionInfo->clientChannel = pReactorChannel;
			}

			/* It is important to make sure that no more interface calls are made using the channel after
			 * calling rsslReactorCloseChannel(). Because this application is single-threaded, it is safe 
			 * to call it inside callback functions. */
			removeClientSessionForChannel(pReactor, pReactorChannel);

			return RSSL_RC_CRET_SUCCESS;
		}
		default:
			printf("Unknown channel event!\n");
			cleanUpAndExit();
	}

	return RSSL_RC_CRET_SUCCESS;

}
/*
 * Handles the run-time for the rsslProvider.  Sends close status
 * messages to all streams on all channels after run-time has elapsed.
 */
static void handleRuntime()
{
	int i, j;
	time_t currentTime = 0;
	RsslRet	retval = 0;

	/* get current time */
	time(&currentTime);

	if (currentTime >= rsslProviderRuntime)
	{
		RsslBool tunnelStreamsOpen = RSSL_FALSE;

		for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
		{
			if (clientSessions[i].clientChannel != NULL)
			{
				/* If any tunnel streams are still open, wait for them to close before quitting. */
				for (j = 0; j < MAX_TUNNEL_STREAMS; j++)
				{
					if (clientSessions[i].simpleTunnelMsgHandler[j].tunnelStreamHandler.pTunnelStream != NULL)
				{
					tunnelStreamsOpen = RSSL_TRUE;
						
					if (!runTimeExpired)
							simpleTunnelMsgHandlerCloseStreams(&clientSessions[i].simpleTunnelMsgHandler[j]);
					else
						break;
				}
			}
		}
		}

		if (!runTimeExpired)
		{
			runTimeExpired = RSSL_TRUE;
			printf("\nrsslVAProvider run-time expired...\n");

			if (tunnelStreamsOpen)
				printf("Waiting for tunnel streams to close...\n");
		}

		if (!tunnelStreamsOpen || currentTime >= rsslProviderRuntime + 10)
		{
			if (currentTime >= rsslProviderRuntime + 10)
				printf("Tunnel streams still open after ten seconds, giving up.\n");

			/* send close status messages to all streams on all channels */
			for (i = 0; i < MAX_CLIENT_SESSIONS; i++)
			{
				if (clientSessions[i].clientChannel != NULL)
				{
					/* send close status messages to all item streams */
					sendItemCloseStatusMsgs(pReactor, clientSessions[i].clientChannel);

					/* send close status messages to dictionary streams */
					sendDictionaryCloseStatusMsgs(pReactor, clientSessions[i].clientChannel);

				}
			}

			cleanUpAndExit();
		}
	}
}
Beispiel #9
0
int
main( int argc, char **argv ) {

    signal( SIGPIPE, SIG_IGN );

    int status;
    int continueAllFlag = 0;
    int sleepSec = 1;
    int rNum = 1;
    int stdinflags;
    int verbose = 0;
    int opt;
    getXmsgTicketInp_t getXmsgTicketInp;
    xmsgTicketInfo_t xmsgTicketInfo;
    xmsgTicketInfo_t *outXmsgTicketInfo;
    sendXmsgInp_t sendXmsgInp;
    rcvXmsgInp_t rcvXmsgInp;
    rcvXmsgOut_t *rcvXmsgOut = NULL;
    char  ubuf[4000];

    /* set up signals */

#ifndef _WIN32
    signal( SIGINT, signalIdbugExit );
    signal( SIGHUP, signalIdbugExit );
    signal( SIGTERM, signalIdbugExit );
    signal( SIGUSR1, signalIdbugExit );
    /* XXXXX switched to SIG_DFL for embedded python. child process
     * went away. But probably have to call waitpid.
     * signal(SIGCHLD, SIG_IGN); */
    signal( SIGCHLD, SIG_DFL );
#endif


    while ( ( opt = getopt( argc, argv, "cChv:" ) ) != EOF ) {
        switch ( opt ) {
        case 'v':
            verbose = atoi( optarg );
            break;
        case 'c':
            continueAllFlag = 1;
            break;
        case 'C':
            continueAllFlag = 2;
            break;
        case 'h':
            printIdbugHelp( argv[0] );
            exit( 0 );
            break;
        default:
            fprintf( stderr, "Error: Unknown Option\n" );
            printIdbugHelp( argv[0] );
            exit( 1 );
            break;
        }
    }


    /* initialize and connect */
    snprintf( lastSent, HEADER_TYPE_LEN, "CMSG:BEGIN" );
    myHostName[0] = '\0';
    gethostname( myHostName, MAX_NAME_LEN );
    connectToX();

    memset( &xmsgTicketInfo, 0, sizeof( xmsgTicketInfo ) );
    memset( &getXmsgTicketInp, 0, sizeof( getXmsgTicketInp ) );

    /* get Ticket */
    getXmsgTicketInp.flag = 1;
    status = rcGetXmsgTicket( conn, &getXmsgTicketInp, &outXmsgTicketInfo );
    if ( status != 0 ) {
        fprintf( stderr, "Unable to get Xmsg Ticket. status = %d\n", status );
        exit( 8 );
    }
    fprintf( stdout, "Debug XMsg Stream= %i\n", outXmsgTicketInfo->sendTicket );
    streamId = outXmsgTicketInfo->sendTicket;


    /* Send STOP message on newly created Debug XMsg Stream */
    if ( continueAllFlag == 0 ) {
        status = sendIDebugCommand( "discontinue", "CMSG:BEGIN" );
    }
    else if ( continueAllFlag == 1 ) {
        status = sendIDebugCommand( "continue", "CMSG:BEGIN" );
    }
    else {
        status = sendIDebugCommand( "Continue", "CMSG:BEGIN" );
    }
    if ( status < 0 ) {
        fprintf( stderr, "Error sending Message to Debug Stream %i = %d\n",
                 streamId, status );
        exit( -1 );
    }


    /*
    memset (&sendXmsgInp, 0, sizeof (sendXmsgInp));
    xmsgTicketInfo.sendTicket = streamId;
    xmsgTicketInfo.rcvTicket = streamId;
    xmsgTicketInfo.flag = 1;
    sendXmsgInp.ticket = xmsgTicketInfo;
    snprintf(sendXmsgInp.sendAddr, NAME_LEN, "%s:%i", myHostName, getpid ());
    sendXmsgInp.sendXmsgInfo.numRcv = 100;
    sendXmsgInp.sendXmsgInfo.msgNumber = mNum;
    strcpy(sendXmsgInp.sendXmsgInfo.msgType, "idbug:client");
    snprintf(ubuf,3999, "stop");
    sendXmsgInp.sendXmsgInfo.msg = ubuf;
    status = sendIDebugCommand(&sendXmsgInp);
    mNum++;
    */

    /* Send Startup messages on Stream 4 */
    memset( &sendXmsgInp, 0, sizeof( sendXmsgInp ) );
    xmsgTicketInfo.sendTicket = 4;
    xmsgTicketInfo.rcvTicket = 4;
    xmsgTicketInfo.flag = 1;
    sendXmsgInp.ticket = xmsgTicketInfo;
    snprintf( sendXmsgInp.sendAddr, NAME_LEN, "%s:%i", myHostName, getpid() );
    sendXmsgInp.sendXmsgInfo.numRcv = 100;
    sendXmsgInp.sendXmsgInfo.msgNumber = 1;
    strcpy( sendXmsgInp.sendXmsgInfo.msgType, "STARTDEBUG" );
    snprintf( ubuf, 3999, "%i", outXmsgTicketInfo->sendTicket );
    sendXmsgInp.sendXmsgInfo.msg = ubuf;
    status = rcSendXmsg( conn, &sendXmsgInp );
    if ( status < 0 ) {
        fprintf( stderr, "Error sending Message to Stream 4 = %d\n", status );
        exit( -1 );
    }
    myMNum = status;

    /* switch off blocking for stdin */
    stdinflags = fcntl( 0, F_GETFL, 0 ); /* get current file status flags */
    stdinflags |= O_NONBLOCK;/* turn off blocking flag */
    if ( int status = fcntl( 0, F_SETFL, stdinflags ) ) { /* set up non-blocking read */
        fprintf( stderr, "fcntl failed with status: %d", status );
    }

    /* print to stdout */
    /*    printf("idbug> ");*/

    while ( 1 ) {
        /* check for user  input */
        ubuf[0] = '\0';
        if ( fgets( ubuf, 3999, stdin ) == NULL ) {
            if ( errno !=  EWOULDBLOCK ) {
                printf( "Exiting idbug\n" );
                cleanUpAndExit();
            }
        }
        else { /* got some user input */
            processUserInput( ubuf );
        }
        /* check for messages */
        ubuf[0] = '\0';
        memset( &rcvXmsgInp, 0, sizeof( rcvXmsgInp ) );
        rcvXmsgInp.rcvTicket = streamId;
        sprintf( rcvXmsgInp.msgCondition, "(*XSEQNUM >= %d) && (*XADDR != \"%s:%i\") ", rNum, myHostName, getpid() );

        status = getIDebugReply( &rcvXmsgInp, &rcvXmsgOut, 0 );
        if ( status == 0 ) {
            if ( verbose == 3 ) {
                printf( "%s:%s#%i::%s: %s",
                        rcvXmsgOut->sendUserName, rcvXmsgOut->sendAddr,
                        rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg );
            }
            else if ( verbose == 2 ) {
                printf( "%s#%i::%s: %s",
                        rcvXmsgOut->sendAddr,
                        rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg );
            }
            else if ( verbose == 1 ) {
                printf( "%i::%s: %s", rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg );
            }
            else {
                printf( "%s: %s", rcvXmsgOut->msgType, rcvXmsgOut->msg );
            }
            if ( strstr( rcvXmsgOut->msg, "PROCESS BEGIN" ) != NULL ) {
                /*  printf(" FROM %s ", rcvXmsgOut->sendAddr); */
                storeSendAddr( rcvXmsgOut->sendAddr );
            }
            if ( strstr( rcvXmsgOut->msg, "PROCESS END" ) != NULL ) {
                printf( " FROM %s ", rcvXmsgOut->sendAddr );
                unstoreSendAddr( rcvXmsgOut->sendAddr );
            }
            if ( rcvXmsgOut->msg[strlen( rcvXmsgOut->msg ) - 1] != '\n' ) {
                printf( "\n" );
            }
            rNum  = rcvXmsgOut->seqNumber + 1;
            sleepSec = 1;
            free( rcvXmsgOut->msg );
            free( rcvXmsgOut );
            rcvXmsgOut = NULL;
            localStatus = 2;
        }
        else {
            sleep( sleepSec );
            sleepSec = 2 * sleepSec;
            /* if (sleepSec > 10) sleepSec = 10; */
            if ( sleepSec > 1 ) {
                sleepSec = 1;
            }
        }
    }
}
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();
	}
}
Beispiel #11
0
int processUserInput( char *buf ) {
    char c;
    char hdr[HEADER_TYPE_LEN];
    int i;
    char *t;
    c = buf[0];


    /*
    if (localStatus == 1 && c != 'q') {
      printf("Waiting on iRODS. User input ignored: %s\n", buf);
      return 0;
    }
    */
    if ( ( t = strstr( buf, " for " ) ) != NULL ) {
        *t = '\0';
        t = t + 5;
        while ( *t == ' ' ) {
            t++;
        }
        if ( ( strstr( t, "all" ) == t ) ) {
            snprintf( hdr, HEADER_TYPE_LEN, "CMSG:ALL" );
        }
        else {
            if ( t[strlen( t ) - 1] == '\n' ) {
                t[strlen( t ) - 1] = '\0';
            }
            if ( sendAddr[( int )atoi( t )] != NULL ) {
                snprintf( hdr, HEADER_TYPE_LEN, "CMSG:%s", sendAddr[( int )atoi( t )] );
            }
            else {
                printf( "Wrong Server: No server found for %s\n", t );
                return 0;
            }
        }
    }
    else {
        if ( sendAddrInx == 1 ) {
            snprintf( hdr, HEADER_TYPE_LEN, "CMSG:%s", sendAddr[0] );
        }
        else {
            snprintf( hdr, HEADER_TYPE_LEN, "%s", lastSent );
        }
    }
    strcpy( lastSent, hdr );

    switch ( c ) {
    case '\n':
    case '\0':
    case ' ':
        break;
    case 'n': /* next */
    case 's': /* step in */
    case 'f': /* step out */
    case 'd': /* discontinue. stop now */
    case 'w': /* where */
    case 'W': /* where */
    case 'c': /* continue */
    case 'C': /* continue */
        sendIDebugCommand( buf, hdr );
        localStatus = 1;
        break;
    case 'b': /* set breakpoint at micro-service or rule-name*/
    case 'e': /* print *,$ parameters */
    case 'p': /* print *,$ parameters */
    case 'l': /* list  $ * variables*/
        if ( strchr( buf, ' ' ) == NULL ) {
            fprintf( stderr, "Error: Unknown Option\n" );
        }
        else {
            localStatus = 1;
            sendIDebugCommand( buf, hdr );
        }
        break;
    case 'q': /* quit debugging */
        cleanUpAndExit();
        break;
    case 'h': /* help */
        printCommandSummary();
        break;
    case 'a': /* list Addresses of Processes */
        for ( i = 0; i < sendAddrInx; i++ ) {
            if ( sendAddr[i] != NULL ) {
                printf( "%i: %s\n", i, sendAddr[i] );
            }
        }
        break;
    default:
        fprintf( stderr, "Error: Unknown Option\n" );
        break;
    }
    return 0;

}
Beispiel #12
0
signalIdbugExit()
#endif
{
    cleanUpAndExit();
}
/*** 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);
}
/* 
 * Processes events about the state of an RsslReactorChannel.
 */
RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pConnEvent)
{
	ChannelStorage *pCommand = (ChannelStorage*)pReactorChannel->userSpecPtr;

	switch(pConnEvent->channelEventType)
	{
		case RSSL_RC_CET_CHANNEL_UP:
		{
			/* A channel that we have requested via rsslReactorConnect() has come up.  Set our
			 * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for
			 * this channel. This will drive the process of setting up the connection
			 * by exchanging the Login, Directory, and (if not already loaded)Dictionary messages. 
			 * The application will receive the response messages in the appropriate callback
			 * function we specified. */

#ifdef _WIN32
			int rcvBfrSize = 65535;
			int sendBfrSize = 65535;
			RsslErrorInfo rsslErrorInfo;
#endif

			printf("Connection up! Channel fd=%d\n\n", pReactorChannel->socketId);

			/* Set file descriptor. */
			FD_SET(pReactorChannel->socketId, &readFds);
			FD_SET(pReactorChannel->socketId, &exceptFds);

			/* Save the channel on our info structure. */
			pCommand->reactorChannel = pReactorChannel;


#ifdef _WIN32
			/* WINDOWS: change size of send/receive buffer since it's small by default */
			if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text);
			}
			if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text);
			}
#endif			

			if (xmlTrace) 
			{
				RsslTraceOptions traceOptions;
				RsslErrorInfo rsslErrorInfo;

				rsslClearTraceOptions(&traceOptions);
				traceOptions.traceMsgFileName = traceOutputFile;
				traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_TO_STDOUT | RSSL_TRACE_TO_MULTIPLE_FILES | RSSL_TRACE_WRITE | RSSL_TRACE_READ;
				traceOptions.traceMsgMaxFileSize = 100000000;

				rsslReactorChannelIoctl(pReactorChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &rsslErrorInfo);
			}

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_READY:
		{
			pCommand->reactorChannelReady = RSSL_TRUE;
			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_FD_CHANGE:
		{
			/* The file descriptor representing the RsslReactorChannel has been changed.
			 * Update our file descriptor sets. */
			printf("Fd change: %d to %d\n", pReactorChannel->oldSocketId, pReactorChannel->socketId);
			FD_CLR(pReactorChannel->oldSocketId, &readFds);
			FD_CLR(pReactorChannel->oldSocketId, &exceptFds);
			FD_SET(pReactorChannel->socketId, &readFds);
			FD_SET(pReactorChannel->socketId, &exceptFds);
			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_DOWN:
		{
			/* The channel has failed and has gone down.  Print the error, close the channel, and reconnect later. */

			printf("Connection down: Channel fd=%d.\n", pReactorChannel->socketId);

			if (pConnEvent->pError)
				printf("	Error text: %s\n\n", pConnEvent->pError->rsslError.text);

			/* It is important to make sure that no more interface calls are made using the channel after
			 * calling rsslReactorCloseChannel(). Because this application is single-threaded, it is safe 
			 * to call it inside callback functions. */
			closeConnection(pReactor, pReactorChannel, pCommand);

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_DOWN_RECONNECTING:
		{
			printf("Connection down, reconnecting.  Channel fd=%d\n", pReactorChannel->socketId);

			if (pReactorChannel->socketId != REACTOR_INVALID_SOCKET)
			{
				FD_CLR(pReactorChannel->socketId, &readFds);
				FD_CLR(pReactorChannel->socketId, &exceptFds);
			}

			clearChannelStorage(pCommand);

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_WARNING:
		{
			/* We have received a warning event for this channel. Print the information and continue. */
			printf("Received warning for Channel fd=%d.\n", pReactorChannel->socketId);
			printf("	Error text: %s\n\n", pConnEvent->pError->rsslError.text);
			return RSSL_RC_CRET_SUCCESS;
		}
		default:
		{
			printf("Unknown connection event!\n");
			cleanUpAndExit(-1);
		}
	}


	return RSSL_RC_CRET_SUCCESS;
}
Beispiel #15
0
int main(int argc, char **argv)
{
	struct timeval time_interval;
	RsslError error;
	fd_set useRead;
	fd_set useExcept;
	int selRet;
	RsslRet	ret = 0;
	RsslBindOptions sopts;
	RsslErrorInfo rsslErrorInfo;

	TimeValue nextTickTime;
	RsslInt32 currentTicks;
	RsslUInt32 currentRuntimeSec = 0, intervalSeconds = 0;

	TimeValue tickSetStartTime; /* Holds when a paritcular run of ticks started(basically one second's worth)*/

	/* Read in configuration and echo it. */
	initProvPerfConfig(argc, argv);
	printProvPerfConfig(stdout);

	if (!(summaryFile = fopen(provPerfConfig.summaryFilename, "w")))
	{
		printf("Error: Failed to open file '%s'.\n", provPerfConfig.summaryFilename);
		exit(-1);
	}

	printProvPerfConfig(summaryFile); fflush(summaryFile);

	// set up a signal handler so we can cleanup before exit
	signal(SIGINT, signal_handler);

	nsecPerTick = 1000000000LL/(RsslInt64)providerThreadConfig.ticksPerSec;

	_currentTime = getTimeNano();
	nextTickTime = _currentTime;
	currentTicks = 0;

	xmlInitParser();

	FD_ZERO(&readfds);
	FD_ZERO(&exceptfds);

	/* Initialize RSSL */
	if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel
	{
		if (rsslInitialize(providerThreadConfig.threadCount > 1 ? RSSL_LOCK_GLOBAL : RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS)
		{
			printf("RsslInitialize failed: %s\n", error.text);
			exit(-1);
		}
	}
	else // use UPA VA Reactor
	{
		/* The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */
		if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &error) != RSSL_RET_SUCCESS)
		{
			printf("RsslInitialize failed: %s\n", error.text);
			exit(-1);
		}
	}

	/* Initialize run-time */
	rsslProviderRuntime = getTimeNano() + ((RsslInt64)provPerfConfig.runTime * 1000000000LL);

	providerInit(&provider, PROVIDER_INTERACTIVE,
			processActiveChannel,
			processInactiveChannel,
			processMsg);

	if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel
	{
		startProviderThreads(&provider, runChannelConnectionHandler);
	}
	else // use UPA VA Reactor
	{
		startProviderThreads(&provider, runReactorConnectionHandler);
	}


	rsslClearBindOpts(&sopts);

	sopts.guaranteedOutputBuffers = provPerfConfig.guaranteedOutputBuffers;
	sopts.serviceName = provPerfConfig.portNo;
	if(strlen(provPerfConfig.interfaceName)) sopts.interfaceName = provPerfConfig.interfaceName;
	sopts.majorVersion = RSSL_RWF_MAJOR_VERSION;
	sopts.minorVersion = RSSL_RWF_MINOR_VERSION;
	sopts.protocolType = RSSL_RWF_PROTOCOL_TYPE;
	sopts.tcp_nodelay = provPerfConfig.tcpNoDelay;
	sopts.sysSendBufSize = provPerfConfig.sendBufSize;
	sopts.sysRecvBufSize = provPerfConfig.recvBufSize;
	sopts.connectionType = RSSL_CONN_TYPE_SOCKET;
	sopts.maxFragmentSize = provPerfConfig.maxFragmentSize;

	if ((rsslSrvr = rsslBind(&sopts, &error)) == 0)
	{
		printf("rsslBind() failed: %d(%s)\n", error.rsslErrorId, error.text);
		exit(-1);
	}

	printf("Server %d bound to port %d.\n\n", rsslSrvr->socketId, rsslSrvr->portNumber);
	FD_SET(rsslSrvr->socketId,&readfds);
	FD_SET(rsslSrvr->socketId,&exceptfds);

	time_interval.tv_sec = 0; time_interval.tv_usec = 0;
	nextTickTime = getTimeNano() + nsecPerTick;
	currentTicks = 0;
	tickSetStartTime = getTimeNano();

	/* this is the main loop */
	while(1)
	{
		useRead = readfds;
		useExcept = exceptfds;

		/* select() on remaining time for this tick. If we went into the next tick, don't delay at all. */
		_currentTime = getTimeNano();
		time_interval.tv_usec = (long)((_currentTime > nextTickTime) ? 0 : ((nextTickTime - _currentTime)/1000));
		selRet = select(FD_SETSIZE, &useRead, NULL, &useExcept, &time_interval);

		if (selRet == 0)
		{
			/* We've reached the next tick. */
			nextTickTime += nsecPerTick;
			++currentTicks;

			if (currentTicks == providerThreadConfig.ticksPerSec)
			{
				++currentRuntimeSec;
				++intervalSeconds;
				currentTicks = 0;
			}

			if (intervalSeconds == provPerfConfig.writeStatsInterval)
			{
				providerCollectStats(&provider, RSSL_TRUE, provPerfConfig.displayStats, currentRuntimeSec,
						provPerfConfig.writeStatsInterval);
				intervalSeconds = 0;
			}

		}
		else if (selRet > 0)
		{
			if ((rsslSrvr != NULL) && (rsslSrvr->socketId != -1) && (FD_ISSET(rsslSrvr->socketId,&useRead)))
			{
				if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel
				{
					RsslChannel *pChannel;
					RsslError	error;
					RsslAcceptOptions acceptOpts = RSSL_INIT_ACCEPT_OPTS;

					if ((pChannel = rsslAccept(rsslSrvr, &acceptOpts, &error)) == 0)
					{
						printf("rsslAccept: failed <%s>\n",error.text);
					}
					else
					{
						printf("Server %d accepting channel %d.\n\n", rsslSrvr->socketId, pChannel->socketId);
						sendToLeastLoadedThread(pChannel);
					}
				}
				else // use UPA VA Reactor
				{
					if (acceptReactorConnection(rsslSrvr, &rsslErrorInfo) != RSSL_RET_SUCCESS)
					{
						printf("acceptReactorConnection: failed <%s>\n", rsslErrorInfo.rsslError.text);
					}
				}
			}
		}
		else if (selRet < 0)
		{
			/* continue */
#ifdef _WIN32
			if (WSAGetLastError() == WSAEINTR)
				continue;
#else
			if (errno == EINTR)
				continue;
#endif
			perror("select");
			exit(1);
		}

		/* Handle run-time */
		if (_currentTime >= rsslProviderRuntime)
		{
			printf("\nRun time of %u seconds has expired.\n", provPerfConfig.runTime);
			signal_shutdown = RSSL_TRUE; /* Tell other threads to shutdown. */
		}

		if (signal_shutdown == RSSL_TRUE)
		{
			cleanUpAndExit();
		}
	}
}
Beispiel #16
0
RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pChannelEvent)
{
	ProviderSession *pProvSession = (ProviderSession *)pReactorChannel->userSpecPtr;
	ProviderThread *pProviderThread = pProvSession->pProviderThread;
	RsslErrorInfo rsslErrorInfo;
	RsslReactorChannelInfo reactorChannelInfo;
	RsslUInt32 count;
	RsslRet ret;

	switch(pChannelEvent->channelEventType)
	{
		case RSSL_RC_CET_CHANNEL_UP:
		{
			/* A channel that we have requested via rsslReactorAccept() has come up.  Set our
			 * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for
			 * this channel. */
			FD_SET(pReactorChannel->socketId, &pProviderThread->readfds);
			FD_SET(pReactorChannel->socketId, &pProviderThread->exceptfds);

#ifdef ENABLE_XML_TRACE
			RsslTraceOptions traceOptions;
			rsslClearTraceOptions(&traceOptions);
			traceOptions.traceMsgFileName = "upacProvPerf";
			traceOptions.traceMsgMaxFileSize = 1000000000;
			traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_WRITE | RSSL_TRACE_READ;
			rsslIoctl(pChannelInfo->pChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &error);
#endif

			if (provPerfConfig.highWaterMark > 0)
			{
				if (rsslReactorChannelIoctl(pReactorChannel, RSSL_HIGH_WATER_MARK, &provPerfConfig.highWaterMark, &rsslErrorInfo) != RSSL_RET_SUCCESS)
                {
					printf("rsslReactorChannelIoctl() of RSSL_HIGH_WATER_MARK failed <%s>\n", rsslErrorInfo.rsslError.text);
					exit(-1);
                }
			}

			if ((ret = rsslReactorGetChannelInfo(pReactorChannel, &reactorChannelInfo, &rsslErrorInfo)) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorGetChannelInfo() failed: %d\n", ret);
				return RSSL_RC_CRET_SUCCESS;
			} 

			printf( "Channel %d active. Channel Info:\n"
					"  maxFragmentSize: %u\n"
					"  maxOutputBuffers: %u\n"
					"  guaranteedOutputBuffers: %u\n"
					"  numInputBuffers: %u\n"
					"  pingTimeout: %u\n"
					"  clientToServerPings: %s\n"
					"  serverToClientPings: %s\n"
					"  sysSendBufSize: %u\n"
					"  sysSendBufSize: %u\n"			
					"  compressionType: %s\n"
					"  compressionThreshold: %u\n"			
					"  ComponentInfo: ", 
					pReactorChannel->socketId,
					reactorChannelInfo.rsslChannelInfo.maxFragmentSize,
					reactorChannelInfo.rsslChannelInfo.maxOutputBuffers, reactorChannelInfo.rsslChannelInfo.guaranteedOutputBuffers,
					reactorChannelInfo.rsslChannelInfo.numInputBuffers,
					reactorChannelInfo.rsslChannelInfo.pingTimeout,
					reactorChannelInfo.rsslChannelInfo.clientToServerPings == RSSL_TRUE ? "true" : "false",
					reactorChannelInfo.rsslChannelInfo.serverToClientPings == RSSL_TRUE ? "true" : "false",
					reactorChannelInfo.rsslChannelInfo.sysSendBufSize, reactorChannelInfo.rsslChannelInfo.sysRecvBufSize,			
					reactorChannelInfo.rsslChannelInfo.compressionType == RSSL_COMP_ZLIB ? "zlib" : "none",
					reactorChannelInfo.rsslChannelInfo.compressionThreshold			
					);

			if (reactorChannelInfo.rsslChannelInfo.componentInfoCount == 0)
				printf("(No component info)");
			else
				for(count = 0; count < reactorChannelInfo.rsslChannelInfo.componentInfoCount; ++count)
				{
					printf("%.*s", 
							reactorChannelInfo.rsslChannelInfo.componentInfo[count]->componentVersion.length,
							reactorChannelInfo.rsslChannelInfo.componentInfo[count]->componentVersion.data);
					if (count < reactorChannelInfo.rsslChannelInfo.componentInfoCount - 1)
						printf(", ");
				}
			printf ("\n\n");

			/* Check that we can successfully pack, if packing messages. */
			if (providerThreadConfig.totalBuffersPerPack > 1
					&& providerThreadConfig.packingBufferLength > reactorChannelInfo.rsslChannelInfo.maxFragmentSize)
			{
				printf("Error(Channel %d): MaxFragmentSize %u is too small for packing buffer size %u\n",
						pReactorChannel->socketId, reactorChannelInfo.rsslChannelInfo.maxFragmentSize, 
						providerThreadConfig.packingBufferLength);
				exit(-1);
			}


			pProvSession->pChannelInfo->pChannel = pReactorChannel->pRsslChannel;
			pProvSession->pChannelInfo->pReactorChannel = pReactorChannel;
			pProvSession->pChannelInfo->pReactor = pReactor;
			rsslQueueAddLinkToBack(&pProviderThread->channelHandler.activeChannelList, &pProvSession->pChannelInfo->queueLink);
			pProvSession->timeActivated = getTimeNano();

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_READY:
		{
			if (ret = (printEstimatedMsgSizes(pProviderThread, pProvSession)) != RSSL_RET_SUCCESS)
			{
				printf("printEstimatedMsgSizes() failed: %d\n", ret);
				return RSSL_RC_CRET_SUCCESS;
			}

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_FD_CHANGE:
		{
			/* The file descriptor representing the RsslReactorChannel has been changed.
			 * Update our file descriptor sets. */
			printf("Fd change: %d to %d\n", pReactorChannel->oldSocketId, pReactorChannel->socketId);
			FD_CLR(pReactorChannel->oldSocketId, &pProviderThread->readfds);
			FD_CLR(pReactorChannel->oldSocketId, &pProviderThread->exceptfds);
			FD_SET(pReactorChannel->socketId, &pProviderThread->readfds);
			FD_SET(pReactorChannel->socketId, &pProviderThread->exceptfds);

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_WARNING:
		{
			/* We have received a warning event for this channel. Print the information and continue. */
			printf("Received warning for Channel fd=%d.\n", pReactorChannel->socketId);
			printf("	Error text: %s\n", pChannelEvent->pError->rsslError.text);

			return RSSL_RC_CRET_SUCCESS;
		}
		case RSSL_RC_CET_CHANNEL_DOWN:
		{
			pProviderThread->stats.inactiveTime = getTimeNano();

			printf("Channel Closed.\n");

			FD_CLR(pReactorChannel->socketId, &pProviderThread->readfds);
			FD_CLR(pReactorChannel->socketId, &pProviderThread->exceptfds);

			--pProviderThread->clientSessionsCount;
			if (pProvSession->pChannelInfo->pReactorChannel && rsslQueueGetElementCount(&pProviderThread->channelHandler.activeChannelList) > 0)
			{
				rsslQueueRemoveLink(&pProviderThread->channelHandler.activeChannelList, &pProvSession->pChannelInfo->queueLink);
			}
	
			if (pProvSession)
			{
				free(pProvSession->pChannelInfo);
				providerSessionDestroy(pProviderThread, pProvSession);
			}

			if (rsslReactorCloseChannel(pReactor, pReactorChannel, &rsslErrorInfo) != RSSL_RET_SUCCESS)
			{
				printf("rsslReactorCloseChannel() failed: %s\n", rsslErrorInfo.rsslError.text);
				cleanUpAndExit();
			}

			return RSSL_RC_CRET_SUCCESS;
		}
		default:
			printf("Unknown channel event!\n");
			cleanUpAndExit();
	}

	return RSSL_RC_CRET_SUCCESS;
}
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer)
{
	RsslRet ret = RSSL_RET_SUCCESS;
	RsslMsg msg = RSSL_INIT_MSG;
	RsslDecodeIterator dIter;
	RsslChannel *chnl = pChannelInfo->pChannel;
	ProviderThread *pProviderThread = (ProviderThread*)pChannelHandler->pUserSpec;
	
	/* clear decode iterator */
	rsslClearDecodeIterator(&dIter);
	
	/* set version info */
	rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion);

	rsslSetDecodeIteratorBuffer(&dIter, pBuffer);

	ret = rsslDecodeMsg(&dIter, &msg);				
	if (ret != RSSL_RET_SUCCESS)
	{
		printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d  Size %d \n", ret, chnl->socketId, pBuffer->length);
		cleanUpAndExit();
	}

	switch ( msg.msgBase.domainType )
	{
		case RSSL_DMT_LOGIN:
		{
			RsslRDMLoginMsg loginMsg;
			char memoryChar[1024];
			RsslBuffer memoryBuffer = { sizeof(memoryChar), memoryChar };
			RsslErrorInfo errorInfo;
			RsslState *pState = NULL;

			if ((ret = rsslDecodeRDMLoginMsg(&dIter, &msg, &loginMsg, &memoryBuffer, &errorInfo)) != RSSL_RET_SUCCESS)
			{
				printf("rsslDecodeRDMLoginMsg() failed: %d(%s)\n", ret, errorInfo.rsslError.text);
				ret = RSSL_RET_FAILURE;
				break;
			}

			switch(loginMsg.rdmMsgBase.rdmMsgType)
			{
				case RDM_LG_MT_REFRESH:
					pState = &loginMsg.refresh.state;

					printf(	"Received login refresh.\n");
					if (loginMsg.refresh.flags &
							RDM_LG_RFF_HAS_APPLICATION_NAME)
						printf( "  ApplicationName: %.*s\n",
								loginMsg.refresh.applicationName.length,
								loginMsg.refresh.applicationName.data);
					printf("\n");

					break;

				case RDM_LG_MT_STATUS:
					printf("Received login status message.\n");
					if (loginMsg.status.flags & RDM_LG_STF_HAS_STATE)
						pState = &loginMsg.status.state;
					break;

				default:
					printf("Received unhandled login message class: %d.\n", msg.msgBase.msgClass);
					break;
			}

			if (pState)
			{
				if (pState->streamState == RSSL_STREAM_OPEN)
				{
					ProviderSession *pProvSession = (ProviderSession*)pChannelInfo->pUserSpec;

					ret = publishDirectoryRefresh(pChannelHandler, pChannelInfo, -1);

					if (ret < RSSL_RET_SUCCESS)
					{
						printf("publishDirectoryRefresh() failed: %d.\n", ret);
						return ret;
					}

					if (niProvPerfConfig.itemPublishCount > 0)
					{
						RsslInt32 itemListUniqueIndex;
						RsslInt32 itemListCount;
						RsslInt32 itemListCountRemainder;

						/* If there are multiple connections, determine which items are
						 * to be published on this connection.
						 * If any items are common to all connections, they are taken from the first
						 * items in the item list.  The rest of the list is then divided to provide a unique
						 * item list for each connection. */

						/* Determine where items unique to this connection start. */
						itemListUniqueIndex = niProvPerfConfig.commonItemCount;
						itemListUniqueIndex += ((niProvPerfConfig.itemPublishCount - niProvPerfConfig.commonItemCount)
							/ providerThreadConfig.threadCount) * (pProviderThread->providerIndex);

						/* Account for remainder. */
						itemListCount = niProvPerfConfig.itemPublishCount / providerThreadConfig.threadCount;
						itemListCountRemainder = niProvPerfConfig.itemPublishCount % providerThreadConfig.threadCount;

						if (pProviderThread->providerIndex < itemListCountRemainder)
						{
							/* This provider publishes an extra item */
							itemListCount += 1;

							/* Shift index by one for each provider before this one, since they publish extra items too. */
							itemListUniqueIndex += pProviderThread->providerIndex;
						}
						else
							/* Shift index by one for each provider that publishes an extra item. */
							itemListUniqueIndex += itemListCountRemainder;

						if ((ret = providerSessionAddPublishingItems(pProviderThread, (ProviderSession*)pChannelInfo->pUserSpec, 
									niProvPerfConfig.commonItemCount, itemListUniqueIndex, itemListCount - niProvPerfConfig.commonItemCount, 
									(RsslUInt16)directoryConfig.serviceId)) != RSSL_RET_SUCCESS)
						{
							printf("providerSessionAddPublishingItems() failed\n");
							return ret;
						}
						else
						{
							printf("Created publishing list.\n");
							ret = RSSL_RET_SUCCESS;
						}

						/* send the first burst of refreshes */
						if (rotatingQueueGetCount(&pProvSession->refreshItemList) != 0)
							ret = sendRefreshBurst(pProviderThread, pProvSession);
						else
							ret = RSSL_RET_SUCCESS;

						if (ret < RSSL_RET_SUCCESS)
							return ret;
					}

					if (ret > RSSL_RET_SUCCESS)
					{
						/* Need to flush */
						providerThreadRequestChannelFlush(pProviderThread, pChannelInfo);
					}

				}
				else
				{
					printf("Login stream closed.\n");
					ret = RSSL_RET_FAILURE;
				}
			}
			else 
				ret = RSSL_RET_SUCCESS;
			break;
		}
		default:
			printf("Received message with unhandled domain: %d\n", msg.msgBase.domainType);
			break;
	}


	if (ret < RSSL_RET_SUCCESS) 
	{
		signal_shutdown = RSSL_TRUE;
		return ret;
	}
	else
	{
		/* Typically these requests result in a response, so call for a flush to make sure it gets out.*/
		providerThreadRequestChannelFlush(pProviderThread, pChannelInfo);
		return ret;
	}
}
int main(int argc, char **argv)
{
	RsslError error;
	RsslUInt32 intervalSeconds = 0, currentRuntimeSec = 0;

	/* Read in configuration and echo it. */
	initNIProvPerfConfig(argc, argv);
	printNIProvPerfConfig(stdout);

	if (!(summaryFile = fopen(niProvPerfConfig.summaryFilename, "w")))
	{
		printf("Error: Failed to open file '%s'.\n", niProvPerfConfig.summaryFilename);
		exit(-1);
	}

	printNIProvPerfConfig(summaryFile); fflush(summaryFile);

	providerInit(&provider, PROVIDER_NONINTERACTIVE,
			processActiveChannel,
			processInactiveChannel,
			processMsg);

	// set up a signal handler so we can cleanup before exit
	signal(SIGINT, signal_handler);

	/* Determine update rates on per-tick basis */
	nsecPerTick = 1000000000LL/(RsslInt64)providerThreadConfig.ticksPerSec;

	xmlInitParser();

	/* Initialize RSSL */
	if (rsslInitialize(providerThreadConfig.threadCount > 1 ? RSSL_LOCK_GLOBAL : RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS)
	{
		printf("rsslInitialize() failed.\n");
		exit(-1);
	}

	/* Initialize runtime timer */
	rsslProviderRuntime = getTimeNano() + ((RsslInt64)niProvPerfConfig.runTime * 1000000000LL);

	startProviderThreads(&provider, runNIProvConnection);

	/* this is the main loop */
	while(!signal_shutdown)
	{
		SLEEP(1);
		++currentRuntimeSec;
		++intervalSeconds;

		if (intervalSeconds == niProvPerfConfig.writeStatsInterval)
		{
			providerCollectStats(&provider, RSSL_TRUE, niProvPerfConfig.displayStats, 
					currentRuntimeSec, niProvPerfConfig.writeStatsInterval);
			intervalSeconds = 0;
		}
		
		/* Handle runtime. */
		if (getTimeNano() >= rsslProviderRuntime)
		{
			printf("\nRun time of %u seconds has expired.\n\n", niProvPerfConfig.runTime);
			signal_shutdown = RSSL_TRUE; /* Tell other threads to shutdown. */
		}


	}

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

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

	time_t currentTime = 0;
	RsslRet ret;

	RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS;

	rsslInitNIChannelCommand(&chnlCommand);

	handleConfig(argc, argv, &chnlCommand);

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

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

	rsslInitializeEx(&initOpts, &rsslErr);

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

	printf("Connections:\n");

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

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

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

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


	printf("\n");

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

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

	setupLoginRequest(&chnlCommand, 1);

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

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

	FD_SET(pReactor->eventFd, &readFds);

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

	printf("Connection started!\n");

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

		handleRuntime();

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

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

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

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

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

			rsslClearReactorSubmitMsgOptions(&submitMsgOpts);
			submitMsgOpts.pRDMMsg = (RsslRDMMsg*)chnlCommand.pRole->ommNIProviderRole.pLoginRequest;
			if ((ret = rsslReactorSubmitMsg(pReactor,chnlCommand.reactorChannel,&submitMsgOpts,&rsslErrorInfo)) != RSSL_RET_SUCCESS)
			{
				printf("Login reissue failed:  %d(%s)\n", ret, rsslErrorInfo.rsslError.text);
			}
			else
			{
				printf("Login reissue sent\n");
			}
			chnlCommand.canSendLoginReissue = RSSL_FALSE;
		}
	}
}
//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;
			}
		}
	}
}
Beispiel #21
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();
}