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.18000Glorifrir FlintshoulderDuring 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
StringThe user uses this name to identify themselves.
Session id
StringUsed 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.↩︎