# 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.py` has 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.py` keeps it for you and prints it in the trace as `finack_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.py` simulates offline, so a protocol that passes `selfcheck.py` should 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?