17f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 27f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# A higher level module for using sockets (or Windows named pipes) 37f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 47f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# multiprocessing/connection.py 57f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 679af245fb24a3608c341410ab9c782ce930401feR. David Murray# Copyright (c) 2006-2008, R Oudkerk 779af245fb24a3608c341410ab9c782ce930401feR. David Murray# All rights reserved. 879af245fb24a3608c341410ab9c782ce930401feR. David Murray# 979af245fb24a3608c341410ab9c782ce930401feR. David Murray# Redistribution and use in source and binary forms, with or without 1079af245fb24a3608c341410ab9c782ce930401feR. David Murray# modification, are permitted provided that the following conditions 1179af245fb24a3608c341410ab9c782ce930401feR. David Murray# are met: 1279af245fb24a3608c341410ab9c782ce930401feR. David Murray# 1379af245fb24a3608c341410ab9c782ce930401feR. David Murray# 1. Redistributions of source code must retain the above copyright 1479af245fb24a3608c341410ab9c782ce930401feR. David Murray# notice, this list of conditions and the following disclaimer. 1579af245fb24a3608c341410ab9c782ce930401feR. David Murray# 2. Redistributions in binary form must reproduce the above copyright 1679af245fb24a3608c341410ab9c782ce930401feR. David Murray# notice, this list of conditions and the following disclaimer in the 1779af245fb24a3608c341410ab9c782ce930401feR. David Murray# documentation and/or other materials provided with the distribution. 1879af245fb24a3608c341410ab9c782ce930401feR. David Murray# 3. Neither the name of author nor the names of any contributors may be 1979af245fb24a3608c341410ab9c782ce930401feR. David Murray# used to endorse or promote products derived from this software 2079af245fb24a3608c341410ab9c782ce930401feR. David Murray# without specific prior written permission. 2179af245fb24a3608c341410ab9c782ce930401feR. David Murray# 2279af245fb24a3608c341410ab9c782ce930401feR. David Murray# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 2379af245fb24a3608c341410ab9c782ce930401feR. David Murray# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2479af245fb24a3608c341410ab9c782ce930401feR. David Murray# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2579af245fb24a3608c341410ab9c782ce930401feR. David Murray# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2679af245fb24a3608c341410ab9c782ce930401feR. David Murray# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2779af245fb24a3608c341410ab9c782ce930401feR. David Murray# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2879af245fb24a3608c341410ab9c782ce930401feR. David Murray# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2979af245fb24a3608c341410ab9c782ce930401feR. David Murray# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3079af245fb24a3608c341410ab9c782ce930401feR. David Murray# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3179af245fb24a3608c341410ab9c782ce930401feR. David Murray# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3279af245fb24a3608c341410ab9c782ce930401feR. David Murray# SUCH DAMAGE. 337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson__all__ = [ 'Client', 'Listener', 'Pipe' ] 367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport os 387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport sys 397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport socket 405d35373706a21dfb11765f92dfbde961c9ed4e8cJesse Nollerimport errno 417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport time 427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport tempfile 437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport itertools 447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonimport _multiprocessing 460c519b3a5e847eea0dffb51ac8df7c68891daf70Neal Norwitzfrom multiprocessing import current_process, AuthenticationError 477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfrom multiprocessing.util import get_temp_dir, Finalize, sub_debug, debug 487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfrom multiprocessing.forking import duplicate, close 497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 557f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin PetersonBUFSIZE = 8192 56c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou# A very generous timeout when it comes to local connections... 57c562ca4625992836919b5f787bd9cb288226dae7Antoine PitrouCONNECTION_TIMEOUT = 20. 587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson_mmap_counter = itertools.count() 607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 617f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondefault_family = 'AF_INET' 627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonfamilies = ['AF_INET'] 637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif hasattr(socket, 'AF_UNIX'): 657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson default_family = 'AF_UNIX' 667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson families += ['AF_UNIX'] 677f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif sys.platform == 'win32': 697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson default_family = 'AF_PIPE' 707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson families += ['AF_PIPE'] 717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 72c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou 73c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitroudef _init_timeout(timeout=CONNECTION_TIMEOUT): 74c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou return time.time() + timeout 75c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou 76c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitroudef _check_timeout(t): 77c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou return time.time() > t 78c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou 797f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 807f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 817f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef arbitrary_address(family): 847f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Return an arbitrary free address for the given family 867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if family == 'AF_INET': 887f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return ('localhost', 0) 897f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson elif family == 'AF_UNIX': 907f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return tempfile.mktemp(prefix='listener-', dir=get_temp_dir()) 917f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson elif family == 'AF_PIPE': 927f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' % 93e03d3fdd204f6e702c9fb3129a50b290294e2a00Benjamin Peterson (os.getpid(), _mmap_counter.next()), dir="") 947f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise ValueError('unrecognized family') 967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 977f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef address_type(address): 997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1007f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Return the types of the address 1017f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1027f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson This can be 'AF_INET', 'AF_UNIX', or 'AF_PIPE' 1037f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if type(address) == tuple: 1057f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return 'AF_INET' 1067f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson elif type(address) is str and address.startswith('\\\\'): 1077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return 'AF_PIPE' 1087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson elif type(address) is str: 1097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return 'AF_UNIX' 1107f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 1117f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise ValueError('address type of %r unrecognized' % address) 1127f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1137f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1147f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Public functions 1157f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 1167f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1177f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonclass Listener(object): 1187f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1197f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Returns a listener object. 1207f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1217f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson This is a wrapper for a bound socket which is 'listening' for 1227f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson connections, or for a Windows named pipe. 1237f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1247f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def __init__(self, address=None, family=None, backlog=1, authkey=None): 1257f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson family = family or (address and address_type(address)) \ 1267f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson or default_family 1277f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address = address or arbitrary_address(family) 1287f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1297f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if family == 'AF_PIPE': 1307f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._listener = PipeListener(address, backlog) 1317f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 1327f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._listener = SocketListener(address, family, backlog) 1337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if authkey is not None and not isinstance(authkey, bytes): 1357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise TypeError, 'authkey should be a byte string' 1367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._authkey = authkey 1387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def accept(self): 1407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Accept a connection on the bound socket or named pipe of `self`. 1427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Returns a `Connection` object. 1447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c = self._listener.accept() 1467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if self._authkey: 1477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson deliver_challenge(c, self._authkey) 1487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson answer_challenge(c, self._authkey) 1497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return c 1507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def close(self): 1527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Close the bound socket or named pipe of `self`. 1547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1557f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return self._listener.close() 1567f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1577f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address = property(lambda self: self._listener._address) 1587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson last_accepted = property(lambda self: self._listener._last_accepted) 1597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1617f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef Client(address, family=None, authkey=None): 1627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Returns a connection to the address of a `Listener` 1647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson family = family or address_type(address) 1667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if family == 'AF_PIPE': 1677f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c = PipeClient(address) 1687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 1697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c = SocketClient(address) 1707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if authkey is not None and not isinstance(authkey, bytes): 1727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise TypeError, 'authkey should be a byte string' 1737f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1747f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if authkey is not None: 1757f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson answer_challenge(c, authkey) 1767f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson deliver_challenge(c, authkey) 1777f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1787f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return c 1797f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1807f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1817f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif sys.platform != 'win32': 1827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def Pipe(duplex=True): 1847f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Returns pair of connection objects at either end of a pipe 1867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 1877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if duplex: 1887f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s1, s2 = socket.socketpair() 189e4b9938d77950811a47fb673ecb4d4554a4efec1Richard Oudkerk s1.setblocking(True) 190e4b9938d77950811a47fb673ecb4d4554a4efec1Richard Oudkerk s2.setblocking(True) 1917f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c1 = _multiprocessing.Connection(os.dup(s1.fileno())) 1927f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c2 = _multiprocessing.Connection(os.dup(s2.fileno())) 1937f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s1.close() 1947f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s2.close() 1957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 1967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson fd1, fd2 = os.pipe() 1977f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c1 = _multiprocessing.Connection(fd1, writable=False) 1987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c2 = _multiprocessing.Connection(fd2, readable=False) 1997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2007f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return c1, c2 2017f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2027f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonelse: 2032f8c8f47c740cadee8c16e5e07657e4657f905ecJesse Noller from _multiprocessing import win32 2047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2057f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def Pipe(duplex=True): 2067f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 2077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Returns pair of connection objects at either end of a pipe 2087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 2097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address = arbitrary_address('AF_PIPE') 2107f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if duplex: 2117f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson openmode = win32.PIPE_ACCESS_DUPLEX 2127f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson access = win32.GENERIC_READ | win32.GENERIC_WRITE 2137f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson obsize, ibsize = BUFSIZE, BUFSIZE 2147f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 2157f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson openmode = win32.PIPE_ACCESS_INBOUND 2167f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson access = win32.GENERIC_WRITE 2177f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson obsize, ibsize = 0, BUFSIZE 2187f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2197f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson h1 = win32.CreateNamedPipe( 2207f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address, openmode, 2217f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | 2227f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_WAIT, 2237f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 1, obsize, ibsize, win32.NMPWAIT_WAIT_FOREVER, win32.NULL 2247f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 2257f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson h2 = win32.CreateFile( 2267f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address, access, 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL 2277f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 2287f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.SetNamedPipeHandleState( 2297f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson h2, win32.PIPE_READMODE_MESSAGE, None, None 2307f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 2317f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2327f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 2337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.ConnectNamedPipe(h1, win32.NULL) 2347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson except WindowsError, e: 2357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if e.args[0] != win32.ERROR_PIPE_CONNECTED: 2367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 2377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c1 = _multiprocessing.PipeConnection(h1, writable=duplex) 2397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson c2 = _multiprocessing.PipeConnection(h2, readable=duplex) 2407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return c1, c2 2427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 2447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Definitions for connections based on sockets 2457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 2467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonclass SocketListener(object): 2487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 2499752195a71fb1c4c706fc5d333bb10d38752b114Mark Dickinson Representation of a socket which is bound to an address and listening 2507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 2517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def __init__(self, address, family, backlog=1): 2527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._socket = socket.socket(getattr(socket, family)) 253709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali try: 254709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 255e4b9938d77950811a47fb673ecb4d4554a4efec1Richard Oudkerk self._socket.setblocking(True) 256709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali self._socket.bind(address) 257709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali self._socket.listen(backlog) 258709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali self._address = self._socket.getsockname() 259709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali except socket.error: 260709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali self._socket.close() 261709aa35a7a2e706d4c21b5ece772382853ae806cCharles-François Natali raise 2627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._family = family 2637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._last_accepted = None 2647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if family == 'AF_UNIX': 2667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._unlink = Finalize( 2679949d6ed4b74e50566abc85ac0154a664e6436eeJesse Noller self, os.unlink, args=(address,), exitpriority=0 2687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 2697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 2707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._unlink = None 2717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def accept(self): 27341072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk while True: 27441072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk try: 27541072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk s, self._last_accepted = self._socket.accept() 27641072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk except socket.error as e: 27741072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk if e.args[0] != errno.EINTR: 27841072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk raise 27941072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk else: 28041072db7099def8bcd26b5d64cb52f8fb6315adbRichard Oudkerk break 281e4b9938d77950811a47fb673ecb4d4554a4efec1Richard Oudkerk s.setblocking(True) 2827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson fd = duplicate(s.fileno()) 2837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn = _multiprocessing.Connection(fd) 2847f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s.close() 2857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return conn 2867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def close(self): 2881aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka try: 2891aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka self._socket.close() 2901aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka finally: 2911aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka unlink = self._unlink 2921aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka if unlink is not None: 2931aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka self._unlink = None 2941aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka unlink() 2957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 2977f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef SocketClient(address): 2987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 2997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Return a connection object connected to the socket given by `address` 3007f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 301c8ef9bc69471b3f5a789dad61d2330cf8193926cRichard Oudkerk family = getattr(socket, address_type(address)) 302c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou t = _init_timeout() 3037f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson while 1: 305c8ef9bc69471b3f5a789dad61d2330cf8193926cRichard Oudkerk s = socket.socket(family) 306c8ef9bc69471b3f5a789dad61d2330cf8193926cRichard Oudkerk s.setblocking(True) 3077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 3087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s.connect(address) 3097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson except socket.error, e: 310c8ef9bc69471b3f5a789dad61d2330cf8193926cRichard Oudkerk s.close() 311c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou if e.args[0] != errno.ECONNREFUSED or _check_timeout(t): 3127f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson debug('failed to connect to address %s', address) 3137f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 3147f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson time.sleep(0.01) 3157f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 3167f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson break 3177f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 3187f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 3197f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3207f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson fd = duplicate(s.fileno()) 3217f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson conn = _multiprocessing.Connection(fd) 3227f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s.close() 3237f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return conn 3247f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3257f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 3267f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Definitions for connections based on named pipes 3277f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 3287f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3297f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonif sys.platform == 'win32': 3307f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3317f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson class PipeListener(object): 3327f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 3337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Representation of a named pipe 3347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 3357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def __init__(self, address, backlog=None): 3367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._address = address 3377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle = win32.CreateNamedPipe( 3387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address, win32.PIPE_ACCESS_DUPLEX, 3397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | 3407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_WAIT, 3417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 3427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.NMPWAIT_WAIT_FOREVER, win32.NULL 3437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 3447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._handle_queue = [handle] 3457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._last_accepted = None 3467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson sub_debug('listener created with address=%r', self._address) 3487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self.close = Finalize( 3507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self, PipeListener._finalize_pipe_listener, 3517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson args=(self._handle_queue, self._address), exitpriority=0 3527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 3537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def accept(self): 3557f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson newhandle = win32.CreateNamedPipe( 3567f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._address, win32.PIPE_ACCESS_DUPLEX, 3577f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_TYPE_MESSAGE | win32.PIPE_READMODE_MESSAGE | 3587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_WAIT, 3597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 3607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.NMPWAIT_WAIT_FOREVER, win32.NULL 3617f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 3627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._handle_queue.append(newhandle) 3637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson handle = self._handle_queue.pop(0) 3647f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 3657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.ConnectNamedPipe(handle, win32.NULL) 3667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson except WindowsError, e: 3679a16fa69dda64ed01b2239a732c0445f22babb57Richard Oudkerk # ERROR_NO_DATA can occur if a client has already connected, 3689a16fa69dda64ed01b2239a732c0445f22babb57Richard Oudkerk # written data and then disconnected -- see Issue 14725. 3699a16fa69dda64ed01b2239a732c0445f22babb57Richard Oudkerk if e.args[0] not in (win32.ERROR_PIPE_CONNECTED, 3709a16fa69dda64ed01b2239a732c0445f22babb57Richard Oudkerk win32.ERROR_NO_DATA): 3717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 3727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _multiprocessing.PipeConnection(handle) 3737f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3747f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson @staticmethod 3757f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def _finalize_pipe_listener(queue, address): 3767f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson sub_debug('closing listener with address=%r', address) 3777f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson for handle in queue: 3787f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson close(handle) 3797f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 3807f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def PipeClient(address): 3817f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 3827f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson Return a connection object connected to the pipe given by `address` 3837f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ''' 384c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou t = _init_timeout() 3857f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson while 1: 3867f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson try: 3877f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.WaitNamedPipe(address, 1000) 3887f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson h = win32.CreateFile( 3897f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson address, win32.GENERIC_READ | win32.GENERIC_WRITE, 3907f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 0, win32.NULL, win32.OPEN_EXISTING, 0, win32.NULL 3917f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 3927f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson except WindowsError, e: 3937f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if e.args[0] not in (win32.ERROR_SEM_TIMEOUT, 394c562ca4625992836919b5f787bd9cb288226dae7Antoine Pitrou win32.ERROR_PIPE_BUSY) or _check_timeout(t): 3957f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 3967f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 3977f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson break 3987f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 3997f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise 4007f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4017f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson win32.SetNamedPipeHandleState( 4027f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson h, win32.PIPE_READMODE_MESSAGE, None, None 4037f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson ) 4047f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return _multiprocessing.PipeConnection(h) 4057f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4067f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 4077f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Authentication stuff 4087f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 4097f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4107f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin PetersonMESSAGE_LENGTH = 20 4117f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 412b09c9396cd74a50c237b77c76efa70e4a1aca863Benjamin PetersonCHALLENGE = b'#CHALLENGE#' 413b09c9396cd74a50c237b77c76efa70e4a1aca863Benjamin PetersonWELCOME = b'#WELCOME#' 414b09c9396cd74a50c237b77c76efa70e4a1aca863Benjamin PetersonFAILURE = b'#FAILURE#' 4157f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4167f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef deliver_challenge(connection, authkey): 4177f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import hmac 4187f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson assert isinstance(authkey, bytes) 4197f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson message = os.urandom(MESSAGE_LENGTH) 4207f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson connection.send_bytes(CHALLENGE + message) 4217f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson digest = hmac.new(authkey, message).digest() 4227f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson response = connection.recv_bytes(256) # reject large message 4237f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if response == digest: 4247f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson connection.send_bytes(WELCOME) 4257f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson else: 4267f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson connection.send_bytes(FAILURE) 4277f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise AuthenticationError('digest received was wrong') 4287f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4297f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef answer_challenge(connection, authkey): 4307f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import hmac 4317f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson assert isinstance(authkey, bytes) 4327f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson message = connection.recv_bytes(256) # reject large message 4337f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message 4347f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson message = message[len(CHALLENGE):] 4357f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson digest = hmac.new(authkey, message).digest() 4367f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson connection.send_bytes(digest) 4377f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson response = connection.recv_bytes(256) # reject large message 4387f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson if response != WELCOME: 4397f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson raise AuthenticationError('digest sent was rejected') 4407f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4417f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 4427f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# Support for using xmlrpclib for serialization 4437f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson# 4447f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4457f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonclass ConnectionWrapper(object): 4467f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def __init__(self, conn, dumps, loads): 4477f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._conn = conn 4487f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._dumps = dumps 4497f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._loads = loads 4507f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson for attr in ('fileno', 'close', 'poll', 'recv_bytes', 'send_bytes'): 4517f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson obj = getattr(conn, attr) 4527f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson setattr(self, attr, obj) 4537f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def send(self, obj): 4547f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s = self._dumps(obj) 4557f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson self._conn.send_bytes(s) 4567f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def recv(self): 4577f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson s = self._conn.recv_bytes() 4587f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return self._loads(s) 4597f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4607f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef _xml_dumps(obj): 4617fe04f1dca5820c43416145789f4cc2b94e918b8Serhiy Storchaka return xmlrpclib.dumps((obj,), None, None, None, 1) 4627f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4637f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef _xml_loads(s): 4647fe04f1dca5820c43416145789f4cc2b94e918b8Serhiy Storchaka (obj,), method = xmlrpclib.loads(s) 4657f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return obj 4667f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4677f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersonclass XmlListener(Listener): 4687f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson def accept(self): 4697f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson global xmlrpclib 4707f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import xmlrpclib 4717f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson obj = Listener.accept(self) 4727f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return ConnectionWrapper(obj, _xml_dumps, _xml_loads) 4737f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson 4747f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Petersondef XmlClient(*args, **kwds): 4757f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson global xmlrpclib 4767f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson import xmlrpclib 4777f03ea77bf43257789469b5cbc16982eb0a63b0fBenjamin Peterson return ConnectionWrapper(Client(*args, **kwds), _xml_dumps, _xml_loads) 478