175 lines
3.1 KiB
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
|
||
|
}
|
||
|
}
|
||
|
}
|