From fd7655adedfa103aba8955ebccd32bdfeee959f8 Mon Sep 17 00:00:00 2001 From: Smile Rex Date: Wed, 4 Mar 2026 01:14:20 +0300 Subject: [PATCH] fix1 --- main.go | 72 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/main.go b/main.go index 0bfa561..6365f45 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "crypto/tls" "log" "net/http" "strings" @@ -24,40 +23,33 @@ type Server struct { } func NewServer() *Server { - return &Server{ - rooms: make(map[string]*Room), - } + return &Server{rooms: make(map[string]*Room)} } func (s *Server) getRoom(name string) *Room { s.mu.Lock() defer s.mu.Unlock() - if room, ok := s.rooms[name]; ok { return room } - - room := &Room{ - conns: make(map[*webtransport.Session]bool), - } + room := &Room{conns: make(map[*webtransport.Session]bool)} s.rooms[name] = room return room } func (s *Server) handleSession(roomName string, sess *webtransport.Session) { room := s.getRoom(roomName) - room.mu.Lock() room.conns[sess] = true room.mu.Unlock() - log.Println("joined room:", roomName) + log.Printf("User joined room: %s", roomName) defer func() { room.mu.Lock() delete(room.conns, sess) room.mu.Unlock() - log.Println("left room:", roomName) + log.Printf("User left room: %s", roomName) }() for { @@ -71,26 +63,26 @@ func (s *Server) handleSession(roomName string, sess *webtransport.Session) { func (s *Server) handleStream(room *Room, sender *webtransport.Session, stream *webtransport.Stream) { buf := make([]byte, 4096) - for { n, err := stream.Read(buf) if err != nil { return } + data := append([]byte(nil), buf[:n]...) room.mu.Lock() for conn := range room.conns { if conn == sender { continue } - go func(c *webtransport.Session, data []byte) { + go func(c *webtransport.Session, d []byte) { out, err := c.OpenStream() if err != nil { return } defer out.Close() - out.Write(data) - }(conn, append([]byte(nil), buf[:n]...)) + out.Write(d) + }(conn, data) } room.mu.Unlock() } @@ -100,61 +92,69 @@ func main() { domain := "qgo-server.quizer.space" email := "serverussnap@outlook.com" + // 1. Настройка CertMagic certmagic.DefaultACME.Email = email certmagic.DefaultACME.Agreed = true - certmagic.Default.Storage = &certmagic.FileStorage{ - Path: "/root/.local/share/certmagic", - } + cfg := certmagic.NewDefault() - tlsConf, err := certmagic.TLS([]string{domain}) + // Важно: ManageSync получит сертификат ДО запуска серверов + err := cfg.ManageSync(context.Background(), []string{domain}) if err != nil { - log.Fatal(err) + log.Fatal("CertMagic error:", err) } - // Обязательно и h3, и http/1.1 + tlsConf := cfg.TLSConfig() + // NextProtos критически важен для WebTransport tlsConf.NextProtos = []string{"h3", "http/1.1"} - tlsConf.MinVersion = tls.VersionTLS13 server := NewServer() - mux := http.NewServeMux() - // WebTransport server поверх HTTP/3 - wtServer := &webtransport.Server{ + // 2. WebTransport сервер + wt := &webtransport.Server{ H3: &http3.Server{ Addr: ":443", TLSConfig: tlsConf, Handler: mux, }, + CheckOrigin: func(r *http.Request) bool { return true }, // Разрешаем подключения отовсюду } mux.HandleFunc("/room/", func(w http.ResponseWriter, r *http.Request) { - roomName := strings.TrimPrefix(r.URL.Path, "/room/") + // Сообщаем браузеру, что сервер поддерживает HTTP/3 на порту 443 + w.Header().Set("Alt-Svc", `h3=":443"; ma=86400`) - sess, err := wtServer.Upgrade(w, r) - if err != nil { - log.Println("upgrade error:", err) + roomName := strings.TrimPrefix(r.URL.Path, "/room/") + if roomName == "" { + http.Error(w, "Room name required", 400) return } + sess, err := wt.Upgrade(w, r) + if err != nil { + log.Printf("Upgrade error (check if you use https): %v", err) + return + } go server.handleSession(roomName, sess) }) - log.Println("Relay running on https://" + domain + "/room/{room}") - - // Запуск HTTP/3 + WebTransport (UDP 443) + // 3. Запуск UDP (HTTP/3 + WebTransport) go func() { - if err := wtServer.ListenAndServe(); err != nil { - log.Fatal(err) + log.Printf("Starting UDP (WebTransport) on https://%s/room/", domain) + if err := wt.ListenAndServe(); err != nil { + log.Fatalf("UDP Server Error: %v", err) } }() - // Отдельный HTTPS сервер (TCP 443) для ACME challenge + // 4. Запуск TCP (HTTPS + ACME Challenge) + // Это нужно, чтобы браузер сначала зашел по TCP и узнал про Alt-Svc + log.Printf("Starting TCP (HTTPS) on https://%s", domain) httpServer := &http.Server{ Addr: ":443", TLSConfig: tlsConf, Handler: mux, } + // Используем ListenAndServeTLS с пустыми путями, так как сертификаты в tlsConf log.Fatal(httpServer.ListenAndServeTLS("", "")) }