From d317e8f6df0e0e16445db606da1d683a6b35f531 Mon Sep 17 00:00:00 2001 From: Alexander Neonxp Kiryukhin Date: Tue, 30 Dec 2025 19:33:39 +0300 Subject: =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/server/server.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 internal/server/server.go (limited to 'internal/server/server.go') diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 0000000..1c28cd5 --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,70 @@ +package server + +import ( + "context" + "encoding/hex" + "fmt" + "log/slog" + "net" + "sync" + + "go.neonxp.ru/qchat/internal/chat" + "go.neonxp.ru/qchat/internal/config" + "golang.org/x/crypto/ssh" +) + +type Server struct { + cfg *config.Config + chat *chat.Chat +} + +func New(cfg *config.Config, ch *chat.Chat) *Server { + return &Server{ + cfg: cfg, + chat: ch, + } +} + +func (s *Server) Run(ctx context.Context) error { + config := &ssh.ServerConfig{ + PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { + return &ssh.Permissions{ + ExtraData: map[any]any{ + "identify": hex.EncodeToString(pubKey.Marshal()), + }, + }, nil + }, + } + + private, err := ssh.ParsePrivateKey([]byte(s.cfg.Server.PrivateKey)) + if err != nil { + return fmt.Errorf("failed to parse private key: %w", err) + } + config.AddHostKey(private) + listener, err := net.Listen("tcp", s.cfg.Server.Addr) + if err != nil { + return fmt.Errorf("failed to parse private key: %w", err) + } + go func() { + <-ctx.Done() + listener.Close() + }() + + wg := sync.WaitGroup{} + defer wg.Wait() + + slog.InfoContext(ctx, "started server at", slog.String("addr", s.cfg.Server.Addr)) + + for { + nConn, err := listener.Accept() + if err != nil { + slog.ErrorContext(ctx, "failed to accept incoming connection", slog.Any("err", err)) + continue + } + wg.Go(func() { + if err := s.serveConn(ctx, nConn, config); err != nil { + slog.ErrorContext(ctx, "connection error", slog.Any("err", err)) + } + }) + } +} -- cgit v1.2.3