forked from byronwilliams/goStrongswanVici
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclientConn.go
132 lines (120 loc) · 2.97 KB
/
clientConn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package goStrongswanVici
import (
"fmt"
"io"
"net"
)
// This object is not thread safe.
// if you want concurrent, you need create more clients.
type ClientConn struct {
conn net.Conn
responseChan chan segment
eventHandlers map[string]func(response map[string]interface{})
lastError error
}
func (c *ClientConn) Close() error {
close(c.responseChan)
c.lastError = io.ErrClosedPipe
return c.conn.Close()
}
func NewClientConn(conn net.Conn) (client *ClientConn) {
client = &ClientConn{
conn: conn,
responseChan: make(chan segment, 2),
eventHandlers: map[string]func(response map[string]interface{}){},
}
go client.readThread()
return client
}
// it dial from unix:///var/run/charon.vici
func NewClientConnFromDefaultSocket() (client *ClientConn, err error) {
conn, err := net.Dial("unix", "/var/run/charon.vici")
if err != nil {
return
}
return NewClientConn(conn), nil
}
func (c *ClientConn) Request(apiname string, request map[string]interface{}) (response map[string]interface{}, err error) {
err = writeSegment(c.conn, segment{
typ: stCMD_REQUEST,
name: apiname,
msg: request,
})
if err != nil {
fmt.Printf("error writing segment \n")
return
}
outMsg := <-c.responseChan
if c.lastError != nil {
return nil, c.lastError
}
if outMsg.typ != stCMD_RESPONSE {
return nil, fmt.Errorf("[%s] response error %d", apiname, outMsg.typ)
}
return outMsg.msg, nil
}
func (c *ClientConn) RegisterEvent(name string, handler func(response map[string]interface{})) (err error) {
if c.eventHandlers[name] != nil {
return fmt.Errorf("[event %s] register a event twice.", name)
}
c.eventHandlers[name] = handler
err = writeSegment(c.conn, segment{
typ: stEVENT_REGISTER,
name: name,
})
if err != nil {
delete(c.eventHandlers, name)
return
}
outMsg := <-c.responseChan
//fmt.Printf("registerEvent %#v\n", outMsg)
if c.lastError != nil {
delete(c.eventHandlers, name)
return c.lastError
}
if outMsg.typ != stEVENT_CONFIRM {
delete(c.eventHandlers, name)
return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
}
return nil
}
func (c *ClientConn) UnregisterEvent(name string) (err error) {
err = writeSegment(c.conn, segment{
typ: stEVENT_UNREGISTER,
name: name,
})
if err != nil {
return
}
outMsg := <-c.responseChan
//fmt.Printf("UnregisterEvent %#v\n", outMsg)
if c.lastError != nil {
return c.lastError
}
if outMsg.typ != stEVENT_CONFIRM {
return fmt.Errorf("[event %s] response error %d", name, outMsg.typ)
}
delete(c.eventHandlers, name)
return nil
}
func (c *ClientConn) readThread() {
for {
outMsg, err := readSegment(c.conn)
if err != nil {
c.lastError = err
return
}
switch outMsg.typ {
case stCMD_RESPONSE, stEVENT_CONFIRM:
c.responseChan <- outMsg
case stEVENT:
handler := c.eventHandlers[outMsg.name]
if handler != nil {
handler(outMsg.msg)
}
default:
c.lastError = fmt.Errorf("[Client.readThread] unknow msg type %d", outMsg.typ)
return
}
}
}