aboutsummaryrefslogtreecommitdiff
path: root/internal/server/client.go
diff options
context:
space:
mode:
author2025-12-31 14:15:42 +0300
committer2025-12-31 14:15:42 +0300
commit8c0b8ad931045c70845f662238230edb81f8cd94 (patch)
tree3bfa44e03bae220fc1233c02d716d0baa27efa3d /internal/server/client.go
parentнемного поправил отображение (diff)
downloadqchat-8c0b8ad931045c70845f662238230edb81f8cd94.tar.gz
qchat-8c0b8ad931045c70845f662238230edb81f8cd94.tar.bz2
qchat-8c0b8ad931045c70845f662238230edb81f8cd94.tar.xz
qchat-8c0b8ad931045c70845f662238230edb81f8cd94.zip
Сделал корректную работу с терминалом и историю
Diffstat (limited to 'internal/server/client.go')
-rw-r--r--internal/server/client.go72
1 files changed, 54 insertions, 18 deletions
diff --git a/internal/server/client.go b/internal/server/client.go
index 698f7fa..8a23c8b 100644
--- a/internal/server/client.go
+++ b/internal/server/client.go
@@ -2,18 +2,30 @@ package server
import (
"context"
+ "encoding/binary"
"io"
"log/slog"
+ "sync"
- "go.neonxp.ru/qchat/internal/chat"
+ "golang.org/x/crypto/ssh"
"golang.org/x/term"
)
-func (s *Server) serveClient(ctx context.Context, rw io.ReadWriteCloser, user *chat.User) {
- t := term.NewTerminal(rw, "[] ")
- // TODO resize terminal to user size
+func (s *Server) serveClient(
+ ctx context.Context,
+ conn *ssh.ServerConn,
+ channel ssh.Channel,
+ requests <-chan *ssh.Request,
+) {
+ wg := sync.WaitGroup{}
- go func() {
+ identify := conn.Permissions.ExtraData["identify"].(string)
+ user := s.chat.NewUser(conn.User(), identify)
+
+ t := term.NewTerminal(channel, "[] ")
+
+ // Обработка ввода пользователя
+ wg.Go(func() {
for {
select {
case <-ctx.Done():
@@ -31,6 +43,8 @@ func (s *Server) serveClient(ctx context.Context, rw io.ReadWriteCloser, user *c
slog.Error("failed read line", slog.Any("err", err))
}
+ conn.Close()
+
return
}
if len(line) == 0 {
@@ -39,20 +53,42 @@ func (s *Server) serveClient(ctx context.Context, rw io.ReadWriteCloser, user *c
s.chat.Input(ctx, user, line)
}
- }()
+ })
- for message := range user.Events {
- switch message := message.(type) {
- case chat.Message:
- displayMessage(t, message, user)
- case chat.SelfMessage:
- displaySelfMessage(t, message)
- case chat.SystemMessage:
- displaySystemMessage(t, message)
- case chat.UserJoined:
- displayUserJoined(t, message)
- case chat.UserLeft:
- displayUserLeft(t, message)
+ wg.Go(func() {
+ for req := range requests {
+ switch req.Type {
+ case "pty-req":
+ termLen := req.Payload[3]
+ w, h := parseDims(req.Payload[termLen+4:])
+ t.SetSize(w, h)
+ req.Reply(true, nil)
+ case "window-change":
+ w, h := parseDims(req.Payload)
+ t.SetSize(w, h)
+ req.Reply(true, nil)
+ case "shell":
+ req.Reply(len(req.Payload) == 0, nil)
+ default:
+ req.Reply(false, nil)
+ }
+ slog.Debug(
+ "req",
+ slog.String("type", req.Type),
+ slog.Bool("want-reply", req.WantReply),
+ slog.String("payload", string(req.Payload)),
+ )
}
+ })
+
+ for message := range user.Events {
+ processUserEvent(message, t, user)
}
}
+
+func parseDims(b []byte) (int, int) {
+ w := binary.BigEndian.Uint32(b)
+ h := binary.BigEndian.Uint32(b[4:])
+
+ return int(w), int(h)
+}