package main import ( "bufio" "fmt" "net" "sync" ) type OpenVpnSrv struct { Remote string `json:"active-vpn"` Status string `json:"status"` hold bool chanHold chan bool m sync.RWMutex ret chan []string buf *bufio.ReadWriter } func (s *OpenVpnSrv) Lock() { s.m.Lock() } func (s *OpenVpnSrv) Unlock() { s.m.Unlock() } func NewOpenVpnSrv(conn net.Conn) *OpenVpnSrv { return &OpenVpnSrv{ buf: bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)), hold: false, chanHold: make(chan bool), ret: make(chan []string), } } // send a command to the server. Set the channel to receive the response func (s *OpenVpnSrv) sendCommand(msg []string) (error, []string) { for _, line := range msg { if _, err := s.buf.WriteString(line + "\r\n"); err != nil { return err, nil } } if err := s.buf.Flush(); err != nil { return err, nil } // wait for the response ret := <-s.ret return nil, ret } func (s *OpenVpnSrv) Response(response []string) { s.Lock() s.ret <- response s.Unlock() } func (s *OpenVpnSrv) GetLine() (string, error) { return s.buf.ReadString('\n') } func (s *OpenVpnSrv) ValidRemote(server, port, proto string) { if s.Remote != "" { s.sendCommand([]string{fmt.Sprintf("remote MOD %s %s %s", s.Remote, port, proto)}) s.Status = "Connected" return } s.Remote = server s.sendCommand([]string{"remote ACCEPT"}) } func (s *OpenVpnSrv) Kill() { } func (s *OpenVpnSrv) Version() (error, []string) { return s.sendCommand([]string{"version"}) } func (s *OpenVpnSrv) SetRemote(server string) error { // already the active server, do nothing if s.Remote == server { return nil } if s.Remote != "" { s.Kill() } s.Remote = server // release Hold if necessary s.ReleaseHold() return nil } func (s *OpenVpnSrv) waitForRelase() { s.hold = true s.Status = "Hold" <-s.chanHold s.sendCommand([]string{"hold release"}) } func (s *OpenVpnSrv) ReleaseHold() { if !s.hold { return } s.hold = false s.chanHold <- true s.Status = "Waiting for connexion" }