@ -24,7 +24,6 @@ type Client struct {
serverKey key . Public // of the DERP server; not a machine or node key
serverKey key . Public // of the DERP server; not a machine or node key
privateKey key . Private
privateKey key . Private
publicKey key . Public // of privateKey
publicKey key . Public // of privateKey
protoVersion int // min of server+client
logf logger . Logf
logf logger . Logf
nc Conn
nc Conn
br * bufio . Reader
br * bufio . Reader
@ -85,11 +84,6 @@ func newClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logg
if err := c . sendClientKey ( ) ; err != nil {
if err := c . sendClientKey ( ) ; err != nil {
return nil , fmt . Errorf ( "derp.Client: failed to send client key: %v" , err )
return nil , fmt . Errorf ( "derp.Client: failed to send client key: %v" , err )
}
}
info , err := c . recvServerInfo ( )
if err != nil {
return nil , fmt . Errorf ( "derp.Client: failed to receive server info: %v" , err )
}
c . protoVersion = minInt ( protocolVersion , info . Version )
return c , nil
return c , nil
}
}
@ -110,12 +104,9 @@ func (c *Client) recvServerKey() error {
return nil
return nil
}
}
func ( c * Client ) recvServerInfo ( ) ( * serverInfo , error ) {
func ( c * Client ) parseServerInfo ( b [ ] byte ) ( * serverInfo , error ) {
fl , err := readFrameTypeHeader ( c . br , frameServerInfo )
if err != nil {
return nil , err
}
const maxLength = nonceLen + maxInfoLen
const maxLength = nonceLen + maxInfoLen
fl := len ( b )
if fl < nonceLen {
if fl < nonceLen {
return nil , fmt . Errorf ( "short serverInfo frame" )
return nil , fmt . Errorf ( "short serverInfo frame" )
}
}
@ -124,21 +115,15 @@ func (c *Client) recvServerInfo() (*serverInfo, error) {
}
}
// TODO: add a read-nonce-and-box helper
// TODO: add a read-nonce-and-box helper
var nonce [ nonceLen ] byte
var nonce [ nonceLen ] byte
if _ , err := io . ReadFull ( c . br , nonce [ : ] ) ; err != nil {
copy ( nonce [ : ] , b )
return nil , fmt . Errorf ( "nonce: %v" , err )
msgbox := b [ nonceLen : ]
}
msgLen := fl - nonceLen
msgbox := make ( [ ] byte , msgLen )
if _ , err := io . ReadFull ( c . br , msgbox ) ; err != nil {
return nil , fmt . Errorf ( "msgbox: %v" , err )
}
msg , ok := box . Open ( nil , msgbox , & nonce , c . serverKey . B32 ( ) , c . privateKey . B32 ( ) )
msg , ok := box . Open ( nil , msgbox , & nonce , c . serverKey . B32 ( ) , c . privateKey . B32 ( ) )
if ! ok {
if ! ok {
return nil , fmt . Errorf ( " msgbox: cannot open len=%d with server key %x", msgLen , c . serverKey [ : ] )
return nil , fmt . Errorf ( "failed to open naclbox from server key %x" , c . serverKey [ : ] )
}
}
info := new ( serverInfo )
info := new ( serverInfo )
if err := json . Unmarshal ( msg , info ) ; err != nil {
if err := json . Unmarshal ( msg , info ) ; err != nil {
return nil , fmt . Errorf ( " msg : %v", err )
return nil , fmt . Errorf ( " invalid JSON : %v", err )
}
}
return info , nil
return info , nil
}
}
@ -318,6 +303,11 @@ type PeerPresentMessage key.Public
func ( PeerPresentMessage ) msg ( ) { }
func ( PeerPresentMessage ) msg ( ) { }
// ServerInfoMessage is sent by the server upon first connect.
type ServerInfoMessage struct { }
func ( ServerInfoMessage ) msg ( ) { }
// Recv reads a message from the DERP server.
// Recv reads a message from the DERP server.
//
//
// The returned message may alias memory owned by the Client; it
// The returned message may alias memory owned by the Client; it
@ -364,7 +354,7 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
// If the frame fits in our bufio.Reader buffer, just use it.
// If the frame fits in our bufio.Reader buffer, just use it.
// In practice it's 4KB (from derphttp.Client's bufio.NewReader(httpConn)) and
// In practice it's 4KB (from derphttp.Client's bufio.NewReader(httpConn)) and
// in practive, WireGuard packets (and thus DERP frames) are under 1.5KB.
// in practive, WireGuard packets (and thus DERP frames) are under 1.5KB.
// So T his is the common path.
// So t his is the common path.
if int ( n ) <= c . br . Size ( ) {
if int ( n ) <= c . br . Size ( ) {
b , err = c . br . Peek ( int ( n ) )
b , err = c . br . Peek ( int ( n ) )
c . peeked = int ( n )
c . peeked = int ( n )
@ -382,6 +372,19 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
switch t {
switch t {
default :
default :
continue
continue
case frameServerInfo :
// Server sends this at start-up. Currently unused.
// Just has a JSON message saying "version: 2",
// but the protocol seems extensible enough as-is without
// needing to wait an RTT to discover the version at startup.
// We'd prefer to give the connection to the client (magicsock)
// to start writing as soon as possible.
_ , err := c . parseServerInfo ( b )
if err != nil {
return nil , fmt . Errorf ( "invalid server info frame: %v" , err )
}
// TODO: add the results of parseServerInfo to ServerInfoMessage if we ever need it.
return ServerInfoMessage { } , nil
case frameKeepAlive :
case frameKeepAlive :
// TODO: eventually we'll have server->client pings that
// TODO: eventually we'll have server->client pings that
// require ack pongs.
// require ack pongs.
@ -406,16 +409,12 @@ func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err erro
case frameRecvPacket :
case frameRecvPacket :
var rp ReceivedPacket
var rp ReceivedPacket
if c . protoVersion < protocolSrcAddrs {
rp . Data = b [ : n ]
} else {
if n < keyLen {
if n < keyLen {
c . logf ( "[unexpected] dropping short packet from DERP server" )
c . logf ( "[unexpected] dropping short packet from DERP server" )
continue
continue
}
}
copy ( rp . Source [ : ] , b [ : keyLen ] )
copy ( rp . Source [ : ] , b [ : keyLen ] )
rp . Data = b [ keyLen : n ]
rp . Data = b [ keyLen : n ]
}
return rp , nil
return rp , nil
}
}
}
}