Files
go_oxspeak_server/network/udp/server.go
2025-11-14 00:34:28 +01:00

119 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package udp
import (
"context"
"fmt"
"net"
"runtime"
"sync"
)
type Server struct {
bindAddr string
routingTable *RoutingTable
conns []*net.UDPConn
wg sync.WaitGroup
ctx context.Context
cancel context.CancelFunc
}
func NewServer(bindAddr string) *Server {
ctx, cancel := context.WithCancel(context.Background())
return &Server{
bindAddr: bindAddr,
ctx: ctx,
cancel: cancel,
}
}
func (s *Server) Run() error {
workerCount := runtime.NumCPU()
conns, err := listenUDP(s.bindAddr, workerCount)
if err != nil {
return fmt.Errorf("cannot listen on address: %w", err)
}
if len(conns) == 0 {
return fmt.Errorf("no UDP connections created")
}
s.conns = conns
for _, conn := range s.conns {
conn.SetReadBuffer(8 * 1024 * 1024)
conn.SetWriteBuffer(8 * 1024 * 1024)
}
fmt.Println("Listening on", s.bindAddr)
for i, conn := range s.conns {
s.wg.Add(1)
go s.workerLoop(i, conn)
}
return nil
}
func (s *Server) sendTo(data []byte, addr *net.UDPAddr) error {
if len(s.conns) == 0 || s.conns[0] == nil {
return fmt.Errorf("server not started")
}
// On utilise la première conn pour lenvoi (cest suffisant pour UDP).
_, err := s.conns[0].WriteToUDP(data, addr)
return err
}
func (s *Server) workerLoop(id int, conn *net.UDPConn) {
defer s.wg.Done()
buffer := make([]byte, 1500)
fmt.Println("Worker", id, "started")
for {
select {
case <-s.ctx.Done():
fmt.Println("Worker", id, "stopped")
return
default:
size, addr, err := conn.ReadFromUDP(buffer)
if err != nil {
if s.ctx.Err() != nil {
return
}
if opErr, ok := err.(*net.OpError); ok && opErr.Temporary() {
continue
}
fmt.Printf("Error reading from UDP (worker %d): %v\n", id, err)
continue
}
s.handlePacket(buffer[:size], addr)
}
}
}
func (s *Server) handlePacket(data []byte, addr *net.UDPAddr) {
if len(data) == 0 {
return
}
pt := PacketType(data[0])
switch pt {
case PacketTypePing:
_ = s.sendTo([]byte{byte(PacketTypePing)}, addr)
return
case PacketTypeConnect:
return
case PacketTypeDisconnect:
return
case PacketTypeVoiceData:
// todo : déterminer le format du packet
// channelID := string(data[1:5])
return
default:
return
}
}