3.4 KiB
Stage 2: what crosses the wire
challenge.py speaks this for you. It is written down so that when something
goes wrong you can tell a protocol mistake from a Go-Back-N or Selective
Repeat mistake, which is the difference between "my JSON was wrong" and "my
window logic was wrong". Only the second one is what this project is about.
There are two channels. Control is TCP and carries one JSON object per line.
Data is UDP and carries exactly the packets packet.py builds, unchanged.
Control, on TCP 8422
client {"msg": "hello", "challenge": "A-sr", "student": "tremaux"}
server {"msg": "session", "challenge": "A-sr", "student": "tremaux",
"udp_port": 8500, "bytes": 24000, "seconds": 90,
"send": "the payload from payload_for(student), 24000 bytes"}
client {"msg": "ready", "udp_port": 51234}
... the UDP transfer happens ...
server {"msg": "result", "ok": true, "challenge": "A-sr",
"flag": "CS4220-RT-A-sr-...", "detail": {...}}
challenge is one of A-gbn, A-sr, B-gbn, B-sr. student is your UCCS
username in lowercase: it decides which payload you are asked for and which
flag you get back, so a capture of someone else's session is no use to you.
udp_port in the session message is the port on the server to send to.
udp_port in the ready message is the port your own socket is bound to,
so the server knows where to send. Send ready only once your socket exists,
because the server starts the moment it arrives.
On a refusal the server answers {"msg": "error", "detail": "..."} and closes.
On a challenge that ran but did not complete it answers {"msg": "result", "ok": false, "reason": "...", "detail": {...}}. The reason is written to be
useful: it says what the server saw, not just that you failed.
Data, on UDP
Exactly packet.py, with no additions:
| type | seq means | |
|---|---|---|
| 0 | DATA |
which packet this is, from 0 |
| 1 | ACK |
cumulative for -gbn ("I have everything before seq"), individual for -sr ("I have seq") |
| 2 | FIN |
how many data packets the sender sent |
| 3 | FINACK |
the receiver has everything and is closing |
Two things to know:
- A FINACK may carry a payload.
packet.pyhas always allowed it and nothing else in this project uses it. In challenge A the server puts your flag there, so the flag arrives in band, on the data channel, as well as on the control channel.challenge.pykeeps it for you and prints it in the trace asfinack_payload. - The path is deliberately awkward. The server drops about 5% of what it
sends, duplicates about 3%, and holds about 5% back to arrive late. This is
the same set of impairments
channel.pysimulates offline, so a protocol that passesselfcheck.pyshould survive it. The seed comes from your student id, so your run is reproducible if you want to dispute a result.
What the server is, and is not
It is a correct implementation of the receiver and the sender for both
protocols, written from P&D 2.5 and not from your code. That is the whole point
of Stage 2: selfcheck.py tests your sender against your receiver, and two
halves written by the same person can agree with each other about a mistake.
It is not a grader. It does not see your source, and it has no opinion about your style. It answers one question: does your half interoperate with a half you did not write?