Merge lp:~martin-v/zodb/ipv6 into lp:zodb

Proposed by Martin v. Löwis on 2010-09-19
Status: Needs review
Proposed branch: lp:~martin-v/zodb/ipv6
Merge into: lp:zodb
Diff against target: 173 lines (+71/-5)
6 files modified
doc/zeo.txt (+3/-0)
src/ZEO/tests/ConnectionTests.py (+16/-0)
src/ZEO/tests/testZEO.py (+2/-2)
src/ZEO/zrpc/client.py (+14/-2)
src/ZEO/zrpc/server.py (+32/-1)
src/ZEO/zrpc/smac.py (+4/-0)
To merge this branch: bzr merge lp:~martin-v/zodb/ipv6
Reviewer Review Type Date Requested Status
Jim Fulton Approve on 2010-09-27
Hanno Schlichting 2010-09-19 Pending
Christian Theune 2010-09-19 Pending
Review via email: mp+35945@code.launchpad.net

Description of the change

This adds IPv6 support to ZEO. It relies on the ZConfig changes in https://code.launchpad.net/~martin-v/zconfig/ipv6/+merge/35944.

On the server side, the major change is the interpretation of listen addresses. '' now indicates wild-card-IPv4-and-IPv6. For wildcard IPv4, 0.0.0.0 needs to be specified (which used to work before as well), for wildcard IPv6, :: must be used. On systems that don't support dual-stack sockets, '' continues to mean 0.0.0.0. To bind ZEO explicitly to an IPv6 address, [addr]:port needs to be used.

On the client side, there are two major changes:

- IPv6 addresses can now be specified, using [addr]:port (or ('addr', port) in the API).

- DNS usage has changed. The client RPC now looks up all addresses, in the order recommended by the operating system (i.e. through getaddrinfo). The resulting list is considered a sublist of the regular fail-over address list, i.e. all addresses are being contacted simultaneously, and the first one connecting is used. This was discussed with Christian Theune at the DZUG sprint.

As tests, the connection tests now include IPv6 versions of all tests.

The only other change to the tests was a doctest which now prints 127.0.0.1 instead of localhost.

To post a comment you must log in.
lp:~martin-v/zodb/ipv6 updated on 2010-09-19
3957. By Martin v. Löwis on 2010-09-19

Remove debugging code.

3958. By Martin v. Löwis on 2010-09-19

Only check for IPPROTO_IPV6 if socket creation succeeded.
Look for AttributeError, not NameError, when checking IPPROTO_IPV6 presence.

Jim Fulton (jim-zope) wrote :

> - DNS usage has changed. The client RPC now looks up all addresses, in
> the order recommended by the operating system (i.e. through
> getaddrinfo). The resulting list is considered a sublist of the
> regular fail-over address list, i.e. all addresses are being
> contacted simultaneously, and the first one connecting is used. This
> was discussed with Christian Theune at the DZUG sprint.

What is the rational for this?

Why would a user want this?

Jim Fulton (jim-zope) wrote :

I should note that I have limited confidence in the thread-tastic
abstraction-astronomic implementation of the client-storage connection
logic. :) I plan to reimplement it with a simpler event-based approach
and, in the mean time, an leery of asking it to work harder.

Jim Fulton (jim-zope) wrote :

I'm fanatical about source lines being less than or equal to 80
characters in length. :)

Martin v. Löwis (martin-v) wrote :

Re: DNS. Users currently configure DNS names in zrpc clients to contact ZEO servers, so I guess there is a rationale for that (i.e. users want to use names instead of addresses - in particular with IPv6).

Now, if you allow DNS names, the question is what lookups should you do. The common approach is to look for both AAAA and A, and process them in the order in which the operating system returns them. This is what all client software supporting IPv6 does, so it's also what users expect it to do.

So now that we have one or more IPv6 addresses per name, and one or more IPv4 addresses, which ones should we use? zrpc currently supports connecting to multiple addresses simultaneously, and then taking the one that comes back first. With multiple addresses coming out of DNS, it can speed-up connection establishment when they are tried simultaneously. There is also precedence in other client software doing this, e.g. Apple Safari. As you might have to test each address sequentially, you can just as well do so in parallel.

In addition, it was easier to implement that way. If you think it's undesirable, I can try to come up with a way to do them sequentially.

Martin v. Löwis (martin-v) wrote :

Re: line length. Will redo.

Jim Fulton (jim-zope) wrote :
Download full text (3.6 KiB)

Meta comment: I'm new to IPv6, so if I ask dumb questions or say dumb
things, please be patient. :)

> Re: DNS. Users currently configure DNS names in zrpc clients to contact ZEO
> servers, so I guess there is a rationale for that (i.e. users want to use
> names instead of addresses - in particular with IPv6).

Yup. +1 on supporting names. :)

> Now, if you allow DNS names, the question is what lookups should you do. The
> common approach is to look for both AAAA and A, and process them in the order
> in which the operating system returns them. This is what all client software
> supporting IPv6 does, so it's also what users expect it to do.

Maybe I'm missinterpreting what you mean by "process".

I'd be surprised is "all client software" tried each address returned.
I would expect most client software to simply use an address in bind
or connect and get watever address is prefered for the type of socket
they created.

> So now that we have one or more IPv6 addresses per name, and one or more IPv4
> addresses, which ones should we use? zrpc currently supports connecting to
> multiple addresses simultaneously, and then taking the one that comes back
> first.

It's slightly more complicated, but yeah. :)

> With multiple addresses coming out of DNS, it can speed-up connection
> establishment when they are tried simultaneously.

I'm not sure what you mean here. But yeah, if you're going to do
multiple things, doing them in parallel is generally a good strategy.

> There is also precedence in
> other client software doing this, e.g. Apple Safari. As you might have to test
> each address sequentially, you can just as well do so in parallel.
>
> In addition, it was easier to implement that way. If you think it's
> undesirable, I can try to come up with a way to do them
> sequentially.

I'm not clear on what was easier to implement.

I'll try to guess. :)

I see a number of possible issues that this might try to solve.

1. Given a host name, you have to decide whether to bind or connect
   using a v4 or v6 socket.

2. If multiple machines have the same host name, maybe you want to
   treat them as a high-availability pool and connect to whichever one
   is providing the desired service.

   Is there any other reason why there would be multiple v4 addresses
   or multiple v6 addresses for the same host name. (Leaving aside a
   host having obe v4 address and one v6 address)?

Are these the problems you're trying to solve?

For 1, it would be just as easy to grab the first result from
getaddrinfo.

BTW, the patch for the server always uses a v4 socket if a host name
is given, but perhaps I don't understand how v6 interacts with bind.

For 2, I can see real benefits in giving multiple redundant servers
the same host name.

What I'm worried about having clients connect to the same server more
than once. There are 2 reasons for this:

1. It becomes ambiguous whether a v4 or v6 socket will be used.

2. As I mentioned earlier, the ZEO client connection logic has issues.
   We use ZRS to provide a primary secondary replication scheme.
   We used to have primaries and secondaries listen on the same port
   and apps that wanted writable connections would eit...

Read more...

Jim Fulton (jim-zope) wrote :

How did you see my comments? Did you get email, or did you poll?

I didn't see your replies until I checked back.

Martin v. Löwis (martin-v) wrote :
Download full text (5.2 KiB)

> Maybe I'm missinterpreting what you mean by "process".
>
> I'd be surprised is "all client software" tried each address returned.
> I would expect most client software to simply use an address in bind
> or connect and get watever address is prefered for the type of socket
> they created.

With IPv6, it is now common and recommended that each host gets at least
two addresses: one for IPv4 and one for IPv6 (dual stack). In addition,
some systems have multiple IPv6 addresses (e.g. assigned by various
tunneling systems). It's not universally clear that any of these
addresses is better than any other: it depends, in particular, on the
client connectivity (IPv6 available or not, IPv4 available or not).

The new resolver API recommended for use it getaddrinfo(3). It gives you
a list of addrinfo(family, socktype, proto, canonname, addr), mixing
IPv4 and IPv6 addresses. Today, systems have a policy (e.g.
/etc/gai.conf) to determine in which order to return them (e.g. IPv6
global first, then IPv4, then IPv6 tunnel). Applications must not
normally chose for themselves whether they want IPv4 or IPv6
connections, but should let the system decide.

In turn, you can't actually create the socket until getaddrinfo
returns, as it will tell you what socket family to use. Hence
the typically connect code looks like this:

  for family,address in getaddrinfo():
     try:
         s = socket.socket(family)
         s.connect(address, port)
     except socket.error:
         continue
  if not s:
     raise "None of these addresses worked"

The IPv6 server code is entirely different: typically, you either
bind to all addresses (v4 and v6) of a system (preferably using
dual-stack sockets using a wildcard address), or you bind to a (list
of) specifically configured addresses; no DNS involved. When binding
to a list of addresses, you need to create multiple server sockets.
IIUC, ZEO currently doesn't support that (and IMO doesn't need to).

>> With multiple addresses coming out of DNS, it can speed-up connection
>> establishment when they are tried simultaneously.
>
> I'm not sure what you mean here. But yeah, if you're going to do
> multiple things, doing them in parallel is generally a good strategy.

See above: the for loop can run in parallel.

>> In addition, it was easier to implement that way. If you think it's
>> undesirable, I can try to come up with a way to do them
>> sequentially.
>
> I'm not clear on what was easier to implement.
>
> I'll try to guess. :)
>
> I see a number of possible issues that this might try to solve.
>
> 1. Given a host name, you have to decide whether to bind or connect
> using a v4 or v6 socket.

No, you would need to iterate over all getaddrinfo results either way.

> 2. If multiple machines have the same host name, maybe you want to
> treat them as a high-availability pool and connect to whichever one
> is providing the desired service.

That is now possible, but only a side effect. But yes, it was easier
to treat a list of addresses returned from DNS as a high-availability
pool - easier than modifying ConnectWrapper to execute the loop.

> Is there any other reason why there would be multiple v4 addresses
> ...

Read more...

Martin v. Löwis (martin-v) wrote :

Am 27.09.2010 19:01, schrieb Jim Fulton:
> How did you see my comments? Did you get email, or did you poll?

I got an email, and then replied over the web.

> I didn't see your replies until I checked back.

Hmm. Did you email-reply? This one has your address in the CC.

Jim Fulton (jim-zope) wrote :

On Mon, Sep 27, 2010 at 2:13 PM, "Martin v. Löwis" <martin@v.loewis.de> wrote:
> Am 27.09.2010 19:01, schrieb Jim Fulton:
>> How did you see my comments? Did you get email, or did you poll?
>
> I got an email, and then replied over the web.
>
>> I didn't see your replies until I checked back.
>
> Hmm. Did you email-reply? This one has your address in the CC.

Nope.

<shrug>

Fortunately, I got this one and the previous one via email. :)

Jim

--
Jim Fulton

Jim Fulton (jim-zope) wrote :
Download full text (6.9 KiB)

On Mon, Sep 27, 2010 at 2:12 PM, "Martin v. Löwis" <martin@v.loewis.de> wrote:
>> Maybe I'm missinterpreting what you mean by "process".
>>
>> I'd be surprised is "all client software" tried each address returned.
>> I would expect most client software to simply use an address in bind
>> or connect and get watever address is prefered for the type of socket
>> they created.
>
> With IPv6, it is now common and recommended that each host gets at least
> two addresses: one for IPv4 and one for IPv6 (dual stack).

Makes sense.

> In addition,
> some systems have multiple IPv6 addresses (e.g. assigned by various
> tunneling systems).

Hm. Sounds complicated. :)

> It's not universally clear that any of these
> addresses is better than any other: it depends, in particular, on the
> client connectivity (IPv6 available or not, IPv4 available or not).

Hm.

> The new resolver API recommended for use it getaddrinfo(3). It gives you
> a list of addrinfo(family, socktype, proto, canonname, addr), mixing
> IPv4 and IPv6 addresses. Today, systems have a policy (e.g.
> /etc/gai.conf) to determine in which order to return them (e.g. IPv6
> global first, then IPv4, then IPv6 tunnel). Applications must not
> normally chose for themselves whether they want IPv4 or IPv6
> connections, but should let the system decide.
>
> In turn, you can't actually create the socket until getaddrinfo
> returns, as it will tell you what socket family to use. Hence
> the typically connect code looks like this:
>
>  for family,address in getaddrinfo():
>     try:
>         s = socket.socket(family)
>         s.connect(address, port)
>     except socket.error:
>         continue
>  if not s:
>     raise "None of these addresses worked"

I'm hoping there's a missing break or return in there somewhere. :)

> The IPv6 server code is entirely different: typically, you either
> bind to all addresses (v4 and v6) of a system (preferably using
> dual-stack sockets using a wildcard address), or you bind to a (list
> of) specifically configured addresses; no DNS involved.

I wonder why the asymmetry. Or, at least, why it wouldn't at least
make sense to at least listen for both v4 and v6 for the same host name.

> When binding
> to a list of addresses, you need to create multiple server sockets.

OK.

> IIUC, ZEO currently doesn't support that

Right.

> (and IMO doesn't need to).

Not sure wrt IPv6.

I have wanted to be able to listen on both a TCP socket and a
unix-domain socket. There's nothing hard about this for ZEO per se,
but figuring how to spell this in ZConfig schema has been just enough
of a pain to make it not happen. :)

>>> With multiple addresses coming out of DNS, it can speed-up connection
>>> establishment when they are tried simultaneously.
>>
>> I'm not sure what you mean here.  But yeah, if you're going to do
>> multiple things, doing them in parallel is generally a good strategy.
>
> See above: the for loop can run in parallel.
>
>>> In addition, it was easier to implement that way. If you think it's
>>> undesirable, I can try to come up with a way to do them
>>> sequentially.
>>
>> I'm not clear on what was easier to implement.
>>
>> I'll try to guess. :)
>>
>> I see a...

Read more...

Martin v. Löwis (martin-v) wrote :

>> The IPv6 server code is entirely different: typically, you either
>> bind to all addresses (v4 and v6) of a system (preferably using
>> dual-stack sockets using a wildcard address), or you bind to a (list
>> of) specifically configured addresses; no DNS involved.
>
> I wonder why the asymmetry. Or, at least, why it wouldn't at least
> make sense to at least listen for both v4 and v6 for the same host name.

It always was asymmetric: you can use a wildcard address on the server,
but not on the client, as a special feature of the socket API.

Some servers support binding to multiple explicit interfaces (e.g.
Apache Listen), but I'm not aware of a precedent that supports
DNS in that part of the configuration, and supports DNS returning
multiple addresses (i.e. expanding them to multiple Listen statements).

> I have wanted to be able to listen on both a TCP socket and a
> unix-domain socket. There's nothing hard about this for ZEO per se,
> but figuring how to spell this in ZConfig schema has been just enough
> of a pain to make it not happen. :)

Ok. So do you want me to change the patch to bind to multiple addresses?

I think StorageServer would need to change, to support multiple
addresses, and also multiple Dispatcher objects.

> I don't mind trying multiple paths (addresses) to do the low-level
> connections, but I'm worried about making multiple connections to the
> same server.

I could try to find out how to prevent that: it should be possible
to keep track what DNS names each connection originated from, and then
close any redundant connections that get connected (assuming zrpc
can deal with connections on which no data gets transmitted).

> I'm good with merging the branch. Do you want to do this (using some
> LP tool)? Or do you want me to?

I would rather see you merge the patch. However, if you want me to
make some modifications first, we can also wait (I won't be able to
work on this really for the next two weeks).

Jim Fulton (jim-zope) wrote :

On Mon, Sep 27, 2010 at 3:56 PM, "Martin v. Löwis" <martin@v.loewis.de> wrote:
>>> The IPv6 server code is entirely different: typically, you either
>>> bind to all addresses (v4 and v6) of a system (preferably using
>>> dual-stack sockets using a wildcard address), or you bind to a (list
>>> of) specifically configured addresses; no DNS involved.
>>
>> I wonder why the asymmetry.  Or, at least, why it wouldn't at least
>> make sense to at least listen for both v4 and v6 for the same host name.
>
> It always was asymmetric: you can use a wildcard address on the server,
> but not on the client, as a special feature of the socket API.
>
> Some servers support binding to multiple explicit interfaces (e.g.
> Apache Listen), but I'm not aware of a precedent that supports
> DNS in that part of the configuration, and supports DNS returning
> multiple addresses (i.e. expanding them to multiple Listen statements).
>
>> I have wanted to be able to listen on both a TCP socket and a
>> unix-domain socket.  There's nothing hard about this for ZEO per se,
>> but figuring how to spell this in ZConfig schema has been just enough
>> of a pain to make it not happen. :)
>
> Ok. So do you want me to change the patch to bind to multiple addresses?

No. I was just mentioning that I'd considered adding support for listening
on multiple addresses.

...

>> I don't mind trying multiple paths (addresses) to do the low-level
>> connections, but I'm worried about making multiple connections to the
>> same server.
>
> I could try to find out how to prevent that: it should be possible
> to keep track what DNS names each connection originated from, and then
> close any redundant connections that get connected (assuming zrpc
> can deal with connections on which no data gets transmitted).

Nah. The connection logic is already too complicated.
I plan a major refactoring of it down the road.

>> I'm good with merging the branch.  Do you want to do this (using some
>> LP tool)? Or do you want me to?
>
> I would rather see you merge the patch.

Cool. That seems easier.

> However, if you want me to
> make some modifications first, we can also wait (I won't be able to
> work on this really for the next two weeks).

No, I'm fine with it as it is.

Thanks.

Jim

--
Jim Fulton

Jim Fulton (jim-zope) wrote :

Merged to trunk. This will be in ZODB 3.10b7.

review: Approve

Unmerged revisions

3958. By Martin v. Löwis on 2010-09-19

Only check for IPPROTO_IPV6 if socket creation succeeded.
Look for AttributeError, not NameError, when checking IPPROTO_IPV6 presence.

3957. By Martin v. Löwis on 2010-09-19

Remove debugging code.

3956. By Martin v. Löwis on 2010-09-19

Adjust test case to display numeric IP instead of hostname.

3955. By Martin v. Löwis on 2010-09-19

Add IPv6 support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'doc/zeo.txt'
2--- doc/zeo.txt 2008-01-19 18:53:09 +0000
3+++ doc/zeo.txt 2010-09-19 09:56:47 +0000
4@@ -164,6 +164,9 @@
5 be used to with a system that arranges to provide hot backups of
6 servers in the case of failure.
7
8+If a single address resolves to multiple IPv4 or IPv6 addresses,
9+the client will connect to an arbitrary of these addresses.
10+
11 Authentication
12 ~~~~~~~~~~~~~~
13
14
15=== modified file 'src/ZEO/tests/ConnectionTests.py'
16--- src/ZEO/tests/ConnectionTests.py 2010-07-11 14:17:01 +0000
17+++ src/ZEO/tests/ConnectionTests.py 2010-09-19 09:56:47 +0000
18@@ -16,6 +16,7 @@
19 import sys
20 import time
21 import random
22+import socket
23 import asyncore
24 import threading
25 import logging
26@@ -1197,3 +1198,18 @@
27 c.close()
28 except:
29 pass
30+
31+# Run IPv6 tests if V6 sockets are supported
32+try:
33+ socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
34+except (socket.error, AttributeError):
35+ pass
36+else:
37+ class V6Setup:
38+ def _getAddr(self):
39+ return '::1', forker.get_port(self)
40+
41+ _g = globals()
42+ for name, value in _g.items():
43+ if isinstance(value, type) and issubclass(value, CommonSetupTearDown):
44+ _g[name+"V6"] = type(name+"V6", (V6Setup, value), {})
45
46=== modified file 'src/ZEO/tests/testZEO.py'
47--- src/ZEO/tests/testZEO.py 2010-09-16 20:19:20 +0000
48+++ src/ZEO/tests/testZEO.py 2010-09-19 09:56:47 +0000
49@@ -1148,13 +1148,13 @@
50 ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
51 ZEO.ClientStorage CRITICAL client
52 Client has seen newer transactions than server!
53- ZEO.zrpc ERROR (...) CW: error in notifyConnected (('localhost', ...))
54+ ZEO.zrpc ERROR (...) CW: error in notifyConnected (('127.0.0.1', ...))
55 Traceback (most recent call last):
56 ...
57 ClientStorageError: client Client has seen newer transactions than server!
58 ZEO.ClientStorage CRITICAL client
59 Client has seen newer transactions than server!
60- ZEO.zrpc ERROR (...) CW: error in notifyConnected (('localhost', ...))
61+ ZEO.zrpc ERROR (...) CW: error in notifyConnected (('127.0.0.1', ...))
62 Traceback (most recent call last):
63 ...
64 ClientStorageError: client Client has seen newer transactions than server!
65
66=== modified file 'src/ZEO/zrpc/client.py'
67--- src/ZEO/zrpc/client.py 2010-09-09 18:38:51 +0000
68+++ src/ZEO/zrpc/client.py 2010-09-19 09:56:47 +0000
69@@ -188,7 +188,7 @@
70 if (len(addr) == 2
71 and isinstance(addr[0], types.StringType)
72 and isinstance(addr[1], types.IntType)):
73- return socket.AF_INET
74+ return socket.AF_INET # also denotes IPv6
75
76 # not anything I know about
77 return None
78@@ -436,10 +436,22 @@
79 del wrappers
80 return 0
81
82+ def _expand_addrlist(self):
83+ for domain, (host, port) in self.addrlist:
84+ # AF_INET really means either IPv4 or IPv6,
85+ # possibly indirected by DNS. By design, DNS lookup is deferred until
86+ # connections get established, so that DNS reconfiguration can affect failover
87+ if domain == socket.AF_INET:
88+ for family, socktype, proto, cannoname, sockaddr in socket.getaddrinfo(host, port):
89+ # for IPv6, drop flowinfo, and restrict addresses to [host]:port
90+ yield family, sockaddr[:2]
91+ else:
92+ yield domain, addr
93+
94 def _create_wrappers(self):
95 # Create socket wrappers
96 wrappers = {} # keys are active wrappers
97- for domain, addr in self.addrlist:
98+ for domain, addr in self._expand_addrlist():
99 wrap = ConnectWrapper(domain, addr, self.mgr, self.client)
100 wrap.connect_procedure()
101 if wrap.state == "notified":
102
103=== modified file 'src/ZEO/zrpc/server.py'
104--- src/ZEO/zrpc/server.py 2010-06-21 14:33:46 +0000
105+++ src/ZEO/zrpc/server.py 2010-09-19 09:56:47 +0000
106@@ -15,6 +15,23 @@
107 import socket
108 import types
109
110+# _has_dualstack: True if the dual-stack sockets are supported
111+try:
112+ # Check whether IPv6 sockets can be created
113+ s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
114+except (socket.error, AttributeError):
115+ _has_dualstack = False
116+else:
117+ # Check whether enabling dualstack (disabling v6only) works
118+ try:
119+ s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
120+ except (socket.error, AttributeError):
121+ _has_dualstack = False
122+ else:
123+ _has_dualstack = True
124+ s.close()
125+ del s
126+
127 from ZEO.zrpc.connection import Connection
128 from ZEO.zrpc.log import log
129 import ZEO.zrpc.log
130@@ -35,7 +52,18 @@
131
132 def _open_socket(self):
133 if type(self.addr) == types.TupleType:
134- self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
135+ if self.addr[0] == '' and _has_dualstack:
136+ # Wildcard listen on all interfaces, both IPv4 and IPv6 if possible
137+ self.create_socket(socket.AF_INET6, socket.SOCK_STREAM)
138+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
139+ elif ':' in self.addr[0]:
140+ self.create_socket(socket.AF_INET6, socket.SOCK_STREAM)
141+ if _has_dualstack:
142+ # On Linux, IPV6_V6ONLY is off by default.
143+ # If the user explicitly asked for IPv6, don't bind to IPv4
144+ self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, True)
145+ else:
146+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
147 else:
148 self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
149 self.set_reuse_addr()
150@@ -56,6 +84,9 @@
151 log("accepted failed: %s" % msg)
152 return
153
154+ # Drop flow-info from IPv6 addresses
155+ addr = addr[:2]
156+
157 # We could short-circuit the attempt below in some edge cases
158 # and avoid a log message by checking for addr being None.
159 # Unfortunately, our test for the code below,
160
161=== modified file 'src/ZEO/zrpc/smac.py'
162--- src/ZEO/zrpc/smac.py 2010-06-21 14:33:46 +0000
163+++ src/ZEO/zrpc/smac.py 2010-09-19 09:56:47 +0000
164@@ -120,6 +120,10 @@
165
166 self.__super_init(sock, map)
167
168+ # asyncore overwrites addr with the getpeername result
169+ # restore our value
170+ self.addr = addr
171+
172 def setSessionKey(self, sesskey):
173 log("set session key %r" % sesskey)
174

Subscribers

People subscribed via source and target branches

to all changes: