Skip to content

Commit 895224d

Browse files
janusz-jJanusz Jaskiewiczchrjohn
authored
Preventing the acceptor session from accepting Logon message when Logout was initiated locally. (#360)
* Preventing the acceptor session from accepting Logon message when Logout was initiated locally. When Logon sequence was initiated externally. i.e. counterparty initiated Logout sequence, acceptor should still accept subsequent Logon attempts from that counterparty. Co-authored-by: Janusz Jaskiewicz <janusz.jaskiewicz@capitalmarkets.technology> Co-authored-by: Christoph John <christoph.john@macd.com>
1 parent 9d1c547 commit 895224d

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

quickfixj-core/src/main/java/quickfix/Session.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,9 +881,8 @@ public void reset() {
881881
((ApplicationExtended) application).onBeforeSessionReset(sessionID);
882882
}
883883
state.setResetStatePending(true);
884-
logout("Session reset");
884+
generateLogout("Session reset");
885885
getLog().onEvent("Initiated logout request");
886-
generateLogout(state.getLogoutReason());
887886
} else {
888887
resetState();
889888
}
@@ -1405,6 +1404,7 @@ private void nextLogout(Message logout) throws IOException, RejectLogon, FieldNo
14051404
return;
14061405
}
14071406

1407+
final boolean logoutInitiatedLocally = state.isLogoutSent();
14081408
state.setLogoutReceived(true);
14091409

14101410
String msg;
@@ -1430,6 +1430,10 @@ private void nextLogout(Message logout) throws IOException, RejectLogon, FieldNo
14301430
}
14311431

14321432
disconnect(msg, false);
1433+
1434+
if (!state.isInitiator() && !logoutInitiatedLocally) {
1435+
setEnabled(true);
1436+
}
14331437
}
14341438

14351439
public void generateLogout() {
@@ -2082,11 +2086,6 @@ public void disconnect(String reason, boolean logError) throws IOException {
20822086
stateListener.onLogout();
20832087
}
20842088
} finally {
2085-
// QFJ-457 now enabled again if acceptor
2086-
if (!state.isInitiator()) {
2087-
setEnabled(true);
2088-
}
2089-
20902089
state.setLogonReceived(false);
20912090
state.setLogonSent(false);
20922091
state.setLogoutSent(false);
@@ -2106,6 +2105,9 @@ public void disconnect(String reason, boolean logError) throws IOException {
21062105
private void nextLogon(Message logon) throws FieldNotFound, RejectLogon, IncorrectDataFormat,
21072106
IncorrectTagValue, UnsupportedMessageType, IOException, InvalidMessage {
21082107

2108+
if (!enabled) {
2109+
throw new RejectLogon("Logon attempt when session is disabled");
2110+
}
21092111
// QFJ-357
21102112
// If this check is not done here, the Logon would be accepted and
21112113
// immediately followed by a Logout (due to check in Session.next()).

quickfixj-core/src/test/java/quickfix/SessionTest.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ public void testNonpersistedGapFill() throws Exception {
18761876

18771877
@Test
18781878
// QFJ-457
1879-
public void testAcceptorRelogon() throws Exception {
1879+
public void testAcceptorRejectsLogonWhenLogoutInitiatedLocally() throws Exception {
18801880
final UnitTestApplication application = new UnitTestApplication();
18811881
try (Session session = setUpSession(application, false,
18821882
new UnitTestResponder())) {
@@ -1895,13 +1895,40 @@ public void testAcceptorRelogon() throws Exception {
18951895
UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS));
18961896
logout.getHeader().setInt(MsgSeqNum.FIELD, 2);
18971897
session.next(logout);
1898-
1899-
// session.reset();
1898+
1899+
assertFalse(session.isEnabled());
19001900
assertFalse(session.isLoggedOn());
19011901
logonTo(session, 3);
19021902
Message lastToAdminMessage = application.lastToAdminMessage();
1903-
assertNotEquals(Logout.MSGTYPE, lastToAdminMessage.getHeader()
1904-
.getString(MsgType.FIELD));
1903+
assertEquals(Logout.MSGTYPE, lastToAdminMessage.getHeader().getString(MsgType.FIELD));
1904+
}
1905+
}
1906+
1907+
@Test
1908+
public void testAcceptorAcceptsLogonWhenLogoutInitiatedExternally() throws Exception {
1909+
final UnitTestApplication application = new UnitTestApplication();
1910+
try (Session session = setUpSession(application, false,
1911+
new UnitTestResponder())) {
1912+
1913+
logonTo(session);
1914+
assertTrue(session.isEnabled());
1915+
assertTrue(session.isLoggedOn());
1916+
1917+
final Message logout = new Logout();
1918+
logout.getHeader().setString(SenderCompID.FIELD, "TARGET");
1919+
logout.getHeader().setString(TargetCompID.FIELD, "SENDER");
1920+
logout.getHeader().setString(SendingTime.FIELD,
1921+
UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS));
1922+
logout.getHeader().setInt(MsgSeqNum.FIELD, 2);
1923+
session.next(logout);
1924+
1925+
session.next();
1926+
1927+
assertTrue(session.isEnabled());
1928+
assertFalse(session.isLoggedOn());
1929+
logonTo(session, 3);
1930+
Message lastToAdminMessage = application.lastToAdminMessage();
1931+
assertEquals(Logon.MSGTYPE, lastToAdminMessage.getHeader().getString(MsgType.FIELD));
19051932
}
19061933
}
19071934

quickfixj-core/src/test/java/quickfix/mina/SessionConnectorTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public void testConnector() throws Exception {
9999

100100
assertTrue(session.isEnabled());
101101
connector.logoutAllSessions(true);
102-
// Acceptors should get re-enabled after Logout
103-
assertTrue(session.isEnabled());
102+
// Acceptors should not get re-enabled after initiating Logout
103+
assertFalse(session.isEnabled());
104104

105105
assertEquals(9999, connector.getIntSetting(Acceptor.SETTING_SOCKET_ACCEPT_PORT));
106106

0 commit comments

Comments
 (0)