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 5package main 6 7import ( 8 "errors" 9 "net" 10 "os" 11 "syscall" 12) 13 14func main() { 15 if err := run(); err != nil { 16 println(err) 17 os.Exit(1) 18 } 19} 20 21func run() error { 22 l, err := findListener() 23 if err != nil { 24 return err 25 } 26 if l == nil { 27 return errors.New("no pre-opened sockets available") 28 } 29 defer l.Close() 30 31 c, err := l.Accept() 32 if err != nil { 33 return err 34 } 35 return handleConn(c) 36} 37 38func handleConn(c net.Conn) error { 39 defer c.Close() 40 41 var buf [128]byte 42 n, err := c.Read(buf[:]) 43 if err != nil { 44 return err 45 } 46 if _, err := c.Write(buf[:n]); err != nil { 47 return err 48 } 49 if err := c.(*net.TCPConn).CloseWrite(); err != nil { 50 return err 51 } 52 return c.Close() 53} 54 55func findListener() (net.Listener, error) { 56 // We start looking for pre-opened sockets at fd=3 because 0, 1, and 2 57 // are reserved for stdio. Pre-opened directors also start at fd=3, so 58 // we skip fds that aren't sockets. Once we reach EBADF we know there 59 // are no more pre-opens. 60 for preopenFd := uintptr(3); ; preopenFd++ { 61 f := os.NewFile(preopenFd, "") 62 l, err := net.FileListener(f) 63 f.Close() 64 65 var se syscall.Errno 66 switch errors.As(err, &se); se { 67 case syscall.ENOTSOCK: 68 continue 69 case syscall.EBADF: 70 err = nil 71 } 72 return l, err 73 } 74} 75