You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.6 KiB

4 years ago
  1. """Helper methods to tune a TCP connection"""
  2. import asyncio
  3. import socket
  4. from contextlib import suppress
  5. from typing import Optional # noqa
  6. __all__ = ('tcp_keepalive', 'tcp_nodelay', 'tcp_cork')
  7. if hasattr(socket, 'TCP_CORK'): # pragma: no cover
  8. CORK = socket.TCP_CORK # type: Optional[int]
  9. elif hasattr(socket, 'TCP_NOPUSH'): # pragma: no cover
  10. CORK = socket.TCP_NOPUSH # type: ignore
  11. else: # pragma: no cover
  12. CORK = None
  13. if hasattr(socket, 'SO_KEEPALIVE'):
  14. def tcp_keepalive(transport: asyncio.Transport) -> None:
  15. sock = transport.get_extra_info('socket')
  16. if sock is not None:
  17. sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
  18. else:
  19. def tcp_keepalive(
  20. transport: asyncio.Transport) -> None: # pragma: no cover
  21. pass
  22. def tcp_nodelay(transport: asyncio.Transport, value: bool) -> None:
  23. sock = transport.get_extra_info('socket')
  24. if sock is None:
  25. return
  26. if sock.family not in (socket.AF_INET, socket.AF_INET6):
  27. return
  28. value = bool(value)
  29. # socket may be closed already, on windows OSError get raised
  30. with suppress(OSError):
  31. sock.setsockopt(
  32. socket.IPPROTO_TCP, socket.TCP_NODELAY, value)
  33. def tcp_cork(transport: asyncio.Transport, value: bool) -> None:
  34. sock = transport.get_extra_info('socket')
  35. if CORK is None:
  36. return
  37. if sock is None:
  38. return
  39. if sock.family not in (socket.AF_INET, socket.AF_INET6):
  40. return
  41. value = bool(value)
  42. with suppress(OSError):
  43. sock.setsockopt(
  44. socket.IPPROTO_TCP, CORK, value)