Issues with the previous scheme... When we have just encountered an EMSGSIZE, the odds of encountering another one straight away, when attemtping to send a verification packet with the lower mtu, are slim, since for a new, lower mtu to be set some packet must have made it further then the one that triggered the icmp3.4 that gave rise to the EMSGSIZE, and we must have received the resulting icmp3.4. All of which takes time. Also, sending a bunch of udp packets in rapid succession is not a great way to improve their chances of making it through to the other peer, since they could easily all get dropped by a single congestion event or other network glitch. Now we send a single verification packet, wait for a short while, and if we don't get a response then we send another one, wait for longer period (2x), etc, until some upper bound is reached, at which point we lower the pmtu and start the verification process again (same as currently happens). We are now also calling flush() to send the verification packet, just as we do for ordinary packets. This makes for shorter code, consistent error handling, and introduces a nice little recursion :)
305 lines
5.6 KiB
Go
305 lines
5.6 KiB
Go
package weave
|
|
|
|
import (
|
|
"bytes"
|
|
"code.google.com/p/go-bit/bit"
|
|
"code.google.com/p/gopacket"
|
|
"code.google.com/p/gopacket/layers"
|
|
"encoding/gob"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Router struct {
|
|
Ourself *Peer
|
|
Iface *net.Interface
|
|
PeersSubscribeChan chan<- chan<- map[string]Peer
|
|
Macs *MacCache
|
|
Peers *PeerCache
|
|
UDPListener *net.UDPConn
|
|
Topology *Topology
|
|
ConnectionMaker *ConnectionMaker
|
|
Password *[]byte
|
|
ConnLimit int
|
|
BufSz int
|
|
LogFrame func(string, []byte, *layers.Ethernet)
|
|
}
|
|
|
|
type Peer struct {
|
|
sync.RWMutex
|
|
Name PeerName
|
|
NameByte []byte
|
|
connections map[PeerName]Connection
|
|
version uint64
|
|
UID uint64
|
|
Router *Router
|
|
localRefCount uint64
|
|
queryChan chan<- *PeerInteraction
|
|
}
|
|
|
|
type PeerInteraction struct {
|
|
Interaction
|
|
payload interface{}
|
|
}
|
|
|
|
type Connection interface {
|
|
Local() *Peer
|
|
Remote() *Peer
|
|
RemoteTCPAddr() string
|
|
Established() bool
|
|
Shutdown()
|
|
}
|
|
|
|
type RemoteConnection struct {
|
|
local *Peer
|
|
remote *Peer
|
|
remoteTCPAddr string
|
|
}
|
|
|
|
type LocalConnection struct {
|
|
sync.RWMutex
|
|
RemoteConnection
|
|
TCPConn *net.TCPConn
|
|
tcpSender TCPSender
|
|
remoteUDPAddr *net.UDPAddr
|
|
established bool
|
|
stackFrag bool
|
|
effectivePMTU int
|
|
pmtuVerified bool
|
|
SessionKey *[32]byte
|
|
heartbeatStop chan<- interface{}
|
|
forwardChan chan<- *ForwardedFrame
|
|
forwardChanDF chan<- *ForwardedFrame
|
|
stopForward chan<- interface{}
|
|
stopForwardDF chan<- interface{}
|
|
Decryptor Decryptor
|
|
Router *Router
|
|
UID uint64
|
|
shutdown bool
|
|
queryChan chan<- *ConnectionInteraction
|
|
}
|
|
|
|
type ConnectionInteraction struct {
|
|
Interaction
|
|
payload interface{}
|
|
}
|
|
|
|
type Forwarder struct {
|
|
conn *LocalConnection
|
|
ch <-chan *ForwardedFrame
|
|
stop <-chan interface{}
|
|
pmtuVerifyTick <-chan time.Time
|
|
pmtuVerifyCount uint
|
|
enc Encryptor
|
|
udpSender UDPSender
|
|
maxPayload int
|
|
effectivePMTU int
|
|
}
|
|
|
|
type UDPPacket struct {
|
|
Name PeerName
|
|
Packet []byte
|
|
Sender *net.UDPAddr
|
|
}
|
|
|
|
type EthernetDecoder struct {
|
|
eth layers.Ethernet
|
|
ip layers.IPv4
|
|
decoded []gopacket.LayerType
|
|
parser *gopacket.DecodingLayerParser
|
|
}
|
|
|
|
type MsgTooBigError struct {
|
|
PMTU int // actual pmtu, i.e. what the kernel told us
|
|
}
|
|
|
|
type FrameTooBigError struct {
|
|
EPMTU int // effective pmtu, i.e. what we tell packet senders
|
|
}
|
|
|
|
type UnknownPeersError struct {
|
|
}
|
|
|
|
type NameCollisionError struct {
|
|
Name PeerName
|
|
}
|
|
|
|
type LocalAddress struct {
|
|
ip net.IP
|
|
network *net.IPNet
|
|
}
|
|
|
|
type ForwardedFrame struct {
|
|
srcPeer *Peer
|
|
dstPeer *Peer
|
|
frame []byte
|
|
}
|
|
|
|
type Interaction struct {
|
|
code int
|
|
resultChan chan<- interface{}
|
|
}
|
|
|
|
type Topology struct {
|
|
sync.RWMutex
|
|
queryChan chan<- *Interaction
|
|
unicast map[PeerName]PeerName
|
|
broadcast map[PeerName][]PeerName
|
|
router *Router
|
|
}
|
|
|
|
type ConnectionMakerInteraction struct {
|
|
Interaction
|
|
foundAt string
|
|
name PeerName
|
|
}
|
|
|
|
type ConnectionMaker struct {
|
|
router *Router
|
|
queryChan chan<- *ConnectionMakerInteraction
|
|
activeConnections map[string]string
|
|
failedConnections map[PeerName]*FailedConnection
|
|
}
|
|
|
|
type FailedConnection struct {
|
|
foundAt map[string]bool
|
|
tryAfter time.Time
|
|
tryInterval time.Duration
|
|
attemptCount int
|
|
}
|
|
|
|
// UDPSender interface and implementations
|
|
|
|
type UDPSender interface {
|
|
Send([]byte) error
|
|
Shutdown() error
|
|
}
|
|
|
|
type SimpleUDPSender struct {
|
|
conn *LocalConnection
|
|
udpConn *net.UDPConn
|
|
}
|
|
|
|
type RawUDPSender struct {
|
|
ipBuf gopacket.SerializeBuffer
|
|
opts gopacket.SerializeOptions
|
|
udpHeader *layers.UDP
|
|
socket *net.IPConn
|
|
conn *LocalConnection
|
|
}
|
|
|
|
// TCPSender interface and implementations
|
|
|
|
type TCPSender interface {
|
|
Send([]byte) error
|
|
}
|
|
|
|
type SimpleTCPSender struct {
|
|
encoder *gob.Encoder
|
|
}
|
|
|
|
type EncryptedTCPSender struct {
|
|
sync.RWMutex
|
|
outerEncoder *gob.Encoder
|
|
innerEncoder *gob.Encoder
|
|
buffer *bytes.Buffer
|
|
conn *LocalConnection
|
|
msgCount int
|
|
}
|
|
|
|
type EncryptedTCPMessage struct {
|
|
Number int
|
|
Body []byte
|
|
}
|
|
|
|
// TCPReceiver interface and implementations
|
|
|
|
type TCPReceiver interface {
|
|
Decode([]byte) ([]byte, error)
|
|
}
|
|
|
|
type SimpleTCPReceiver struct {
|
|
}
|
|
|
|
type EncryptedTCPReceiver struct {
|
|
conn *LocalConnection
|
|
decoder *gob.Decoder
|
|
buffer *bytes.Buffer
|
|
msgCount int
|
|
}
|
|
|
|
// Encryptor interface and implementations
|
|
|
|
type Encryptor interface {
|
|
FrameOverhead() int
|
|
PacketOverhead() int
|
|
IsEmpty() bool
|
|
Bytes() []byte
|
|
AppendFrame(*ForwardedFrame)
|
|
TotalLen() int
|
|
}
|
|
|
|
type NonEncryptor struct {
|
|
buf []byte
|
|
bufTail []byte
|
|
buffered int
|
|
prefixLen int
|
|
}
|
|
|
|
type NaClEncryptor struct {
|
|
NonEncryptor
|
|
buf []byte
|
|
offset uint16
|
|
nonce *[24]byte
|
|
nonceChan chan *[24]byte
|
|
flags uint16
|
|
prefixLen int
|
|
conn *LocalConnection
|
|
df bool
|
|
}
|
|
|
|
// Decryptor interface and implementations
|
|
|
|
type FrameConsumer func(*LocalConnection, *net.UDPAddr, []byte, []byte, uint16, []byte) error
|
|
|
|
type Decryptor interface {
|
|
IterateFrames(FrameConsumer, *UDPPacket) error
|
|
ReceiveNonce([]byte)
|
|
Shutdown()
|
|
}
|
|
|
|
type NonDecryptor struct {
|
|
conn *LocalConnection
|
|
}
|
|
|
|
type NaClDecryptor struct {
|
|
NonDecryptor
|
|
instance *NaClDecryptorInstance
|
|
instanceDF *NaClDecryptorInstance
|
|
}
|
|
|
|
type NaClDecryptorInstance struct {
|
|
nonce *[24]byte
|
|
previousNonce *[24]byte
|
|
usedOffsets *bit.Set
|
|
previousUsedOffsets *bit.Set
|
|
highestOffsetSeen uint16
|
|
nonceChan chan *[24]byte
|
|
}
|
|
|
|
// Packet capture/inject interfaces
|
|
|
|
type PacketSource interface {
|
|
ReadPacket() ([]byte, error)
|
|
}
|
|
|
|
type PacketSink interface {
|
|
WritePacket([]byte) error
|
|
}
|
|
|
|
type PacketSourceSink interface {
|
|
PacketSource
|
|
PacketSink
|
|
}
|