Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🕳️ PulseTP

Packets carry no data. The silence between them does.

Go >=1.24 Transport: UDP Encoding: Timing License: MIT

📡 UDP · ⏱️ gap-encoded bits · 🎛️ self-calibrating · 🐹 pure Go


PulseTP is a rhythm-based network protocol: Morse code for sockets. A sender fires nearly-empty UDP packets at a receiver; the packets themselves say almost nothing. What actually carries the message is the silence between one packet and the next: a short gap means one bit, a long gap means the other. The receiver listens to the rhythm, not the payload, and taps the message back out.

PulseTP demo: pulsetp listen calibrating against the preamble, then decoding a live rhythm of cyan and pink pulses into the message 'This is PulseTP'

🎼 What's inside

  • Rhythm is the payload, gaps between packets encode bits, not packet contents. Each pulse is a 15-byte struct with a sequence number and a timestamp, nothing more.
  • No header, just a sync tone: the first 8 pulses form a known, fixed-rhythm preamble, like a modem handshake, so the receiver can calibrate before real data starts.
  • Self-calibrating, not hardcoded: the receiver measures actual short/long gap timing off the preamble and derives its own threshold and jitter tolerance, so it adapts to whatever the real network looks like.
  • Silence is the terminator: there's no end-of-message packet. The sender just stops, and a long enough pause tells the receiver the message is complete.
  • A CLI worth watching: pulsetp listen renders the incoming rhythm live, colored dot by dot, with the decoded message filling in as bytes assemble.
  • Files work too: --file on send and --output on listen transmit and save raw bytes instead of text, at exactly the same (deliberately slow) bits-per-second as everything else.
  • Optional encryption: by default anyone watching the timing can decode a message as easily as the real receiver, --key on both ends (AES-256-GCM, scrypt-derived) fixes that. See docs/PROTOCOL.md for exactly what it does and doesn't protect against.
  • Optional repetition coding: --repeat N (odd, both ends must match) sends each data bit as N gaps instead of one, and the receiver takes a majority vote, tolerating an occasional jitter-induced misclassification at the cost of a slower transfer.

🚀 Get it running

macOS/Linux:

git clone https://github.com/MAXIVA11/PulseTP.git
cd PulseTP
go build -o bin/pulsetp ./cmd/pulsetp
./bin/pulsetp listen --port 9000        # terminal 1
./bin/pulsetp send --to localhost:9000 --message "hello"   # terminal 2

Windows (PowerShell or cmd.exe):

git clone https://github.com/MAXIVA11/PulseTP.git
cd PulseTP
go build -o bin\pulsetp.exe .\cmd\pulsetp
bin\pulsetp.exe listen --port 9000
bin\pulsetp.exe send --to localhost:9000 --message "hello"

Watch the rhythm arrive, and the message appear.

🔍 Don't take our word for it

Real capture, real Wireshark: 129 packets of "This is PulseTP" on the left, and what Follow UDP Stream sees when it tries to reassemble them into a message on the right.

Wireshark showing captured PulseTP packets on the left and the Follow UDP Stream panel on the right, containing nothing but repeating 'PT' magic bytes and noise, no trace of the message

Just noise and a repeating "PT" tag. The message was never in the packets.

🧠 Curious how the timing actually works?

The full wire format, calibration math, and receiver state machine, the mini-RFC behind all of this, lives in docs/PROTOCOL.md.


MIT License, built for messages that would rather be heard than read

About

A rhythm-based network protocol: the timing between UDP packets is the payload, not their contents.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages