]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/client/udp.go
Upgrade Client
[govpn.git] / src / cypherpunks.ru / govpn / client / udp.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package client
20
21 import (
22         "net"
23         "sync/atomic"
24         "time"
25
26         "github.com/pkg/errors"
27
28         "cypherpunks.ru/govpn"
29 )
30
31 func (c *Client) startUDP() {
32         l := c.logger.WithField("func", "startUDP")
33
34         // TODO move resolution into the loop, as the name might change over time
35         l.Debug("Resolve UDP address")
36         remote, err := net.ResolveUDPAddr("udp", c.config.RemoteAddress)
37         if err != nil {
38                 c.Error <- errors.Wrapf(err, "net.ResolveUDPAddr %s", c.config.RemoteAddress)
39                 return
40         }
41         l.WithField("remote", remote.String()).Debug("dial")
42         conn, err := net.DialUDP("udp", nil, remote)
43         if err != nil {
44                 c.Error <- errors.Wrapf(err, "net.DialUDP %s", c.config.RemoteAddress)
45                 return
46         }
47         l.WithFields(c.config.LogFields()).Info("Connected")
48
49         l.Debug("Handshake start")
50         hs, err := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
51         if err != nil {
52                 govpn.CloseLog(conn, c.logger, c.LogFields())
53                 c.Error <- errors.Wrap(err, "govpn.HandshakeStart")
54                 return
55         }
56         l.Debug("Handshake done")
57
58         buf := make([]byte, c.config.Peer.MTU*2)
59         var n int
60         var timeouts int
61         var peer *govpn.Peer
62         var deadLine time.Time
63         var terminator chan struct{}
64         timeout := int(c.config.Peer.Timeout.Seconds())
65         l.Debug("Main cycle")
66
67 MainCycle:
68         for {
69                 select {
70                 case <-c.termination:
71                         break MainCycle
72                 default:
73                 }
74
75                 deadLine = time.Now().Add(time.Second)
76                 if err = conn.SetReadDeadline(deadLine); err != nil {
77                         c.Error <- errors.Wrapf(err, "conn.SetReadDeadline %s", deadLine.String())
78                         break MainCycle
79                 }
80                 l.Debug("conn.Read")
81                 n, err = conn.Read(buf)
82                 if timeouts >= timeout {
83                         l.WithFields(c.LogFields()).Debug("Connection timeouted")
84                         c.timeouted <- struct{}{}
85                         break
86                 }
87                 if err != nil {
88                         l.WithError(err).WithFields(c.LogFields()).Debug("Can't read from connection")
89                         timeouts++
90                         continue
91                 }
92                 if peer != nil {
93                         c.logger.WithFields(c.LogFields()).Debug("No peer yet, process packet")
94                         if peer.PktProcess(buf[:n], c.tap, true) {
95                                 l.WithFields(c.LogFields()).Debug("Packet processed")
96                                 timeouts = 0
97                         } else {
98                                 l.WithFields(c.LogFields()).Debug("Packet unauthenticated")
99                                 timeouts++
100                         }
101                         if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
102                                 l.WithFields(c.LogFields()).Debug("Rehandshake required")
103                                 c.rehandshaking <- struct{}{}
104                                 break MainCycle
105                         }
106                         continue
107                 }
108                 if _, err = c.idsCache.Find(buf[:n]); err != nil {
109                         l.WithError(err).WithFields(c.LogFields()).Debug("Identity invalid")
110                         continue
111                 }
112                 timeouts = 0
113                 peer, err = hs.Client(buf[:n])
114                 if err != nil {
115                         c.Error <- errors.Wrap(err, "hs.Client")
116                         continue
117                 }
118                 // no error, but handshake not yet completed
119                 if peer == nil {
120                         continue
121                 }
122                 l.WithFields(c.LogFields()).Info("Handshake completed")
123                 c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
124                 if err = c.postUpAction(); err != nil {
125                         c.Error <- errors.Wrap(err, "c.postUpAction")
126                         continue
127                 }
128                 hs.Zero()
129                 terminator = make(chan struct{})
130                 go govpn.PeerTapProcessor(peer, c.tap, terminator)
131         }
132         if terminator != nil {
133                 terminator <- struct{}{}
134         }
135         if hs != nil {
136                 hs.Zero()
137         }
138         if err = conn.Close(); err != nil {
139                 c.Error <- errors.Wrap(err, "conn.Close")
140         }
141         if err = c.tap.Close(); err != nil {
142                 c.Error <- errors.Wrap(err, logFuncPrefix+"Client.tap.Close")
143         }
144 }