-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
133 lines (100 loc) · 2.84 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package eio
import (
"errors"
"net/http"
"net/url"
"sync"
"time"
"github.com/byonchev/go-engine.io/internal/config"
"github.com/byonchev/go-engine.io/internal/logger"
"github.com/byonchev/go-engine.io/internal/packet"
"github.com/byonchev/go-engine.io/internal/transport"
)
// Server defines engine.io http endpoint and holds connected clients
type Server struct {
config.Config
sync.RWMutex
clients map[string]*Session
events chan interface{}
}
// NewServer creates a new engine server
func NewServer() *Server {
server := &Server{
clients: make(map[string]*Session),
events: make(chan interface{}),
Config: config.Config{
PingInterval: 25 * time.Second,
PingTimeout: 60 * time.Second,
Transports: []string{transport.PollingType, transport.WebsocketType},
AllowUpgrades: true,
UpgradeTimeout: 10 * time.Second,
PollingBufferFlushLimit: 10,
PollingBufferReceiveLimit: 10,
WebsocketReadBufferSize: 1024,
WebsocketWriteBufferSize: 1024,
PerMessageDeflate: true,
CheckOrigin: func(*http.Request) bool { return true },
},
}
go server.checkPing()
return server
}
func (server *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
defer request.Body.Close()
sessionID := request.URL.Query().Get("sid")
var client *Session
if sessionID == "" {
client = server.createSession(request.URL.Query())
} else {
client = server.findSession(sessionID)
}
if client == nil {
logger.Error("Session ", sessionID, " not found")
return
}
client.HandleRequest(writer, request)
}
// Events returns the channel for session events
func (server *Server) Events() <-chan interface{} {
return server.events
}
// Send sends message to a specific session
func (server *Server) Send(id string, binary bool, data []byte) error {
server.RLock()
session := server.findSession(id)
server.RUnlock()
if session == nil {
return errors.New("invalid session")
}
return session.Send(packet.NewMessage(binary, data))
}
// SetLogger initializes logging with a specific implementation
func (server *Server) SetLogger(loggerInstance logger.Logger) {
logger.Init(loggerInstance)
}
func (server *Server) checkPing() {
interval := server.PingInterval + server.PingTimeout
for {
time.Sleep(interval)
server.Lock()
for id, session := range server.clients {
if session.Expired() {
go session.Close("ping timeout")
delete(server.clients, id)
}
}
server.Unlock()
}
}
func (server *Server) createSession(params url.Values) *Session {
session := NewSession(server.Config, server.events)
server.Lock()
defer server.Unlock()
server.clients[session.ID()] = session
return session
}
func (server *Server) findSession(id string) *Session {
server.RLock()
defer server.RUnlock()
return server.clients[id]
}