golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/buildlet/ssh_windows.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "fmt" 9 "io" 10 "log" 11 12 "github.com/UserExistsError/conpty" 13 "github.com/gliderlabs/ssh" 14 ) 15 16 func startSSHServerSwarming() { 17 buildletSSHServer = &ssh.Server{ 18 Addr: "localhost:" + sshPort(), 19 Handler: sshHandler, 20 PublicKeyHandler: func(ctx ssh.Context, key ssh.PublicKey) bool { 21 allowed, _, _, _, err := ssh.ParseAuthorizedKey(buldletAuthKeys) 22 if err != nil { 23 log.Printf("error parsing authorized key: %s", err) 24 return false 25 } 26 return ssh.KeysEqual(key, allowed) 27 }, 28 } 29 go func() { 30 err := buildletSSHServer.ListenAndServe() 31 if err != nil { 32 log.Printf("buildlet SSH Server stopped: %s", err) 33 } 34 }() 35 teardownFuncs = append(teardownFuncs, func() { 36 buildletSSHServer.Close() 37 log.Println("shutting down SSH Server") 38 }) 39 } 40 41 func sshHandler(s ssh.Session) { 42 ptyReq, winCh, isPty := s.Pty() 43 if !isPty { 44 fmt.Fprint(s, "scp is not supported\n") 45 return 46 } 47 f, err := conpty.Start(shell(), conpty.ConPtyDimensions(ptyReq.Window.Width, ptyReq.Window.Height)) 48 if err != nil { 49 fmt.Fprintf(s, "unable to start shell %q: %s\n", shell(), err) 50 log.Printf("unable to start shell: %s", err) 51 return 52 } 53 defer f.Close() 54 go func() { 55 for win := range winCh { 56 err := f.Resize(win.Width, win.Height) 57 if err != nil { 58 log.Printf("error resizing pty: %s", err) 59 } 60 } 61 }() 62 go io.Copy(f, s) // stdin 63 go io.Copy(s, f) // stdout 64 _, err = f.Wait(s.Context()) 65 if err != nil { 66 log.Printf("Error: %s", err) 67 return 68 } 69 }