Skip to content

Commit

Permalink
Make FIX handling work properly (issue #207)
Browse files Browse the repository at this point in the history
  • Loading branch information
rlktradewright committed May 10, 2023
1 parent 309a762 commit 909c868
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 98 deletions.
33 changes: 26 additions & 7 deletions resources/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -329,13 +329,16 @@ ExistingSessionDetectedAction=manual
# Override TWS API Port Number
# ----------------------------
#
# If OverrideTwsApiPort is set to an integer, IBC changes the
# 'Socket port' in TWS's API configuration to that number shortly
# after startup. Leaving the setting blank will make no change to
# the current setting. This setting is only intended for use in
# certain specialized situations where the port number needs to
# be set dynamically at run-time: most users will never need it,
# so don't use it unless you know you need it.
# If OverrideTwsApiPort is set to an integer, IBC changes the
# 'Socket port' in TWS's API configuration to that number shortly
# after startup (but note that for the FIX Gateway, this setting is
# actually stored in jts.ini rather than the Gateway's settings
# file). Leaving the setting blank will make no change to
# the current setting. This setting is only intended for use in
# certain specialized situations where the port number needs to
# be set dynamically at run-time, and for the FIX Gateway: most
# non-FIX users will never need it, so don't use it unless you know
# you need it.

OverrideTwsApiPort=

Expand Down Expand Up @@ -428,6 +431,22 @@ AcceptBidAskLastSizeDisplayUpdateNotification=
SendMarketDataInLotsForUSstocks=


# Trusted API Client IPs
# ----------------------
#
# NB: THIS SETTING IS ONLY RELEVANT FOR THE GATEWAY, AND ONLY WHEN FIX=yes.
# In all other cases it is ignored.
#
# This is a list of IP addresses separated by commas. API clients with IP
# addresses in this list are able to connect to the API without Gateway
# generating the 'Incoming connection' popup.
#
# Note that 127.0.0.1 is always permitted to connect, so do not include it
# in this setting.

TrustedTwsApiClientIPs=



# =============================================================================
# 4. TWS Auto-Logoff and Auto-Restart
Expand Down
2 changes: 1 addition & 1 deletion src/ibcalpha/ibc/AbstractLoginHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public final void handleWindow(Window window, int eventID) {
switch (LoginManager.loginManager().getLoginState()){
case LOGGED_OUT:
// don't initiate login if we're auto-restarting
if (! SessionManager.IsRestart()) initiateLogin(window);
if (! SessionManager.isRestart()) initiateLogin(window);
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/ibcalpha/ibc/CommandChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ final class CommandChannel {
if (! setupStreams()) return;

writeInfo("IBC Command Server");
writePrompt();

}

void close() {
Expand Down
12 changes: 12 additions & 0 deletions src/ibcalpha/ibc/CommandDispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ private void handleEnableAPICommand() {
}

private void handleReconnectDataCommand() {
if (SessionManager.isFIX()) {
mChannel.writeNack("RECONNECTDATA is not valid for the FIX Gateway");
return;
}
JFrame jf = MainWindowManager.mainWindowManager().getMainWindow(1, TimeUnit.MILLISECONDS);

int modifiers = KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK;
Expand All @@ -86,6 +90,10 @@ private void handleReconnectDataCommand() {
}

private void handleReconnectAccountCommand() {
if (SessionManager.isFIX()) {
mChannel.writeNack("RECONNECTACCOUNT is not valid for the FIX Gateway");
return;
}
JFrame jf = MainWindowManager.mainWindowManager().getMainWindow();

int modifiers = KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK;
Expand All @@ -104,6 +112,10 @@ private void handleStopCommand() {
}

private void handleRestartCommand() {
if (SessionManager.isFIX()) {
mChannel.writeNack("RESTART is not valid for the FIX Gateway");
return;
}
(new RestartTask(mChannel)).run(); // run on the current thread
}

Expand Down
85 changes: 39 additions & 46 deletions src/ibcalpha/ibc/DefaultLoginManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,25 @@ public DefaultLoginManager() {
/* don't actually get the credentials yet because the settings
* provider might be changed
*/
fromSettings = true;
message = "getting username and password from settings";
ibapiCredentialsFromArgs = false;
fixCredentialsFromArgs = false;
message = "will get username and password from settings";
}

public DefaultLoginManager(String[] args) {
if (isFIX()) {
getTWSUserNameAndPasswordFromArguments(args);
fromSettings = !getFIXUserNameAndPasswordFromArguments(args);
} else {
fromSettings = !getTWSUserNameAndPasswordFromArguments(args);
}
if (fromSettings) {
message = "getting username and password from args but not found. Will get from settings";
} else {
message = "getting username and password from args";
}
ibapiCredentialsFromArgs = getTWSUserNameAndPasswordFromArguments(args);
fixCredentialsFromArgs = getFIXUserNameAndPasswordFromArguments(args);
message = "will get username and password from " +
(fixCredentialsFromArgs ? "args" : "settings") +
"; FIX username and password (if required) from " +
(fixCredentialsFromArgs ? "args" : "settings");
}

public DefaultLoginManager(String username, String password) {
IBAPIUserName = username;
IBAPIPassword = password;
fromSettings = false;
ibapiCredentialsFromArgs = true;
fixCredentialsFromArgs = false;
message = "getting username and password from constructor";
}

Expand All @@ -56,15 +53,17 @@ public DefaultLoginManager(String FIXUsername, String FIXPassword, String IBAPIU
this.FIXPassword = FIXPassword;
this.IBAPIUserName = IBAPIUsername;
this.IBAPIPassword = IBAPIPassword;
fromSettings = false;
ibapiCredentialsFromArgs = true;
fixCredentialsFromArgs = true;
message = "getting username and password from constructor (including FIX)";
}

private final String message;

private volatile AbstractLoginHandler loginHandler = null;

private final boolean fromSettings;
private final boolean ibapiCredentialsFromArgs;
private final boolean fixCredentialsFromArgs;

/**
* IBAPI username - can either be supplied from the .ini file or as args[1]
Expand Down Expand Up @@ -101,26 +100,26 @@ public void logDiagnosticMessage(){

@Override
public String FIXPassword() {
if (fromSettings) return getFIXPasswordFromSettings();
return FIXPassword;
if (fixCredentialsFromArgs) return FIXPassword;
return getFIXPasswordFromSettings();
}

@Override
public String FIXUserName() {
if (fromSettings) return getFIXUserNameFromSettings();
return FIXUserName;
if (fixCredentialsFromArgs) return FIXUserName;
return getFIXUserNameFromSettings();
}

@Override
public String IBAPIPassword() {
if (fromSettings) return getTWSPasswordFromSettings();
return IBAPIPassword;
if (ibapiCredentialsFromArgs) return IBAPIPassword;
return getTWSPasswordFromSettings();
}

@Override
public String IBAPIUserName() {
if (fromSettings) return getTWSUserNameFromSettings();
return IBAPIUserName;
if (ibapiCredentialsFromArgs) return IBAPIUserName;
return getTWSUserNameFromSettings();
}

@Override
Expand Down Expand Up @@ -172,33 +171,27 @@ private static String getTWSUserNameFromSettings() {
}

private boolean getTWSUserNameAndPasswordFromArguments(String[] args) {
if (isFIX()) {
if (args.length == 5 || args.length == 6) {
IBAPIUserName = args[3];
IBAPIPassword = args[4];
return true;
} else {
return false;
}
} else if (args.length == 3 || args.length == 4) {
if (args.length == 5 || args.length == 6) {
IBAPIUserName = args[3];
IBAPIPassword = args[4];
return true;

}
if (args.length == 3 || args.length == 4) {
IBAPIUserName = args[1];
IBAPIPassword = args[2];
return true;
} else if (args.length == 5 || args.length == 6) {
Utils.logError("Incorrect number of arguments passed. quitting...");
Utils.logRawToConsole("Number of arguments = " +args.length + " which is only permitted if FIX=yes");
for (String arg : args) {
Utils.logRawToConsole(arg);
}
Utils.exitWithError(ErrorCodes.ERROR_CODE_INCORRECT_NUMBER_OF_ARGUMENTS);
return false;
} else {
}
if (args.length <= 2) {
return false;
}
}

private static boolean isFIX() {
return Settings.settings().getBoolean("FIX", false);
Utils.logError("Incorrect number of arguments passed. quitting...");
Utils.logRawToConsole("Number of arguments = " +args.length);
for (int i = 0; i < args.length; i++) {
Utils.logRawToConsole("arg[" + i + "]=" + args[i]);
}
Utils.exitWithError(ErrorCodes.ERROR_CODE_INCORRECT_NUMBER_OF_ARGUMENTS);
return false;
}

}
7 changes: 4 additions & 3 deletions src/ibcalpha/ibc/ExistingSessionDetectedDialogHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ public void handleWindow(Window window, int eventID) {

if (setting.equalsIgnoreCase("secondary")) {
Utils.logToConsole("End this session and let the other session proceed (scenario 2)");
if (!SwingUtils.clickButton(window, "Cancel") && !SwingUtils.clickButton(window, "Exit Application")) {
Utils.logError("could not handle 'Existing session detected' dialog because the 'Cancel' or 'Exit Application' button wasn't found.");
}
if (!SwingUtils.clickButton(window, "Cancel") && !SwingUtils.clickButton(window, "Exit Application")) {
Utils.logError("could not handle 'Existing session detected' dialog because the 'Cancel' or 'Exit Application' button wasn't found.");
}
return;
}

/* The handling of this dialog is based on the following observed
Expand Down
12 changes: 9 additions & 3 deletions src/ibcalpha/ibc/GatewayLoginFrameHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected final boolean initialise(final Window window, int eventID) throws IbcE
@Override
protected final boolean preLogin(final Window window, int eventID) throws IbcException {
boolean result;
if (Settings.settings().getBoolean("FIX", false)) {
if (SessionManager.isFIX()) {
result = setMissingFIXCredentials(window);
} else {
result = setMissingIBAPICredentials(window);
Expand Down Expand Up @@ -90,20 +90,26 @@ private boolean setMissingIBAPICredentials(Window window) {

@Override
protected final boolean setFields(Window window, int eventID) throws IbcException {
if (Settings.settings().getBoolean("FIX", false)) {
if (SessionManager.isFIX()) {
Utils.logToConsole("Setting FIX user name");
setCredential(window, "FIX user name", 0, LoginManager.loginManager().FIXUserName());
Utils.logToConsole("Setting FIX password");
setCredential(window, "FIX password", 1, LoginManager.loginManager().FIXPassword());
Utils.logToConsole("Setting API user name");
setCredential(window, "IBAPI user name", 2, LoginManager.loginManager().IBAPIUserName());
Utils.logToConsole("Setting API password");
setCredential(window, "IBAPI password", 3, LoginManager.loginManager().IBAPIPassword());
} else {
Utils.logToConsole("Setting user name");
setCredential(window, "IBAPI user name", 0, LoginManager.loginManager().IBAPIUserName());
Utils.logToConsole("Setting password");
setCredential(window, "IBAPI password", 1, LoginManager.loginManager().IBAPIPassword());
}
return true;
}

private void selectGatewayMode(Window window) throws IbcException {
if (Settings.settings().getBoolean("FIX", false)) {
if (SessionManager.isFIX()) {
switchToFIX(window);
} else {
switchToIBAPI(window);
Expand Down
Loading

0 comments on commit 909c868

Please sign in to comment.