summaryrefslogtreecommitdiff
path: root/internal/server/server.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-01-24 00:10:15 +0200
committerPaul Buetow <paul@buetow.org>2026-01-24 00:10:15 +0200
commit65ec49a97b1fcf633c1c6ba92e3db71ecd477196 (patch)
tree48b47389e1384f86ff81f849fd526a09ab9c4e0d /internal/server/server.go
parentecb963eb98dd9174d017dd504a48fb2ea048c42d (diff)
refactor: split large functions for maintainability
Split functions exceeding 50 lines into smaller, focused helpers: - DirectTurboWriter.WriteLineData (~97 lines) split into: - WriteLineData (dispatcher, 9 lines) - writeServerlessLine (serverless mode, 48 lines) - writeNetworkLine (network mode, 40 lines) - TurboNetworkWriter.WriteLineData (~60 lines) split into: - WriteLineData (builds protocol line, 33 lines) - sendToTurboChannel (channel send with retry, 28 lines) - Server.handleRequests (~67 lines) split into: - handleRequests (request loop, 23 lines) - handleShellRequest (shell session setup, 57 lines) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/server/server.go')
-rw-r--r--internal/server/server.go107
1 files changed, 61 insertions, 46 deletions
diff --git a/internal/server/server.go b/internal/server/server.go
index 8b581b1..38b042f 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -170,52 +170,7 @@ func (s *Server) handleRequests(ctx context.Context, sshConn gossh.Conn,
switch req.Type {
case "shell":
- var handler handlers.Handler
- switch user.Name {
- case config.HealthUser:
- handler = handlers.NewHealthHandler(user)
- default:
- handler = handlers.NewServerHandler(user, s.catLimiter, s.tailLimiter)
- }
- terminate := func() {
- handler.Shutdown()
- sshConn.Close()
- }
-
- go func() {
- defer terminate()
- // Broken pipe, cancel
- if _, err := io.Copy(channel, handler); err != nil {
- dlog.Server.Trace(user, fmt.Errorf("channel->handler: %w", err))
- }
- }()
- go func() {
- defer terminate()
- // Broken pipe, cancel
- if _, err := io.Copy(handler, channel); err != nil {
- dlog.Server.Trace(user, fmt.Errorf("handler->channel: %w", err))
- }
- }()
- go func() {
- select {
- case <-ctx.Done():
- case <-handler.Done():
- }
- terminate()
- }()
- go func() {
- if err := sshConn.Wait(); err != nil && err != io.EOF {
- dlog.Server.Error(user, err)
- }
- s.stats.decrementConnections()
- dlog.Server.Info(user, "Good bye Mister!")
- terminate()
- }()
-
- // Only serving shell type
- if err := req.Reply(true, nil); err != nil {
- dlog.Server.Trace(user, fmt.Errorf("reply(true): %w", err))
- }
+ s.handleShellRequest(ctx, sshConn, channel, user, req)
default:
if err := req.Reply(false, nil); err != nil {
dlog.Server.Trace(user, fmt.Errorf("reply(false): %w", err))
@@ -227,6 +182,66 @@ func (s *Server) handleRequests(ctx context.Context, sshConn gossh.Conn,
return nil
}
+// handleShellRequest sets up the shell session with handler goroutines for I/O,
+// context cancellation, and connection lifecycle management.
+func (s *Server) handleShellRequest(ctx context.Context, sshConn gossh.Conn,
+ channel gossh.Channel, user *user.User, req *gossh.Request) {
+
+ // Create the appropriate handler based on user type
+ var handler handlers.Handler
+ switch user.Name {
+ case config.HealthUser:
+ handler = handlers.NewHealthHandler(user)
+ default:
+ handler = handlers.NewServerHandler(user, s.catLimiter, s.tailLimiter)
+ }
+
+ terminate := func() {
+ handler.Shutdown()
+ sshConn.Close()
+ }
+
+ // Start goroutine to copy data from channel to handler
+ go func() {
+ defer terminate()
+ if _, err := io.Copy(channel, handler); err != nil {
+ dlog.Server.Trace(user, fmt.Errorf("channel->handler: %w", err))
+ }
+ }()
+
+ // Start goroutine to copy data from handler to channel
+ go func() {
+ defer terminate()
+ if _, err := io.Copy(handler, channel); err != nil {
+ dlog.Server.Trace(user, fmt.Errorf("handler->channel: %w", err))
+ }
+ }()
+
+ // Start goroutine to handle context or handler completion
+ go func() {
+ select {
+ case <-ctx.Done():
+ case <-handler.Done():
+ }
+ terminate()
+ }()
+
+ // Start goroutine to handle connection lifecycle and cleanup
+ go func() {
+ if err := sshConn.Wait(); err != nil && err != io.EOF {
+ dlog.Server.Error(user, err)
+ }
+ s.stats.decrementConnections()
+ dlog.Server.Info(user, "Good bye Mister!")
+ terminate()
+ }()
+
+ // Reply to indicate shell request was accepted
+ if err := req.Reply(true, nil); err != nil {
+ dlog.Server.Trace(user, fmt.Errorf("reply(true): %w", err))
+ }
+}
+
// Callback for SSH authentication.
func (s *Server) Callback(c gossh.ConnMetadata,
authPayload []byte) (*gossh.Permissions, error) {