Skip to content

Commit c73c4c7

Browse files
authored
Add custom tags to Logon message. (#285)
Adds possibility to specify tags via setting `LogonTag` or `LogonTag<n>`. Example: ``` LogonTag=553=user LogonTag1=554=password ``` It is checked whether a data dictionary is present to determine whether the specified tag is a header field. Otherwise it is put into the body of the message.
1 parent a31be10 commit c73c4c7

File tree

6 files changed

+189
-20
lines changed

6 files changed

+189
-20
lines changed

quickfixj-core/src/main/doc/usermanual/usage/configuration.html

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,29 @@ <H3>QuickFIX Settings</H3>
11921192

11931193
<TD COLSPAN="4" class="subsection"><A NAME="Miscellaneous">Miscellaneous</A></TD>
11941194
</TR>
1195-
<TR ALIGN="left" VALIGN="middle">
1195+
<TR ALIGN="left" VALIGN="middle">
1196+
<TD> <I>LogonTag</I> </TD>
1197+
<TD> Tag/value pair which will be set on sent or received Logon message. </TD>
1198+
<TD> &lt;tag&gt;=&lt;value&gt;, where "tag" has to be a positive integer and "value" a String <br>
1199+
Example: <br>
1200+
LogonTag=553=foo
1201+
</TD>
1202+
<TD> </TD>
1203+
</TR>
1204+
<TR ALIGN="left" VALIGN="middle">
1205+
<TD> <I>LogonTag&lt;n&gt;</I> </TD>
1206+
<TD> Additional tag/value pairs which will be set on sent or received Logon message,<br>
1207+
where <b>n</b> is a positive integer, i.e. LogonTag1, LogonTag2, etc.
1208+
Must be consecutive.
1209+
</TD>
1210+
<TD> &lt;tag&gt;=&lt;value&gt;, where "tag" has to be a positive integer and "value" a String <br>
1211+
Example: <br>
1212+
LogonTag=553=user<br>
1213+
LogonTag1=554=password
1214+
</TD>
1215+
<TD> </TD>
1216+
</TR>
1217+
<TR ALIGN="left" VALIGN="middle">
11961218
<TD> <I>ResetOnLogon</I> </TD>
11971219
<TD> Determines if sequence numbers should be reset before sending/receiving a logon request. </TD>
11981220
<TD> Y<br>N</TD>
@@ -1202,13 +1224,11 @@ <H3>QuickFIX Settings</H3>
12021224
<TD> <I>ResetOnLogout</I> </TD>
12031225
<TD> Determines if sequence numbers should be reset to 1 after a normal logout termination. </TD>
12041226
<TD> Y<br>N</TD>
1205-
12061227
<TD> N </TD>
12071228
</TR>
12081229
<TR ALIGN="left" VALIGN="middle">
12091230
<TD> <I>ResetOnDisconnect</I> </TD>
12101231
<TD> Determines if sequence numbers should be reset to 1 after an abnormal termination. </TD>
1211-
12121232
<TD> Y<br>N</TD>
12131233
<TD> N </TD>
12141234
</TR>

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import quickfix.field.DefaultApplVerID;
2626

2727
import java.net.InetAddress;
28+
import java.util.ArrayList;
2829
import java.util.Arrays;
2930
import java.util.Enumeration;
31+
import java.util.List;
3032
import java.util.Properties;
3133
import java.util.Set;
3234

@@ -214,6 +216,8 @@ public Session create(SessionID sessionID, SessionSettings settings) throws Conf
214216

215217
final SessionSchedule sessionSchedule = sessionScheduleFactory.create(sessionID, settings);
216218

219+
final List<StringField> logonTags = getLogonTags(settings, sessionID);
220+
217221
final Session session = new Session(application, messageStoreFactory, sessionID,
218222
dataDictionaryProvider, sessionSchedule, logFactory,
219223
messageFactory, heartbeatInterval, checkLatency, maxLatency, timestampPrecision,
@@ -224,7 +228,7 @@ public Session create(SessionID sessionID, SessionSettings settings) throws Conf
224228
rejectInvalidMessage, rejectMessageOnUnhandledException, requiresOrigSendingTime,
225229
forceResendWhenCorruptedStore, allowedRemoteAddresses, validateIncomingMessage,
226230
resendRequestChunkSize, enableNextExpectedMsgSeqNum, enableLastMsgSeqNumProcessed,
227-
validateChecksum);
231+
validateChecksum, logonTags);
228232

229233
session.setLogonTimeout(logonTimeout);
230234
session.setLogoutTimeout(logoutTimeout);
@@ -427,4 +431,21 @@ private UtcTimestampPrecision getTimestampPrecision(SessionSettings settings, Se
427431
}
428432
}
429433

434+
private List<StringField> getLogonTags(SessionSettings settings, SessionID sessionID) throws ConfigError, FieldConvertError {
435+
List<StringField> logonTags = new ArrayList<>();
436+
for (int index = 0;; index++) {
437+
final String logonTagSetting = Session.SETTING_LOGON_TAG
438+
+ (index == 0 ? "" : NumbersCache.get(index));
439+
if (settings.isSetting(sessionID, logonTagSetting)) {
440+
String tag = settings.getString(sessionID, logonTagSetting);
441+
String[] split = tag.split("=", 2);
442+
StringField stringField = new StringField(Integer.valueOf(split[0]), split[1]);
443+
logonTags.add(stringField);
444+
} else {
445+
break;
446+
}
447+
}
448+
return logonTags;
449+
}
450+
430451
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ public T getObject() {
8080
}
8181

8282
/**
83-
* Return's the formatted field (tag=value<SOH>)
83+
* Returns the formatted field (tag=value<SOH>)
8484
*
8585
* @return the formatted field
8686
*/
87+
@Override
8788
public String toString() {
8889
calculate();
8990
return data;

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ public class Session implements Closeable {
224224
*/
225225
public static final String SETTING_LOGOUT_TIMEOUT = "LogoutTimeout";
226226

227+
/**
228+
* Session setting for custom logon tags. Single entry or consecutive list of
229+
* tag=value pairs, e.g. LogonTag=553=user and LogonTag1=554=password.
230+
*/
231+
public static final String SETTING_LOGON_TAG = "LogonTag";
232+
227233
/**
228234
* Session setting for doing an automatic sequence number reset on logout.
229235
* Valid values are "Y" or "N". Default is "N".
@@ -437,6 +443,8 @@ public class Session implements Closeable {
437443
private static final String BAD_ORIG_TIME_TEXT = new FieldException(BAD_TIME_REJ_REASON, OrigSendingTime.FIELD).getMessage();
438444
private static final String BAD_TIME_TEXT = new FieldException(BAD_TIME_REJ_REASON, SendingTime.FIELD).getMessage();
439445

446+
private final List<StringField> logonTags;
447+
440448
protected static final Logger LOG = LoggerFactory.getLogger(Session.class);
441449

442450

@@ -446,8 +454,8 @@ public class Session implements Closeable {
446454
this(application, messageStoreFactory, sessionID, dataDictionaryProvider, sessionSchedule,
447455
logFactory, messageFactory, heartbeatInterval, true, DEFAULT_MAX_LATENCY, UtcTimestampPrecision.MILLIS,
448456
false, false, false, false, true, false, true, false,
449-
DEFAULT_TEST_REQUEST_DELAY_MULTIPLIER, null, true, new int[] { 5 }, false, false,
450-
false, false, true, false, true, false, null, true, DEFAULT_RESEND_RANGE_CHUNK_SIZE, false, false, false);
457+
DEFAULT_TEST_REQUEST_DELAY_MULTIPLIER, null, true, new int[]{5}, false, false,
458+
false, false, true, false, true, false, null, true, DEFAULT_RESEND_RANGE_CHUNK_SIZE, false, false, false, new ArrayList<StringField>());
451459
}
452460

453461
Session(Application application, MessageStoreFactory messageStoreFactory, SessionID sessionID,
@@ -465,7 +473,7 @@ public class Session implements Closeable {
465473
boolean forceResendWhenCorruptedStore, Set<InetAddress> allowedRemoteAddresses,
466474
boolean validateIncomingMessage, int resendRequestChunkSize,
467475
boolean enableNextExpectedMsgSeqNum, boolean enableLastMsgSeqNumProcessed,
468-
boolean validateChecksum) {
476+
boolean validateChecksum, List<StringField> logonTags) {
469477
this.application = application;
470478
this.sessionID = sessionID;
471479
this.sessionSchedule = sessionSchedule;
@@ -499,6 +507,7 @@ public class Session implements Closeable {
499507
this.enableNextExpectedMsgSeqNum = enableNextExpectedMsgSeqNum;
500508
this.enableLastMsgSeqNumProcessed = enableLastMsgSeqNumProcessed;
501509
this.validateChecksum = validateChecksum;
510+
this.logonTags = logonTags;
502511

503512
final Log engineLog = (logFactory != null) ? logFactory.create(sessionID) : null;
504513
if (engineLog instanceof SessionStateListener) {
@@ -2020,6 +2029,8 @@ private boolean generateLogon() throws IOException {
20202029
logon.setInt(NextExpectedMsgSeqNum.FIELD, nextExpectedMsgNum);
20212030
state.setLastExpectedLogonNextSeqNum(nextExpectedMsgNum);
20222031
}
2032+
2033+
setLogonTags(logon);
20232034
return sendRaw(logon, 0);
20242035
}
20252036

@@ -2534,6 +2545,8 @@ private void generateLogon(Message otherLogon, int expectedTargetNum) throws Fie
25342545
} else {
25352546
getLog().onEvent("Responding to Logon request");
25362547
}
2548+
2549+
setLogonTags(logon);
25372550
sendRaw(logon, 0);
25382551
state.setLogonSent(true);
25392552
}
@@ -3004,4 +3017,15 @@ private String getMessageToLog(final Message message) {
30043017
return (message.toRawString() != null ? message.toRawString() : message.toString());
30053018
}
30063019

3020+
private void setLogonTags(final Message logon) {
3021+
for (StringField field : logonTags) {
3022+
if (dataDictionaryProvider != null
3023+
&& dataDictionaryProvider.getSessionDataDictionary(sessionID.getBeginString()).isHeaderField(field.getTag())) {
3024+
logon.getHeader().setField(field);
3025+
continue;
3026+
}
3027+
logon.setField(field);
3028+
}
3029+
}
3030+
30073031
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import quickfix.field.DefaultApplVerID;
44

55
import java.net.InetAddress;
6+
import java.util.ArrayList;
7+
import java.util.List;
68
import java.util.Set;
79
import java.util.function.Supplier;
810

@@ -108,6 +110,7 @@ public static final class Builder {
108110
private boolean enableNextExpectedMsgSeqNum = false;
109111
private final boolean enableLastMsgSeqNumProcessed = false;
110112
private final boolean validateChecksum = true;
113+
private List<StringField> logonTags = new ArrayList<>();
111114

112115
public Session build() {
113116
return new Session(applicationSupplier.get(), messageStoreFactorySupplier.get(), sessionIDSupplier.get(),
@@ -119,7 +122,7 @@ public Session build() {
119122
resetOnError, disconnectOnError, disableHeartBeatCheck, false, rejectInvalidMessage,
120123
rejectMessageOnUnhandledException, requiresOrigSendingTime, forceResendWhenCorruptedStore,
121124
allowedRemoteAddresses, validateIncomingMessage, resendRequestChunkSize, enableNextExpectedMsgSeqNum,
122-
enableLastMsgSeqNumProcessed, validateChecksum);
125+
enableLastMsgSeqNumProcessed, validateChecksum, logonTags);
123126
}
124127

125128
public Builder setBeginString(final String beginString) {
@@ -169,6 +172,11 @@ public Builder setLogFactory(final LogFactory logFactory) {
169172
return this;
170173
}
171174

175+
public Builder setLogonTags(final List<StringField> logonTags) {
176+
this.logonTags = logonTags;
177+
return this;
178+
}
179+
172180
public Builder setMessageFactory(final MessageFactory messageFactory) {
173181
this.messageFactorySupplier = () -> messageFactory;
174182
return this;

0 commit comments

Comments
 (0)