1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
|
# Port of Python 3.3's socket module to gevent
"""
Python 3 socket module.
"""
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
# pylint: disable=too-many-statements,too-many-branches
# pylint: disable=too-many-public-methods,unused-argument
from __future__ import absolute_import
import io
import os
import sys
from gevent import _socketcommon
from gevent._util import copy_globals
from gevent._compat import PYPY
from gevent.timeout import Timeout
import _socket
from os import dup
copy_globals(_socketcommon, globals(),
names_to_ignore=_socketcommon.__extensions__,
dunder_names_to_keep=())
try:
from errno import EHOSTUNREACH
from errno import ECONNREFUSED
except ImportError:
EHOSTUNREACH = -1
ECONNREFUSED = -1
__socket__ = _socketcommon.__socket__
__implements__ = _socketcommon._implements
__extensions__ = _socketcommon.__extensions__
__imports__ = _socketcommon.__imports__
__dns__ = _socketcommon.__dns__
SocketIO = __socket__.SocketIO # pylint:disable=no-member
def _get_memory(data):
mv = memoryview(data)
if mv.shape:
return mv
# No shape, probably working with a ctypes object,
# or something else exotic that supports the buffer interface
return mv.tobytes()
timeout_default = object()
class _wrefsocket(_socket.socket):
# Plain stdlib socket.socket objects subclass _socket.socket
# and add weakref ability. The ssl module, for one, counts on this.
# We don't create socket.socket objects (because they may have been
# monkey patched to be the object from this module), but we still
# need to make sure what we do create can be weakrefd.
__slots__ = ("__weakref__", )
if PYPY:
# server.py unwraps the socket object to get the raw _sock;
# it depends on having a timeout property alias, which PyPy does not
# provide.
timeout = property(lambda s: s.gettimeout(),
lambda s, nv: s.settimeout(nv))
from gevent._hub_primitives import wait_on_socket as _wait_on_socket
class socket(object):
"""
gevent `socket.socket <https://docs.python.org/3/library/socket.html#socket-objects>`_
for Python 3.
This object should have the same API as the standard library socket linked to above. Not all
methods are specifically documented here; when they are they may point out a difference
to be aware of or may document a method the standard library does not.
"""
# Subclasses can set this to customize the type of the
# native _socket.socket we create. It MUST be a subclass
# of _wrefsocket. (gevent internal usage only)
_gevent_sock_class = _wrefsocket
_io_refs = 0
_closed = False
_read_event = None
_write_event = None
# Take the same approach as socket2: wrap a real socket object,
# don't subclass it. This lets code that needs the raw _sock (not tied to the hub)
# get it. This shows up in tests like test__example_udp_server.
if sys.version_info[:2] < (3, 7):
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
self._sock = self._gevent_sock_class(family, type, proto, fileno)
self.timeout = None
self.__init_common()
else:
# In 3.7, socket changed to auto-detecting family, type, and proto
# when given a fileno.
def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
if fileno is None:
if family == -1:
family = AF_INET
if type == -1:
type = SOCK_STREAM
if proto == -1:
proto = 0
self._sock = self._gevent_sock_class(family, type, proto, fileno)
self.timeout = None
self.__init_common()
def __init_common(self):
_socket.socket.setblocking(self._sock, False)
fileno = _socket.socket.fileno(self._sock)
self.hub = get_hub()
io_class = self.hub.loop.io
self._read_event = io_class(fileno, 1)
self._write_event = io_class(fileno, 2)
self.timeout = _socket.getdefaulttimeout()
def __getattr__(self, name):
return getattr(self._sock, name)
if hasattr(_socket, 'SOCK_NONBLOCK'):
# Only defined under Linux
@property
def type(self):
# See https://github.com/gevent/gevent/pull/399
if self.timeout != 0.0:
return self._sock.type & ~_socket.SOCK_NONBLOCK # pylint:disable=no-member
return self._sock.type
def getblocking(self):
"""
Returns whether the socket will approximate blocking
behaviour.
.. versionadded:: 1.3a2
Added in Python 3.7.
"""
return self.timeout != 0.0
def __enter__(self):
return self
def __exit__(self, *args):
if not self._closed:
self.close()
def __repr__(self):
"""Wrap __repr__() to reveal the real class name."""
try:
s = _socket.socket.__repr__(self._sock)
except Exception as ex: # pylint:disable=broad-except
# Observed on Windows Py3.3, printing the repr of a socket
# that just suffered a ConnectionResetError [WinError 10054]:
# "OverflowError: no printf formatter to display the socket descriptor in decimal"
# Not sure what the actual cause is or if there's a better way to handle this
s = '<socket [%r]>' % ex
if s.startswith("<socket object"):
s = "<%s.%s%s%s" % (self.__class__.__module__,
self.__class__.__name__,
getattr(self, '_closed', False) and " [closed] " or "",
s[7:])
return s
def __getstate__(self):
raise TypeError("Cannot serialize socket object")
def _get_ref(self):
return self._read_event.ref or self._write_event.ref
def _set_ref(self, value):
self._read_event.ref = value
self._write_event.ref = value
ref = property(_get_ref, _set_ref)
_wait = _wait_on_socket
def dup(self):
"""dup() -> socket object
Return a new socket object connected to the same system resource.
"""
fd = dup(self.fileno())
sock = self.__class__(self.family, self.type, self.proto, fileno=fd)
sock.settimeout(self.gettimeout())
return sock
def accept(self):
"""accept() -> (socket object, address info)
Wait for an incoming connection. Return a new socket
representing the connection, and the address of the client.
For IP sockets, the address info is a pair (hostaddr, port).
"""
while True:
try:
fd, addr = self._accept()
break
except BlockingIOError:
if self.timeout == 0.0:
raise
self._wait(self._read_event)
sock = socket(self.family, self.type, self.proto, fileno=fd)
# Python Issue #7995: if no default timeout is set and the listening
# socket had a (non-zero) timeout, force the new socket in blocking
# mode to override platform-specific socket flags inheritance.
# XXX do we need to do this?
if getdefaulttimeout() is None and self.gettimeout():
sock.setblocking(True)
return sock, addr
def makefile(self, mode="r", buffering=None, *,
encoding=None, errors=None, newline=None):
"""Return an I/O stream connected to the socket
The arguments are as for io.open() after the filename,
except the only mode characters supported are 'r', 'w' and 'b'.
The semantics are similar too.
"""
# (XXX refactor to share code?)
for c in mode:
if c not in {"r", "w", "b"}:
raise ValueError("invalid mode %r (only r, w, b allowed)")
writing = "w" in mode
reading = "r" in mode or not writing
assert reading or writing
binary = "b" in mode
rawmode = ""
if reading:
rawmode += "r"
if writing:
rawmode += "w"
raw = SocketIO(self, rawmode)
self._io_refs += 1
if buffering is None:
buffering = -1
if buffering < 0:
buffering = io.DEFAULT_BUFFER_SIZE
if buffering == 0:
if not binary:
raise ValueError("unbuffered streams must be binary")
return raw
if reading and writing:
buffer = io.BufferedRWPair(raw, raw, buffering)
elif reading:
buffer = io.BufferedReader(raw, buffering)
else:
assert writing
buffer = io.BufferedWriter(raw, buffering)
if binary:
return buffer
text = io.TextIOWrapper(buffer, encoding, errors, newline)
text.mode = mode
return text
def _decref_socketios(self):
# Called by SocketIO when it is closed.
if self._io_refs > 0:
self._io_refs -= 1
if self._closed:
self.close()
def _drop_events(self):
if self._read_event is not None:
self.hub.cancel_wait(self._read_event, cancel_wait_ex, True)
self._read_event = None
if self._write_event is not None:
self.hub.cancel_wait(self._write_event, cancel_wait_ex, True)
self._write_event = None
def _real_close(self, _ss=_socket.socket, cancel_wait_ex=cancel_wait_ex):
# This function should not reference any globals. See Python issue #808164.
# Break any reference to the loop.io objects. Our fileno,
# which they were tied to, is now free to be reused, so these
# objects are no longer functional.
self._drop_events()
_ss.close(self._sock)
# Break any references to the underlying socket object. Tested
# by test__refcount. (Why does this matter?). Be sure to
# preserve our same family/type/proto if possible (if we
# don't, we can get TypeError instead of OSError; see
# test_socket.SendmsgUDP6Test.testSendmsgAfterClose)... but
# this isn't always possible (see test_socket.test_unknown_socket_family_repr)
# TODO: Can we use a simpler proxy, like _socket2 does?
try:
self._sock = self._gevent_sock_class(self.family, self.type, self.proto)
except OSError:
pass
else:
_ss.close(self._sock)
def close(self):
# This function should not reference any globals. See Python issue #808164.
self._closed = True
if self._io_refs <= 0:
self._real_close()
@property
def closed(self):
return self._closed
def detach(self):
"""detach() -> file descriptor
Close the socket object without closing the underlying file descriptor.
The object cannot be used after this call, but the file descriptor
can be reused for other purposes. The file descriptor is returned.
"""
self._closed = True
return self._sock.detach()
def connect(self, address):
if self.timeout == 0.0:
return _socket.socket.connect(self._sock, address)
address = _socketcommon._resolve_addr(self._sock, address)
with Timeout._start_new_or_dummy(self.timeout, timeout("timed out")):
while True:
err = self.getsockopt(SOL_SOCKET, SO_ERROR)
if err:
raise error(err, strerror(err))
result = _socket.socket.connect_ex(self._sock, address)
if not result or result == EISCONN:
break
elif (result in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (result == EINVAL and is_windows):
self._wait(self._write_event)
else:
if (isinstance(address, tuple)
and address[0] == 'fe80::1'
and result == EHOSTUNREACH):
# On Python 3.7 on mac, we see EHOSTUNREACH
# returned for this link-local address, but it really is
# supposed to be ECONNREFUSED according to the standard library
# tests (test_socket.NetworkConnectionNoServer.test_create_connection)
# (On previous versions, that code passed the '127.0.0.1' IPv4 address, so
# ipv6 link locals were never a factor; 3.7 passes 'localhost'.)
# It is something of a mystery how the stdlib socket code doesn't
# produce EHOSTUNREACH---I (JAM) can't see how socketmodule.c would avoid
# that. The normal connect just calls connect_ex much like we do.
result = ECONNREFUSED
raise error(result, strerror(result))
def connect_ex(self, address):
try:
return self.connect(address) or 0
except timeout:
return EAGAIN
except gaierror: # pylint:disable=try-except-raise
# gaierror/overflowerror/typerror is not silenced by connect_ex;
# gaierror extends OSError (aka error) so catch it first
raise
except error as ex:
# error is now OSError and it has various subclasses.
# Only those that apply to actually connecting are silenced by
# connect_ex.
if ex.errno:
return ex.errno
raise # pragma: no cover
def recv(self, *args):
while True:
try:
return _socket.socket.recv(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
if hasattr(_socket.socket, 'recvmsg'):
# Only on Unix; PyPy 3.5 5.10.0 provides sendmsg and recvmsg, but not
# recvmsg_into (at least on os x)
def recvmsg(self, *args):
while True:
try:
return _socket.socket.recvmsg(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
if hasattr(_socket.socket, 'recvmsg_into'):
def recvmsg_into(self, *args):
while True:
try:
return _socket.socket.recvmsg_into(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
def recvfrom(self, *args):
while True:
try:
return _socket.socket.recvfrom(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
def recvfrom_into(self, *args):
while True:
try:
return _socket.socket.recvfrom_into(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
def recv_into(self, *args):
while True:
try:
return _socket.socket.recv_into(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._read_event)
def send(self, data, flags=0, timeout=timeout_default):
if timeout is timeout_default:
timeout = self.timeout
try:
return _socket.socket.send(self._sock, data, flags)
except error as ex:
if ex.args[0] not in _socketcommon.GSENDAGAIN or timeout == 0.0:
raise
self._wait(self._write_event)
try:
return _socket.socket.send(self._sock, data, flags)
except error as ex2:
if ex2.args[0] == EWOULDBLOCK:
return 0
raise
def sendall(self, data, flags=0):
# XXX Now that we run on PyPy3, see the notes in _socket2.py's sendall()
# and implement that here if needed.
# PyPy3 is not optimized for performance yet, and is known to be slower than
# PyPy2, so it's possibly premature to do this. However, there is a 3.5 test case that
# possibly exposes this in a severe way.
data_memory = _get_memory(data)
return _socketcommon._sendall(self, data_memory, flags)
def sendto(self, *args):
try:
return _socket.socket.sendto(self._sock, *args)
except error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._write_event)
try:
return _socket.socket.sendto(self._sock, *args)
except error as ex2:
if ex2.args[0] == EWOULDBLOCK:
return 0
raise
if hasattr(_socket.socket, 'sendmsg'):
# Only on Unix
def sendmsg(self, buffers, ancdata=(), flags=0, address=None):
try:
return _socket.socket.sendmsg(self._sock, buffers, ancdata, flags, address)
except error as ex:
if flags & getattr(_socket, 'MSG_DONTWAIT', 0):
# Enable non-blocking behaviour
# XXX: Do all platforms that have sendmsg have MSG_DONTWAIT?
raise
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
self._wait(self._write_event)
try:
return _socket.socket.sendmsg(self._sock, buffers, ancdata, flags, address)
except error as ex2:
if ex2.args[0] == EWOULDBLOCK:
return 0
raise
def setblocking(self, flag):
# Beginning in 3.6.0b3 this is supposed to raise
# if the file descriptor is closed, but the test for it
# involves closing the fileno directly. Since we
# don't touch the fileno here, it doesn't make sense for
# us.
if flag:
self.timeout = None
else:
self.timeout = 0.0
def settimeout(self, howlong):
if howlong is not None:
try:
f = howlong.__float__
except AttributeError:
raise TypeError('a float is required')
howlong = f()
if howlong < 0.0:
raise ValueError('Timeout value out of range')
self.__dict__['timeout'] = howlong
def gettimeout(self):
return self.__dict__['timeout']
def shutdown(self, how):
if how == 0: # SHUT_RD
self.hub.cancel_wait(self._read_event, cancel_wait_ex)
elif how == 1: # SHUT_WR
self.hub.cancel_wait(self._write_event, cancel_wait_ex)
else:
self.hub.cancel_wait(self._read_event, cancel_wait_ex)
self.hub.cancel_wait(self._write_event, cancel_wait_ex)
self._sock.shutdown(how)
# sendfile: new in 3.5. But there's no real reason to not
# support it everywhere. Note that we can't use os.sendfile()
# because it's not cooperative.
def _sendfile_use_sendfile(self, file, offset=0, count=None):
# This is called directly by tests
raise __socket__._GiveupOnSendfile() # pylint:disable=no-member
def _sendfile_use_send(self, file, offset=0, count=None):
self._check_sendfile_params(file, offset, count)
if self.gettimeout() == 0:
raise ValueError("non-blocking sockets are not supported")
if offset:
file.seek(offset)
blocksize = min(count, 8192) if count else 8192
total_sent = 0
# localize variable access to minimize overhead
file_read = file.read
sock_send = self.send
try:
while True:
if count:
blocksize = min(count - total_sent, blocksize)
if blocksize <= 0:
break
data = memoryview(file_read(blocksize))
if not data:
break # EOF
while True:
try:
sent = sock_send(data)
except BlockingIOError:
continue
else:
total_sent += sent
if sent < len(data):
data = data[sent:]
else:
break
return total_sent
finally:
if total_sent > 0 and hasattr(file, 'seek'):
file.seek(offset + total_sent)
def _check_sendfile_params(self, file, offset, count):
if 'b' not in getattr(file, 'mode', 'b'):
raise ValueError("file should be opened in binary mode")
if not self.type & SOCK_STREAM:
raise ValueError("only SOCK_STREAM type sockets are supported")
if count is not None:
if not isinstance(count, int):
raise TypeError(
"count must be a positive integer (got {!r})".format(count))
if count <= 0:
raise ValueError(
"count must be a positive integer (got {!r})".format(count))
def sendfile(self, file, offset=0, count=None):
"""sendfile(file[, offset[, count]]) -> sent
Send a file until EOF is reached by using high-performance
os.sendfile() and return the total number of bytes which
were sent.
*file* must be a regular file object opened in binary mode.
If os.sendfile() is not available (e.g. Windows) or file is
not a regular file socket.send() will be used instead.
*offset* tells from where to start reading the file.
If specified, *count* is the total number of bytes to transmit
as opposed to sending the file until EOF is reached.
File position is updated on return or also in case of error in
which case file.tell() can be used to figure out the number of
bytes which were sent.
The socket must be of SOCK_STREAM type.
Non-blocking sockets are not supported.
.. versionadded:: 1.1rc4
Added in Python 3.5, but available under all Python 3 versions in
gevent.
"""
return self._sendfile_use_send(file, offset, count)
# get/set_inheritable new in 3.4
if hasattr(os, 'get_inheritable') or hasattr(os, 'get_handle_inheritable'):
# pylint:disable=no-member
if os.name == 'nt':
def get_inheritable(self):
return os.get_handle_inheritable(self.fileno())
def set_inheritable(self, inheritable):
os.set_handle_inheritable(self.fileno(), inheritable)
else:
def get_inheritable(self):
return os.get_inheritable(self.fileno())
def set_inheritable(self, inheritable):
os.set_inheritable(self.fileno(), inheritable)
_added = "\n\n.. versionadded:: 1.1rc4 Added in Python 3.4"
get_inheritable.__doc__ = "Get the inheritable flag of the socket" + _added
set_inheritable.__doc__ = "Set the inheritable flag of the socket" + _added
del _added
if sys.version_info[:2] == (3, 4) and sys.version_info[:3] <= (3, 4, 2):
# Python 3.4, up to and including 3.4.2, had a bug where the
# SocketType enumeration overwrote the SocketType class imported
# from _socket. This was fixed in 3.4.3 (http://bugs.python.org/issue20386
# and https://github.com/python/cpython/commit/0d2f85f38a9691efdfd1e7285c4262cab7f17db7).
# Prior to that, if we replace SocketType with our own class, the implementation
# of socket.type breaks with "OSError: [Errno 97] Address family not supported by protocol".
# Therefore, on these old versions, we must preserve it as an enum; while this
# seems like it could lead to non-green behaviour, code on those versions
# cannot possibly be using SocketType as a class anyway.
SocketType = __socket__.SocketType # pylint:disable=no-member
# Fixup __all__; note that we get exec'd multiple times during unit tests
if 'SocketType' in __implements__:
__implements__.remove('SocketType')
if 'SocketType' not in __imports__:
__imports__.append('SocketType')
else:
SocketType = socket
def fromfd(fd, family, type, proto=0):
""" fromfd(fd, family, type[, proto]) -> socket object
Create a socket object from a duplicate of the given file
descriptor. The remaining arguments are the same as for socket().
"""
nfd = dup(fd)
return socket(family, type, proto, nfd)
if hasattr(_socket.socket, "share"):
def fromshare(info):
""" fromshare(info) -> socket object
Create a socket object from a the bytes object returned by
socket.share(pid).
"""
return socket(0, 0, 0, info)
__implements__.append('fromshare')
if hasattr(_socket, "socketpair"):
def socketpair(family=None, type=SOCK_STREAM, proto=0):
"""socketpair([family[, type[, proto]]]) -> (socket object, socket object)
Create a pair of socket objects from the sockets returned by the platform
socketpair() function.
The arguments are the same as for socket() except the default family is
AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
.. versionchanged:: 1.2
All Python 3 versions on Windows supply this function (natively
supplied by Python 3.5 and above).
"""
if family is None:
try:
family = AF_UNIX
except NameError:
family = AF_INET
a, b = _socket.socketpair(family, type, proto)
a = socket(family, type, proto, a.detach())
b = socket(family, type, proto, b.detach())
return a, b
else: # pragma: no cover
# Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
# gevent: taken from 3.6 release. Expected to be used only on Win. Added to Win/3.5
# gevent: for < 3.5, pass the default value of 128 to lsock.listen()
# (3.5+ uses this as a default and the original code passed no value)
_LOCALHOST = '127.0.0.1'
_LOCALHOST_V6 = '::1'
def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
if family == AF_INET:
host = _LOCALHOST
elif family == AF_INET6:
host = _LOCALHOST_V6
else:
raise ValueError("Only AF_INET and AF_INET6 socket address families "
"are supported")
if type != SOCK_STREAM:
raise ValueError("Only SOCK_STREAM socket type is supported")
if proto != 0:
raise ValueError("Only protocol zero is supported")
# We create a connected TCP socket. Note the trick with
# setblocking(False) that prevents us from having to create a thread.
lsock = socket(family, type, proto)
try:
lsock.bind((host, 0))
lsock.listen(128)
# On IPv6, ignore flow_info and scope_id
addr, port = lsock.getsockname()[:2]
csock = socket(family, type, proto)
try:
csock.setblocking(False)
try:
csock.connect((addr, port))
except (BlockingIOError, InterruptedError):
pass
csock.setblocking(True)
ssock, _ = lsock.accept()
except:
csock.close()
raise
finally:
lsock.close()
return (ssock, csock)
if sys.version_info[:2] < (3, 5):
# Not provided natively
if 'socketpair' in __implements__:
# Multiple imports can cause this to be missing if _socketcommon
# was successfully imported, leading to subsequent imports to cause
# ValueError
__implements__.remove('socketpair')
if hasattr(__socket__, 'close'): # Python 3.7b1+
close = __socket__.close # pylint:disable=no-member
__imports__ += ['close']
__all__ = __implements__ + __extensions__ + __imports__
|