nmdc-webfrontend/vendor/github.com/googollee/go-socket.io/socket.go

175 lines
3.1 KiB
Go

package socketio
import (
"net/http"
"sync"
"github.com/googollee/go-engine.io"
)
// Socket is the socket object of socket.io.
type Socket interface {
// Id returns the session id of socket.
Id() string
// Rooms returns the rooms name joined now.
Rooms() []string
// Request returns the first http request when established connection.
Request() *http.Request
// On registers the function f to handle an event.
On(event string, f interface{}) error
// Emit emits an event with given args.
Emit(event string, args ...interface{}) error
// Join joins the room.
Join(room string) error
// Leave leaves the room.
Leave(room string) error
// Disconnect disconnect the socket.
Disconnect()
// BroadcastTo broadcasts an event to the room with given args.
BroadcastTo(room, event string, args ...interface{}) error
}
type socket struct {
*socketHandler
conn engineio.Conn
namespace string
id int
mu sync.Mutex
}
func newSocket(conn engineio.Conn, base *baseHandler) *socket {
ret := &socket{
conn: conn,
}
ret.socketHandler = newSocketHandler(ret, base)
return ret
}
func (s *socket) Id() string {
return s.conn.Id()
}
func (s *socket) Request() *http.Request {
return s.conn.Request()
}
func (s *socket) Emit(event string, args ...interface{}) error {
if err := s.socketHandler.Emit(event, args...); err != nil {
return err
}
if event == "disconnect" {
s.conn.Close()
}
return nil
}
func (s *socket) Disconnect() {
s.conn.Close()
}
func (s *socket) send(args []interface{}) error {
packet := packet{
Type: _EVENT,
Id: -1,
NSP: s.namespace,
Data: args,
}
encoder := newEncoder(s.conn)
return encoder.Encode(packet)
}
func (s *socket) sendConnect() error {
packet := packet{
Type: _CONNECT,
Id: -1,
NSP: s.namespace,
}
encoder := newEncoder(s.conn)
return encoder.Encode(packet)
}
func (s *socket) sendId(args []interface{}) (int, error) {
s.mu.Lock()
packet := packet{
Type: _EVENT,
Id: s.id,
NSP: s.namespace,
Data: args,
}
s.id++
if s.id < 0 {
s.id = 0
}
s.mu.Unlock()
encoder := newEncoder(s.conn)
err := encoder.Encode(packet)
if err != nil {
return -1, nil
}
return packet.Id, nil
}
func (s *socket) loop() error {
defer func() {
s.LeaveAll()
p := packet{
Type: _DISCONNECT,
Id: -1,
}
s.socketHandler.onPacket(nil, &p)
}()
p := packet{
Type: _CONNECT,
Id: -1,
}
encoder := newEncoder(s.conn)
if err := encoder.Encode(p); err != nil {
return err
}
s.socketHandler.onPacket(nil, &p)
for {
decoder := newDecoder(s.conn)
var p packet
if err := decoder.Decode(&p); err != nil {
return err
}
ret, err := s.socketHandler.onPacket(decoder, &p)
if err != nil {
return err
}
switch p.Type {
case _CONNECT:
s.namespace = p.NSP
s.sendConnect()
case _BINARY_EVENT:
fallthrough
case _EVENT:
if p.Id >= 0 {
p := packet{
Type: _ACK,
Id: p.Id,
NSP: s.namespace,
Data: ret,
}
encoder := newEncoder(s.conn)
if err := encoder.Encode(p); err != nil {
return err
}
}
case _DISCONNECT:
return nil
}
}
}