package chat import ( "fmt" "os" "time" "github.com/gorilla/websocket" ) type User struct { Username string `json:"username"` Token string `json:"token"` } type Client struct { conn *websocket.Conn server *Server receivedMessages chan (WrappedMessage) username string id string } type WrappedMessage struct { DataType string `json:"datatype"` Data Message `json:"data"` } var deadline = time.Second * 60 func (c *Client) disconnect() { dcString := fmt.Sprint("server "+c.server.Name+" ended connection with ", c.username) delete(c.server.clients, c.id) c.server.sendMessage(dcString) fmt.Println(dcString) fmt.Println(c.server.reportClients(), "clients connected to "+c.server.Name) c.conn.WriteControl(websocket.CloseGoingAway, []byte("reconnected"), time.Now().Add(deadline)) c.conn.Close() } func (c *Client) pongHandler(string) error { return c.conn.SetReadDeadline(time.Now().Add(deadline)) } func (c *Client) awaitDisconnect() { c.conn.SetReadDeadline(time.Now().Add(deadline)) c.conn.SetPongHandler(c.pongHandler) for { _, _, err := c.conn.ReadMessage() if err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) { fmt.Fprintln(os.Stderr, "Unexpected socket close error:", err.Error()) } c.disconnect() return } } } func (c *Client) awaitMessage() { ticker := time.NewTicker(deadline / 2) for { select { case mess := <-c.receivedMessages: { jsonData, ok := encodeJson(mess) if !ok { continue } if !c.sendMessage(websocket.TextMessage, jsonData) { return } } case <-ticker.C: { if !c.sendMessage(websocket.PingMessage, nil) { return } } } } } func (c *Client) sendMessage(messageType int, data []byte) bool { if err := c.conn.WriteMessage(messageType, data); err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) { fmt.Fprintln(os.Stderr, "Unexpected socket close error:", err.Error()) c.disconnect() } return false } return true }