111 lines
1.8 KiB
Go
111 lines
1.8 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net"
|
|
"sync"
|
|
)
|
|
|
|
var errControlClosed = errors.New("control connection is closed")
|
|
|
|
type control struct {
|
|
// enc and dec are responsible for encoding and decoding json values forth
|
|
// and back
|
|
enc *json.Encoder
|
|
dec *json.Decoder
|
|
|
|
// underlying connection responsible for encoder and decoder
|
|
nc net.Conn
|
|
|
|
// identifier associated with this control
|
|
identifier string
|
|
|
|
mu sync.Mutex // guards the following
|
|
closed bool // if Close() and quits
|
|
}
|
|
|
|
func newControl(nc net.Conn) *control {
|
|
c := &control{
|
|
enc: json.NewEncoder(nc),
|
|
dec: json.NewDecoder(nc),
|
|
nc: nc,
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func (c *control) send(v interface{}) error {
|
|
if c.enc == nil {
|
|
return errors.New("encoder is not initialized")
|
|
}
|
|
|
|
c.mu.Lock()
|
|
if c.closed {
|
|
c.mu.Unlock()
|
|
return errControlClosed
|
|
}
|
|
c.mu.Unlock()
|
|
|
|
return c.enc.Encode(v)
|
|
}
|
|
|
|
func (c *control) recv(v interface{}) error {
|
|
if c.dec == nil {
|
|
return errors.New("decoder is not initialized")
|
|
}
|
|
|
|
c.mu.Lock()
|
|
if c.closed {
|
|
c.mu.Unlock()
|
|
return errControlClosed
|
|
}
|
|
c.mu.Unlock()
|
|
|
|
return c.dec.Decode(v)
|
|
}
|
|
|
|
func (c *control) Close() error {
|
|
if c.nc == nil {
|
|
return nil
|
|
}
|
|
|
|
c.mu.Lock()
|
|
c.closed = true
|
|
c.mu.Unlock()
|
|
|
|
return c.nc.Close()
|
|
}
|
|
|
|
type controls struct {
|
|
sync.Mutex
|
|
controls map[string]*control
|
|
}
|
|
|
|
func newControls() *controls {
|
|
return &controls{
|
|
controls: make(map[string]*control),
|
|
}
|
|
}
|
|
|
|
func (c *controls) getControl(identifier string) (*control, bool) {
|
|
c.Lock()
|
|
control, ok := c.controls[identifier]
|
|
c.Unlock()
|
|
return control, ok
|
|
}
|
|
|
|
func (c *controls) addControl(identifier string, control *control) {
|
|
control.identifier = identifier
|
|
|
|
c.Lock()
|
|
c.controls[identifier] = control
|
|
c.Unlock()
|
|
}
|
|
|
|
func (c *controls) deleteControl(identifier string) {
|
|
c.Lock()
|
|
delete(c.controls, identifier)
|
|
c.Unlock()
|
|
}
|