diff options
author | hiddenpath <hiddenpath@yandex-team.com> | 2024-04-02 23:50:23 +0300 |
---|---|---|
committer | hiddenpath <hiddenpath@yandex-team.com> | 2024-04-03 00:02:31 +0300 |
commit | 8923c6d2c438e0aeed2e06b8b0275e1864eeee33 (patch) | |
tree | 6b5e476699fc0be5091cb650654ef5f602c8afff /contrib/go/_std_1.22/src/net/sock_posix.go | |
parent | d18afd09df2a08cd023012593b46109b77713a6c (diff) | |
download | ydb-8923c6d2c438e0aeed2e06b8b0275e1864eeee33.tar.gz |
Update golang to 1.22.1
2967d19c907adf59101a1f47b4208bd0b04a6186
Diffstat (limited to 'contrib/go/_std_1.22/src/net/sock_posix.go')
-rw-r--r-- | contrib/go/_std_1.22/src/net/sock_posix.go | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/contrib/go/_std_1.22/src/net/sock_posix.go b/contrib/go/_std_1.22/src/net/sock_posix.go new file mode 100644 index 0000000000..d04c26e7ef --- /dev/null +++ b/contrib/go/_std_1.22/src/net/sock_posix.go @@ -0,0 +1,226 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build unix || windows + +package net + +import ( + "context" + "internal/poll" + "os" + "syscall" +) + +// socket returns a network file descriptor that is ready for +// asynchronous I/O using the network poller. +func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) (fd *netFD, err error) { + s, err := sysSocket(family, sotype, proto) + if err != nil { + return nil, err + } + if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil { + poll.CloseFunc(s) + return nil, err + } + if fd, err = newFD(s, family, sotype, net); err != nil { + poll.CloseFunc(s) + return nil, err + } + + // This function makes a network file descriptor for the + // following applications: + // + // - An endpoint holder that opens a passive stream + // connection, known as a stream listener + // + // - An endpoint holder that opens a destination-unspecific + // datagram connection, known as a datagram listener + // + // - An endpoint holder that opens an active stream or a + // destination-specific datagram connection, known as a + // dialer + // + // - An endpoint holder that opens the other connection, such + // as talking to the protocol stack inside the kernel + // + // For stream and datagram listeners, they will only require + // named sockets, so we can assume that it's just a request + // from stream or datagram listeners when laddr is not nil but + // raddr is nil. Otherwise we assume it's just for dialers or + // the other connection holders. + + if laddr != nil && raddr == nil { + switch sotype { + case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET: + if err := fd.listenStream(ctx, laddr, listenerBacklog(), ctrlCtxFn); err != nil { + fd.Close() + return nil, err + } + return fd, nil + case syscall.SOCK_DGRAM: + if err := fd.listenDatagram(ctx, laddr, ctrlCtxFn); err != nil { + fd.Close() + return nil, err + } + return fd, nil + } + } + if err := fd.dial(ctx, laddr, raddr, ctrlCtxFn); err != nil { + fd.Close() + return nil, err + } + return fd, nil +} + +func (fd *netFD) ctrlNetwork() string { + switch fd.net { + case "unix", "unixgram", "unixpacket": + return fd.net + } + switch fd.net[len(fd.net)-1] { + case '4', '6': + return fd.net + } + if fd.family == syscall.AF_INET { + return fd.net + "4" + } + return fd.net + "6" +} + +func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error { + var c *rawConn + if ctrlCtxFn != nil { + c = newRawConn(fd) + var ctrlAddr string + if raddr != nil { + ctrlAddr = raddr.String() + } else if laddr != nil { + ctrlAddr = laddr.String() + } + if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), ctrlAddr, c); err != nil { + return err + } + } + + var lsa syscall.Sockaddr + var err error + if laddr != nil { + if lsa, err = laddr.sockaddr(fd.family); err != nil { + return err + } else if lsa != nil { + if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { + return os.NewSyscallError("bind", err) + } + } + } + var rsa syscall.Sockaddr // remote address from the user + var crsa syscall.Sockaddr // remote address we actually connected to + if raddr != nil { + if rsa, err = raddr.sockaddr(fd.family); err != nil { + return err + } + if crsa, err = fd.connect(ctx, lsa, rsa); err != nil { + return err + } + fd.isConnected = true + } else { + if err := fd.init(); err != nil { + return err + } + } + // Record the local and remote addresses from the actual socket. + // Get the local address by calling Getsockname. + // For the remote address, use + // 1) the one returned by the connect method, if any; or + // 2) the one from Getpeername, if it succeeds; or + // 3) the one passed to us as the raddr parameter. + lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) + if crsa != nil { + fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa)) + } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil { + fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) + } else { + fd.setAddr(fd.addrFunc()(lsa), raddr) + } + return nil +} + +func (fd *netFD) listenStream(ctx context.Context, laddr sockaddr, backlog int, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error { + var err error + if err = setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil { + return err + } + var lsa syscall.Sockaddr + if lsa, err = laddr.sockaddr(fd.family); err != nil { + return err + } + + if ctrlCtxFn != nil { + c := newRawConn(fd) + if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), laddr.String(), c); err != nil { + return err + } + } + + if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { + return os.NewSyscallError("bind", err) + } + if err = listenFunc(fd.pfd.Sysfd, backlog); err != nil { + return os.NewSyscallError("listen", err) + } + if err = fd.init(); err != nil { + return err + } + lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) + fd.setAddr(fd.addrFunc()(lsa), nil) + return nil +} + +func (fd *netFD) listenDatagram(ctx context.Context, laddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) error { + switch addr := laddr.(type) { + case *UDPAddr: + // We provide a socket that listens to a wildcard + // address with reusable UDP port when the given laddr + // is an appropriate UDP multicast address prefix. + // This makes it possible for a single UDP listener to + // join multiple different group addresses, for + // multiple UDP listeners that listen on the same UDP + // port to join the same group address. + if addr.IP != nil && addr.IP.IsMulticast() { + if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil { + return err + } + addr := *addr + switch fd.family { + case syscall.AF_INET: + addr.IP = IPv4zero + case syscall.AF_INET6: + addr.IP = IPv6unspecified + } + laddr = &addr + } + } + var err error + var lsa syscall.Sockaddr + if lsa, err = laddr.sockaddr(fd.family); err != nil { + return err + } + + if ctrlCtxFn != nil { + c := newRawConn(fd) + if err := ctrlCtxFn(ctx, fd.ctrlNetwork(), laddr.String(), c); err != nil { + return err + } + } + if err = syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { + return os.NewSyscallError("bind", err) + } + if err = fd.init(); err != nil { + return err + } + lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) + fd.setAddr(fd.addrFunc()(lsa), nil) + return nil +} |