92 lines
1.5 KiB
Go
92 lines
1.5 KiB
Go
package websocket
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"net/textproto"
|
|
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
type Socket struct {
|
|
*websocket.Conn
|
|
Listeners map[string](chan<- []byte)
|
|
done chan struct{}
|
|
errd bool
|
|
errsig chan error
|
|
}
|
|
|
|
var client *Socket
|
|
|
|
func NewClient(remote string) (*Socket, error) {
|
|
if remote == "" {
|
|
return nil, errors.New("remote url is empty")
|
|
}
|
|
var err error
|
|
|
|
headers := http.Header{}
|
|
|
|
headers.Set(
|
|
textproto.CanonicalMIMEHeaderKey("X-Auth-Key"),
|
|
"rpi",
|
|
)
|
|
c, resp, err := websocket.DefaultDialer.Dial(remote, headers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
client = &Socket{
|
|
Conn: c,
|
|
Listeners: make(map[string](chan<- []byte)),
|
|
done: make(chan struct{}, 0),
|
|
errd: false,
|
|
errsig: make(chan error),
|
|
}
|
|
|
|
return client, nil
|
|
}
|
|
|
|
func (p *Socket) Listen() error {
|
|
go func() {
|
|
defer close(p.done)
|
|
for {
|
|
_, msg, err := p.ReadMessage()
|
|
if err != nil {
|
|
p.errsig <- err
|
|
}
|
|
|
|
for _, v := range p.Listeners {
|
|
v <- msg
|
|
}
|
|
}
|
|
}()
|
|
|
|
select {
|
|
case <-p.done:
|
|
return nil
|
|
case err := <-p.errsig:
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (p *Socket) AddListener(alias string, c chan<- []byte) error {
|
|
if _, ok := p.Listeners[alias]; ok {
|
|
return errors.New("listener name exists")
|
|
}
|
|
p.Listeners[alias] = c
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Socket) RemoveListener(alias string) error {
|
|
if v, ok := p.Listeners[alias]; !ok {
|
|
return errors.New("listener not exists")
|
|
} else {
|
|
close(v)
|
|
delete(p.Listeners, alias)
|
|
}
|
|
|
|
return nil
|
|
}
|