Test Failed
Push — master ( 219109...51ce82 )
by Vyacheslav
01:35
created

interface.go (1 issue)

Severity
1
package goagi
2
3
import (
4
	"bufio"
5
	"fmt"
6
	"strings"
7
)
8
9
// AGI interface structure
10
type AGI struct {
11
	env map[string]string
12
	arg []string
13
	io  *bufio.ReadWriter
14
}
15
16
var (
17
	// error returned when AGI environment header is not valid
0 ignored issues
show
comment on exported var EInvalEnv should be of the form "EInvalEnv ..."
Loading history...
18
	EInvalEnv = errorNew("Invalid AGI env variable")
19
)
20
21
func newInterface(iodev *bufio.ReadWriter) (*AGI, error) {
22
	agi := &AGI{make(map[string]string), make([]string, 0), iodev}
23
	scanner := bufio.NewScanner(iodev)
24
	for scanner.Scan() {
25
		line := scanner.Text()
26
		if line == "" {
27
			break
28
		}
29
		if err := agi.setEnv(line); err != nil {
30
			return nil, err
31
		}
32
	}
33
	if err := scanner.Err(); err != nil {
34
		return nil, err
35
	}
36
	return agi, nil
37
}
38
39
// Env returns AGI environment variable by key
40
func (agi *AGI) Env(key string) string {
41
	val, ok := agi.env[key]
42
	if ok {
43
		return val
44
	}
45
	return ""
46
}
47
48
// EnvArgs returns list of environment arguments
49
func (agi *AGI) EnvArgs() []string {
50
	return agi.arg
51
}
52
53
func (agi *AGI) setEnv(line string) error {
54
	if !strings.HasPrefix(line, "agi_") {
55
		return EInvalEnv.withInfo(line)
56
	}
57
	idx := strings.Index(line, ": ")
58
	if idx == -1 {
59
		return EInvalEnv.withInfo(line)
60
	}
61
	if strings.HasPrefix(line, "agi_arg_") {
62
		agi.arg = append(agi.arg, line[idx+2:])
63
	} else {
64
		agi.env[line[4:idx]] = line[idx+2:]
65
	}
66
	return nil
67
}
68
69
func (agi *AGI) execute(cmd string, args ...interface{}) (*agiResp, error) {
70
	_, err := agi.io.WriteString(compileCmd(cmd, args...))
71
	if err != nil {
72
		return nil, err
73
	}
74
	agi.io.Flush()
75
76
	chStr, chErr := agi.read()
77
	select {
78
	case str := <-chStr:
79
		return parseResponse(str)
80
	case err := <-chErr:
81
		return nil, err
82
	}
83
}
84
85
func (agi *AGI) read() (chan string, chan error) {
86
	chStr := make(chan string)
87
	chErr := make(chan error)
88
	go func() {
89
		defer close(chStr)
90
		defer close(chErr)
91
92
		str, err := agi.io.ReadString('\n')
93
		if err != nil {
94
			chErr <- err
95
			return
96
		}
97
		if !strings.HasPrefix(str, "520-") {
98
			chStr <- str
99
			return
100
		}
101
		for {
102
			s, err := agi.io.ReadString('\n')
103
			if err != nil {
104
				chErr <- err
105
				return
106
			}
107
			str += s
108
			if strings.HasPrefix(s, "520 End") {
109
				chStr <- str
110
				return
111
			}
112
		}
113
	}()
114
	return chStr, chErr
115
}
116
117
func compileCmd(cmd string, args ...interface{}) string {
118
	for _, arg := range args {
119
		val := fmt.Sprintf("%v", arg)
120
		if len(val) > 0 {
121
			cmd = fmt.Sprintf("%s %s", cmd, val)
122
		} else {
123
			cmd = fmt.Sprintf("%s \"\"", cmd)
124
		}
125
	}
126
127
	return fmt.Sprintf("%s\n", cmd)
128
}
129