crusader e2ef11e395 ing
2017-08-31 19:33:40 +09:00

125 lines
2.4 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
sh SocketHandler
conn *websocket.Conn
path string
messageType int
writeCh chan []byte
disconnectCh chan bool
}
func NewSocket(ctx context.Context, id string, path string, sh SocketHandler, conn *websocket.Conn) Socket {
c := &socket{
ctx: ctx,
id: id,
sh: sh,
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.sh.GetReadTimeout() > 0
soc.conn.SetReadLimit(soc.sh.GetMaxMessageSize())
defer func() {
soc.onDisconnected()
}()
go soc.listenWrite()
for {
if hasReadTimeout {
soc.conn.SetReadDeadline(time.Now().Add(soc.sh.GetReadTimeout()))
}
// 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.sh.(*SocketHandlers).onDisconnected(soc)
}
func (soc *socket) onMessage(messageType int, r io.Reader) {
result := soc.sh.GetProtocol().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.sh.GetWriteTimeout(); 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
}
}
}