Due: Friday, February 5, 9pm
Submission:
At the top-level of Khoury Github, create a directory A4
with the following:
a directory src/
containing the source code for the program a4
from Task 1
the file traveller-integration-report.md
from Task 2
optionally: a PDF new-project-programming-language.pdf
– if you are switching your programming language for the project
Create a new release on GitHub, tagged a4
and add a ZIP file a4-exec.zip
as the “binary” containing the a4
executable and any auxiliary files required by the executable. Details on how to do that are here.
Download the Source code (zip) from the release and submit it via Handins. If you are storing additional (binary) assets (e.g., compiled libraries, JAR files) in your Github repo, the ZIP file might be too large for submission on Handins. In that case, you will need to remove these third-party files from the ZIP manually before submitting.
Implement a client program for the TCP Traveller server according to the protocol specification below.
After starting up and connecting to the server via TCP, the client enters an interactive loop, reading JSON requests for the Traveller service from STDIN, processing them and passing the corresponding TCP requests to the server, and rendering responses to STDOUT. The client accepts well-formed JSON requests following Task 3 in Warm-up 3. An interactive session is ended when the user sends a ^D
(Ctrl-D) to STDIN.
The client, a4
, should take the following arguments, in this order:
Example call:
$ ./a4 127.0.0.1 8080 ferd
If the name is missing, use Glorifrir Flintshoulder
as default. If the port is missing, use 8000
as the default. If the IP address is also missing, use 127.0.0.1
(localhost). That is, if a4
is called without arguments, it should connect to 127.0.0.1
on port 8000
and use Glorifrir Flintshoulder
as the user’s name. If only one argument is given, it is the IP address. If two, they are the address and port.
For this task, you only need to implement a client that follows the given protocol. To test your client, you can implement a mock server. The Wikipedia page on Mock Objects is a good starting point on this concept. Alternatively, you can simulate a server using netcat
in listen mode and manually entering server responses or preparing a script. See man netcat
and, e.g., https://linuxize.com/post/netcat-nc-command-with-examples/#creating-a-simple-chat-server.
The idea with this task is to further practice implementing to a specification. Unless you decide to write an example server yourself, you won’t have an actual server implementation to test against. However, the interactions with the server are few and relatively simple. As such, it should be fairly straightforward to write a script exercising a particular scenario.
Within 24 hours of this assignment being published, you will receive an implementation of your specification for a Traveller
server module (aka, back-end) in the directory A4/inbox
of your master branch. Alternatively, there might be a memo explaining why the specification could not be implemented.
If you received an implementation, write a short (1-2 pages) memo addressing the following questions:
If you received an explanation of why the specification could not be implemented, or why it is incomplete, instead of answering 1 and 2 above, write a reply to the explanation and include an answer to 3.
Complete this task if and only if you wish to switch your chosen programming language.
As this is the last warm-up assignment, you now have the option to choose a different language to use for the remainder of the semester.
The above points form a minimum, but not an exhaustive list of concepts you will acquire on the side for software system construction. Over the course of the semester, your chosen language will have to support other essential concepts from software systems building.
The first three sections explain the interaction arrangements between the user, the client program (a4
), and the server
component. The remaining sections specify the format of the messages.
In the protocol specification, the square brackets [
]
enclose references to message shapes explained below.
---------------------------------------------------------------------------------------------
Traveller service server +------- user launches `./a4'
|| | |
| || traveller client <----+ |
| || | |
|<-----------------------------| tcp connect |
| || | |
|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| [sign-up name] |
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| receive [session id] |
| || | |
| || |<----------------------------| create a road network
|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| send [create request] |
The client program should be prepared to consume up to three arguments:
127.0.0.1
8000
Glorifrir Flintshoulder
During this phase the client can send multiple batch requests. A batch request consists of a sequence of character placements, terminated by a single query about the safe passage of a character.
---------------------------------------------------------------------------------------------
Traveller server || Traveller client user enters requests
|| |
| || | |
| || |<----------------------------| place character requests
| || | |
... .... ... ...
| || | |
| || |<----------------------------| passage-safe? query
|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| send [batch] |
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| receive [response] |
| || |---------------------------->| render response
| || | | ...
| || |<----------------------------| place character requests
| || | |
... .... ... ...
| || | |
| || |<----------------------------| passage-safe? query
|<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| send [batch] |
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>| receive [response] |
| || |---------------------------->| render response
... .... ... ...
---------------------------------------------------------------------------------------------
Traveller server || Traveller client user closes STDIN
| || | |
| || |<--------------------------- | ^D to client
|<-----------------------------| tcp disconnect ---
| || ---
The user interacts with the client a4
on STDIN using the exact same JSON commands as specified in Warm-up 3.
Note the difference between the road network creation JSON request and the protocol message passed through TCP.
Sign-up name
String
The user uses this name to identify themselves.
Session id
String
Used for distinguishing connections.
Create request
{ "towns" : [ String, String, ...],
"roads" : [ {"from" : String, "to" : String }, ... ] }
Sets up a network of towns with roads between them.
Batch request
{ "characters" : [ { "name" : String, "town" : String }, ... ],
"query" : { "character" : String, "destination" : String } }
A batch adds characters to the town network and asks whether a character can safely travel to the given destination town.
Response
{ "invalid" : [ { "name" : String, "town" : String }, ... ],
"response" : Boolean }
The response to a batch request contains a (possibly) empty list of character placements deemed invalid by the server (see below) and the Boolean response to the query.
From the perspective of the client program, all JSON values that match the above format are well-formed and valid, and can be sent to the server. If the user enters JSON that does not represent a well-formed request, the client program says
{ "error" : "not a request",
"object" : <JSON> }
where <JSON>
stands for the JSON the user entered.
From the perspective of server
, validity requires the satisfaction of additional constraints:
A Create request is only valid if each "from"
and "to"
element is in the list of towns (the "towns"
key).
A Batch request is only valid if
The server will shut down the connection if:
Any character placement request which is well-formed but invalid gets sent back as a part of the response to a batch.
The client program a4
renders responses as quasi-English JSON for the user as follows:
["the server will call me", String]
["invalid placement", { "name" : String, "town" : String } ]
["the response for", { "character" : String, "destination" : String} , "is", Boolean]
It does not have to accept a hostname. However, we will be pleased if it does.↩︎