k3s/vendor/github.com/bronze1man/goStrongswanVici/clientConn.go
2019-09-27 18:33:04 -07:00

155 lines
3.4 KiB
Go

package goStrongswanVici
import (
"fmt"
"io"
"net"
"time"
)
const (
DefaultReadTimeout = 15 * time.Second
)
// 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
// ReadTimeout specifies a time limit for requests made
// by this client.
ReadTimeout time.Duration
}
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{}){},
ReadTimeout: DefaultReadTimeout,
}
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.readResponse()
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) readResponse() segment {
select {
case outMsg := <-c.responseChan:
return outMsg
case <-time.After(c.ReadTimeout):
if c.lastError == nil {
c.lastError = fmt.Errorf("Timeout waiting for message response")
}
return segment{}
}
}
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.readResponse()
//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.readResponse()
//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
}
}
}