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  }