github.com/puellanivis/breton@v0.2.16/lib/files/socketfiles/udp.go (about) 1 package socketfiles 2 3 import ( 4 "context" 5 "net" 6 "net/url" 7 "os" 8 9 "github.com/puellanivis/breton/lib/files" 10 ) 11 12 type udpHandler struct{} 13 14 func init() { 15 files.RegisterScheme(&udpHandler{}, "udp") 16 } 17 18 func (h *udpHandler) Open(ctx context.Context, uri *url.URL) (files.Reader, error) { 19 if uri.Host == "" { 20 return nil, files.PathError("open", uri.String(), errInvalidURL) 21 } 22 23 laddr, err := net.ResolveUDPAddr("udp", uri.Host) 24 if err != nil { 25 return nil, files.PathError("open", uri.String(), err) 26 } 27 28 conn, err := net.ListenUDP("udp", laddr) 29 if err != nil { 30 return nil, files.PathError("open", uri.String(), err) 31 } 32 33 // Maybe we asked for an arbitrary port, 34 // so, refresh our address to the one we’re actually listening on. 35 laddr = conn.LocalAddr().(*net.UDPAddr) 36 37 sock, err := sockReader(conn, uri.Query()) 38 if err != nil { 39 conn.Close() 40 return nil, files.PathError("open", uri.String(), err) 41 } 42 43 return newDatagramReader(ctx, sock), nil 44 } 45 46 func (h *udpHandler) Create(ctx context.Context, uri *url.URL) (files.Writer, error) { 47 if uri.Host == "" { 48 return nil, files.PathError("create", uri.String(), errInvalidURL) 49 } 50 51 raddr, err := net.ResolveUDPAddr("udp", uri.Host) 52 if err != nil { 53 return nil, files.PathError("create", uri.String(), err) 54 } 55 56 q := uri.Query() 57 58 var laddr *net.UDPAddr 59 60 host := q.Get(FieldLocalAddress) 61 port := q.Get(FieldLocalPort) 62 if host != "" || port != "" { 63 laddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(host, port)) 64 if err != nil { 65 return nil, files.PathError("create", uri.String(), err) 66 } 67 } 68 69 var conn *net.UDPConn 70 dial := func() error { 71 var err error 72 73 conn, err = net.DialUDP("udp", laddr, raddr) 74 75 return err 76 } 77 78 if err := do(ctx, dial); err != nil { 79 return nil, files.PathError("create", uri.String(), err) 80 } 81 82 sock, err := sockWriter(conn, laddr != nil, q) 83 if err != nil { 84 conn.Close() 85 return nil, files.PathError("create", uri.String(), err) 86 } 87 88 return newDatagramWriter(ctx, sock), nil 89 } 90 91 func (h *udpHandler) List(ctx context.Context, uri *url.URL) ([]os.FileInfo, error) { 92 return nil, files.PathError("readdir", uri.String(), os.ErrInvalid) 93 }