1package socketio 2 3import ( 4 "net/http" 5 6 engineio "github.com/googollee/go-socket.io/engineio" 7) 8 9// Server is a go-socket.io server. 10type Server struct { 11 handlers map[string]*namespaceHandler 12 eio *engineio.Server 13} 14 15// NewServer returns a server. 16func NewServer(c *engineio.Options) (*Server, error) { 17 eio, err := engineio.NewServer(c) 18 if err != nil { 19 return nil, err 20 } 21 return &Server{ 22 handlers: make(map[string]*namespaceHandler), 23 eio: eio, 24 }, nil 25} 26 27// Close closes server. 28func (s *Server) Close() error { 29 return s.eio.Close() 30} 31 32func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 33 s.eio.ServeHTTP(w, r) 34} 35 36// OnConnect set a handler function f to handle open event for 37// namespace nsp. 38func (s *Server) OnConnect(nsp string, f func(Conn) error) { 39 h := s.getNamespace(nsp, true) 40 h.OnConnect(f) 41} 42 43// OnDisconnect set a handler function f to handle disconnect event for 44// namespace nsp. 45func (s *Server) OnDisconnect(nsp string, f func(Conn, string)) { 46 h := s.getNamespace(nsp, true) 47 h.OnDisconnect(f) 48} 49 50// OnError set a handler function f to handle error for namespace nsp. 51func (s *Server) OnError(nsp string, f func(Conn, error)) { 52 h := s.getNamespace(nsp, true) 53 h.OnError(f) 54} 55 56// OnEvent set a handler function f to handle event for namespace nsp. 57func (s *Server) OnEvent(nsp, event string, f interface{}) { 58 h := s.getNamespace(nsp, true) 59 h.OnEvent(event, f) 60} 61 62// Serve serves go-socket.io server 63func (s *Server) Serve() error { 64 for { 65 conn, err := s.eio.Accept() 66 if err != nil { 67 return err 68 } 69 go s.serveConn(conn) 70 } 71} 72 73// JoinRoom joins given connection to the room 74func (s *Server) JoinRoom(namespace string, room string, connection Conn) bool { 75 nspHandler := s.getNamespace(namespace, false) 76 if nspHandler != nil { 77 nspHandler.broadcast.Join(room, connection) 78 return true 79 } 80 return false 81} 82 83// LeaveRoom leaves given connection from the room 84func (s *Server) LeaveRoom(namespace string, room string, connection Conn) bool { 85 nspHandler := s.getNamespace(namespace, false) 86 if nspHandler != nil { 87 nspHandler.broadcast.Leave(room, connection) 88 return true 89 } 90 return false 91} 92 93// LeaveAllRooms leaves the given connection from all rooms 94func (s *Server) LeaveAllRooms(namespace string, connection Conn) bool { 95 nspHandler := s.getNamespace(namespace, false) 96 if nspHandler != nil { 97 nspHandler.broadcast.LeaveAll(connection) 98 return true 99 } 100 return false 101} 102 103// ClearRoom clears the room 104func (s *Server) ClearRoom(namespace string, room string) bool { 105 nspHandler := s.getNamespace(namespace, false) 106 if nspHandler != nil { 107 nspHandler.broadcast.Clear(room) 108 return true 109 } 110 return false 111} 112 113// BroadcastToRoom broadcasts given event & args to all the connections in the room 114func (s *Server) BroadcastToRoom(namespace string, room, event string, args ...interface{}) bool { 115 nspHandler := s.getNamespace(namespace, false) 116 if nspHandler != nil { 117 nspHandler.broadcast.Send(room, event, args...) 118 return true 119 } 120 return false 121} 122 123// RoomLen gives number of connections in the room 124func (s *Server) RoomLen(namespace string, room string) int { 125 nspHandler := s.getNamespace(namespace, false) 126 if nspHandler != nil { 127 return nspHandler.broadcast.Len(room) 128 } 129 return -1 130} 131 132// Rooms gives list of all the rooms 133func (s *Server) Rooms(namespace string) []string { 134 nspHandler := s.getNamespace(namespace, false) 135 if nspHandler != nil { 136 return nspHandler.broadcast.Rooms(nil) 137 } 138 return nil 139} 140 141// Count number of connections 142func (s *Server) Count() int { 143 return s.eio.Count() 144} 145 146func (s *Server) ForEach(namespace string, room string, f EachFunc) bool { 147 nspHandler := s.getNamespace(namespace, false) 148 if nspHandler != nil { 149 nspHandler.broadcast.ForEach(room, f) 150 return true 151 } 152 return false 153} 154 155func (s *Server) serveConn(c engineio.Conn) { 156 _, err := newConn(c, s.handlers) 157 if err != nil { 158 root := s.handlers[""] 159 if root != nil && root.onError != nil { 160 root.onError(nil, err) 161 } 162 return 163 } 164} 165 166func (s *Server) getNamespace(nsp string, create bool) *namespaceHandler { 167 if nsp == "/" { 168 nsp = "" 169 } 170 ret, ok := s.handlers[nsp] 171 if ok { 172 return ret 173 } 174 if create { 175 handler := newHandler() 176 s.handlers[nsp] = handler 177 return handler 178 } else { 179 return nil 180 } 181} 182