Skip to content

Instantly share code, notes, and snippets.

@schmichael
Last active December 25, 2015 20:28
Show Gist options
  • Save schmichael/7034672 to your computer and use it in GitHub Desktop.
Save schmichael/7034672 to your computer and use it in GitHub Desktop.

Original gist: https://gist.github.com/schmichael/7034672

Whispering Gophers

See: http://whispering-gophers.appspot.com/talk.slide#1 via

{
    "ID": "<unique string>",
    "Addr": "<IP:Port of sender>",
    "Body": "<the actual message to display>"
}

Basic protocol:

  • Manually connect to at least 1 peer; connect to new peers seen in Addr fields
  • Accept connections from any peer
  • Broadcast all messages to all peers (except Addr); store list of Seen messages by ID to avoid rebroadcasting
  • Output non-local messages to stdout; send messages from stdin
  • Payloads without a Body and/or with unknown keys should be silently ignored to support extensions

Stretch goals:

Roughly ordered based on difficulty.

  1. Drop old messages - requires Timestamp field
  2. Forget old messages (the basic daemon slowly uses all memory) - may use Timestamp field - see below
  3. Base ID on hash of Addr + Body + Timestamp - see below
  4. Discover based on UDP broadcasts See below
  5. Build web interface into daemon
  6. Simple input form (textbox + submit button)
  7. Chat output (refreshed on a timer or using websockets if you're really fancy)
  8. Peer connection controls (connect to a new host, disconnect from a host)
  9. File transfers - see below
  10. Send backlog to newly connected peers - see backlog below
  11. Flood control: Disconnect and blacklist peers whose activity exceeds a threshold
  12. PKI all the things
  13. Scalable routing

UDP Broadcast Protocol

Broadcasts should be of the form: ":" and may be sent on behalf of any peers.

Timestamp field

To support various features, messages should include an optional Timestamp field of the format milliseconds since UNIX epoch as a number. For example:

{
    "ID": "abc123",
    "Addr": "192.168.1.53:2345",
    "Body": "Hello world!",
    "Timestamp": 1382050782085
}

Hashed ID field

To support very rudimentary payload verification, use a hash of the concatenated Addr, Body, and Timestamp fields. To allow backward compatibility with old clients, hashed IDs should be of the form:

{
    "ID": "hash:sha256:<hash>",
    ...
}

Where each string starts with "hash:" followed by the name of the hash function used, followed by a colon and the hex encoded hash.

Unknown hash functions should cause the reader to revert to the basic random-string-ID behavior.

Peers should drop messages whose hashes don't match the current message payload.

File transfers

Two new keys: "FileType" and "FileContents"

  • FileType should be the MIME type like: "image/gif"
  • FileContents should be the Base64 encoded file contents

Backlog

Upon receiving a new connection from a peer, a daemon should replay that peer the last N messages (the actual number shouldn't be important) to the peer.

Next?

  • Make protocol newline delimited. Golang's Decoder makes it quick and easy to get up and running quickly, but it also makes lots of common error cases impossible to handle. Breaking change.
  • Define whether Addrs (the sender's address) should be ephemeral or persistent. Seemed like most implementations had ephemeral conenctions for sending which breaks the peer autodetection.
  • Gavin's UDP broadcast feature is another fix for this, but ephemeral clients are still troublesome.
  • Polyglot hack night?
@justinbarry
Copy link

With our network up could we could trade develop our own cyber currency. It could present some fun problems to work on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment