2024-01-20 01:58:57 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/ectrc/snow/aid"
|
|
|
|
"github.com/ectrc/snow/person"
|
|
|
|
"github.com/gofiber/contrib/websocket"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
2024-01-20 23:08:29 +00:00
|
|
|
type SocketType string
|
2024-01-21 17:49:14 +00:00
|
|
|
const SocketTypeXmpp SocketType = "xmpp"
|
|
|
|
const SocketTypeUnknown SocketType = "unknown"
|
2024-01-20 23:08:29 +00:00
|
|
|
|
2024-01-20 01:58:57 +00:00
|
|
|
type Socket struct {
|
|
|
|
ID string
|
|
|
|
Connection *websocket.Conn
|
|
|
|
Person *person.Person
|
2024-01-21 17:49:14 +00:00
|
|
|
|
|
|
|
Type SocketType
|
|
|
|
PresenceState *PresenceState
|
2024-01-20 01:58:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 00:18:40 +00:00
|
|
|
type MessageToWrite struct {
|
|
|
|
Socket *Socket
|
|
|
|
Message []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Socket) Write(message []byte) {
|
|
|
|
socketWriteQueue <- MessageToWrite{
|
|
|
|
Socket: s,
|
|
|
|
Message: message,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-20 01:58:57 +00:00
|
|
|
var (
|
2024-01-21 00:18:40 +00:00
|
|
|
socketWriteQueue = make(chan MessageToWrite, 1000)
|
|
|
|
socketHandlers = map[SocketType]func(string) {
|
2024-01-21 17:49:14 +00:00
|
|
|
SocketTypeXmpp: presenceSocketHandle,
|
2024-01-20 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
2024-01-20 01:58:57 +00:00
|
|
|
sockets = aid.GenericSyncMap[Socket]{}
|
|
|
|
)
|
|
|
|
|
|
|
|
func MiddlewareWebsocket(c *fiber.Ctx) error {
|
|
|
|
if !websocket.IsWebSocketUpgrade(c) {
|
|
|
|
return fiber.ErrUpgradeRequired
|
|
|
|
}
|
|
|
|
|
2024-01-20 23:08:29 +00:00
|
|
|
var protocol SocketType
|
|
|
|
switch c.Get("Sec-WebSocket-Protocol") {
|
|
|
|
case "xmpp":
|
|
|
|
protocol = SocketTypeXmpp
|
|
|
|
default:
|
|
|
|
protocol = SocketTypeUnknown
|
|
|
|
}
|
|
|
|
|
2024-01-20 01:58:57 +00:00
|
|
|
c.Locals("uuid", uuid.New().String())
|
2024-01-20 23:08:29 +00:00
|
|
|
c.Locals("protocol", protocol)
|
2024-01-20 01:58:57 +00:00
|
|
|
return c.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
func WebsocketConnection(c *websocket.Conn) {
|
2024-01-20 23:08:29 +00:00
|
|
|
protocol := c.Locals("protocol").(SocketType)
|
2024-01-20 01:58:57 +00:00
|
|
|
uuid := c.Locals("uuid").(string)
|
|
|
|
|
|
|
|
sockets.Add(uuid, &Socket{
|
|
|
|
ID: uuid,
|
2024-01-20 23:08:29 +00:00
|
|
|
Type: protocol,
|
2024-01-20 01:58:57 +00:00
|
|
|
Connection: c,
|
|
|
|
})
|
2024-01-21 00:18:40 +00:00
|
|
|
defer func() {
|
|
|
|
socket, ok := sockets.Get(uuid)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
socket.Connection.Close()
|
|
|
|
sockets.Delete(uuid)
|
|
|
|
aid.Print("(xmpp) connection closed", uuid)
|
|
|
|
}()
|
2024-01-20 01:58:57 +00:00
|
|
|
|
2024-01-21 00:18:40 +00:00
|
|
|
if handle, ok := socketHandlers[protocol]; ok {
|
2024-01-20 23:08:29 +00:00
|
|
|
handle(uuid)
|
|
|
|
}
|
2024-01-20 01:58:57 +00:00
|
|
|
}
|
|
|
|
|
2024-01-21 17:49:14 +00:00
|
|
|
func GetSocketByPerson(person *person.Person) *Socket {
|
|
|
|
var recieverSocket *Socket
|
|
|
|
sockets.Range(func(key string, value *Socket) bool {
|
|
|
|
if value.Person == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
if value.Person.ID == person.ID {
|
|
|
|
recieverSocket = value
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
return recieverSocket
|
|
|
|
}
|
|
|
|
|
2024-01-21 00:18:40 +00:00
|
|
|
func init() {
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
if aid.Config != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aid.Print("(socket) write queue started")
|
|
|
|
|
|
|
|
for {
|
|
|
|
message := <-socketWriteQueue
|
2024-01-21 17:49:14 +00:00
|
|
|
aid.Print("(socket) writing message to", message.Socket.ID, string(message.Message))
|
2024-01-21 00:18:40 +00:00
|
|
|
message.Socket.Connection.WriteMessage(websocket.TextMessage, message.Message)
|
|
|
|
}
|
|
|
|
}()
|
2024-01-20 01:58:57 +00:00
|
|
|
}
|