Re: [Quickfix-developers] Contributing code
Brought to you by:
orenmnero
From: Howard E. <ho...@ex...> - 2003-11-18 13:50:01
|
I have made minor modifications to the qf lib to fix the following two issues. These changes have been tested and running on our servers without problems. I hope they can be added for future release. thanks, Howard Issues: 1.) A second socket connection (to acceptor) made using a SessionID already in uses causes the library to behave erratically. 2.) FIX Field 141 (ResetSeqNumFlag) on the Logon Message is ignored. Issue #1 If a FIX client connects to the QuickFIX acceptor, using a SessionID already in use, it fouls the state of the Session object associated with that SessionID resulting in the Second connection being dropped, but the first connection no longer calling events on the Application class. It is also impossible to prevent the second connection from being accepted within the Application class override, because the OnLogon event is never raised. Fix My fix for this solution is to disconnect an existing connection when a second connection with a "connected" SessionID comes in. The first connection is disconnected (App gets LogOut event) and the second connection is accepted (App gets Logon event). Modules Affected: (Acceptor.cpp, SocketConnection.cpp) Acceptor.cpp ====================================== Method: Acceptor::getSession, at line 149 Adding the disconnect line will cause any existing session using that SessionID to be LoggedOff and the socket connection to be closed. If there is no connection currently using that SessionID the call is harmless. Change --------------- Sessions::iterator i = m_sessions.find( sessionID ); if ( i != m_sessions.end() ) { i->second->setResponder( &responder ); return i->second; } To --------------- Sessions::iterator i = m_sessions.find( sessionID ); if ( i != m_sessions.end() ) { // ADD THE NEXT LINE i->second->disconnect(); i->second->setResponder( &responder ); return i->second; } SocketConnection.cpp ====================================== Method: SocketConnection::disconnect This clearing the Session ptr of a SocketConnection prevents the Session disconnect method from being called twice (called the first time in the Acceptor::getSession method) when the SocketMonitor drop is processed. Change --------------- void SocketConnection::disconnect() { QF_STACK_PUSH(SocketConnection::disconnect) if ( m_pMonitor ) m_pMonitor->drop( m_socket ); QF_STACK_POP } To --------------- void SocketConnection::disconnect() { QF_STACK_PUSH(SocketConnection::disconnect) // ADD THE NEXT LINE m_pSession = 0; if ( m_pMonitor ) m_pMonitor->drop( m_socket ); QF_STACK_POP } Issue #2 The ResetSeqNumFlag tag is ignored when Sessions logon to quickfix server. Fix Add code to the Session::nextLogon and the Session::generateLogon methods to handle the request. I list the diffs, followed by the full modified methods Modules Affected: (Session.cpp) Session.cpp ====================================== Method: Session::nextLogon Remove ------------ < bool verified = verify( logon, false, true ); Add ------------ > ResetSeqNumFlag resetSeqNumFlag(false); > logon.getField(resetSeqNumFlag); > > bool verified = verify( logon, false, (false == resetSeqNumFlag.getValue()) ); 213a217,224 > if (resetSeqNumFlag.getValue() == true) > { > m_state.onEvent( "Received Logon with SequenceReset FROM: " > + IntConvertor::convert(getExpectedTargetNum()) + > " TO: 1" ); > m_state.store()->reset(); > } > Method: Session::generateLogon Add ------------ 544a556,563 > > if (aLogon.isSetField(FIELD::ResetSeqNumFlag)) > { > ResetSeqNumFlag resetSeqNumFlag(false); > aLogon.getField(resetSeqNumFlag); > logon.setField(resetSeqNumFlag); > } > void Session::nextLogon( const Message& logon ) { QF_STACK_PUSH(Session::nextLogon) if ( m_state.shouldSendLogon() ) { m_state.onEvent( "Received logon response before sending request" ); disconnect(); return ; } SenderCompID senderCompID; TargetCompID targetCompID; logon.getHeader().getField( senderCompID ); logon.getHeader().getField( targetCompID ); ResetSeqNumFlag resetSeqNumFlag(false); logon.getField(resetSeqNumFlag); bool verified = verify( logon, false, (false == resetSeqNumFlag.getValue()) ); if ( isCorrectCompID( senderCompID, targetCompID ) ) m_state.receivedLogon( true ); if ( !verified ) return ; if ( !m_state.initiate() ) { logon.getField( m_state.heartBtInt() ); m_state.onEvent( "Received logon request" ); generateLogon( logon ); m_state.onEvent( "Responding to logon request" ); } else m_state.onEvent( "Received logon response" ); if (resetSeqNumFlag.getValue() == true) { m_state.onEvent( "Received Logon with SequenceReset FROM: " + IntConvertor::convert(getExpectedTargetNum()) + " TO: 1" ); m_state.store()->reset(); } MsgSeqNum msgSeqNum; logon.getHeader().getField( msgSeqNum ); if ( isTargetTooHigh( msgSeqNum ) ) { doTargetTooHigh( logon ); } else { m_state.incrNextTargetMsgSeqNum(); nextQueued(); } if ( isLoggedOn() ) m_application.onLogon( m_sessionID ); QF_STACK_POP } void Session::generateLogon( const Message& aLogon ) { QF_STACK_PUSH(Session::generateLogon) Message logon; EncryptMethod encryptMethod; HeartBtInt heartBtInt; logon.setField( EncryptMethod( 0 ) ); aLogon.getField( heartBtInt ); logon.getHeader().setField( MsgType( "A" ) ); logon.setField( heartBtInt ); if (aLogon.isSetField(FIELD::ResetSeqNumFlag)) { ResetSeqNumFlag resetSeqNumFlag(false); aLogon.getField(resetSeqNumFlag); logon.setField(resetSeqNumFlag); } fill( logon.getHeader() ); sendRaw( logon ); m_state.sentLogon( true ); QF_STACK_POP } On Mon, 2003-11-17 at 23:24, qui...@li... wrote: > > --__--__-- > > Message: 2 > Subject: Re: [Quickfix-developers] Contributing code > Date: Mon, 17 Nov 2003 12:02:23 -0600 > From: "Miller, Oren" <OM...@ri...> > To: <ho...@ex...>, > <qui...@li...> > > Post them to this list. > > -------------------------- > Sent from my BlackBerry Wireless Handheld > > > -----Original Message----- > From: Howard Engelhart <ho...@ex...> > To: QuickFIX Questions <qui...@li...> > Sent: Mon Nov 17 11:43:03 2003 > Subject: [Quickfix-developers] Contributing code > > I have made a couple of minor changes to the QuickFIX lib that I would = > like to submit for review for possible inclusion into the next version = > of QuickFIX. Is that possible? If so how should I proceed? > > Thanks, > > Howard > ho...@ex... > |