Test Failed
Push — master ( 6bec68...5ed558 )
by Vyacheslav
01:53
created

agi.go   A

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 56
dl 0
loc 154
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
B goagi.NewFastAGI 0 31 7
A goagi.*FastAGI.Err 0 5 1
A goagi.*FastAGI.Close 0 3 1
A goagi.*FastAGI.Conn 0 2 1
A goagi.*FastAGI.setErr 0 4 1
A goagi.NewAGI 0 9 2
1
package goagi
2
3
import (
4
	"bufio"
5
	"net"
6
	"os"
7
	"sync"
8
)
9
10
/*
11
NewAGI creates and returns AGI object.
12
Parses AGI arguments and set ready for communication.
13
14
Usage example:
15
16
```go
17
	import (
18
		"github.com/staskobzar/goagi"
19
		"log"
20
	)
21
22
	int main() {
23
		agi, err := goagi.NewAGI()
24
		if err != nil {
25
			log.Fatalln(err)
26
		}
27
		agi.Verbose("New AGI session.")
28
		if err := agi.SetMusic("on", "jazz"); err != nil {
29
			log.Fatalln(err)
30
		}
31
32
		clid, err := agi.GetVariable("CALLERID")
33
		if err != nil {
34
			log.Fatalln(err)
35
		}
36
		agi.Verbose("Call from " + clid)
37
		if err := agi.SetMusic("off"); err != nil {
38
			log.Fatalln(err)
39
		}
40
	}
41
```
42
43
*/
44
func NewAGI() (*AGI, error) {
45
	in := bufio.NewWriter(os.Stdout)
46
	out := bufio.NewReader(os.Stdin)
47
48
	agi, err := newInterface(bufio.NewReadWriter(out, in))
49
	if err != nil {
50
		return nil, err
51
	}
52
	return agi, nil
53
}
54
55
// FastAGI defines sturcture of fast AGI server
56
type FastAGI struct {
57
	mu  sync.Mutex
58
	ch  chan *AGI
59
	ln  net.Listener
60
	err error
61
}
62
63
// Conn returns AGI instance on every Asterisk connection
64
func (fagi *FastAGI) Conn() <-chan *AGI {
65
	return fagi.ch
66
}
67
68
// Err sets error on Fast AGI processing error
69
func (fagi *FastAGI) Err() error {
70
	fagi.mu.Lock()
71
	err := fagi.err
72
	fagi.mu.Unlock()
73
	return err
74
}
75
76
// Close terminates Fast AGI
77
func (fagi *FastAGI) Close() {
78
	fagi.ln.Close()
79
	close(fagi.ch)
80
}
81
82
func (fagi *FastAGI) setErr(err error) {
83
	fagi.mu.Lock()
84
	fagi.err = err
85
	fagi.mu.Unlock()
86
}
87
88
/*
89
NewFastAGI starts listening and serve AGI network calls.
90
91
Usage example:
92
```go
93
	import (
94
    	"github.com/staskobzar/goagi"
95
		"time"
96
    	"log"
97
    )
98
99
	func main() {
100
		// listen, serve and reconnect on fail
101
		for {
102
			fagi, err := goagi.NewFastAGI(":8000")
103
			if err != nil {
104
				log.Println("Connection error. Re-try in 3 sec.")
105
				<-time.After(time.Second * 3)
106
				continue
107
			}
108
109
			for agi := range fagi.Conn() {
110
				agi.Verbose("New FastAGI session")
111
				agi.Answer()
112
				if clid, err := agi.GetVariable("CALLERID"); err == nil {
113
					log.Printf("CallerID %s\n", clid)
114
					ag.Varbose("Call from " + clid)
115
				}
116
			}
117
			if agi.Err() != nil {
118
				fmt.Printf("Error: %s\n", agi.Err())
119
			}
120
		}
121
	}
122
```
123
*/
124
func NewFastAGI(listenAddr string) (*FastAGI, error) {
125
	ln, err := net.Listen("tcp", listenAddr)
126
	if err != nil {
127
		return nil, err
128
	}
129
	ch := make(chan *AGI)
130
	fagi := &FastAGI{ln: ln, ch: ch}
131
132
	go func(fastagi *FastAGI) {
133
		for {
134
			conn, err := ln.Accept()
135
			if err != nil {
136
				fastagi.setErr(err)
137
				return
138
			}
139
140
			in := bufio.NewWriter(conn)
141
			out := bufio.NewReader(conn)
142
			agi, err := newInterface(bufio.NewReadWriter(out, in))
143
			if err != nil {
144
				fastagi.setErr(err)
145
				return
146
			}
147
			fastagi.mu.Lock()
148
			if fastagi.err == nil {
149
				fastagi.ch <- agi
150
			}
151
			fastagi.mu.Unlock()
152
		}
153
	}(fagi)
154
	return fagi, nil
155
}
156