AcceptorIoHandler extends AbstractIoHandler { @Override protected void processMessage(IoSession protocolSession, Message message) throws Exception { Session qfSession = (Session) protocolSession.getAttribute(SessionConnector.QF_SESSION); if (qfSession == null) { final Optional<String> msgTypeField = message.getHeader().getOptionalString(MsgType.FIELD); if (msgTypeField.isPresent() && msgTypeField.get().equals(MsgType.LOGON)) { final SessionID sessionID = MessageUtils.getReverseSessionID(message); qfSession = sessionProvider.getSession(sessionID, eventHandlingStrategy.getSessionConnector()); if (qfSession != null) { final Log sessionLog = qfSession.getLog(); Responder responder = qfSession.getResponder(); if (responder != null) { sessionLog.onErrorEvent("Multiple logons/connections for this session are not allowed." + " Closing connection from " + protocolSession.getRemoteAddress() + " since session is already established from " + responder.getRemoteAddress()); protocolSession.closeNow(); return; } sessionLog.onEvent("Accepting session " + qfSession.getSessionID() + " from " + protocolSession.getRemoteAddress()); final int heartbeatInterval = message.isSetField(HeartBtInt.FIELD) ? message.getInt(HeartBtInt.FIELD) : 0; qfSession.setHeartBeatInterval(heartbeatInterval); sessionLog.onEvent("Acceptor heartbeat set to " + heartbeatInterval + " seconds"); protocolSession.setAttribute(SessionConnector.QF_SESSION, qfSession); final NetworkingOptions networkingOptions = getNetworkingOptions(); qfSession.setResponder(new IoSessionResponder(protocolSession, networkingOptions.getSynchronousWrites(), networkingOptions .getSynchronousWriteTimeout(), qfSession.getMaxScheduledWriteRequests())); if (sessionID.isFIXT()) { if (message.isSetField(DefaultApplVerID.FIELD)) { final ApplVerID applVerID = new ApplVerID( message.getString(DefaultApplVerID.FIELD)); qfSession.setTargetDefaultApplicationVersionID(applVerID); sessionLog.onEvent("Setting DefaultApplVerID (" + DefaultApplVerID.FIELD + "=" + applVerID.getValue() + ") from Logon"); } } } else { log.error("Unknown session ID during logon: {} cannot be found in session list {} (connecting from {} to {})", sessionID, eventHandlingStrategy.getSessionConnector().getSessions(), protocolSession.getRemoteAddress(), protocolSession.getLocalAddress()); return; } } else { log.warn("Ignoring non-logon message before session establishment: {}", message); protocolSession.closeNow(); return; } } eventHandlingStrategy.onMessage(qfSession, message); } AcceptorIoHandler(AcceptorSessionProvider sessionProvider,
            NetworkingOptions networkingOptions, EventHandlingStrategy eventHandlingStrategy); @Override void sessionCreated(IoSession session);  }
@Test public void testFIXTLogonAndApplVerID() throws Exception { EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); IoSession mockIoSession = mock(IoSession.class); final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIXT11, "SENDER", "TARGET"); try (Session session = SessionFactoryTestSupport.createSession(sessionID, new UnitTestApplication(), false)) { stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); final HashMap<SessionID, Session> acceptorSessions = new HashMap<>(); acceptorSessions.put(sessionID, session); final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, new NetworkingOptions(new Properties()), mockEventHandlingStrategy); final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), new HeartBtInt(30), defaultApplVerID); message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); message.getHeader().setField(new SendingTime(LocalDateTime.now())); message.getHeader().setInt(MsgSeqNum.FIELD, 1); handler.processMessage(mockIoSession, message); assertEquals(defaultApplVerID.getValue(), session.getTargetDefaultApplicationVersionID() .getValue()); } }
@Test public void testMessageBeforeLogon() throws Exception { IoSession mockIoSession = mock(IoSession.class); stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); HashMap<SessionID, Session> acceptorSessions = new HashMap<>(); AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), new NetworkingOptions(new Properties()), mockEventHandlingStrategy); handler.processMessage(mockIoSession, new Logout()); verify(mockIoSession).getAttribute("QF_SESSION"); verifyNoMoreInteractions(mockEventHandlingStrategy); }
@Test public void testMessageBeforeLogonWithBoundSession() throws Exception { IoSession mockIoSession = mock(IoSession.class); try (Session qfSession = SessionFactoryTestSupport.createSession()) { stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(qfSession); EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); Logout logout = new Logout(); logout.getHeader() .setString(SenderCompID.FIELD, qfSession.getSessionID().getSenderCompID()); logout.getHeader() .setString(TargetCompID.FIELD, qfSession.getSessionID().getTargetCompID()); HashMap<SessionID, Session> acceptorSessions = new HashMap<>(); AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), new NetworkingOptions(new Properties()), mockEventHandlingStrategy); handler.processMessage(mockIoSession, logout); verify(mockIoSession).getAttribute("QF_SESSION"); verify(mockEventHandlingStrategy).onMessage(qfSession, logout); } }
@Test public void testMessageBeforeLogonWithKnownButUnboundSession() throws Exception { IoSession mockIoSession = mock(IoSession.class); stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); try (Session qfSession = SessionFactoryTestSupport.createSession()) { Logout logout = new Logout(); logout.getHeader() .setString(SenderCompID.FIELD, qfSession.getSessionID().getSenderCompID()); logout.getHeader() .setString(TargetCompID.FIELD, qfSession.getSessionID().getTargetCompID()); HashMap<SessionID, Session> acceptorSessions = new HashMap<>(); acceptorSessions.put(qfSession.getSessionID(), qfSession); AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), new NetworkingOptions(new Properties()), mockEventHandlingStrategy); handler.processMessage(mockIoSession, logout); verify(mockIoSession).getAttribute("QF_SESSION"); verifyNoMoreInteractions(mockEventHandlingStrategy); } }
@Test public void testLogonWithoutHeartBtInt() throws Exception { EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); IoSession mockIoSession = mock(IoSession.class); final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIXT11, "SENDER", "TARGET"); try (Session session = SessionFactoryTestSupport.createSession(sessionID, new UnitTestApplication(), false)) { stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); final HashMap<SessionID, Session> acceptorSessions = new HashMap<>(); acceptorSessions.put(sessionID, session); final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, new NetworkingOptions(new Properties()), mockEventHandlingStrategy); final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), new HeartBtInt(30), defaultApplVerID); message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); message.getHeader().setField(new SendingTime(LocalDateTime.now())); message.getHeader().setInt(MsgSeqNum.FIELD, 1); message.removeField(HeartBtInt.FIELD); handler.processMessage(mockIoSession, message); } }