125 lines
2.3 KiB
Go
125 lines
2.3 KiB
Go
package overflow_gateway_websocket
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"log"
|
|
"time"
|
|
|
|
"git.loafle.net/overflow/overflow_gateway_websocket/websocket"
|
|
)
|
|
|
|
type Socket interface {
|
|
ID() string
|
|
Conn() *websocket.Conn
|
|
Path() string
|
|
Write(m []byte)
|
|
run()
|
|
}
|
|
|
|
type socket struct {
|
|
ctx context.Context
|
|
id string
|
|
o *SocketOptions
|
|
conn *websocket.Conn
|
|
path string
|
|
messageType int
|
|
writeCh chan []byte
|
|
disconnectCh chan bool
|
|
}
|
|
|
|
func NewSocket(ctx context.Context, id string, path string, o *SocketOptions, conn *websocket.Conn) Socket {
|
|
c := &socket{
|
|
ctx: ctx,
|
|
id: id,
|
|
o: o,
|
|
conn: conn,
|
|
path: path,
|
|
writeCh: make(chan []byte),
|
|
disconnectCh: make(chan bool),
|
|
messageType: websocket.TextMessage,
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func (soc *socket) ID() string {
|
|
return soc.id
|
|
}
|
|
|
|
func (soc *socket) Conn() *websocket.Conn {
|
|
return soc.conn
|
|
}
|
|
|
|
func (soc *socket) Path() string {
|
|
return soc.path
|
|
}
|
|
|
|
func (soc *socket) Write(m []byte) {
|
|
soc.writeCh <- m
|
|
}
|
|
|
|
func (soc *socket) run() {
|
|
hasReadTimeout := soc.o.ReadTimeout > 0
|
|
soc.conn.SetReadLimit(soc.o.MaxMessageSize)
|
|
|
|
defer func() {
|
|
soc.onDisconnected()
|
|
}()
|
|
|
|
go soc.listenWrite()
|
|
|
|
for {
|
|
if hasReadTimeout {
|
|
soc.conn.SetReadDeadline(time.Now().Add(soc.o.ReadTimeout))
|
|
}
|
|
|
|
// messageType, data, err := c.conn.ReadMessage()
|
|
messageType, r, err := soc.conn.NextReader()
|
|
if err != nil {
|
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
|
//c.fireError(err)
|
|
}
|
|
break
|
|
} else {
|
|
soc.onMessage(messageType, r)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func (soc *socket) onDisconnected() {
|
|
soc.disconnectCh <- true
|
|
soc.o.onDisconnected(soc)
|
|
}
|
|
|
|
func (soc *socket) onMessage(messageType int, r io.Reader) {
|
|
result := soc.o.Handler.OnMessage(soc, messageType, r)
|
|
if nil == result {
|
|
return
|
|
}
|
|
soc.Write(result)
|
|
}
|
|
|
|
func (soc *socket) listenWrite() {
|
|
for {
|
|
select {
|
|
// send message to the client
|
|
case w := <-soc.writeCh:
|
|
if writeTimeout := soc.o.WriteTimeout; writeTimeout > 0 {
|
|
err := soc.conn.SetWriteDeadline(time.Now().Add(writeTimeout))
|
|
log.Printf("Socket timeout: %v", err)
|
|
}
|
|
|
|
err := soc.conn.WriteMessage(soc.messageType, w)
|
|
if nil != err {
|
|
log.Printf("Socket Write error: %v", err)
|
|
}
|
|
|
|
// receive done request
|
|
case <-soc.disconnectCh:
|
|
return
|
|
}
|
|
}
|
|
}
|