Skip to content

Don't increment sequence number on rejected logon #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion quickfixj-core/src/main/java/quickfix/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,10 @@ ignore the message and let the problem correct itself (optimistic approach).
generateLogout(e.getMessage());
}
}
state.incrNextTargetMsgSeqNum();
// 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)) {
Expand Down
62 changes: 62 additions & 0 deletions quickfixj-core/src/test/java/quickfix/SessionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down