package overflow_gateway_websocket import ( "context" "fmt" "io" "time" "git.loafle.net/commons_go/logging" "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.getOnDisconnected()(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)) logging.Logger.Info(fmt.Sprintf("Socket timeout: %v", err)) } err := soc.conn.WriteMessage(soc.messageType, w) if nil != err { logging.Logger.Error(fmt.Sprintf("Socket Write error: %v", err)) } // receive done request case <-soc.disconnectCh: return } } }