func (p *Profile) parseLine(line string) { p.pushOutput(string(line)) if strings.Contains(line, "Initialization Sequence Completed") { p.Status = "connected" p.update() } else if strings.Contains(line, "Inactivity timeout") { p.Status = "reconnecting" p.update() } else if strings.Contains(line, "AUTH_FAILED") || strings.Contains( line, "auth-failure") { evt := event.Event{ Type: "auto_error", Data: p, } evt.Init() } else if strings.Contains(line, "link remote:") { sIndex := strings.LastIndex(line, "]") + 1 eIndex := strings.LastIndex(line, ":") p.ServerAddr = line[sIndex:eIndex] p.update() } else if strings.Contains(line, "network/local/netmask") { eIndex := strings.LastIndex(line, "/") line = line[:eIndex] sIndex := strings.LastIndex(line, "/") + 1 p.ClientAddr = line[sIndex:] p.update() } else if strings.Contains(line, "ifconfig") && strings.Contains( line, "netmask") { sIndex := strings.Index(line, "ifconfig") + 9 eIndex := strings.Index(line, "netmask") line = line[sIndex:eIndex] split := strings.Split(line, " ") if len(split) > 2 { p.ClientAddr = split[1] p.update() } } else if strings.Contains(line, "ip addr add dev") { sIndex := strings.Index(line, "ip addr add dev") + 16 eIndex := strings.Index(line, "broadcast") line = line[sIndex:eIndex] split := strings.Split(line, " ") if len(split) > 1 { split := strings.Split(split[1], "/") if len(split) > 1 { p.ClientAddr = split[0] p.update() } } } }
func (p *Profile) update() { evt := event.Event{ Type: "update", Data: p, } evt.Init() status := GetStatus() if status { evt := event.Event{ Type: "connected", } evt.Init() } else { evt := event.Event{ Type: "disconnected", } evt.Init() } }
func (p *Profile) Start(timeout bool) (err error) { start := time.Now() p.Status = "connecting" p.Timestamp = start.Unix() profilesLock.Lock() _, ok := Profiles[p.Id] if ok { profilesLock.Unlock() return } Profiles[p.Id] = p profilesLock.Unlock() confPath, err := p.write() if err != nil { p.clearStatus(start) return } var authPath string if p.Username != "" || p.Password != "" { authPath, err = p.writeAuth() if err != nil { p.clearStatus(start) return } } p.update() args := []string{ "--config", confPath, "--script-security", "1", "--verb", "2", } if authPath != "" { args = append(args, "--auth-user-pass", authPath) } cmd := exec.Command(getOpenvpnPath(), args...) p.cmd = cmd stdout, err := cmd.StdoutPipe() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to get stdout"), } p.clearStatus(start) return } stderr, err := cmd.StderrPipe() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to get stderr"), } p.clearStatus(start) return } go func() { out := bufio.NewReader(stdout) for { line, _, err := out.ReadLine() if err != nil { if err != io.EOF { err = &ExecError{ errors.Wrap(err, "profile: Failed to read stdout"), } logrus.WithFields(logrus.Fields{ "error": err, }).Error("profile: Stdout error") } return } p.parseLine(string(line)) } }() go func() { out := bufio.NewReader(stderr) for { line, _, err := out.ReadLine() if err != nil { if err != io.EOF { err = &ExecError{ errors.Wrap(err, "profile: Failed to read stderr"), } logrus.WithFields(logrus.Fields{ "error": err, }).Error("profile: Stderr error") } return } p.parseLine(string(line)) } }() err = cmd.Start() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to start openvpn"), } p.clearStatus(start) return } running := true go func() { cmd.Wait() running = false p.clearStatus(start) delete(Profiles, p.Id) }() if timeout { go func() { time.Sleep(connTimeout) if p.Status != "connected" && running { cmd.Process.Kill() evt := event.Event{ Type: "timeout_error", Data: p, } evt.Init() } }() } return }
func (p *Profile) Start(timeout bool) (err error) { start := time.Now() p.remPaths = []string{} p.Status = "connecting" p.Timestamp = start.Unix() profilesLock.Lock() _, ok := Profiles[p.Id] if ok { profilesLock.Unlock() return } Profiles[p.Id] = p profilesLock.Unlock() confPath, err := p.write() if err != nil { p.clearStatus(start) return } p.remPaths = append(p.remPaths, confPath) var authPath string if p.Username != "" || p.Password != "" { authPath, err = p.writeAuth() if err != nil { p.clearStatus(start) return } p.remPaths = append(p.remPaths, authPath) } p.update() args := []string{ "--config", confPath, "--verb", "2", } if runtime.GOOS == "windows" { p.intf, err = utils.AcquireTap() if err != nil { return } if p.intf != nil { args = append(args, "--dev-node", p.intf.Name) } } if runtime.GOOS == "darwin" { upPath, e := p.writeUp() if e != nil { err = e p.clearStatus(start) return } p.remPaths = append(p.remPaths, upPath) downPath, e := p.writeDown() if e != nil { err = e p.clearStatus(start) return } p.remPaths = append(p.remPaths, downPath) preDownPath, e := p.writePreDown() if e != nil { err = e p.clearStatus(start) return } p.remPaths = append(p.remPaths, preDownPath) blockPath, e := p.writeBlock() if e != nil { err = e p.clearStatus(start) return } p.remPaths = append(p.remPaths, blockPath) args = append(args, "--script-security", "2", "--up", upPath, "--down", downPath, "--route-pre-down", preDownPath, "--tls-verify", blockPath, "--ipchange", blockPath, "--route-up", blockPath, ) } else { args = append(args, "--script-security", "1") } if authPath != "" { args = append(args, "--auth-user-pass", authPath) } cmd := exec.Command(getOpenvpnPath(), args...) p.cmd = cmd stdout, err := cmd.StdoutPipe() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to get stdout"), } p.clearStatus(start) return } stderr, err := cmd.StderrPipe() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to get stderr"), } p.clearStatus(start) return } go func() { out := bufio.NewReader(stdout) for { line, _, err := out.ReadLine() if err != nil { if err != io.EOF { err = &ExecError{ errors.Wrap(err, "profile: Failed to read stdout"), } logrus.WithFields(logrus.Fields{ "error": err, }).Error("profile: Stdout error") } return } p.parseLine(string(line)) } }() go func() { out := bufio.NewReader(stderr) for { line, _, err := out.ReadLine() if err != nil { if err != io.EOF { err = &ExecError{ errors.Wrap(err, "profile: Failed to read stderr"), } logrus.WithFields(logrus.Fields{ "error": err, }).Error("profile: Stderr error") } return } p.parseLine(string(line)) } }() err = cmd.Start() if err != nil { err = &ExecError{ errors.Wrap(err, "profile: Failed to start openvpn"), } p.clearStatus(start) return } running := true go func() { cmd.Wait() running = false p.clearStatus(start) delete(Profiles, p.Id) }() if timeout { go func() { time.Sleep(connTimeout) if p.Status != "connected" && running { cmd.Process.Kill() evt := event.Event{ Type: "timeout_error", Data: p, } evt.Init() } }() } return }