major change of websocket dbmHandler structure

This commit is contained in:
Adrian Zürcher
2025-04-23 21:53:01 +02:00
parent a1f947e24a
commit 0a137c9d86
35 changed files with 1676 additions and 424 deletions

View File

@@ -1,49 +0,0 @@
package server
import (
"context"
"log"
"sync"
"github.com/coder/websocket"
"github.com/coder/websocket/wsjson"
"github.com/zuadi/tecamino-dbm.git/models"
)
var (
clients = make(map[*Client]bool)
clientsMu sync.Mutex
)
type Client struct {
conn *websocket.Conn
ctx context.Context
}
func registerClient(c *Client) {
clientsMu.Lock()
defer clientsMu.Unlock()
clients[c] = true
log.Printf("Client connected (%d total)", len(clients))
}
func unregisterClient(c *Client) {
clientsMu.Lock()
defer clientsMu.Unlock()
delete(clients, c)
log.Printf("Client disconnected (%d total)", len(clients))
}
func broadcast(data models.JsonData) {
clientsMu.Lock()
defer clientsMu.Unlock()
for c := range clients {
go func(client *Client) {
err := wsjson.Write(client.ctx, client.conn, data)
if err != nil {
log.Printf("Broadcast error: %v", err)
}
}(c)
}
}

27
server/jsonRequest.go Normal file
View File

@@ -0,0 +1,27 @@
package server
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/zuadi/tecamino-dbm/models"
)
func (s *Server) JsonRequest(c *gin.Context) {
var payload models.JsonData
if err := c.BindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if payload.Set != nil {
}
c.JSON(200, gin.H{
"name": payload,
})
return
}

82
server/models/clients.go Normal file
View File

@@ -0,0 +1,82 @@
package models
import (
"context"
"fmt"
"net/http"
"github.com/coder/websocket"
"github.com/gin-gonic/gin"
)
var Origins []string = []string{"*"}
type Clients map[string]*Client
type Client struct {
Connected *bool `json:"connected"`
Conn *websocket.Conn `json:"-"`
}
func NewClients() Clients {
return make(Clients)
}
// Connect a recieving websocket connection
func (c *Clients) ConnectRecievingWsConnection(id string, ctx *gin.Context) error {
if _, exists := (*c)[id]; exists {
return nil
}
conn, err := websocket.Accept(ctx.Writer, ctx.Request, &websocket.AcceptOptions{
OriginPatterns: Origins,
})
if err != nil {
return fmt.Errorf("error accept websocket client: %s", err)
}
b := true
(*c)[id] = &Client{
Connected: &b,
Conn: conn,
}
return nil
}
// Connect a recieving websocket connection
func (c *Clients) ConnectSendingWsConnection(id, url string) (*websocket.Conn, error) {
if _, exists := (*c)[id]; exists {
return (*c)[id].Conn, nil
}
header := http.Header{}
header.Set("Authorization", "Bearer "+id)
conn, _, err := websocket.Dial(context.Background(), url, &websocket.DialOptions{
HTTPHeader: header,
})
if err != nil {
return nil, err
}
b := true
(*c)[id] = &Client{
Connected: &b,
Conn: conn,
}
return conn, nil
}
func (c *Clients) RemoveClient(id string) {
delete(*c, id)
}
func (c *Clients) GetClientPointer(id string) *bool {
return (*c)[id].Connected
}
func (c *Clients) DisconnectWsConnection(id string, code websocket.StatusCode, reason string) {
*(*c)[id].Connected = false
(*c)[id].Conn.Close(code, reason)
}

View File

@@ -1,13 +0,0 @@
package server
import "github.com/gin-gonic/gin"
func (s *Server) AddRoutes() {
s.engine.GET("/json_data", func(c *gin.Context) {
handleWebSocket(c.Writer, c.Request)
})
s.engine.GET("/", func(c *gin.Context) {
c.String(200, "WebSocket Broadcast Server is running!")
})
}

View File

@@ -2,25 +2,29 @@ package server
import (
"fmt"
"sync"
"github.com/gin-gonic/gin"
"github.com/tecamino/tecamino-logger/logging"
"github.com/zuadi/tecamino-dbm/cert"
)
type Server struct {
engine *gin.Engine
Routes *gin.Engine
sync.RWMutex
Logger *logging.Logger
}
func NewServer() *Server {
s := Server{
engine: gin.Default(),
return &Server{
Routes: gin.Default(),
}
s.AddRoutes()
return &s
}
func (s *Server) Serve(port uint) error {
if err := s.engine.Run(fmt.Sprintf(":%d", port)); err != nil {
return fmt.Errorf("failed to run server: %v", err)
}
return nil
func (s *Server) ServeHttp(port uint) error {
return s.Routes.Run(fmt.Sprintf(":%d", port))
}
func (s *Server) ServeHttps(port uint, cert cert.Cert) error {
return s.Routes.RunTLS(fmt.Sprintf(":%d", port), cert.CertFile, cert.KeyFile)
}

View File

@@ -1,62 +0,0 @@
package server
import (
"context"
"log"
"net/http"
"time"
"github.com/coder/websocket"
"github.com/coder/websocket/wsjson"
"github.com/zuadi/tecamino-dbm.git/models"
)
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{
OriginPatterns: []string{"*"},
})
if err != nil {
log.Println("WebSocket accept error:", err)
return
}
defer conn.Close(websocket.StatusInternalError, "Internal error")
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Minute)
defer cancel()
client := &Client{conn: conn, ctx: ctx}
// Register client
registerClient(client)
defer unregisterClient(client)
// Read loop
for {
var data models.JsonData
err := wsjson.Read(ctx, conn, &data)
if err != nil {
log.Println("Read error:", err)
var response struct {
Code int `json:"errorCode"`
Message string `json:"message"`
Error bool `json:"error"`
}
response.Code = 404
response.Error = true
response.Message = err.Error()
err = wsjson.Write(ctx, conn, response)
if err != nil {
log.Println("Read error:", err)
}
break
}
log.Printf("Received: %v", data)
// Broadcast to all
broadcast(data)
}
conn.Close(websocket.StatusNormalClosure, "Normal closure")
}