Reading — step 1 of 5
Read
Peer Handshake
The tracker hands you addresses; everything after that is peer-to-peer. You open a TCP connection (or uTP, the UDP-based transport) and the very first bytes each side sends are the handshake — the only message in the whole protocol without a length-prefixed frame. It is fixed at 68 bytes:
| Offset | Size | Field | Value |
|---|---|---|---|
| 0 | 1 | pstrlen | 19 (0x13) |
| 1–19 | 19 | pstr | BitTorrent protocol |
| 20–27 | 8 | reserved | extension bits (all zero for a vanilla client) |
| 28–47 | 20 | info_hash | which torrent this connection is about |
| 48–67 | 20 | peer_id | who you are |
1 + 19 + 8 + 20 + 20 = 68. The pstrlen/pstr pair doubles as a protocol magic: a stream that does not begin 0x13 + BitTorrent protocol is not a BitTorrent peer — close it.
The reserved bytes advertise optional capabilities, one bit each. The three you will actually meet:
- byte 5 & 0x10 — extension protocol (BEP 10), the hook that magnet metadata fetching (
ut_metadata) hangs off - byte 7 & 0x01 — DHT support (BEP 5)
- byte 7 & 0x04 — fast extension (BEP 6)
Why info_hash rides in the handshake
One client, one listening port, many torrents. The initiator states the infohash up front so the receiver can route the connection to the right torrent — and refuse it. If the info_hash names a torrent you do not serve, BEP 3 says sever the connection; there is no error reply. Both sides send their handshake immediately (the initiator does not wait for the other side), and each validates the other's info_hash the same way. The peer_id serves sanity checks: detecting a connection to yourself, or a peer whose id differs from what the tracker reported.
After the handshake
The framed protocol begins: every subsequent message carries a 4-byte length prefix. First comes an optional bitfield declaring which pieces the sender already has — optional, because a peer with zero pieces may (and usually does) skip it. Then the choke/interested negotiation decides who may download, and request/piece traffic starts. A choke is a polite "you get nothing from me right now" — BitTorrent's fairness mechanism, which gets its own lesson later.
Your exercise
BUILD a 68-byte handshake (printed as 136 hex chars) and VERIFY a received one. Mistakes the grader catches:
- peer_id padding.
-qB4500-abc1234567is 18 bytes: pad with zero bytes to exactly 20, so the expected hex ends...3536370000. Skip the padding and you print 132 hex chars — wrong. A peer_id longer than 20 bytes must print exactlyERR peer_id too long. - Off-by-one slicing in VERIFY. info_hash is bytes 28–47 (skip 1 + 19 + 8), peer_id is bytes 48–67. Slice from 27 or 29 and a perfectly good handshake reports a mismatch. The mismatch line must be formatted exactly like
MISMATCH expected=ffff... got=0102..., both values as full 40-char hex. - Printing the padding. The hidden test's peer_id is
shortpidplus twelve zero bytes; the expected output isOK peer_id=shortpid. Strip trailing NUL bytes before printing, or your line carries invisible garbage and fails the comparison.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…