Opened 4 years ago

Last modified 6 weeks ago

#5087 enhancement new

Accept IPv6 address literals (with embedded scope ids) in IUDPTransport.connect

Reported by: exarkun Owned by:
Priority: normal Milestone:
Component: core Keywords: ipv6
Cc: Branch:
Author: Launchpad Bug:

Description (last modified by thijs)

At around the time #5086 is resolved, it would also make sense to support IPv6 address literals in the host argument to IUDPTransport.connect. This would only be supported for UDP ports which are listening on an IPv6 address.

It will have the same affect as using connect with an IPv4 address: future calls to IUDPTransport.write should only be made with one argument, the datagram, and the datagram will be sent to the address which was connected to.

Attachments (1)

Selection_009.png (99.0 KB) - added by jMyles 6 weeks ago.
Screenshot of socket.connect() behavior

Download all attachments as: .zip

Change History (4)

comment:1 Changed 17 months ago by thijs

  • Description modified (diff)

add link to IPv6 page.

Changed 6 weeks ago by jMyles

Screenshot of socket.connect() behavior

comment:2 Changed 6 weeks ago by jMyles

I understand neither the specifics of the desired behavior (in particular, the precise definition of a properly formatted ipv6 address) nor the current behavior. For example, if you refer to the screenshot I have attached, you'll notice that the socket library emits different errors for differently formatted IPv6 addresses. I don't understand why, nor do I understand which are desirable.

comment:3 Changed 6 weeks ago by jMyles

<exarkun> jMyles: All of your examples except for the first fail because you have to create a different kind of socket to be able to connect to an IPv6 address (usually). Since the attempt to connect to an IPv4 address succeeded, I guess that socket is not the kind that can connect to an IPv6 address.
<exarkun> "Address family or hostname not supported" sounds like it goes along with this
<jMyles> What I currently don't understand is why, even if an IPv6 address passes muster per abstract.isIPv6Address(), it still fails at socket.connect()
<exarkun> Even if it's an AF_INET6 socket?
<jMyles> exarkun: I'm not sure what that means - help me read up.
<exarkun> The BSD socket API works by assigning sockets a family and a type and a protocol. These are all mandatory parameters.
<exarkun> The Python bindings to the BSD socket API are like "lol no one cares about anything except TCP" and lets you make a socket without knowing about *any* of those three things.
<exarkun> But an interesting thing to know is that socket.socket() is the same as socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
<exarkun> AF_INET means "IPv4"
<exarkun> (A)ddress (F)amily
<exarkun> So the addresses the socket deals with come from the IPv4 address family.
<exarkun> Using AF_INET with SOCK_STREAM means TCP (IPPROTO_TCP is sort of a mis-prediction made by the designers of the BSD socket API - they predicted that there would be multiple protocols you might run over an AF_INET SOCK_STREAM socket - but there aren't: there's only TCP)
<exarkun> There are other kinds of SOCK_STREAM - eg, one kind of UNIX sockets are AF_UNIX combined with SOCK_STREAM (there are datagram UNIX sockets too - SOCK_DGRAM)
<exarkun> So when you do socket.socket() in Python you get a TCP-over-IPv4 socket.
<exarkun> The endpoints of that socket can only be IPv4 addresses.
<exarkun> Exactly the same if you do socket.socket(socket.AF_INET, socket.SOCK_STREAM) since those are the defaults
<exarkun> If you do socket.socket(AF_INET, socket.SOCK_DGRAM) you get a UDP-over-IPv4 socket
<exarkun> And the endpoints of that socket can only be IPv4 addresses too
<exarkun> (UDP doesn't really have connections, but the UDP socket has a local address it is bound to - and that must be an IPv4 address in this case - and remote addresses it can send traffic to - and those must be IPv4 addresses in this case)
<exarkun> Enter AF_INET6.
<jMyles> exarkun: with you so far.
<exarkun> If you substitute AF_INET6 for AF_INET in any of these examples, then you have a whatever-over-IPv6 socket instead.
<exarkun> And the endpoints must be IPv6 addresses.
<exarkun> And that's really the crux of the matter
<exarkun> When you try to connect to ::1 using an IPv4 socket, it complains because it *knows* that's an IPv6 address (this is Python-level trickery really - Python knows it's an IPv6 address and turns it into the right struct to pass to the C API and the C API says "you screwed up dude")
<exarkun> Does that give you an idea about what practical changes to make to your experiment to make something more successful?
<skreech> exarkun: at least I feel better educated on the topic
<jMyles> exarkun: Aye!

Note: See TracTickets for help on using tickets.