]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/client/client.go
76635a88ec9a9e84e8b456e53943e4cc518a08da
[govpn.git] / src / cypherpunks.ru / govpn / client / client.go
1 package client
2
3 import (
4         "errors"
5         "fmt"
6         "net"
7         "os"
8         "time"
9
10         "github.com/agl/ed25519"
11
12         "cypherpunks.ru/govpn"
13 )
14
15 type Protocol uint8
16
17 const (
18         ProtocolUDP Protocol = iota
19         ProtocolTCP
20 )
21
22 type Configuration struct {
23         PrivateKey          *[ed25519.PrivateKeySize]byte
24         Peer                *govpn.PeerConf
25         Protocol            Protocol
26         InterfaceName       string
27         ProxyAddress        string
28         ProxyAuthentication string
29         RemoteAddress       string
30         UpPath              string
31         DownPath            string
32         StatsAddress        string
33         NoReconnect         bool
34         MTU                 int
35 }
36
37 func (c *Configuration) Validate() error {
38         if c.MTU > govpn.MTUMax {
39                 return fmt.Errorf("Invalid MTU %d, maximum allowable is %d", c.MTU, govpn.MTUMax)
40         }
41         if len(c.RemoteAddress) == 0 {
42                 return errors.New("Missing RemoteAddress")
43         }
44         if len(c.InterfaceName) == 0 {
45                 return errors.New("Missing InterfaceName")
46         }
47         return nil
48 }
49
50 func (c *Configuration) isProxy() bool {
51         return len(c.ProxyAddress) > 0
52 }
53
54 type Client struct {
55         idsCache      *govpn.MACCache
56         tap           *govpn.TAP
57         knownPeers    govpn.KnownPeers
58         statsPort     net.Listener
59         timeouted     chan struct{}
60         rehandshaking chan struct{}
61         termination   chan struct{}
62         firstUpCall   bool
63         termSignal    chan os.Signal
64         config        Configuration
65
66         // Error channel receives any kind of routine errors
67         Error chan error
68 }
69
70 func (c *Client) MainCycle() {
71         var err error
72         c.tap, err = govpn.TAPListen(c.config.InterfaceName, c.config.MTU)
73         if err != nil {
74                 c.Error <- fmt.Errorf("Can not listen on TUN/TAP interface: %s", err.Error())
75                 return
76         }
77
78         if len(c.config.StatsAddress) > 0 {
79                 c.statsPort, err = net.Listen("tcp", c.config.StatsAddress)
80                 if err != nil {
81                         c.Error <- fmt.Errorf("Can't listen on stats port: %s", err.Error())
82                         return
83                 }
84                 c.knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer))
85                 go govpn.StatsProcessor(c.statsPort, &c.knownPeers)
86         }
87
88 MainCycle:
89         for {
90                 c.timeouted = make(chan struct{})
91                 c.rehandshaking = make(chan struct{})
92                 c.termination = make(chan struct{})
93                 switch c.config.Protocol {
94                 case ProtocolUDP:
95                         go c.startUDP()
96                 case ProtocolTCP:
97                         if c.config.isProxy() {
98                                 go c.proxyTCP()
99                         } else {
100                                 go c.startTCP()
101                         }
102                 }
103                 select {
104                 case <-c.termSignal:
105                         govpn.BothPrintf(`[finish remote="%s"]`, c.config.RemoteAddress)
106                         c.termination <- struct{}{}
107                         // empty value signals that everything is fine
108                         c.Error <- nil
109                         break MainCycle
110                 case <-c.timeouted:
111                         if c.config.NoReconnect {
112                                 break MainCycle
113                         }
114                         govpn.BothPrintf(`[sleep seconds="%d"]`, c.config.Peer.Timeout)
115                         time.Sleep(c.config.Peer.Timeout)
116                 case <-c.rehandshaking:
117                 }
118                 close(c.timeouted)
119                 close(c.rehandshaking)
120                 close(c.termination)
121         }
122         if _, err = govpn.ScriptCall(
123                 c.config.DownPath,
124                 c.config.InterfaceName,
125                 c.config.RemoteAddress,
126         ); err != nil {
127                 c.Error <- err
128         }
129 }
130
131 func NewClient(conf Configuration, verifier *govpn.Verifier, termSignal chan os.Signal) *Client {
132         client := Client{
133                 idsCache:    govpn.NewMACCache(),
134                 firstUpCall: true,
135                 config:      conf,
136                 termSignal:  termSignal,
137                 Error:       make(chan error, 1),
138         }
139         confs := map[govpn.PeerId]*govpn.PeerConf{*verifier.Id: conf.Peer}
140         client.idsCache.Update(&confs)
141         return &client
142 }