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