_socketcommon.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. # Copyright (c) 2009-2014 Denis Bilenko and gevent contributors. See LICENSE for details.
  2. from __future__ import absolute_import
  3. # standard functions and classes that this module re-implements in a gevent-aware way:
  4. _implements = [
  5. 'create_connection',
  6. 'socket',
  7. 'SocketType',
  8. 'fromfd',
  9. 'socketpair',
  10. ]
  11. __dns__ = [
  12. 'getaddrinfo',
  13. 'gethostbyname',
  14. 'gethostbyname_ex',
  15. 'gethostbyaddr',
  16. 'getnameinfo',
  17. 'getfqdn',
  18. ]
  19. _implements += __dns__
  20. # non-standard functions that this module provides:
  21. __extensions__ = [
  22. 'cancel_wait',
  23. 'wait_read',
  24. 'wait_write',
  25. 'wait_readwrite',
  26. ]
  27. # standard functions and classes that this module re-imports
  28. __imports__ = [
  29. 'error',
  30. 'gaierror',
  31. 'herror',
  32. 'htonl',
  33. 'htons',
  34. 'ntohl',
  35. 'ntohs',
  36. 'inet_aton',
  37. 'inet_ntoa',
  38. 'inet_pton',
  39. 'inet_ntop',
  40. 'timeout',
  41. 'gethostname',
  42. 'getprotobyname',
  43. 'getservbyname',
  44. 'getservbyport',
  45. 'getdefaulttimeout',
  46. 'setdefaulttimeout',
  47. # Windows:
  48. 'errorTab',
  49. ]
  50. __py3_imports__ = [
  51. # Python 3
  52. 'AddressFamily',
  53. 'SocketKind',
  54. 'CMSG_LEN',
  55. 'CMSG_SPACE',
  56. 'dup',
  57. 'if_indextoname',
  58. 'if_nameindex',
  59. 'if_nametoindex',
  60. 'sethostname',
  61. ]
  62. __imports__.extend(__py3_imports__)
  63. import sys
  64. from gevent.hub import get_hub
  65. from gevent.hub import ConcurrentObjectUseError
  66. from gevent.timeout import Timeout
  67. from gevent._compat import string_types, integer_types, PY3
  68. from gevent._util import copy_globals
  69. from gevent._util import _NONE
  70. is_windows = sys.platform == 'win32'
  71. # pylint:disable=no-name-in-module,unused-import
  72. if is_windows:
  73. # no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN
  74. from errno import WSAEINVAL as EINVAL
  75. from errno import WSAEWOULDBLOCK as EWOULDBLOCK
  76. from errno import WSAEINPROGRESS as EINPROGRESS
  77. from errno import WSAEALREADY as EALREADY
  78. from errno import WSAEISCONN as EISCONN
  79. from gevent.win32util import formatError as strerror
  80. EAGAIN = EWOULDBLOCK
  81. else:
  82. from errno import EINVAL
  83. from errno import EWOULDBLOCK
  84. from errno import EINPROGRESS
  85. from errno import EALREADY
  86. from errno import EAGAIN
  87. from errno import EISCONN
  88. from os import strerror
  89. try:
  90. from errno import EBADF
  91. except ImportError:
  92. EBADF = 9
  93. import _socket
  94. _realsocket = _socket.socket
  95. import socket as __socket__
  96. _name = _value = None
  97. __imports__ = copy_globals(__socket__, globals(),
  98. only_names=__imports__,
  99. ignore_missing_names=True)
  100. for _name in __socket__.__all__:
  101. _value = getattr(__socket__, _name)
  102. if isinstance(_value, (integer_types, string_types)):
  103. globals()[_name] = _value
  104. __imports__.append(_name)
  105. del _name, _value
  106. _timeout_error = timeout # pylint: disable=undefined-variable
  107. def wait(io, timeout=None, timeout_exc=_NONE):
  108. """
  109. Block the current greenlet until *io* is ready.
  110. If *timeout* is non-negative, then *timeout_exc* is raised after
  111. *timeout* second has passed. By default *timeout_exc* is
  112. ``socket.timeout('timed out')``.
  113. If :func:`cancel_wait` is called on *io* by another greenlet,
  114. raise an exception in this blocking greenlet
  115. (``socket.error(EBADF, 'File descriptor was closed in another
  116. greenlet')`` by default).
  117. :param io: A libev watcher, most commonly an IO watcher obtained from
  118. :meth:`gevent.core.loop.io`
  119. :keyword timeout_exc: The exception to raise if the timeout expires.
  120. By default, a :class:`socket.timeout` exception is raised.
  121. If you pass a value for this keyword, it is interpreted as for
  122. :class:`gevent.timeout.Timeout`.
  123. """
  124. if io.callback is not None:
  125. raise ConcurrentObjectUseError('This socket is already used by another greenlet: %r' % (io.callback, ))
  126. if timeout is not None:
  127. timeout_exc = timeout_exc if timeout_exc is not _NONE else _timeout_error('timed out')
  128. timeout = Timeout.start_new(timeout, timeout_exc)
  129. try:
  130. return get_hub().wait(io)
  131. finally:
  132. if timeout is not None:
  133. timeout.cancel()
  134. # rename "io" to "watcher" because wait() works with any watcher
  135. def wait_read(fileno, timeout=None, timeout_exc=_NONE):
  136. """
  137. Block the current greenlet until *fileno* is ready to read.
  138. For the meaning of the other parameters and possible exceptions,
  139. see :func:`wait`.
  140. .. seealso:: :func:`cancel_wait`
  141. """
  142. io = get_hub().loop.io(fileno, 1)
  143. return wait(io, timeout, timeout_exc)
  144. def wait_write(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
  145. """
  146. Block the current greenlet until *fileno* is ready to write.
  147. For the meaning of the other parameters and possible exceptions,
  148. see :func:`wait`.
  149. :keyword event: Ignored. Applications should not pass this parameter.
  150. In the future, it may become an error.
  151. .. seealso:: :func:`cancel_wait`
  152. """
  153. # pylint:disable=unused-argument
  154. io = get_hub().loop.io(fileno, 2)
  155. return wait(io, timeout, timeout_exc)
  156. def wait_readwrite(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
  157. """
  158. Block the current greenlet until *fileno* is ready to read or
  159. write.
  160. For the meaning of the other parameters and possible exceptions,
  161. see :func:`wait`.
  162. :keyword event: Ignored. Applications should not pass this parameter.
  163. In the future, it may become an error.
  164. .. seealso:: :func:`cancel_wait`
  165. """
  166. # pylint:disable=unused-argument
  167. io = get_hub().loop.io(fileno, 3)
  168. return wait(io, timeout, timeout_exc)
  169. #: The exception raised by default on a call to :func:`cancel_wait`
  170. class cancel_wait_ex(error): # pylint: disable=undefined-variable
  171. def __init__(self):
  172. super(cancel_wait_ex, self).__init__(
  173. EBADF,
  174. 'File descriptor was closed in another greenlet')
  175. def cancel_wait(watcher, error=cancel_wait_ex):
  176. """See :meth:`gevent.hub.Hub.cancel_wait`"""
  177. get_hub().cancel_wait(watcher, error)
  178. class BlockingResolver(object):
  179. def __init__(self, hub=None):
  180. pass
  181. def close(self):
  182. pass
  183. for method in ['gethostbyname',
  184. 'gethostbyname_ex',
  185. 'getaddrinfo',
  186. 'gethostbyaddr',
  187. 'getnameinfo']:
  188. locals()[method] = staticmethod(getattr(_socket, method))
  189. def gethostbyname(hostname):
  190. """
  191. gethostbyname(host) -> address
  192. Return the IP address (a string of the form '255.255.255.255') for a host.
  193. .. seealso:: :doc:`dns`
  194. """
  195. return get_hub().resolver.gethostbyname(hostname)
  196. def gethostbyname_ex(hostname):
  197. """
  198. gethostbyname_ex(host) -> (name, aliaslist, addresslist)
  199. Return the true host name, a list of aliases, and a list of IP addresses,
  200. for a host. The host argument is a string giving a host name or IP number.
  201. Resolve host and port into list of address info entries.
  202. .. seealso:: :doc:`dns`
  203. """
  204. return get_hub().resolver.gethostbyname_ex(hostname)
  205. def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0):
  206. """
  207. Resolve host and port into list of address info entries.
  208. Translate the host/port argument into a sequence of 5-tuples that contain
  209. all the necessary arguments for creating a socket connected to that service.
  210. host is a domain name, a string representation of an IPv4/v6 address or
  211. None. port is a string service name such as 'http', a numeric port number or
  212. None. By passing None as the value of host and port, you can pass NULL to
  213. the underlying C API.
  214. The family, type and proto arguments can be optionally specified in order to
  215. narrow the list of addresses returned. Passing zero as a value for each of
  216. these arguments selects the full range of results.
  217. .. seealso:: :doc:`dns`
  218. """
  219. return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags)
  220. if PY3:
  221. # The name of the socktype param changed to type in Python 3.
  222. # See https://github.com/gevent/gevent/issues/960
  223. # Using inspect here to directly detect the condition is painful because we have to
  224. # wrap it with a try/except TypeError because not all Python 2
  225. # versions can get the args of a builtin; we also have to use a with to suppress
  226. # the deprecation warning.
  227. d = getaddrinfo.__doc__
  228. def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): # pylint:disable=function-redefined
  229. return get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags)
  230. getaddrinfo.__doc__ = d
  231. del d
  232. def gethostbyaddr(ip_address):
  233. """
  234. gethostbyaddr(ip_address) -> (name, aliaslist, addresslist)
  235. Return the true host name, a list of aliases, and a list of IP addresses,
  236. for a host. The host argument is a string giving a host name or IP number.
  237. .. seealso:: :doc:`dns`
  238. """
  239. return get_hub().resolver.gethostbyaddr(ip_address)
  240. def getnameinfo(sockaddr, flags):
  241. """
  242. getnameinfo(sockaddr, flags) -> (host, port)
  243. Get host and port for a sockaddr.
  244. .. seealso:: :doc:`dns`
  245. """
  246. return get_hub().resolver.getnameinfo(sockaddr, flags)
  247. def getfqdn(name=''):
  248. """Get fully qualified domain name from name.
  249. An empty argument is interpreted as meaning the local host.
  250. First the hostname returned by gethostbyaddr() is checked, then
  251. possibly existing aliases. In case no FQDN is available, hostname
  252. from gethostname() is returned.
  253. """
  254. # pylint: disable=undefined-variable
  255. name = name.strip()
  256. if not name or name == '0.0.0.0':
  257. name = gethostname()
  258. try:
  259. hostname, aliases, _ = gethostbyaddr(name)
  260. except error:
  261. pass
  262. else:
  263. aliases.insert(0, hostname)
  264. for name in aliases: # EWW! pylint:disable=redefined-argument-from-local
  265. if isinstance(name, bytes):
  266. if b'.' in name:
  267. break
  268. elif '.' in name:
  269. break
  270. else:
  271. name = hostname
  272. return name