diff --git a/p2p/README.md b/p2p/README.md
index 94419848..941c93ee 100644
--- a/p2p/README.md
+++ b/p2p/README.md
@@ -1,35 +1,77 @@
-# P2P Module
+# `tendermint/p2p`
-P2P provides an abstraction around peer-to-peer communication.
-Communication happens via Reactors that react to messages from peers.
-Each Reactor has one or more Channels of communication for each Peer.
-Channels are multiplexed automatically and can be configured.
-A Switch is started upon app start, and handles Peer management.
-A PEXReactor implementation is provided to automate peer discovery.
+`tendermint/p2p` provides an abstraction around peer-to-peer communication.
-## Channels
+## Peer/MConnection/Channel
-Each peer connection is multiplexed into channels.
-The p2p module comes with a channel implementation used for peer
-discovery (called PEX, short for "peer exchange").
+Each peer has one `MConnection` (multiplex connection) instance.
-
-
- Channel |
- "PEX" |
-
-
- Messages |
-
-
- - pexRequestMsg
- - pexResponseMsg
-
- |
-
-
-
+__multiplex__ *noun* a system or signal involving simultaneous transmission of
+several messages along a single channel of communication.
-## Resources
+Each `MConnection` handles message transmission on multiple abstract communication
+`Channel`s. Each channel has a globally unique byte id.
+The byte id and the relative priorities of each `Channel` are configured upon
+initialization of the connection.
-* http://www.upnp-hacks.org/upnp.html
+There are two methods for sending messages:
+```go
+func (m MConnection) Send(chId byte, msg interface{}) bool {}
+func (m MConnection) TrySend(chId byte, msg interface{}) bool {}
+```
+
+`Send(chId, msg)` is a blocking call that waits until `msg` is successfully queued
+for the channel with the given id byte `chId`. The message `msg` is serialized
+using the `tendermint/binary` submodule's `WriteBinary()` reflection routine.
+
+`TrySend(chId, msg)` is a nonblocking call that returns false if the channel's
+queue is full.
+
+`Send()` and `TrySend()` are also exposed for each `Peer`.
+
+## Switch/Reactor
+
+The `Switch` handles peer connections and exposes an API to receive incoming messages
+on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one
+or more `Channels`. So while sending outgoing messages is typically performed on the peer,
+incoming messages are received on the reactor.
+
+```go
+// Declare a MyReactor reactor that handles messages on MyChannelId.
+type MyReactor struct{}
+
+func (reactor MyReactor) GetChannels() []*ChannelDescriptor {
+ return []*ChannelDescriptor{ChannelDescriptor{Id:MyChannelId, Priority: 1}}
+}
+
+func (reactor MyReactor) Receive(chId byte, peer *Peer, msgBytes []byte) {
+ r, n, err := bytes.NewBuffer(msgBytes), new(int64), new(error)
+ msgString := ReadString(r, n, err)
+ fmt.Println(msgString)
+}
+
+// Other Reactor methods omitted for brevity
+...
+
+switch := NewSwitch([]Reactor{MyReactor{}})
+
+...
+
+// Send a random message to all outbound connections
+for _, peer := range switch.Peers().List() {
+ if peer.IsOutbound() {
+ peer.Send(MyChannelId, "Here's a random message")
+ }
+}
+```
+
+### PexReactor/AddrBook
+
+A `PEXReactor` reactor implementation is provided to automate peer discovery.
+
+```go
+book := p2p.NewAddrBook(config.AddrBookFile())
+pexReactor := p2p.NewPEXReactor(book)
+...
+switch := NewSwitch([]Reactor{pexReactor, myReactor, ...})
+```
diff --git a/p2p/connection.go b/p2p/connection.go
index ccc16447..607f9120 100644
--- a/p2p/connection.go
+++ b/p2p/connection.go
@@ -34,8 +34,27 @@ type receiveCbFunc func(chId byte, msgBytes []byte)
type errorCbFunc func(interface{})
/*
-A MConnection wraps a network connection and handles buffering and multiplexing.
-