You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
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
|
|
}
|