131 lines
2.1 KiB
Go
131 lines
2.1 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/gorilla/websocket"
|
|
"github.com/pion/webrtc/v2"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type Client struct {
|
|
ID int
|
|
Name string
|
|
Status int
|
|
Conn *websocket.Conn
|
|
PeerConn *webrtc.PeerConnection
|
|
In chan *Message
|
|
Out chan *Message
|
|
|
|
AudioTrack *webrtc.Track
|
|
SequenceNumber uint16
|
|
|
|
Terminated chan bool
|
|
}
|
|
|
|
func NewClient(conn *websocket.Conn) *Client {
|
|
c := Client{Conn: conn, Name: "Anonymous", In: make(chan *Message, 10), Out: make(chan *Message, 10), SequenceNumber: 1, Terminated: make(chan bool)}
|
|
|
|
go c.handleRead()
|
|
go c.handleWrite()
|
|
|
|
return &c
|
|
}
|
|
|
|
func (c *Client) handleRead() {
|
|
var (
|
|
messageTypeInt int
|
|
messageType MessageType
|
|
message []byte
|
|
err error
|
|
)
|
|
for {
|
|
c.Conn.SetReadDeadline(time.Now().Add(1 * time.Minute))
|
|
messageTypeInt, message, err = c.Conn.ReadMessage()
|
|
if err != nil || c.Status == -1 {
|
|
c.Close()
|
|
return
|
|
}
|
|
messageType = MessageType(messageTypeInt)
|
|
|
|
in := Message{}
|
|
if messageType == 2 {
|
|
in.T = messageType
|
|
in.M = message
|
|
} else {
|
|
err = json.Unmarshal(message, &in)
|
|
if err != nil {
|
|
// TODO Place error behind debug/verbose var
|
|
log.Println(string(message))
|
|
log.Println()
|
|
log.Println(err)
|
|
|
|
c.Close()
|
|
return
|
|
}
|
|
}
|
|
|
|
in.S = c.ID
|
|
c.In <- &in
|
|
}
|
|
}
|
|
|
|
func (c *Client) handleWrite() {
|
|
var (
|
|
out []byte
|
|
err error
|
|
)
|
|
for msg := range c.Out {
|
|
if msg == nil {
|
|
return
|
|
}
|
|
|
|
out, err = json.Marshal(msg)
|
|
if err != nil {
|
|
c.Close()
|
|
return
|
|
}
|
|
|
|
c.Conn.WriteMessage(1, out)
|
|
}
|
|
}
|
|
|
|
func (c *Client) Close() {
|
|
if c.Status == -1 {
|
|
return
|
|
}
|
|
c.Status = -1
|
|
c.AudioTrack = nil
|
|
|
|
if c.PeerConn != nil {
|
|
c.PeerConn.Close()
|
|
}
|
|
if c.Conn != nil {
|
|
c.Conn.Close()
|
|
}
|
|
|
|
c.In <- nil
|
|
c.Out <- nil
|
|
|
|
// TODO Place behind debug/verbose flag
|
|
log.Printf("%+v", errors.New("Closing client #"+strconv.Itoa(c.ID)))
|
|
|
|
go func() {
|
|
c.Terminated <- true
|
|
}()
|
|
}
|
|
|
|
func (c *Client) ClosePeerConn() {
|
|
if c.PeerConn == nil {
|
|
return
|
|
}
|
|
|
|
c.PeerConn.Close()
|
|
c.AudioTrack = nil
|
|
c.PeerConn = nil
|
|
c.SequenceNumber = 1
|
|
}
|