mirror of https://github.com/k3s-io/k3s
155 lines
3.4 KiB
Go
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
|
||
|
}
|
||
|
}
|
||
|
}
|