Skip to content
Peer Handshake
step 1/5

Reading — step 1 of 5

Read

~3 min readPeer Wire Protocol

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:

OffsetSizeFieldValue
01pstrlen19 (0x13)
1–1919pstrBitTorrent protocol
20–278reservedextension bits (all zero for a vanilla client)
28–4720info_hashwhich torrent this connection is about
48–6720peer_idwho 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:

  1. peer_id padding. -qB4500-abc1234567 is 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 exactly ERR peer_id too long.
  2. 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.
  3. Printing the padding. The hidden test's peer_id is shortpid plus twelve zero bytes; the expected output is OK 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…