TCP Socket Interface
1. Introduction
1.1 Interfacing with the Socket Interface
4. Monitor Mode
Appendix 1. Protocol Version Differences
Appendix 2. Expose Localhost-only Port to the Network
merccc has a TCP socket interface that external programs can connect to to get information about the current state of the competition and to optionally be informed of state changes. The socket interface is used by passing the '-p <port>' option to the program. If a loopback port is desired, use the '--localport <port>' option. If initialization is successful, merccc will start listening to the port and serve a line-oriented socket stream with LF character (ASCII hex 0A) as line delimiter. This interface can handle multiple clients.
Upon connecting, the client will be sent a header line with the version of the server and its capabilities, e.g. for version 1.3.0: merccc-1.3.0 for non-local port and merccc-1.3.0 local for a loopback socket. The server will print "> " prompt (without new line) to the client to indicate that it is ready to receive a command (unless it is in monitor mode or if the prompt is disabled).
A program such as netcat can be used to interact with the server through the console. PuTTY with raw mode and implied CR option can be used in Windows.
To programmatically interface with merccc through the TCP socket, it is recommended to turn off the prompt to ease parsing of messages from the server. Upon connecting, the client program will need to read the header line and then send promptoff to turn off the prompt. After the server received this command, the response from the server will be > PROMPT OFF in a single line. The client can flush this line (scan until LF character) and begin interfacing with the merccc server with the commands and monitor mode described in the rest of this document without having to deal with the prompt.
In addition to querying the state of the program, the loopback port also supports commands that can change the state of the program. These commands can be used to extend the functionality of the program without modifying merccc itself.
The following is a list of commands for the socket interface (local and otherwise):
Command | Description |
---|---|
config | get the configuration file contents |
hash | get 32-bit configuration hash |
teams | get the list of teams |
header | get scoring data header |
data | get recorded scoring data, if any |
classification | get current classification list |
annotations | get current team annotations |
q | close connection |
state | get current state of the scoring software |
monitor | go into monitor mode to be notified of changes |
break (monitor mode only) | break away from monitor mode |
promptoff | turn off prompt |
resolution | get display window resolution |
merccc will send a DONE message on its own line after sending a multi-line response and before sending the prompt. This does not apply to the q, state, hash, monitor, break, promptoff, and resolution commands. promptoff will return PROMPT OFF when invoked and the prompt will never be sent for the remainder of the connection.
An ERROR message will be sent if the client transmitted an invalid command.
The following is the format of a line of the returned data for each command:
config:
lines of text from the config file
hash:
HASH [32-bit hash in signed integer representation]
teams:
TEAM [team#], [team_name], [team_institution], [badge_filename], [best_score]
header:
HEADER [col_header_name]
data:
DATA [data entry following the order as given by the header]
classification:
CLASSIFICATION [rank], [team#], [team_name], [team_institution], [best_score]
annotations:
ANNOTATION [team#] [comma_separated_annotations]
The following commands only return a single line:
state:
STATE [state] or
STATE [state] [team#] [run#] [time_left_ms] [paused] [redflagged]
... where state is -1 for IDLE, 0 for SETUP, 1 for RUN, and 2 for POST-RUN
resolution:
RESOLUTION [width]x[height]
... width and height will be returned as '-1x-1' if the display is hidden
When the "monitor" command is invoked, merccc will reply with MONITOR and stop acknowledging commands other than the "break" command. While in this mode, merccc will emit a line of data to the client signifying an event that has occured. The following is a list of events that the client will be notified of when they occur:
STATE_CHANGE_IDLE |
the control program has gone into an idle state |
STATE_CHANGE_SETUP [team#] [max_attempts] [setup_duration] [window_duration] |
a scoring session for the team with team# ID number has started and the program is now in setup state. Durations are in seconds |
STATE_CHANGE_RUN |
the run phase has started |
STATE_CHANGE_POSTRUN |
the run phase has ended, but a score may still be committed |
SCORE_CHANGE [fieldKey] [field#] [new_value] |
a score field has been changed in a scoring session. fieldKey is specified in the fields section of the configuration file (left-hand identifier). field# is the order of the score field in the fields section |
SESSION_PAUSED |
the scoring session timer was paused. This event may occur during setup or run states |
SESSION_RESUMED |
the scoring session timer was resumed after being paused |
SESSION_REDFLAGGED |
the scoring session was "red flagged". The meaning of the red flag is up to interpretation for the particular competition |
SESSION_GREENFLAGGED |
the red flag state has ended |
SESSION_ATTEMPT_COMMITTED [team#] [run#] [score] |
the current active scored run has been committed to the database. team# is the team number of the active team and run# is the run number of the current scoring session that the score belongs to |
SESSION_ATTEMPT_DISCARDED [team#] [run#] |
the current team has just discarded its scored run, no new data is committed to the database |
SESSION_TIME_ADDED [signed time_secs] |
time has been added during either setup or run states |
DATA_CLEARED |
all scoring data from the database has been cleared |
DATA_IMPORTED |
a previously saved scoring data has been loaded into the database |
DATA_RECORD_EXPUNGED [team#] [score#] |
a score entry for a particular team has been deleted |
DATA_CHANGED [team#] [score#] [fieldKey] [new_value] |
a score entry in the database has been modified |
DATA_ADDED [team#] [score#] |
a new score entry has been added for the team outside a scoring session |
TEAM_PRE_SELECT [team#] |
team currently selected by the operator to run next |
DISPLAY_MODE_CHANGE [mode] |
display mode changed (0 for logo and time, 1 for run status, 2 for classification) |
DISPLAY_HIDE |
display was made hidden |
DISPLAY_SHOW |
display was made visible |
DISPLAY_RANK_START [starting_rank] |
operator has set the first rank to display in classification mode |
The following commands are only available using the local loopback socket interface. Unless otherwise noted, the commands will send OK if there was no error, and ERROR followed by a reason if an error occured during execution of the command. These responses will be on a single line.
add-score [teamID] [values...] |
add a score for the specified team. The values for the score fields are in the order specified in the configuration file and header command |
delete-score [teamID] [scoreID] |
delete a score of the specified team. scoreID can be found using the 'data' command in the column after the team number and name (Score# from 'header') |
clear-data |
clear all scored runs. Dangerous |
save-data [file] |
save scoring data to the specified file |
load-data [file] |
load scoring data from the specified file. Existing scoring data will not be deleted |
start-scoring-session [teamID] [attempts] [setup_window_ms] [run_window_ms] |
start a scoring session for the specified team. The server must be in the idle state |
end-scoring-session |
end the current scoring session. Uncommitted scored runs will be lost |
skip-setup |
skip the setup period. Running this command outside of the setup state will have no effect |
change-active-score-field [fieldKey] [value] |
change the value of a score field specified by fieldKey during a scoring session (run and post-run states) |
get-current-score |
get the current (uncommitted) score. The server will return with the following format: CURRENT RUN=[run#] FIELD1=[value]...FIELDX=[value] |
commit-score |
commit the current score to the database, start next run or end the run state if max attempts have been reached |
discard-score |
discard the current score, start next run or end the run state if max attempts have been reached |
pause |
pause the timer if in the setup or run states |
resume |
resume the timer if in the setup or run states |
add-time [seconds] |
add/deduct setup or run window time (use negative number to deduct) |
redflag |
raise the red flag state if in the setup or run states |
greenflag |
cancel the red flag state if in the setup or run states |
trigger-display-change [mode] |
trigger a display mode change event (for display clients that are connected to the server) |
trigger-display-rank-start [start_rank] |
trigger a display rank start event (for display clients that are connected to the server) |
current-directory |
get current working directory |
change-directory [path] |
change current working directory |
0.9.4: the TCP socket interface is included
0.9.5: the local loopback interface is included
0.9.9: DONE message after multi-line response, updated monitor events, added hash and promptoff commands
1.3.0: resolution command and extended local socket interface. Added OK and ERROR responses to commands. Server will always use LF as the line delimiter even if it is running on Windows
1.4.3: annotations command added. data no longer returns annotations on the last column as in 1.4.0 to 1.4.2
merccc will only listen to the localhost network 127.0.0.1 if the --localport option is used. But if you trust the local network and would like to execute the localhost-only commands from another computer in the network, you can use the program socat to forward a public port to the local only port in Unix-like systems, and you can use portproxy in Windows
To listen to port 19005 and open a connection to merccc localhost-only port 19001, you can run the following command:
socat tcp-listen:19005,fork,reuseaddr tcp-connect:127.0.0.1:19001
Point the client program to the IP address of the computer hosting merccc server and port 19005 to open the connection. The client program will be able to run the commands specified in section 5. Terminate the program to disable the port forwarding.
In Windows systems, portproxy can be used to forward a public port. portproxy requires the IP Helper service to be running and the IPv6 option must be installed for your network adapter. Run the following command in a command prompt with administrator privilege to enable port forwarding with portproxy:
netsh interface portproxy add v4tov4 19005 127.0.0.1 connectport=19001
To disable the proxy, run the following command:
netsh interface portproxy delete v4tov4 19005
You will need to allow incoming TCP connections to the port 19005 in the Advanced Firewall settings, e.g.:
netsh advfirewall firewall add rule name="Open Port 19005" dir=in action=allow protocol=TCP localport=19005
Run the following command to delete the firewall rule:
netsh advfirewall firewall delete rule name="Open Port 19005"