PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/gevent/socket.py

https://bitbucket.org/op/gevent
Python | 716 lines | 648 code | 26 blank | 42 comment | 23 complexity | 02f9860e1d32a2efb5437824c42dabf4 MD5 | raw file
  1. # Copyright (c) 2005-2006, Bob Ippolito
  2. # Copyright (c) 2007, Linden Research, Inc.
  3. # Copyright (c) 2009-2010 Denis Bilenko
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. # THE SOFTWARE.
  22. """Cooperative socket module.
  23. This module provides socket operations and some related functions.
  24. The API of the functions and classes matches the API of the corresponding
  25. items in standard :mod:`socket` module exactly, but the synchronous functions
  26. in this module only block the current greenlet and let the others run.
  27. For convenience, exceptions (like :class:`error <socket.error>` and :class:`timeout <socket.timeout>`)
  28. as well as the constants from :mod:`socket` module are imported into this module.
  29. """
  30. __all__ = ['create_connection',
  31. 'error',
  32. 'fromfd',
  33. 'gaierror',
  34. 'getaddrinfo',
  35. 'gethostbyname',
  36. 'inet_aton',
  37. 'inet_ntoa',
  38. 'inet_pton',
  39. 'inet_ntop',
  40. 'socket',
  41. 'socketpair',
  42. 'timeout',
  43. 'ssl',
  44. 'sslerror',
  45. 'SocketType',
  46. 'wait_read',
  47. 'wait_write',
  48. 'wait_readwrite']
  49. import sys
  50. import errno
  51. import time
  52. import random
  53. import re
  54. is_windows = sys.platform == 'win32'
  55. if is_windows:
  56. # no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN
  57. from errno import WSAEINVAL as EINVAL
  58. from errno import WSAEWOULDBLOCK as EWOULDBLOCK
  59. from errno import WSAEINPROGRESS as EINPROGRESS
  60. from errno import WSAEALREADY as EALREADY
  61. from errno import WSAEISCONN as EISCONN
  62. from gevent.win32util import formatError as strerror
  63. EGAIN = EWOULDBLOCK
  64. else:
  65. from errno import EINVAL
  66. from errno import EWOULDBLOCK
  67. from errno import EINPROGRESS
  68. from errno import EALREADY
  69. from errno import EAGAIN
  70. from errno import EISCONN
  71. from os import strerror
  72. import _socket
  73. error = _socket.error
  74. timeout = _socket.timeout
  75. _realsocket = _socket.socket
  76. __socket__ = __import__('socket')
  77. _fileobject = __socket__._fileobject
  78. gaierror = _socket.gaierror
  79. # Import public constants from the standard socket (called __socket__ here) into this module.
  80. for name in __socket__.__all__:
  81. if name[:1].isupper():
  82. value = getattr(__socket__, name)
  83. if isinstance(value, (int, basestring)):
  84. globals()[name] = value
  85. __all__.append(name)
  86. elif name == 'getfqdn':
  87. globals()[name] = getattr(__socket__, name)
  88. __all__.append(name)
  89. del name, value
  90. inet_ntoa = _socket.inet_ntoa
  91. inet_aton = _socket.inet_aton
  92. try:
  93. inet_ntop = _socket.inet_ntop
  94. except AttributeError:
  95. def inet_ntop(address_family, packed_ip):
  96. if address_family == AF_INET:
  97. return inet_ntoa(packed_ip)
  98. # XXX: ipv6 won't work on windows
  99. raise NotImplementedError('inet_ntop() is not available on this platform')
  100. try:
  101. inet_pton = _socket.inet_pton
  102. except AttributeError:
  103. def inet_pton(address_family, ip_string):
  104. if address_family == AF_INET:
  105. return inet_aton(ip_string)
  106. # XXX: ipv6 won't work on windows
  107. raise NotImplementedError('inet_ntop() is not available on this platform')
  108. # XXX: import other non-blocking stuff, like ntohl
  109. # XXX: implement blocking functions that are not yet implemented
  110. # XXX: add test that checks that socket.__all__ matches gevent.socket.__all__ on all supported platforms
  111. from gevent.hub import getcurrent, get_hub
  112. from gevent import core
  113. _ip4_re = re.compile('^[\d\.]+$')
  114. def _wait_helper(ev, evtype):
  115. current, timeout_exc = ev.arg
  116. if evtype & core.EV_TIMEOUT:
  117. current.throw(timeout_exc)
  118. else:
  119. current.switch(ev)
  120. def wait_read(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None):
  121. """Block the current greenlet until *fileno* is ready to read.
  122. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
  123. By default *timeout_exc* is ``socket.timeout('timed out')``.
  124. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
  125. """
  126. if event is None:
  127. event = core.read_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
  128. else:
  129. assert event.callback == _wait_helper, event.callback
  130. assert event.arg is None, 'This event is already used by another greenlet: %r' % (event.arg, )
  131. event.arg = (getcurrent(), timeout_exc)
  132. event.add(timeout)
  133. try:
  134. switch_result = get_hub().switch()
  135. assert event is switch_result, 'Invalid switch into wait_read(): %r' % (switch_result, )
  136. finally:
  137. event.cancel()
  138. event.arg = None
  139. def wait_write(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None):
  140. """Block the current greenlet until *fileno* is ready to write.
  141. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
  142. By default *timeout_exc* is ``socket.timeout('timed out')``.
  143. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
  144. """
  145. if event is None:
  146. event = core.write_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
  147. else:
  148. assert event.callback == _wait_helper, event.callback
  149. assert event.arg is None, 'This event is already used by another greenlet: %r' % (event.arg, )
  150. event.arg = (getcurrent(), timeout_exc)
  151. event.add(timeout)
  152. try:
  153. switch_result = get_hub().switch()
  154. assert event is switch_result, 'Invalid switch into wait_write(): %r' % (switch_result, )
  155. finally:
  156. event.arg = None
  157. event.cancel()
  158. def wait_readwrite(fileno, timeout=None, timeout_exc=timeout('timed out'), event=None):
  159. """Block the current greenlet until *fileno* is ready to read or write.
  160. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed.
  161. By default *timeout_exc* is ``socket.timeout('timed out')``.
  162. If :func:`cancel_wait` is called, raise ``socket.error(EBADF, 'File descriptor was closed in another greenlet')``.
  163. """
  164. if event is None:
  165. event = core.readwrite_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
  166. else:
  167. assert event.callback == _wait_helper, event.callback
  168. assert event.arg is None, 'This event is already used by another greenlet: %r' % (event.arg, )
  169. event.arg = (getcurrent(), timeout_exc)
  170. event.add(timeout)
  171. try:
  172. switch_result = get_hub().switch()
  173. assert event is switch_result, 'Invalid switch into wait_readwrite(): %r' % (switch_result, )
  174. finally:
  175. event.arg = None
  176. event.cancel()
  177. def __cancel_wait(event):
  178. if event.pending:
  179. arg = event.arg
  180. if arg is not None:
  181. arg[0].throw(error(errno.EBADF, 'File descriptor was closed in another greenlet'))
  182. def cancel_wait(event):
  183. core.active_event(__cancel_wait, event)
  184. if sys.version_info[:2] <= (2, 4):
  185. # implement close argument to _fileobject that we require
  186. realfileobject = _fileobject
  187. class _fileobject(realfileobject):
  188. __slots__ = realfileobject.__slots__ + ['_close']
  189. def __init__(self, *args, **kwargs):
  190. self._close = kwargs.pop('close', False)
  191. realfileobject.__init__(self, *args, **kwargs)
  192. def close(self):
  193. try:
  194. if self._sock:
  195. self.flush()
  196. finally:
  197. if self._close:
  198. self._sock.close()
  199. self._sock = None
  200. if sys.version_info[:2] < (2, 7):
  201. _get_memory = buffer
  202. else:
  203. def _get_memory(string, offset):
  204. return memoryview(string)[offset:]
  205. class _closedsocket(object):
  206. __slots__ = []
  207. def _dummy(*args):
  208. raise error(errno.EBADF, 'Bad file descriptor')
  209. # All _delegate_methods must also be initialized here.
  210. send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
  211. __getattr__ = _dummy
  212. _delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into", "send", "sendto", 'sendall')
  213. timeout_default = object()
  214. class socket(object):
  215. def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
  216. if _sock is None:
  217. self._sock = _realsocket(family, type, proto)
  218. self.timeout = _socket.getdefaulttimeout()
  219. else:
  220. if hasattr(_sock, '_sock'):
  221. self._sock = _sock._sock
  222. self.timeout = getattr(_sock, 'timeout', False)
  223. if self.timeout is False:
  224. self.timeout = _socket.getdefaulttimeout()
  225. else:
  226. self._sock = _sock
  227. self.timeout = _socket.getdefaulttimeout()
  228. self._sock.setblocking(0)
  229. self._read_event = core.event(core.EV_READ, self.fileno(), _wait_helper)
  230. self._write_event = core.event(core.EV_WRITE, self.fileno(), _wait_helper)
  231. self._rw_event = core.event(core.EV_READ|core.EV_WRITE, self.fileno(), _wait_helper)
  232. def __repr__(self):
  233. return '<%s at %s %s>' % (type(self).__name__, hex(id(self)), self._formatinfo())
  234. def __str__(self):
  235. return '<%s %s>' % (type(self).__name__, self._formatinfo())
  236. def _formatinfo(self):
  237. try:
  238. fileno = self.fileno()
  239. except Exception, ex:
  240. fileno = str(ex)
  241. try:
  242. sockname = self.getsockname()
  243. sockname = '%s:%s' % sockname
  244. except Exception:
  245. sockname = None
  246. try:
  247. peername = self.getpeername()
  248. peername = '%s:%s' % peername
  249. except Exception:
  250. peername = None
  251. result = 'fileno=%s' % fileno
  252. if sockname is not None:
  253. result += ' sock=' + str(sockname)
  254. if peername is not None:
  255. result += ' peer=' + str(peername)
  256. if self.timeout is not None:
  257. result += ' timeout=' + str(self.timeout)
  258. return result
  259. def accept(self):
  260. sock = self._sock
  261. while True:
  262. try:
  263. client_socket, address = sock.accept()
  264. break
  265. except error, ex:
  266. if ex[0] != errno.EWOULDBLOCK or self.timeout == 0.0:
  267. raise
  268. sys.exc_clear()
  269. wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
  270. return socket(_sock=client_socket), address
  271. def close(self):
  272. cancel_wait(self._rw_event)
  273. cancel_wait(self._read_event)
  274. cancel_wait(self._write_event)
  275. self._sock = _closedsocket()
  276. dummy = self._sock._dummy
  277. for method in _delegate_methods:
  278. setattr(self, method, dummy)
  279. def connect(self, address):
  280. if isinstance(address, tuple) and len(address)==2:
  281. address = gethostbyname(address[0]), address[1]
  282. if self.timeout == 0.0:
  283. return self._sock.connect(address)
  284. sock = self._sock
  285. if self.timeout is None:
  286. while True:
  287. err = sock.getsockopt(SOL_SOCKET, SO_ERROR)
  288. if err:
  289. raise error(err, strerror(err))
  290. result = sock.connect_ex(address)
  291. if not result or result == EISCONN:
  292. break
  293. elif (result in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (result == EINVAL and is_windows):
  294. wait_readwrite(sock.fileno(), event=self._rw_event)
  295. else:
  296. raise error(result, strerror(result))
  297. else:
  298. end = time.time() + self.timeout
  299. while True:
  300. err = sock.getsockopt(SOL_SOCKET, SO_ERROR)
  301. if err:
  302. raise error(err, strerror(err))
  303. result = sock.connect_ex(address)
  304. if not result or result == EISCONN:
  305. break
  306. elif (result in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (result == EINVAL and is_windows):
  307. timeleft = end - time.time()
  308. if timeleft <= 0:
  309. raise timeout('timed out')
  310. wait_readwrite(sock.fileno(), timeout=timeleft, event=self._rw_event)
  311. else:
  312. raise error(result, strerror(result))
  313. def connect_ex(self, address):
  314. try:
  315. return self.connect(address) or 0
  316. except timeout:
  317. return EAGAIN
  318. except error, ex:
  319. if type(ex) is error:
  320. return ex[0]
  321. else:
  322. raise # gaierror is not silented by connect_ex
  323. def dup(self):
  324. """dup() -> socket object
  325. Return a new socket object connected to the same system resource.
  326. Note, that the new socket does not inherit the timeout."""
  327. return socket(_sock=self._sock)
  328. def makefile(self, mode='r', bufsize=-1):
  329. # note that this does not inherit timeout either (intentionally, because that's
  330. # how the standard socket behaves)
  331. return _fileobject(self.dup(), mode, bufsize)
  332. def recv(self, *args):
  333. sock = self._sock # keeping the reference so that fd is not closed during waiting
  334. while True:
  335. try:
  336. return sock.recv(*args)
  337. except error, ex:
  338. if ex[0] == errno.EBADF:
  339. return ''
  340. if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
  341. raise
  342. # QQQ without clearing exc_info test__refcount.test_clean_exit fails
  343. sys.exc_clear()
  344. try:
  345. wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
  346. except error, ex:
  347. if ex[0] == errno.EBADF:
  348. return ''
  349. raise
  350. def recvfrom(self, *args):
  351. sock = self._sock
  352. while True:
  353. try:
  354. return sock.recvfrom(*args)
  355. except error, ex:
  356. if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
  357. raise
  358. sys.exc_clear()
  359. wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
  360. def recvfrom_into(self, *args):
  361. sock = self._sock
  362. while True:
  363. try:
  364. return sock.recvfrom_into(*args)
  365. except error, ex:
  366. if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
  367. raise
  368. sys.exc_clear()
  369. wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
  370. def recv_into(self, *args):
  371. sock = self._sock
  372. while True:
  373. try:
  374. return sock.recv_into(*args)
  375. except error, ex:
  376. if ex[0] == errno.EBADF:
  377. return 0
  378. if ex[0] != EWOULDBLOCK or self.timeout == 0.0:
  379. raise
  380. sys.exc_clear()
  381. try:
  382. wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
  383. except error, ex:
  384. if ex[0] == errno.EBADF:
  385. return 0
  386. raise
  387. def send(self, data, flags=0, timeout=timeout_default):
  388. sock = self._sock
  389. if timeout is timeout_default:
  390. timeout = self.timeout
  391. try:
  392. return sock.send(data, flags)
  393. except error, ex:
  394. if ex[0] != EWOULDBLOCK or timeout == 0.0:
  395. raise
  396. sys.exc_clear()
  397. try:
  398. wait_write(sock.fileno(), timeout=timeout, event=self._write_event)
  399. except error, ex:
  400. if ex[0] == errno.EBADF:
  401. return 0
  402. raise
  403. try:
  404. return sock.send(data, flags)
  405. except error, ex2:
  406. if ex2[0] == EWOULDBLOCK:
  407. return 0
  408. raise
  409. def sendall(self, data, flags=0):
  410. if isinstance(data, unicode):
  411. data = data.encode()
  412. # this sendall is also reused by SSL subclasses (both from ssl and sslold modules),
  413. # so it should not call self._sock methods directly
  414. if self.timeout is None:
  415. data_sent = 0
  416. while data_sent < len(data):
  417. data_sent += self.send(_get_memory(data, data_sent), flags)
  418. else:
  419. timeleft = self.timeout
  420. end = time.time() + timeleft
  421. data_sent = 0
  422. while True:
  423. data_sent += self.send(_get_memory(data, data_sent), flags, timeout=timeleft)
  424. if data_sent >= len(data):
  425. break
  426. timeleft = end - time.time()
  427. if timeleft <= 0:
  428. raise timeout('timed out')
  429. def sendto(self, *args):
  430. sock = self._sock
  431. try:
  432. return sock.sendto(*args)
  433. except error, ex:
  434. if ex[0] != EWOULDBLOCK or timeout == 0.0:
  435. raise
  436. sys.exc_clear()
  437. wait_write(sock.fileno(), timeout=self.timeout, event=self._write_event)
  438. try:
  439. return sock.sendto(*args)
  440. except error, ex2:
  441. if ex2[0] == EWOULDBLOCK:
  442. return 0
  443. raise
  444. def setblocking(self, flag):
  445. if flag:
  446. self.timeout = None
  447. else:
  448. self.timeout = 0.0
  449. def settimeout(self, howlong):
  450. if howlong is not None:
  451. try:
  452. f = howlong.__float__
  453. except AttributeError:
  454. raise TypeError('a float is required')
  455. howlong = f()
  456. if howlong < 0.0:
  457. raise ValueError('Timeout value out of range')
  458. self.timeout = howlong
  459. def gettimeout(self):
  460. return self.timeout
  461. family = property(lambda self: self._sock.family, doc="the socket family")
  462. type = property(lambda self: self._sock.type, doc="the socket type")
  463. proto = property(lambda self: self._sock.proto, doc="the socket protocol")
  464. # delegate the functions that we haven't implemented to the real socket object
  465. _s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
  466. "%s.__doc__ = _realsocket.%s.__doc__\n")
  467. for _m in set(__socket__._socketmethods) - set(locals()):
  468. exec _s % (_m, _m, _m, _m)
  469. del _m, _s
  470. SocketType = socket
  471. if hasattr(_socket, 'socketpair'):
  472. def socketpair(*args):
  473. one, two = _socket.socketpair(*args)
  474. return socket(_sock=one), socket(_sock=two)
  475. else:
  476. __all__.remove('socketpair')
  477. if hasattr(_socket, 'fromfd'):
  478. def fromfd(*args):
  479. return socket(_sock=_socket.fromfd(*args))
  480. else:
  481. __all__.remove('fromfd')
  482. def bind_and_listen(descriptor, address=('', 0), backlog=50, reuse_addr=True):
  483. if reuse_addr:
  484. try:
  485. descriptor.setsockopt(SOL_SOCKET, SO_REUSEADDR, descriptor.getsockopt(SOL_SOCKET, SO_REUSEADDR) | 1)
  486. except error:
  487. pass
  488. descriptor.bind(address)
  489. descriptor.listen(backlog)
  490. def tcp_listener(address, backlog=50, reuse_addr=True):
  491. """A shortcut to create a TCP socket, bind it and put it into listening state."""
  492. sock = socket()
  493. bind_and_listen(sock, address, backlog=backlog, reuse_addr=reuse_addr)
  494. return sock
  495. try:
  496. _GLOBAL_DEFAULT_TIMEOUT = __socket__._GLOBAL_DEFAULT_TIMEOUT
  497. except AttributeError:
  498. _GLOBAL_DEFAULT_TIMEOUT = object()
  499. def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None):
  500. """Connect to *address* and return the socket object.
  501. Convenience function. Connect to *address* (a 2-tuple ``(host,
  502. port)``) and return the socket object. Passing the optional
  503. *timeout* parameter will set the timeout on the socket instance
  504. before attempting to connect. If no *timeout* is supplied, the
  505. global default timeout setting returned by :func:`getdefaulttimeout`
  506. is used. If *source_address* is set it must be a tuple of (host, port)
  507. for the socket to bind as a source address before making the connection.
  508. An host of '' or port 0 tells the OS to use the default.
  509. """
  510. msg = "getaddrinfo returns an empty list"
  511. host, port = address
  512. for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  513. af, socktype, proto, _canonname, sa = res
  514. sock = None
  515. try:
  516. sock = socket(af, socktype, proto)
  517. if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
  518. sock.settimeout(timeout)
  519. if source_address:
  520. sock.bind(source_address)
  521. sock.connect(sa)
  522. return sock
  523. except error, msg:
  524. if sock is not None:
  525. sock.close()
  526. raise error, msg
  527. try:
  528. from gevent.dns import resolve_ipv4, resolve_ipv6
  529. except Exception:
  530. import traceback
  531. traceback.print_exc()
  532. __all__.remove('gethostbyname')
  533. __all__.remove('getaddrinfo')
  534. else:
  535. def gethostbyname(hostname):
  536. """:func:`socket.gethostbyname` implemented using :mod:`gevent.dns`.
  537. Differs in the following ways:
  538. * raises :class:`DNSError` (a subclass of :class:`socket.gaierror`) with dns error
  539. codes instead of standard socket error codes
  540. * does not support ``/etc/hosts`` but calls the original :func:`socket.gethostbyname`
  541. if *hostname* has no dots
  542. * does not iterate through all addresses, instead picks a random one each time
  543. """
  544. # TODO: this is supposed to iterate through all the addresses
  545. # could use a global dict(hostname, iter)
  546. # - fix these nasty hacks for localhost, ips, etc.
  547. if not isinstance(hostname, str) or '.' not in hostname:
  548. return _socket.gethostbyname(hostname)
  549. if _ip4_re.match(hostname):
  550. return hostname
  551. if hostname == _socket.gethostname():
  552. return _socket.gethostbyname(hostname)
  553. _ttl, addrs = resolve_ipv4(hostname)
  554. return inet_ntoa(random.choice(addrs))
  555. def getaddrinfo(host, port, *args, **kwargs):
  556. """*Some* approximation of :func:`socket.getaddrinfo` implemented using :mod:`gevent.dns`.
  557. If *host* is not a string, does not has any dots or is a numeric IP address, then
  558. the standard :func:`socket.getaddrinfo` is called.
  559. Otherwise, calls either :func:`resolve_ipv4` or :func:`resolve_ipv6` and
  560. formats the result the way :func:`socket.getaddrinfo` does it.
  561. Differs in the following ways:
  562. * raises :class:`DNSError` (a subclass of :class:`gaierror`) with libevent-dns error
  563. codes instead of standard socket error codes
  564. * IPv6 support is untested.
  565. * AF_UNSPEC only tries IPv4
  566. * only supports TCP, UDP, IP protocols
  567. * port must be numeric, does not support string service names. see socket.getservbyname
  568. * *flags* argument is ignored
  569. Additionally, supports *evdns_flags* keyword arguments (default ``0``) that is passed
  570. to :mod:`dns` functions.
  571. """
  572. family, socktype, proto, _flags = args + (None, ) * (4 - len(args))
  573. if not isinstance(host, str) or '.' not in host or _ip4_re.match(host):
  574. return _socket.getaddrinfo(host, port, *args)
  575. evdns_flags = kwargs.pop('evdns_flags', 0)
  576. if kwargs:
  577. raise TypeError('Unsupported keyword arguments: %s' % (kwargs.keys(), ))
  578. if family in (None, AF_INET, AF_UNSPEC):
  579. family = AF_INET
  580. # TODO: AF_UNSPEC means try both AF_INET and AF_INET6
  581. _ttl, addrs = resolve_ipv4(host, evdns_flags)
  582. elif family == AF_INET6:
  583. _ttl, addrs = resolve_ipv6(host, evdns_flags)
  584. else:
  585. raise NotImplementedError('family is not among AF_UNSPEC/AF_INET/AF_INET6: %r' % (family, ))
  586. socktype_proto = [(SOCK_STREAM, 6), (SOCK_DGRAM, 17), (SOCK_RAW, 0)]
  587. if socktype:
  588. socktype_proto = [(x, y) for (x, y) in socktype_proto if socktype == x]
  589. if proto:
  590. socktype_proto = [(x, y) for (x, y) in socktype_proto if proto == y]
  591. result = []
  592. for addr in addrs:
  593. for socktype, proto in socktype_proto:
  594. result.append((family, socktype, proto, '', (inet_ntop(family, addr), port)))
  595. return result
  596. # TODO libevent2 has getaddrinfo that is probably better than the hack above; should wrap that.
  597. _have_ssl = False
  598. try:
  599. from gevent.ssl import sslwrap_simple as ssl, SSLError as sslerror
  600. _have_ssl = True
  601. except ImportError:
  602. try:
  603. from gevent.sslold import ssl, sslerror
  604. _have_ssl = True
  605. except ImportError:
  606. pass
  607. if not _have_ssl:
  608. __all__.remove('ssl')
  609. __all__.remove('sslerror')