socket.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # Copyright (c) 2009-2014 Denis Bilenko and gevent contributors. See LICENSE for details.
  2. """Cooperative low-level networking interface.
  3. This module provides socket operations and some related functions.
  4. The API of the functions and classes matches the API of the corresponding
  5. items in the standard :mod:`socket` module exactly, but the synchronous functions
  6. in this module only block the current greenlet and let the others run.
  7. For convenience, exceptions (like :class:`error <socket.error>` and :class:`timeout <socket.timeout>`)
  8. as well as the constants from the :mod:`socket` module are imported into this module.
  9. """
  10. # Our import magic sadly makes this warning useless
  11. # pylint: disable=undefined-variable
  12. import sys
  13. from gevent._compat import PY3
  14. from gevent._util import copy_globals
  15. if PY3:
  16. from gevent import _socket3 as _source # python 2: pylint:disable=no-name-in-module
  17. else:
  18. from gevent import _socket2 as _source
  19. # define some things we're expecting to overwrite; each module
  20. # needs to define these
  21. __implements__ = __dns__ = __all__ = __extensions__ = __imports__ = ()
  22. class error(Exception):
  23. errno = None
  24. def getfqdn(*args):
  25. # pylint:disable=unused-argument
  26. raise NotImplementedError()
  27. copy_globals(_source, globals(),
  28. dunder_names_to_keep=('__implements__', '__dns__', '__all__',
  29. '__extensions__', '__imports__', '__socket__'),
  30. cleanup_globs=False)
  31. # The _socket2 and _socket3 don't import things defined in
  32. # __extensions__, to help avoid confusing reference cycles in the
  33. # documentation and to prevent importing from the wrong place, but we
  34. # *do* need to expose them here. (NOTE: This may lead to some sphinx
  35. # warnings like:
  36. # WARNING: missing attribute mentioned in :members: or __all__:
  37. # module gevent._socket2, attribute cancel_wait
  38. # These can be ignored.)
  39. from gevent import _socketcommon
  40. copy_globals(_socketcommon, globals(),
  41. only_names=_socketcommon.__extensions__)
  42. try:
  43. _GLOBAL_DEFAULT_TIMEOUT = __socket__._GLOBAL_DEFAULT_TIMEOUT
  44. except AttributeError:
  45. _GLOBAL_DEFAULT_TIMEOUT = object()
  46. def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
  47. """Connect to *address* and return the socket object.
  48. Convenience function. Connect to *address* (a 2-tuple ``(host,
  49. port)``) and return the socket object. Passing the optional
  50. *timeout* parameter will set the timeout on the socket instance
  51. before attempting to connect. If no *timeout* is supplied, the
  52. global default timeout setting returned by :func:`getdefaulttimeout`
  53. is used. If *source_address* is set it must be a tuple of (host, port)
  54. for the socket to bind as a source address before making the connection.
  55. A host of '' or port 0 tells the OS to use the default.
  56. """
  57. host, port = address
  58. err = None
  59. for res in getaddrinfo(host, port, 0 if has_ipv6 else AF_INET, SOCK_STREAM):
  60. af, socktype, proto, _, sa = res
  61. sock = None
  62. try:
  63. sock = socket(af, socktype, proto)
  64. if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
  65. sock.settimeout(timeout)
  66. if source_address:
  67. sock.bind(source_address)
  68. sock.connect(sa)
  69. return sock
  70. except error as ex:
  71. # without exc_clear(), if connect() fails once, the socket is referenced by the frame in exc_info
  72. # and the next bind() fails (see test__socket.TestCreateConnection)
  73. # that does not happen with regular sockets though, because _socket.socket.connect() is a built-in.
  74. # this is similar to "getnameinfo loses a reference" failure in test_socket.py
  75. if not PY3:
  76. sys.exc_clear() # pylint:disable=no-member,useless-suppression
  77. if sock is not None:
  78. sock.close()
  79. err = ex
  80. if err is not None:
  81. raise err # pylint:disable=raising-bad-type
  82. else:
  83. raise error("getaddrinfo returns an empty list")
  84. # This is promised to be in the __all__ of the _source, but, for circularity reasons,
  85. # we implement it in this module. Mostly for documentation purposes, put it
  86. # in the _source too.
  87. _source.create_connection = create_connection