From 8217b3bfc041ba4deb06bf23d225feb5aeae4f1a Mon Sep 17 00:00:00 2001 From: Philip Whitehouse Date: Mon, 30 Oct 2017 17:33:11 +0000 Subject: [PATCH 1/3] Don't increment sequence number on rejected logon --- .../src/main/java/quickfix/Session.java | 2 +- .../src/test/java/quickfix/SessionTest.java | 64 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/quickfixj-core/src/main/java/quickfix/Session.java b/quickfixj-core/src/main/java/quickfix/Session.java index dbfd9235bd..510b024459 100644 --- a/quickfixj-core/src/main/java/quickfix/Session.java +++ b/quickfixj-core/src/main/java/quickfix/Session.java @@ -1073,7 +1073,7 @@ ignore the message and let the problem correct itself (optimistic approach). generateLogout(e.getMessage()); } } - state.incrNextTargetMsgSeqNum(); + //Don't increment sequence number - no guarantee rejected logon was in sequence - can skip messages disconnect("Logon rejected: " + e, true); } catch (final UnsupportedMessageType e) { if (logErrorAndDisconnectIfRequired(e, message)) { diff --git a/quickfixj-core/src/test/java/quickfix/SessionTest.java b/quickfixj-core/src/test/java/quickfix/SessionTest.java index 56e3763437..f5d0dd1665 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionTest.java @@ -1062,7 +1062,7 @@ public void fromAdmin(Message message, SessionID sessionId) assertEquals(false, state.isLogoutTimedOut()); assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); session.close(); } @@ -2336,6 +2336,68 @@ private void testLargeQueue(int N) throws Exception { */ } + @Test + public void testResendSeqWithReject() throws Exception { + final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); + final boolean resetOnLogon = false; + final boolean validateSequenceNumbers = true; + boolean enableNextExpectedMsgSeqNum = false; + boolean isInitiator = false; + + UnitTestApplication app = new UnitTestApplication() { + private int logonCount = 0; + + @Override + public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, + IncorrectDataFormat, IncorrectTagValue, RejectLogon { + super.fromAdmin(message, sessionId); + if (message.getHeader().getString(MsgType.FIELD).equals(Logon.MSGTYPE)) { + logonCount += 1; + } + if (logonCount == 2) { + throw new RejectLogon("RejectLogon"); + } + } + }; + + Session session = new Session(app, new MemoryStoreFactory(), + sessionID, null, null, null, + new DefaultMessageFactory(), isInitiator ? 30 : 0, false, 30, UtcTimestampPrecision.MILLIS, resetOnLogon, + false, false, false, false, false, true, false, 1.5, null, validateSequenceNumbers, + new int[]{5}, false, false, false, true, false, true, false, null, true, 0, + enableNextExpectedMsgSeqNum, false); + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + logonTo(session, 1); + //Do Something + session.next(createAppMessage(2)); + session.next(createAppMessage(3)); + session.disconnect("Disconnecting", true); + session.next(); + session.logon(); + + //Logon + session.setResponder(responder); + logonTo(session, 105); + //Rejected + assertEquals(Logout.MSGTYPE, app.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals("RejectLogon", app.lastToAdminMessage().getString(Text.FIELD)); + + //Logon + session.setResponder(responder); + logonTo(session, 106); + //Accepted + assertEquals(Logon.MSGTYPE, app.lastFromAdminMessage().getHeader().getString(MsgType.FIELD)); + + session.next(); + session.next(); + //ResendRequest + assertEquals(ResendRequest.MSGTYPE, app.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(4, app.lastToAdminMessage().getInt(BeginSeqNo.FIELD)); + assertEquals(0, app.lastToAdminMessage().getInt(EndSeqNo.FIELD)); + } + private News createPossDupAppMessage(int sequence) { // create a regular app message and and add the PossDup // and OrigSendingTime tags to it From bfb3166de9857efe5823e6a434ad8746c0fd1fa6 Mon Sep 17 00:00:00 2001 From: Christoph John Date: Thu, 25 Jan 2018 13:52:27 +0100 Subject: [PATCH 2/3] Changed to check expected seqnum on RejectLogon --- quickfixj-core/src/main/java/quickfix/Session.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quickfixj-core/src/main/java/quickfix/Session.java b/quickfixj-core/src/main/java/quickfix/Session.java index 510b024459..63392d6c4c 100644 --- a/quickfixj-core/src/main/java/quickfix/Session.java +++ b/quickfixj-core/src/main/java/quickfix/Session.java @@ -1073,7 +1073,10 @@ ignore the message and let the problem correct itself (optimistic approach). generateLogout(e.getMessage()); } } - //Don't increment sequence number - no guarantee rejected logon was in sequence - can skip messages + // Only increment seqnum if we are at the expected seqnum + if (getExpectedTargetNum() == header.getInt(MsgSeqNum.FIELD)) { + state.incrNextTargetMsgSeqNum(); + } disconnect("Logon rejected: " + e, true); } catch (final UnsupportedMessageType e) { if (logErrorAndDisconnectIfRequired(e, message)) { From 78387a7f87b50a8513c9a2af7b9add7e4167b397 Mon Sep 17 00:00:00 2001 From: Christoph John Date: Thu, 25 Jan 2018 13:54:17 +0100 Subject: [PATCH 3/3] Reverted unnecessary change in SessionTest --- quickfixj-core/src/test/java/quickfix/SessionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickfixj-core/src/test/java/quickfix/SessionTest.java b/quickfixj-core/src/test/java/quickfix/SessionTest.java index f5d0dd1665..a6e6fe5c6d 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionTest.java @@ -1062,7 +1062,7 @@ public void fromAdmin(Message message, SessionID sessionId) assertEquals(false, state.isLogoutTimedOut()); assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); session.close(); }