protected void logoutAllSessions(boolean forceDisconnect) { log.info("Logging out all sessions"); if (sessions == null) { log.error("Attempt to logout all sessions before initialization is complete."); return; } for (Session session : sessions.values()) { try { session.logout(); } catch (Throwable e) { logError(session.getSessionID(), null, "Error during logout", e); } } if (forceDisconnect && isLoggedOn()) { for (Session session : sessions.values()) { try { if (session.isLoggedOn()) { session.disconnect("Forcibly disconnecting session", false); } } catch (Throwable e) { logError(session.getSessionID(), null, "Error during disconnect", e); } } } if (!forceDisconnect) { waitForLogout(); } }
protected void waitForLogout() { long start = System.currentTimeMillis(); Set<Session> loggedOnSessions; while (!(loggedOnSessions = getLoggedOnSessions()).isEmpty()) { try { Thread.sleep(100L); } catch (InterruptedException e) { log.error(e.getMessage(), e); } final long elapsed = System.currentTimeMillis() - start; Iterator<Session> sessionItr = loggedOnSessions.iterator(); while (sessionItr.hasNext()) { Session session = sessionItr.next(); if (elapsed >= session.getLogoutTimeout() * 1000L) { try { session.disconnect("Logout timeout, force disconnect", false); } catch (IOException e) { log.error(e.getMessage(), e); } sessionItr.remove(); } } // Be sure we don't look forever if (elapsed > 60000L) { log.warn("Stopping session logout wait after 1 minute"); break; } } }
@Override public boolean send(String data) { // Check for and disconnect slow consumers. if (maxScheduledWriteRequests > 0 && ioSession.getScheduledWriteMessages() >= maxScheduledWriteRequests) { Session qfjSession = (Session) ioSession.getAttribute(SessionConnector.QF_SESSION); try { qfjSession.disconnect("Slow consumer", true); } catch (IOException e) { } return false; } // The data is written asynchronously in a MINA thread WriteFuture future = ioSession.write(data); if (synchronousWrites) { try { if (!future.awaitUninterruptibly(synchronousWriteTimeout)) { log.error("Synchronous write timed out after " + synchronousWriteTimeout + "ms"); return false; } } catch (RuntimeException e) { log.error("Synchronous write failed: " + e.getMessage()); return false; } } return true; }
private Set<quickfix.Session> getLoggedOnSessions() { Set<quickfix.Session> loggedOnSessions = new HashSet<quickfix.Session>(sessions.size()); for (Session session : sessions.values()) { if (session.isLoggedOn()) { loggedOnSessions.add(session); } } return loggedOnSessions; }
/** * Check if we have at least one session and that all the sessions are logged on * * @return false if no session or at least one session is not logged on */ public boolean isLoggedOn() { // if no session, not logged on if (sessions.isEmpty()) return false; for (Session session : sessions.values()) { // at least one session not logged on if (!session.isLoggedOn()) return false; } // all the sessions are logged on return true; }
public void run() { try { for (Session session : sessions.values()) { try { session.next(); } catch (IOException e) { logError(session.getSessionID(), null, "Error in session timer processing", e); } } } catch (Throwable e) { log.error("Error during timer processing", e); } }
@Override public void exceptionCaught(IoSession ioSession, Throwable cause) throws Exception { boolean disconnectNeeded = false; Session quickFixSession = findQFSession(ioSession); Throwable realCause = cause; if (cause instanceof ProtocolDecoderException && cause.getCause() != null) { realCause = cause.getCause(); } else { Throwable chain = cause; while (chain != null && chain.getCause() != null) { chain = chain.getCause(); if (chain instanceof IOException) { realCause = chain; break; } } } String reason; if (realCause instanceof IOException) { if (quickFixSession != null && quickFixSession.isEnabled()) { reason = "Socket exception (" + ioSession.getRemoteAddress() + "): " + cause; } else { reason = "Socket (" + ioSession.getRemoteAddress() + "): " + cause; } disconnectNeeded = true; } else if (realCause instanceof CriticalProtocolCodecException) { reason = "Critical protocol codec error: " + cause; disconnectNeeded = true; } else if (realCause instanceof ProtocolCodecException) { reason = "Protocol handler exception: " + cause; } else { reason = cause.toString(); } if (disconnectNeeded) { try { if (quickFixSession != null) { quickFixSession.disconnect(reason, true); } else { log.error(reason, cause); ioSession.closeNow(); } } finally { ioSession.setAttribute("QFJ_RESET_IO_CONNECTOR", Boolean.TRUE); } } else { log.error(reason, cause); } }
public void testOneSessionLoggedOnOneSessionNotLoggedOne() throws Exception { SessionID sessionID1 = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionSettings settings = setUpSessionSettings(sessionID1); DefaultSessionFactory sessionFactory = new DefaultSessionFactory( new UnitTestApplication(), new MemoryStoreFactory(), new ScreenLogFactory(true, true, true)); SessionConnector connector = new SessionConnectorUnderTest(settings, sessionFactory); Session session1 = connector.createSession(sessionID1); assertNotNull(session1); // test add/remove SessionConnectorListener connectorListener = new SessionConnectorListener(); connector.addPropertyChangeListener(connectorListener); connector.removePropertyChangeListener(connectorListener); Map<SessionID, Session> sessions = new HashMap<>(); sessions.put(session1.getSessionID(), session1); connector.setSessions(sessions); assertEquals(0, propertyChangeEvents.size()); assertEquals(1, connector.getManagedSessions().size()); assertEquals(session1, connector.getManagedSessions().get(0)); assertFalse(connector.isLoggedOn()); Field stateField = session1.getClass().getDeclaredField("state"); stateField.setAccessible(true); SessionState state = (SessionState) stateField.get(session1); state.setLogonSent(true); state.setLogonReceived(true); assertTrue(connector.isLoggedOn()); SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD1"); settings.setString( sessionID2, SessionFactory.SETTING_CONNECTION_TYPE, SessionFactory.ACCEPTOR_CONNECTION_TYPE); Session session2 = connector.createSession(sessionID2); assertNotNull(session2); sessions.put(session2.getSessionID(), session2); assertFalse(connector.isLoggedOn()); }
private void doLogonTest(String keyStoreName, String keyStorePassword) throws InterruptedException, ConfigError { ServerThread serverThread = new ServerThread(keyStoreName, keyStorePassword); try { serverThread.setDaemon(true); serverThread.start(); serverThread.waitForInitialization(); SessionID clientSessionID = new SessionID(FixVersions.BEGINSTRING_FIX42, "TW", "ISLD"); SessionSettings settings = getClientSessionSettings(clientSessionID); ClientApplication clientApplication = new ClientApplication(); ThreadedSocketInitiator initiator = new ThreadedSocketInitiator( clientApplication, new MemoryStoreFactory(), settings, new DefaultMessageFactory()); try { log.info("Do login"); clientApplication.setUpLogonExpectation(); initiator.start(); Session clientSession = Session.lookupSession(clientSessionID); assertLoggedOn(clientApplication, clientSession); } finally { initiator.stop(); } } finally { serverThread.interrupt(); serverThread.join(); } }
protected Session findQFSession(IoSession ioSession, SessionID sessionID) { Session quickfixSession = findQFSession(ioSession); if (quickfixSession == null) { quickfixSession = Session.lookupSession(sessionID); } return quickfixSession; }
public void processMessage() { try { if (m_session.hasResponder()) { m_session.next(m_message); } else { try { final String msgType = m_message.getHeader().getString(MsgType.FIELD); if (msgType.equals(MsgType.LOGOUT)) { m_session.next(m_message); } } catch (FieldNotFound ex) { } } } catch (Throwable e) { LogUtil.logThrowable(m_session, e.getMessage(), e); } }
public void onMessage(quickfix.fix43.SecurityDefinition message, SessionID sessionID) throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue { quickfix.fix43.SecurityDefinition echo = message; try { Session.sendToTarget(echo, sessionID); } catch (SessionNotFound snf) { snf.printStackTrace(); } }
private void sendOutMessage(Exchange exchange) throws QFJException { Message camelMessage = exchange.getOut(); quickfix.Message quickfixjMessage = camelMessage.getBody(quickfix.Message.class); log.debug("Sending FIX message reply: {}", quickfixjMessage); SessionID messageSessionID = exchange.getIn().getHeader("SessionID", SessionID.class); Session session = getSession(messageSessionID); if (session == null) { throw new IllegalStateException("Unknown session: " + messageSessionID); } if (!session.send(quickfixjMessage)) { throw new CannotSendException( "Could not send FIX message reply: " + quickfixjMessage.toString()); } }
public void testConnector() throws Exception { SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionSettings settings = setUpSessionSettings(sessionID); DefaultSessionFactory sessionFactory = new DefaultSessionFactory( new UnitTestApplication(), new MemoryStoreFactory(), new ScreenLogFactory(true, true, true)); SessionConnector connector = new SessionConnectorUnderTest(settings, sessionFactory); connector.addPropertyChangeListener(new SessionConnectorListener()); Session session = connector.createSession(sessionID); assertNotNull(session); Map<SessionID, Session> sessions = Collections.singletonMap(session.getSessionID(), session); connector.setSessions(sessions); assertEquals(1, propertyChangeEvents.size()); assertEquals(1, connector.getManagedSessions().size()); assertEquals(session, connector.getManagedSessions().get(0)); assertFalse(connector.isLoggedOn()); Field stateField = session.getClass().getDeclaredField("state"); stateField.setAccessible(true); SessionState state = (SessionState) stateField.get(session); state.setLogonSent(true); state.setLogonReceived(true); assertTrue(connector.isLoggedOn()); assertTrue(session.isEnabled()); connector.logoutAllSessions(true); assertFalse(session.isEnabled()); assertEquals(9999, connector.getIntSetting(Acceptor.SETTING_SOCKET_ACCEPT_PORT)); assertNotNull(connector.getScheduledExecutorService()); assertEquals(settings, connector.getSettings()); }
@Override public void messageReceived(IoSession ioSession, Object message) throws Exception { String messageString = (String) message; SessionID remoteSessionID = MessageUtils.getReverseSessionID(messageString); Session quickFixSession = findQFSession(ioSession, remoteSessionID); if (quickFixSession != null) { quickFixSession.getLog().onIncoming(messageString); try { Message fixMessage = parse(quickFixSession, messageString); processMessage(ioSession, fixMessage); } catch (InvalidMessage e) { if (MsgType.LOGON.equals(MessageUtils.getMessageType(messageString))) { log.error("Invalid LOGON message, disconnecting: " + e.getMessage()); ioSession.closeNow(); } else { log.error("Invalid message: " + e.getMessage()); } } } else { log.error("Disconnecting; received message for unknown session: " + messageString); ioSession.closeNow(); } }
private void doApplicationMessageEventsTest( SessionID acceptorSessionID, SessionID initiatorSessionID, QuickfixjEngine quickfixjEngine) throws SessionNotFound, InterruptedException, FieldNotFound { final List<EventRecord> events = new ArrayList<EventRecord>(); final CountDownLatch messageLatch = new CountDownLatch(1); QuickfixjEventListener messageListener = new QuickfixjEventListener() { @Override public synchronized void onEvent( QuickfixjEventCategory eventCategory, SessionID sessionID, Message message) { EventRecord event = new EventRecord(eventCategory, sessionID, message); events.add(event); if (eventCategory == QuickfixjEventCategory.AppMessageReceived) { messageLatch.countDown(); } } }; quickfixjEngine.addEventListener(messageListener); Email email = TestSupport.createEmailMessage("Test"); Session.sendToTarget(email, initiatorSessionID); assertTrue("Application message not received", messageLatch.await(5000, TimeUnit.MILLISECONDS)); quickfixjEngine.removeEventListener(messageListener); assertThat(events.size(), is(2)); EventRecord sendEvent = new EventRecord(QuickfixjEventCategory.AppMessageSent, initiatorSessionID, new Message()); assertTrue(events.contains(sendEvent)); int sendEventIndex = events.indexOf(sendEvent); assertThat( events.get(sendEventIndex).message.getHeader().getString(MsgType.FIELD), is(MsgType.EMAIL)); EventRecord receiveEvent = new EventRecord( QuickfixjEventCategory.AppMessageReceived, acceptorSessionID, new Message()); assertTrue(events.contains(receiveEvent)); int receiveEventIndex = events.indexOf(receiveEvent); assertThat( events.get(receiveEventIndex).message.getHeader().getString(MsgType.FIELD), is(MsgType.EMAIL)); }
/** Test that adding/removing dynamic sessions works correctly */ public void testAddingRemovingDymaicSessions() throws Exception { SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "me", "you"); SessionSettings settings = setUpSessionSettings(sessionID); DefaultSessionFactory sessionFactory = new DefaultSessionFactory( new UnitTestApplication(), new MemoryStoreFactory(), new ScreenLogFactory(true, true, true)); SessionConnector connector = new SessionConnectorUnderTest(settings, sessionFactory); connector.setSessions(new HashMap<>()); Session session = connector.createSession(sessionID); // one-time use connector to create a slightly different session SessionSettings settings2 = setUpSessionSettings(sessionID2); SessionConnector connector2 = new SessionConnectorUnderTest(settings2, sessionFactory); connector.setSessions(new HashMap<>()); Session session2 = connector2.createSession(sessionID2); assertNotNull(session); assertNotNull(session2); assertEquals(0, connector.getManagedSessions().size()); connector.addDynamicSession(session); assertEquals(1, connector.getManagedSessions().size()); connector.addDynamicSession(session2); assertEquals(2, connector.getManagedSessions().size()); // the list can be in arbitrary order so let's make sure that we get both HashMap<SessionID, Session> map = new HashMap<>(); for (Session s : connector.getManagedSessions()) { map.put(s.getSessionID(), s); } assertEquals(session, map.get(session.getSessionID())); assertEquals(session2, map.get(session2.getSessionID())); connector.removeDynamicSession(session.getSessionID()); assertEquals(1, connector.getManagedSessions().size()); assertEquals(session2, connector.getManagedSessions().get(0)); connector.removeDynamicSession(session2.getSessionID()); assertEquals(0, connector.getManagedSessions().size()); }
public void process(Message message, SessionID sessionID) throws FieldNotFound { quickfix.Message echo = (quickfix.Message) message.clone(); PossResend possResend = new PossResend(false); if (message.getHeader().isSetField(possResend)) message.getHeader().getField(possResend); ClOrdID clOrdID = new ClOrdID(); message.getField(clOrdID); Pair pair = new Pair(clOrdID, sessionID); if (possResend.getValue() == true) { if (orderIDs.contains(pair)) return; } orderIDs.add(pair); try { Session.sendToTarget(echo, sessionID); } catch (SessionNotFound snf) { } }
private void assertLoggedOn(ClientApplication clientApplication, Session clientSession) throws InterruptedException { assertNotNull("no client session", clientSession); clientApplication.logonLatch.await(20, TimeUnit.SECONDS); assertTrue("client session not logged in", clientSession.isLoggedOn()); }
Session getSession(SessionID messageSessionID) { return Session.lookupSession(messageSessionID); }
public void addDynamicSession(Session inSession) { sessions.put(inSession.getSessionID(), inSession); log.debug("adding session for " + inSession.getSessionID()); propertyChangeSupport.firePropertyChange(SESSIONS_PROPERTY, null, sessions); }