/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
package client
import (
- "fmt"
"net"
"sync/atomic"
"time"
+ "github.com/pkg/errors"
+
"cypherpunks.ru/govpn"
)
func (c *Client) startUDP() {
+ l := c.logger.WithField("func", "startUDP")
+
+ // TODO move resolution into the loop, as the name might change over time
+ l.Debug("Resolve UDP address")
remote, err := net.ResolveUDPAddr("udp", c.config.RemoteAddress)
if err != nil {
- c.Error <- fmt.Errorf("Can not resolve remote address: %s", err)
+ c.Error <- errors.Wrapf(err, "net.ResolveUDPAddr %s", c.config.RemoteAddress)
return
}
+ l.WithField("remote", remote.String()).Debug("dial")
conn, err := net.DialUDP("udp", nil, remote)
if err != nil {
- c.Error <- fmt.Errorf("Can not connect remote address: %s", err)
+ c.Error <- errors.Wrapf(err, "net.DialUDP %s", c.config.RemoteAddress)
+ return
+ }
+ l.WithFields(c.config.LogFields()).Info("Connected")
+
+ l.Debug("Handshake start")
+ hs, err := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
+ if err != nil {
+ govpn.CloseLog(conn, c.logger, c.LogFields())
+ c.Error <- errors.Wrap(err, "govpn.HandshakeStart")
return
}
- govpn.Printf(`[connected remote="%s"]`, c.config.RemoteAddress)
+ l.Debug("Handshake done")
- hs := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
- buf := make([]byte, c.config.MTU*2)
+ buf := make([]byte, c.config.Peer.MTU*2)
var n int
var timeouts int
var peer *govpn.Peer
+ var deadLine time.Time
var terminator chan struct{}
timeout := int(c.config.Peer.Timeout.Seconds())
+ l.Debug("Main cycle")
+
MainCycle:
for {
select {
default:
}
- if err = conn.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
- c.Error <- err
+ deadLine = time.Now().Add(time.Second)
+ if err = conn.SetReadDeadline(deadLine); err != nil {
+ c.Error <- errors.Wrapf(err, "conn.SetReadDeadline %s", deadLine.String())
break MainCycle
}
+ l.Debug("conn.Read")
n, err = conn.Read(buf)
- if timeouts == timeout {
- govpn.Printf(`[connection-timeouted remote="%s"]`, c.config.RemoteAddress)
+ if timeouts >= timeout {
+ l.WithFields(c.LogFields()).Debug("Connection timeouted")
c.timeouted <- struct{}{}
break
}
if err != nil {
+ l.WithError(err).WithFields(c.LogFields()).Debug("Can't read from connection")
timeouts++
continue
}
if peer != nil {
+ c.logger.WithFields(c.LogFields()).Debug("No peer yet, process packet")
if peer.PktProcess(buf[:n], c.tap, true) {
+ l.WithFields(c.LogFields()).Debug("Packet processed")
timeouts = 0
} else {
- govpn.Printf(`[packet-unauthenticated remote="%s"]`, c.config.RemoteAddress)
+ l.WithFields(c.LogFields()).Debug("Packet unauthenticated")
timeouts++
}
if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
- govpn.Printf(`[rehandshake-required remote="%s"]`, c.config.RemoteAddress)
+ l.WithFields(c.LogFields()).Debug("Rehandshake required")
c.rehandshaking <- struct{}{}
break MainCycle
}
continue
}
- if c.idsCache.Find(buf[:n]) == nil {
- govpn.Printf(`[identity-invalid remote="%s"]`, c.config.RemoteAddress)
+ if _, err = c.idsCache.Find(buf[:n]); err != nil {
+ l.WithError(err).WithFields(c.LogFields()).Debug("Identity invalid")
continue
}
timeouts = 0
- peer = hs.Client(buf[:n])
+ peer, err = hs.Client(buf[:n])
+ if err != nil {
+ c.Error <- errors.Wrap(err, "hs.Client")
+ continue
+ }
+ // no error, but handshake not yet completed
if peer == nil {
continue
}
- govpn.Printf(`[handshake-completed remote="%s"]`, c.config.RemoteAddress)
+ l.WithFields(c.LogFields()).Info("Handshake completed")
c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
- if c.firstUpCall {
- go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress)
- c.firstUpCall = false
+ if err = c.postUpAction(); err != nil {
+ c.Error <- errors.Wrap(err, "c.postUpAction")
+ continue
}
hs.Zero()
terminator = make(chan struct{})
hs.Zero()
}
if err = conn.Close(); err != nil {
- c.Error <- err
+ c.Error <- errors.Wrap(err, "conn.Close")
+ }
+ if err = c.tap.Close(); err != nil {
+ c.Error <- errors.Wrap(err, logFuncPrefix+"Client.tap.Close")
}
}