1import os
2import sys
3import select
4import socket as _stdlib_socket
5from functools import wraps as _wraps
6from typing import TYPE_CHECKING
7
8import idna as _idna
9
10import trio
11from . import _core
12
13
14# Usage:
15#
16#   async with _try_sync():
17#       return sync_call_that_might_fail_with_exception()
18#   # we only get here if the sync call in fact did fail with a
19#   # BlockingIOError
20#   return await do_it_properly_with_a_check_point()
21#
22class _try_sync:
23    def __init__(self, blocking_exc_override=None):
24        self._blocking_exc_override = blocking_exc_override
25
26    def _is_blocking_io_error(self, exc):
27        if self._blocking_exc_override is None:
28            return isinstance(exc, BlockingIOError)
29        else:
30            return self._blocking_exc_override(exc)
31
32    async def __aenter__(self):
33        await trio.lowlevel.checkpoint_if_cancelled()
34
35    async def __aexit__(self, etype, value, tb):
36        if value is not None and self._is_blocking_io_error(value):
37            # Discard the exception and fall through to the code below the
38            # block
39            return True
40        else:
41            await trio.lowlevel.cancel_shielded_checkpoint()
42            # Let the return or exception propagate
43            return False
44
45
46################################################################
47# CONSTANTS
48################################################################
49
50try:
51    from socket import IPPROTO_IPV6
52except ImportError:
53    # As of at least 3.6, python on Windows is missing IPPROTO_IPV6
54    # https://bugs.python.org/issue29515
55    if sys.platform == "win32":  # pragma: no branch
56        IPPROTO_IPV6 = 41
57
58################################################################
59# Overrides
60################################################################
61
62_resolver = _core.RunVar("hostname_resolver")
63_socket_factory = _core.RunVar("socket_factory")
64
65
66def set_custom_hostname_resolver(hostname_resolver):
67    """Set a custom hostname resolver.
68
69    By default, Trio's :func:`getaddrinfo` and :func:`getnameinfo` functions
70    use the standard system resolver functions. This function allows you to
71    customize that behavior. The main intended use case is for testing, but it
72    might also be useful for using third-party resolvers like `c-ares
73    <https://c-ares.haxx.se/>`__ (though be warned that these rarely make
74    perfect drop-in replacements for the system resolver). See
75    :class:`trio.abc.HostnameResolver` for more details.
76
77    Setting a custom hostname resolver affects all future calls to
78    :func:`getaddrinfo` and :func:`getnameinfo` within the enclosing call to
79    :func:`trio.run`. All other hostname resolution in Trio is implemented in
80    terms of these functions.
81
82    Generally you should call this function just once, right at the beginning
83    of your program.
84
85    Args:
86      hostname_resolver (trio.abc.HostnameResolver or None): The new custom
87          hostname resolver, or None to restore the default behavior.
88
89    Returns:
90      The previous hostname resolver (which may be None).
91
92    """
93    old = _resolver.get(None)
94    _resolver.set(hostname_resolver)
95    return old
96
97
98def set_custom_socket_factory(socket_factory):
99    """Set a custom socket object factory.
100
101    This function allows you to replace Trio's normal socket class with a
102    custom class. This is very useful for testing, and probably a bad idea in
103    any other circumstance. See :class:`trio.abc.HostnameResolver` for more
104    details.
105
106    Setting a custom socket factory affects all future calls to :func:`socket`
107    within the enclosing call to :func:`trio.run`.
108
109    Generally you should call this function just once, right at the beginning
110    of your program.
111
112    Args:
113      socket_factory (trio.abc.SocketFactory or None): The new custom
114          socket factory, or None to restore the default behavior.
115
116    Returns:
117      The previous socket factory (which may be None).
118
119    """
120    old = _socket_factory.get(None)
121    _socket_factory.set(socket_factory)
122    return old
123
124
125################################################################
126# getaddrinfo and friends
127################################################################
128
129_NUMERIC_ONLY = _stdlib_socket.AI_NUMERICHOST | _stdlib_socket.AI_NUMERICSERV
130
131
132async def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
133    """Look up a numeric address given a name.
134
135    Arguments and return values are identical to :func:`socket.getaddrinfo`,
136    except that this version is async.
137
138    Also, :func:`trio.socket.getaddrinfo` correctly uses IDNA 2008 to process
139    non-ASCII domain names. (:func:`socket.getaddrinfo` uses IDNA 2003, which
140    can give the wrong result in some cases and cause you to connect to a
141    different host than the one you intended; see `bpo-17305
142    <https://bugs.python.org/issue17305>`__.)
143
144    This function's behavior can be customized using
145    :func:`set_custom_hostname_resolver`.
146
147    """
148
149    # If host and port are numeric, then getaddrinfo doesn't block and we can
150    # skip the whole thread thing, which seems worthwhile. So we try first
151    # with the _NUMERIC_ONLY flags set, and then only spawn a thread if that
152    # fails with EAI_NONAME:
153    def numeric_only_failure(exc):
154        return (
155            isinstance(exc, _stdlib_socket.gaierror)
156            and exc.errno == _stdlib_socket.EAI_NONAME
157        )
158
159    async with _try_sync(numeric_only_failure):
160        return _stdlib_socket.getaddrinfo(
161            host, port, family, type, proto, flags | _NUMERIC_ONLY
162        )
163    # That failed; it's a real hostname. We better use a thread.
164    #
165    # Also, it might be a unicode hostname, in which case we want to do our
166    # own encoding using the idna module, rather than letting Python do
167    # it. (Python will use the old IDNA 2003 standard, and possibly get the
168    # wrong answer - see bpo-17305). However, the idna module is picky, and
169    # will refuse to process some valid hostname strings, like "::1". So if
170    # it's already ascii, we pass it through; otherwise, we encode it to.
171    if isinstance(host, str):
172        try:
173            host = host.encode("ascii")
174        except UnicodeEncodeError:
175            # UTS-46 defines various normalizations; in particular, by default
176            # idna.encode will error out if the hostname has Capital Letters
177            # in it; with uts46=True it will lowercase them instead.
178            host = _idna.encode(host, uts46=True)
179    hr = _resolver.get(None)
180    if hr is not None:
181        return await hr.getaddrinfo(host, port, family, type, proto, flags)
182    else:
183        return await trio.to_thread.run_sync(
184            _stdlib_socket.getaddrinfo,
185            host,
186            port,
187            family,
188            type,
189            proto,
190            flags,
191            cancellable=True,
192        )
193
194
195async def getnameinfo(sockaddr, flags):
196    """Look up a name given a numeric address.
197
198    Arguments and return values are identical to :func:`socket.getnameinfo`,
199    except that this version is async.
200
201    This function's behavior can be customized using
202    :func:`set_custom_hostname_resolver`.
203
204    """
205    hr = _resolver.get(None)
206    if hr is not None:
207        return await hr.getnameinfo(sockaddr, flags)
208    else:
209        return await trio.to_thread.run_sync(
210            _stdlib_socket.getnameinfo, sockaddr, flags, cancellable=True
211        )
212
213
214async def getprotobyname(name):
215    """Look up a protocol number by name. (Rarely used.)
216
217    Like :func:`socket.getprotobyname`, but async.
218
219    """
220    return await trio.to_thread.run_sync(
221        _stdlib_socket.getprotobyname, name, cancellable=True
222    )
223
224
225# obsolete gethostbyname etc. intentionally omitted
226# likewise for create_connection (use open_tcp_stream instead)
227
228################################################################
229# Socket "constructors"
230################################################################
231
232
233def from_stdlib_socket(sock):
234    """Convert a standard library :func:`socket.socket` object into a Trio
235    socket object.
236
237    """
238    return _SocketType(sock)
239
240
241@_wraps(_stdlib_socket.fromfd, assigned=(), updated=())
242def fromfd(fd, family, type, proto=0):
243    """Like :func:`socket.fromfd`, but returns a Trio socket object."""
244    family, type, proto = _sniff_sockopts_for_fileno(family, type, proto, fd)
245    return from_stdlib_socket(_stdlib_socket.fromfd(fd, family, type, proto))
246
247
248if sys.platform == "win32" or (
249    not TYPE_CHECKING and hasattr(_stdlib_socket, "fromshare")
250):
251
252    @_wraps(_stdlib_socket.fromshare, assigned=(), updated=())
253    def fromshare(*args, **kwargs):
254        return from_stdlib_socket(_stdlib_socket.fromshare(*args, **kwargs))
255
256
257@_wraps(_stdlib_socket.socketpair, assigned=(), updated=())
258def socketpair(*args, **kwargs):
259    """Like :func:`socket.socketpair`, but returns a pair of Trio socket
260    objects.
261
262    """
263    left, right = _stdlib_socket.socketpair(*args, **kwargs)
264    return (from_stdlib_socket(left), from_stdlib_socket(right))
265
266
267@_wraps(_stdlib_socket.socket, assigned=(), updated=())
268def socket(
269    family=_stdlib_socket.AF_INET,
270    type=_stdlib_socket.SOCK_STREAM,
271    proto=0,
272    fileno=None,
273):
274    """Create a new Trio socket, like :func:`socket.socket`.
275
276    This function's behavior can be customized using
277    :func:`set_custom_socket_factory`.
278
279    """
280    if fileno is None:
281        sf = _socket_factory.get(None)
282        if sf is not None:
283            return sf.socket(family, type, proto)
284    else:
285        family, type, proto = _sniff_sockopts_for_fileno(family, type, proto, fileno)
286    stdlib_socket = _stdlib_socket.socket(family, type, proto, fileno)
287    return from_stdlib_socket(stdlib_socket)
288
289
290def _sniff_sockopts_for_fileno(family, type, proto, fileno):
291    """Correct SOCKOPTS for given fileno, falling back to provided values."""
292    # Wrap the raw fileno into a Python socket object
293    # This object might have the wrong metadata, but it lets us easily call getsockopt
294    # and then we'll throw it away and construct a new one with the correct metadata.
295    if sys.platform != "linux":
296        return family, type, proto
297    from socket import SO_DOMAIN, SO_PROTOCOL, SOL_SOCKET, SO_TYPE
298
299    sockobj = _stdlib_socket.socket(family, type, proto, fileno=fileno)
300    try:
301        family = sockobj.getsockopt(SOL_SOCKET, SO_DOMAIN)
302        proto = sockobj.getsockopt(SOL_SOCKET, SO_PROTOCOL)
303        type = sockobj.getsockopt(SOL_SOCKET, SO_TYPE)
304    finally:
305        # Unwrap it again, so that sockobj.__del__ doesn't try to close our socket
306        sockobj.detach()
307    return family, type, proto
308
309
310################################################################
311# _SocketType
312################################################################
313
314# sock.type gets weird stuff set in it, in particular on Linux:
315#
316#   https://bugs.python.org/issue21327
317#
318# But on other platforms (e.g. Windows) SOCK_NONBLOCK and SOCK_CLOEXEC aren't
319# even defined. To recover the actual socket type (e.g. SOCK_STREAM) from a
320# socket.type attribute, mask with this:
321_SOCK_TYPE_MASK = ~(
322    getattr(_stdlib_socket, "SOCK_NONBLOCK", 0)
323    | getattr(_stdlib_socket, "SOCK_CLOEXEC", 0)
324)
325
326
327# This function will modify the given socket to match the behavior in python
328# 3.7. This will become unnecessary and can be removed when support for versions
329# older than 3.7 is dropped.
330def real_socket_type(type_num):
331    return type_num & _SOCK_TYPE_MASK
332
333
334def _make_simple_sock_method_wrapper(methname, wait_fn, maybe_avail=False):
335    fn = getattr(_stdlib_socket.socket, methname)
336
337    @_wraps(fn, assigned=("__name__",), updated=())
338    async def wrapper(self, *args, **kwargs):
339        return await self._nonblocking_helper(fn, args, kwargs, wait_fn)
340
341    wrapper.__doc__ = f"""Like :meth:`socket.socket.{methname}`, but async.
342
343            """
344    if maybe_avail:
345        wrapper.__doc__ += (
346            f"Only available on platforms where :meth:`socket.socket.{methname}` is "
347            "available."
348        )
349    return wrapper
350
351
352class SocketType:
353    def __init__(self):
354        raise TypeError(
355            "SocketType is an abstract class; use trio.socket.socket if you "
356            "want to construct a socket object"
357        )
358
359
360class _SocketType(SocketType):
361    def __init__(self, sock):
362        if type(sock) is not _stdlib_socket.socket:
363            # For example, ssl.SSLSocket subclasses socket.socket, but we
364            # certainly don't want to blindly wrap one of those.
365            raise TypeError(
366                "expected object of type 'socket.socket', not '{}".format(
367                    type(sock).__name__
368                )
369            )
370        self._sock = sock
371        self._sock.setblocking(False)
372        self._did_shutdown_SHUT_WR = False
373
374    ################################################################
375    # Simple + portable methods and attributes
376    ################################################################
377
378    # NB this doesn't work because for loops don't create a scope
379    # for _name in [
380    #         ]:
381    #     _meth = getattr(_stdlib_socket.socket, _name)
382    #     @_wraps(_meth, assigned=("__name__", "__doc__"), updated=())
383    #     def _wrapped(self, *args, **kwargs):
384    #         return getattr(self._sock, _meth)(*args, **kwargs)
385    #     locals()[_meth] = _wrapped
386    # del _name, _meth, _wrapped
387
388    _forward = {
389        "detach",
390        "get_inheritable",
391        "set_inheritable",
392        "fileno",
393        "getpeername",
394        "getsockname",
395        "getsockopt",
396        "setsockopt",
397        "listen",
398        "share",
399    }
400
401    def __getattr__(self, name):
402        if name in self._forward:
403            return getattr(self._sock, name)
404        raise AttributeError(name)
405
406    def __dir__(self):
407        return super().__dir__() + list(self._forward)
408
409    def __enter__(self):
410        return self
411
412    def __exit__(self, *exc_info):
413        return self._sock.__exit__(*exc_info)
414
415    @property
416    def family(self):
417        return self._sock.family
418
419    @property
420    def type(self):
421        # Modify the socket type do match what is done on python 3.7. When
422        # support for versions older than 3.7 is dropped, this can be updated
423        # to just return self._sock.type
424        return real_socket_type(self._sock.type)
425
426    @property
427    def proto(self):
428        return self._sock.proto
429
430    @property
431    def did_shutdown_SHUT_WR(self):
432        return self._did_shutdown_SHUT_WR
433
434    def __repr__(self):
435        return repr(self._sock).replace("socket.socket", "trio.socket.socket")
436
437    def dup(self):
438        """Same as :meth:`socket.socket.dup`."""
439        return _SocketType(self._sock.dup())
440
441    def close(self):
442        if self._sock.fileno() != -1:
443            trio.lowlevel.notify_closing(self._sock)
444            self._sock.close()
445
446    async def bind(self, address):
447        address = await self._resolve_local_address_nocp(address)
448        if (
449            hasattr(_stdlib_socket, "AF_UNIX")
450            and self.family == _stdlib_socket.AF_UNIX
451            and address[0]
452        ):
453            # Use a thread for the filesystem traversal (unless it's an
454            # abstract domain socket)
455            return await trio.to_thread.run_sync(self._sock.bind, address)
456        else:
457            # POSIX actually says that bind can return EWOULDBLOCK and
458            # complete asynchronously, like connect. But in practice AFAICT
459            # there aren't yet any real systems that do this, so we'll worry
460            # about it when it happens.
461            await trio.lowlevel.checkpoint()
462            return self._sock.bind(address)
463
464    def shutdown(self, flag):
465        # no need to worry about return value b/c always returns None:
466        self._sock.shutdown(flag)
467        # only do this if the call succeeded:
468        if flag in [_stdlib_socket.SHUT_WR, _stdlib_socket.SHUT_RDWR]:
469            self._did_shutdown_SHUT_WR = True
470
471    def is_readable(self):
472        # use select.select on Windows, and select.poll everywhere else
473        if sys.platform == "win32":
474            rready, _, _ = select.select([self._sock], [], [], 0)
475            return bool(rready)
476        p = select.poll()
477        p.register(self._sock, select.POLLIN)
478        return bool(p.poll(0))
479
480    async def wait_writable(self):
481        await _core.wait_writable(self._sock)
482
483    ################################################################
484    # Address handling
485    ################################################################
486
487    # Take an address in Python's representation, and returns a new address in
488    # the same representation, but with names resolved to numbers,
489    # etc.
490    #
491    # NOTE: this function does not always checkpoint
492    async def _resolve_address_nocp(self, address, flags):
493        # Do some pre-checking (or exit early for non-IP sockets)
494        if self._sock.family == _stdlib_socket.AF_INET:
495            if not isinstance(address, tuple) or not len(address) == 2:
496                raise ValueError("address should be a (host, port) tuple")
497        elif self._sock.family == _stdlib_socket.AF_INET6:
498            if not isinstance(address, tuple) or not 2 <= len(address) <= 4:
499                raise ValueError(
500                    "address should be a (host, port, [flowinfo, [scopeid]]) tuple"
501                )
502        elif self._sock.family == _stdlib_socket.AF_UNIX:
503            # unwrap path-likes
504            return os.fspath(address)
505        else:
506            return address
507
508        # -- From here on we know we have IPv4 or IPV6 --
509        host, port, *_ = address
510        # Fast path for the simple case: already-resolved IP address,
511        # already-resolved port. This is particularly important for UDP, since
512        # every sendto call goes through here.
513        if isinstance(port, int):
514            try:
515                _stdlib_socket.inet_pton(self._sock.family, address[0])
516            except (OSError, TypeError):
517                pass
518            else:
519                return address
520        # Special cases to match the stdlib, see gh-277
521        if host == "":
522            host = None
523        if host == "<broadcast>":
524            host = "255.255.255.255"
525        # Since we always pass in an explicit family here, AI_ADDRCONFIG
526        # doesn't add any value -- if we have no ipv6 connectivity and are
527        # working with an ipv6 socket, then things will break soon enough! And
528        # if we do enable it, then it makes it impossible to even run tests
529        # for ipv6 address resolution on travis-ci, which as of 2017-03-07 has
530        # no ipv6.
531        # flags |= AI_ADDRCONFIG
532        if self._sock.family == _stdlib_socket.AF_INET6:
533            if not self._sock.getsockopt(IPPROTO_IPV6, _stdlib_socket.IPV6_V6ONLY):
534                flags |= _stdlib_socket.AI_V4MAPPED
535        gai_res = await getaddrinfo(
536            host, port, self._sock.family, self.type, self._sock.proto, flags
537        )
538        # AFAICT from the spec it's not possible for getaddrinfo to return an
539        # empty list.
540        assert len(gai_res) >= 1
541        # Address is the last item in the first entry
542        (*_, normed), *_ = gai_res
543        # The above ignored any flowid and scopeid in the passed-in address,
544        # so restore them if present:
545        if self._sock.family == _stdlib_socket.AF_INET6:
546            normed = list(normed)
547            assert len(normed) == 4
548            if len(address) >= 3:
549                normed[2] = address[2]
550            if len(address) >= 4:
551                normed[3] = address[3]
552            normed = tuple(normed)
553        return normed
554
555    # Returns something appropriate to pass to bind()
556    #
557    # NOTE: this function does not always checkpoint
558    async def _resolve_local_address_nocp(self, address):
559        return await self._resolve_address_nocp(address, _stdlib_socket.AI_PASSIVE)
560
561    # Returns something appropriate to pass to connect()/sendto()/sendmsg()
562    #
563    # NOTE: this function does not always checkpoint
564    async def _resolve_remote_address_nocp(self, address):
565        return await self._resolve_address_nocp(address, 0)
566
567    async def _nonblocking_helper(self, fn, args, kwargs, wait_fn):
568        # We have to reconcile two conflicting goals:
569        # - We want to make it look like we always blocked in doing these
570        #   operations. The obvious way is to always do an IO wait before
571        #   calling the function.
572        # - But, we also want to provide the correct semantics, and part
573        #   of that means giving correct errors. So, for example, if you
574        #   haven't called .listen(), then .accept() raises an error
575        #   immediately. But in this same circumstance, then on macOS, the
576        #   socket does not register as readable. So if we block waiting
577        #   for read *before* we call accept, then we'll be waiting
578        #   forever instead of properly raising an error. (On Linux,
579        #   interestingly, AFAICT a socket that can't possible read/write
580        #   *does* count as readable/writable for select() purposes. But
581        #   not on macOS.)
582        #
583        # So, we have to call the function once, with the appropriate
584        # cancellation/yielding sandwich if it succeeds, and if it gives
585        # BlockingIOError *then* we fall back to IO wait.
586        #
587        # XX think if this can be combined with the similar logic for IOCP
588        # submission...
589        async with _try_sync():
590            return fn(self._sock, *args, **kwargs)
591        # First attempt raised BlockingIOError:
592        while True:
593            await wait_fn(self._sock)
594            try:
595                return fn(self._sock, *args, **kwargs)
596            except BlockingIOError:
597                pass
598
599    ################################################################
600    # accept
601    ################################################################
602
603    _accept = _make_simple_sock_method_wrapper("accept", _core.wait_readable)
604
605    async def accept(self):
606        """Like :meth:`socket.socket.accept`, but async."""
607        sock, addr = await self._accept()
608        return from_stdlib_socket(sock), addr
609
610    ################################################################
611    # connect
612    ################################################################
613
614    async def connect(self, address):
615        # nonblocking connect is weird -- you call it to start things
616        # off, then the socket becomes writable as a completion
617        # notification. This means it isn't really cancellable... we close the
618        # socket if cancelled, to avoid confusion.
619        try:
620            address = await self._resolve_remote_address_nocp(address)
621            async with _try_sync():
622                # An interesting puzzle: can a non-blocking connect() return EINTR
623                # (= raise InterruptedError)? PEP 475 specifically left this as
624                # the one place where it lets an InterruptedError escape instead
625                # of automatically retrying. This is based on the idea that EINTR
626                # from connect means that the connection was already started, and
627                # will continue in the background. For a blocking connect, this
628                # sort of makes sense: if it returns EINTR then the connection
629                # attempt is continuing in the background, and on many system you
630                # can't then call connect() again because there is already a
631                # connect happening. See:
632                #
633                #   http://www.madore.org/~david/computers/connect-intr.html
634                #
635                # For a non-blocking connect, it doesn't make as much sense --
636                # surely the interrupt didn't happen after we successfully
637                # initiated the connect and are just waiting for it to complete,
638                # because a non-blocking connect does not wait! And the spec
639                # describes the interaction between EINTR/blocking connect, but
640                # doesn't have anything useful to say about non-blocking connect:
641                #
642                #   http://pubs.opengroup.org/onlinepubs/007904975/functions/connect.html
643                #
644                # So we have a conundrum: if EINTR means that the connect() hasn't
645                # happened (like it does for essentially every other syscall),
646                # then InterruptedError should be caught and retried. If EINTR
647                # means that the connect() has successfully started, then
648                # InterruptedError should be caught and ignored. Which should we
649                # do?
650                #
651                # In practice, the resolution is probably that non-blocking
652                # connect simply never returns EINTR, so the question of how to
653                # handle it is moot.  Someone spelunked macOS/FreeBSD and
654                # confirmed this is true there:
655                #
656                #   https://stackoverflow.com/questions/14134440/eintr-and-non-blocking-calls
657                #
658                # and exarkun seems to think it's true in general of non-blocking
659                # calls:
660                #
661                #   https://twistedmatrix.com/pipermail/twisted-python/2010-September/022864.html
662                # (and indeed, AFAICT twisted doesn't try to handle
663                # InterruptedError).
664                #
665                # So we don't try to catch InterruptedError. This way if it
666                # happens, someone will hopefully tell us, and then hopefully we
667                # can investigate their system to figure out what its semantics
668                # are.
669                return self._sock.connect(address)
670            # It raised BlockingIOError, meaning that it's started the
671            # connection attempt. We wait for it to complete:
672            await _core.wait_writable(self._sock)
673        except trio.Cancelled:
674            # We can't really cancel a connect, and the socket is in an
675            # indeterminate state. Better to close it so we don't get
676            # confused.
677            self._sock.close()
678            raise
679        # Okay, the connect finished, but it might have failed:
680        err = self._sock.getsockopt(_stdlib_socket.SOL_SOCKET, _stdlib_socket.SO_ERROR)
681        if err != 0:
682            raise OSError(err, "Error in connect: " + os.strerror(err))
683
684    ################################################################
685    # recv
686    ################################################################
687
688    recv = _make_simple_sock_method_wrapper("recv", _core.wait_readable)
689
690    ################################################################
691    # recv_into
692    ################################################################
693
694    recv_into = _make_simple_sock_method_wrapper("recv_into", _core.wait_readable)
695
696    ################################################################
697    # recvfrom
698    ################################################################
699
700    recvfrom = _make_simple_sock_method_wrapper("recvfrom", _core.wait_readable)
701
702    ################################################################
703    # recvfrom_into
704    ################################################################
705
706    recvfrom_into = _make_simple_sock_method_wrapper(
707        "recvfrom_into", _core.wait_readable
708    )
709
710    ################################################################
711    # recvmsg
712    ################################################################
713
714    if hasattr(_stdlib_socket.socket, "recvmsg"):
715        recvmsg = _make_simple_sock_method_wrapper(
716            "recvmsg", _core.wait_readable, maybe_avail=True
717        )
718
719    ################################################################
720    # recvmsg_into
721    ################################################################
722
723    if hasattr(_stdlib_socket.socket, "recvmsg_into"):
724        recvmsg_into = _make_simple_sock_method_wrapper(
725            "recvmsg_into", _core.wait_readable, maybe_avail=True
726        )
727
728    ################################################################
729    # send
730    ################################################################
731
732    send = _make_simple_sock_method_wrapper("send", _core.wait_writable)
733
734    ################################################################
735    # sendto
736    ################################################################
737
738    @_wraps(_stdlib_socket.socket.sendto, assigned=(), updated=())
739    async def sendto(self, *args):
740        """Similar to :meth:`socket.socket.sendto`, but async."""
741        # args is: data[, flags], address)
742        # and kwargs are not accepted
743        args = list(args)
744        args[-1] = await self._resolve_remote_address_nocp(args[-1])
745        return await self._nonblocking_helper(
746            _stdlib_socket.socket.sendto, args, {}, _core.wait_writable
747        )
748
749    ################################################################
750    # sendmsg
751    ################################################################
752
753    if sys.platform != "win32" or (
754        not TYPE_CHECKING and hasattr(_stdlib_socket.socket, "sendmsg")
755    ):
756
757        @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
758        async def sendmsg(self, *args):
759            """Similar to :meth:`socket.socket.sendmsg`, but async.
760
761            Only available on platforms where :meth:`socket.socket.sendmsg` is
762            available.
763
764            """
765            # args is: buffers[, ancdata[, flags[, address]]]
766            # and kwargs are not accepted
767            if len(args) == 4 and args[-1] is not None:
768                args = list(args)
769                args[-1] = await self._resolve_remote_address_nocp(args[-1])
770            return await self._nonblocking_helper(
771                _stdlib_socket.socket.sendmsg, args, {}, _core.wait_writable
772            )
773
774    ################################################################
775    # sendfile
776    ################################################################
777
778    # Not implemented yet:
779    # async def sendfile(self, file, offset=0, count=None):
780    #     XX
781
782    # Intentionally omitted:
783    #   sendall
784    #   makefile
785    #   setblocking/getblocking
786    #   settimeout/gettimeout
787    #   timeout
788