-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPv6 support, phase 1 (direct connection) #1938
Conversation
@@ -31,6 +31,7 @@ CClient::CClient ( const quint16 iPortNumber, | |||
const QString& strMIDISetup, | |||
const bool bNoAutoJackConnect, | |||
const QString& strNClientName, | |||
const bool bNEnableIPv6, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't need the ugly N
, generally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was just following what appeared to be the majority convention. No strong view either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not going to block it for that, either. (It's just on my list of things to get rid of.)
Um... Given IPv4 is always enabled and given that only IPv4 is used to communicate with directory servers (for now), is there any reason not to have IPv6 always enabled? |
I wondered that. It would fail on a system that didn't have an IPv6 stack. Such as a Linux box with a file containing "blacklist ipv6" in /etc/modprobe.d/ (I did test that on my Pi). We could try creating an AF_INET6 socket first and falling back to AF_INET, but would then need to propagate the result of that to a global variable that all classes could consult. |
Well, rather than set |
I did try something like that earlier, but found that it wasn't easy to pass the result of the test back up from the I could perhaps create a static method of But we also need to consider the implications for:
|
You've given reasons to switch IPv6 off. Maybe the command line parameter should do that? I'm thinking of other software with internet connectivity -- I don't have to tell my web browser or email client whether or not to support IPv6, for example. |
Best case if host name is given: try to request an A record via DNS. Use ipv4 as fallback. But does Jamulus need to handle that? Isn’t that an OS functionality? Not only Jamulus will have this problem?! If I‘m giving an ipv6 address it should fail and not try to get a connection over ipv4. How does Firefox/Chrome/whatever handle this? Edit see this: https://blog.counterpath.com/ipv6 |
Use the bind IP option and only provide an ipv6/ipv4 address? |
Firefox does have a configuration option to disable IPv6 entirely to speed things up a bit if you know you're on a network without external IPv6 connectivity (it's still not that unusual to have local IPv6 but not routable to the world). |
Certainly very interesting, but quite complex, and I feel it's likely to be overkill for Jamulus. It's primarily concerned with resolving DNS names using both AAAA and A records, and then trying to connect with the returned addresses, preferring IPv6. In Jamulus, an operator of a private server using IPv6 will likely give his invitees a literal address or have a specific AAAA record for it. And once we extend to directory servers, they will return to the client literal IPv6 (if any) and IPv4 addresses, not DNS names. |
Maybe, but I think the number of people with an IPv6-capable computer but an IPv4-only internet connection would be a lot larger than the number of people who specifically want to use IPv6. So we would be requiring the much larger number of people to do something different. I would prefer to have the new IPv6 functionality be optional in the first one or two releases that contain it, and once we have gained more experience with it, we could make it the default. |
What makes you sure about that? From a UX point of view, I think just giving one address (with AAAA and A records) is the preferable outcome. Maybe - but for debugging purposes only - the admin sends over an IP to force ipv6/ipv4. That’s just my opinion… For directories we‘re skipping DNS? Can we send ping messages over IPv6 and IPv4, and constantly calculate the time difference between both as soon as the connection window is open? The client will then know which one to choose before connecting. Issues:
Pro:
|
So -6 is a client and server option? Tested ipv4 and ipv6 over a dual stack VDSL line. To me it seems as if ipv4 has a little better connectivity in terms of latency. But probably this varies depending on the provider. |
Yes. |
I'm not sure, it just seems likely to me. Most people I know with private servers haven't set up a DNS name and just give their friends the IP. There are a few more technical ones who have set up a DNS name.
We can use a DNS name to find a directory, but when a server registers with a directory, it does so just by IP (the directory stores the IP it registered from). The directory then tells a requesting client just the server's IP, not a DNS name, plus other relevant information (name, private IP, port number, etc).
That might well be a useful enhancement for the future, but I don't think we should hold up the basic feature waiting for that particular lily to be gilded. |
Ok. So what really needs to be tested to get this merged? IPv6/IPv4 over a dual stack connection seems to work. |
Well I've tested it quite a bit in my environment, on Linux, Windows and Mac, and it's running on my server as mentioned above. I think it's good to go, and that it is beneficial to have So it just needs two approvals (which can be tricky), and it could be merged. I would then start thinking about Directory Servers.
Cool! |
Agreed for the "experimental support" version. If the short version is going to change to mean |
|
||
UdpPort = &UdpSocketAddr.sa6.sin6_port; // where to put the port number | ||
|
||
// FIXME: If binding a dual-protocol interface to a specific address, does it cease to be dual-protocol? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A socket listening on an IPv4 address is only listening for IPv4 traffic. But the same interface could have a separate socket listening on an IPv6 address, I believe. The interface has the MAC address (or equivalent). The protocol has the IPv4 or IPv6 address that goes with the socket layer in use. (That's why the union
is used for the address: there can be only one - on that socket.)
At least, that's my understanding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A socket listening on an IPv4 address is only listening for IPv4 traffic. But the same interface could have a separate socket listening on an IPv6 address, I believe.
Yes it could, but Jamulus only expects to listen on one socket. So I think that makes it unable to bind to a specific interface address and remain dual-stack. I don't think it's a problem, unless someone flags up a scenario where it is. The default of binding to ::
will allow it to receive both IPv4 and IPv6 traffic without needing two sockets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it could, but Jamulus only expects to listen on one socket.
The default of binding to :: will allow it to receive both IPv4 and IPv6 traffic without needing two sockets.
How does an IPv4 client know what address to use? Does the IPv6 socket "just know" it's got two addresses really? (I've some vague memory that every IPv4 address has an IPv6 address direct equivalent...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IPv4 client will connect in the same way as at present, by being told the IP address, either explicitly, or from a hostname lookup, or by a directory server.
Binding an AF_INET6
socket to ::
(declared as in6addr_any
) is the IPv6 equivalent of binding an AF_INET
socket to 0.0.0.0
(INADDR_ANY
), which means it will accept any incoming packet that arrives on any interface. If the socket has been setsockopt
ed to dual stack (as we do), it will accept both IPv4 and IPv6 packets.
An IPv4 address mapped to IPv6 uses 0000:0000:0000:0000:0000:ffff
as the first 96 bits, which denotes that the last 32 bits contain an IPv4 address in network byte order. Often expressed like ::ffff:192.168.1.1
. This mapping is used in CSocket::SendPacket()
and checked for in CSocket::OnDataReceived()
.
src/socket.cpp
Outdated
@@ -172,6 +232,15 @@ CSocket::~CSocket() | |||
|
|||
void CSocket::SendPacket ( const CVector<uint8_t>& vecbySendBuf, const CHostAddress& HostAddr ) | |||
{ | |||
union |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this go in a header somewhere as a type, so it can be re-used more easily? socket.h
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess, although that makes it more opaque when reading socket.cpp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could argue that for every definition that isn't in line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems simple. Nevertheless some comments:
- You're removing the chinese .qm file? Any reason for that?
- See comments
- As it works on my ipv6 connection (and you tested it), I think the functionality is ok.
@@ -937,6 +955,7 @@ QString UsageArguments ( char** argv ) | |||
" -Q, --qos set the QoS value. Default is 128. Disable with 0\n" | |||
" (see the Jamulus website to enable QoS on Windows)\n" | |||
" -t, --notranslation disable translation (use English language)\n" | |||
" -6, --enableipv6 enable IPv6 addressing (IPv4 is always enabled)\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
" -6, --enableipv6 enable IPv6 addressing (IPv4 is always enabled)\n" | |
" -6, --enableipv6 enable IPv6 addressing for direct connection to client/server (IPv4 is always enabled).\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this adds anything at all. It still requires further explanation as to what "direct connection to client/server" means, so it's useless verbosity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But do we agree that the original proposal needs more clarification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with the wording Tony used. It's concise and says what it does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think it's not clear. Probably the question is:
Does the user need to know that connections to public servers is still IPv4 only?
If we want to be specific: Yes. If we think it confuses the user: No.
Maybe it's worth mentioning it at least in the release announcement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the user need to know that connections to public servers is still IPv4 only?
Not "public", use the word "registered". You can register with a directory no one knows about. That's not particularly public.
To operate the software, no. They can just select a listed entry from the directory and the software will use the returned IPv4 address.
If you want to use IPv6, you need to:
a) pass "-6" on the command line, thus indicating you understand how to operate with IPv6 addresses, so need no further help
b) enter an IPv6 name or address in the connection dialogue "Server Address", by hand, so you know that you've chosen a specific server rather than a registered one.
As I say, the help text need not say anything else. This is not the final form for the feature. It's intended to be somewhat experimental and the documentation should make that clear. Those who choose to use it should thus be given the credit for understanding what they've chosen to do.
if ( UdpSocket == -1 ) | ||
{ | ||
// IPv6 requested but not available, throw error | ||
throw CGenErr ( "IPv6 requested but not available on this system.", "Network Error" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw CGenErr ( "IPv6 requested but not available on this system.", "Network Error" ); | |
throw CGenErr ( "You requested IPv6, but it's not available with your system configuration.", "Network Error" ); |
As far as I know active voice is preferred to passive voice (https://jamulus.io/contribute/Style-and-Tone)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see any reference to active vs passive voice in that page, although I know some other wider contexts promote a preference for active voice. In this case, I have a slight preference for the shorter message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @gilgongo mentioned it somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I halluciated it then - I recall @mulyaj mentioning it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I've mentioned a preference for active voice. Reading this at first glance, the subject is vague:
"IPv6 requested..." - who requested?
Then, if the subject is vague, the guideline for concise and specific is broken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be happy with "IPv6 is not available." It's issued as a response to the user making a request to use an address. It doesn't need to tell the user they used an address, just why it hasn't worked.
if ( UdpSocket == -1 ) | ||
{ | ||
// IPv4 requested but not available, throw error (should never happen, but check anyway) | ||
throw CGenErr ( "IPv4 requested but not available on this system.", "Network Error" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, but now with ipv4 ofc.
Since it's not enabled by default, I think we can tag it for 3.8.1. |
No, must be an accident. I'll correct that before merging.
Thanks, will respond individually.
Cool. |
As soon as the Chinese qm file is added, I think it’s ready to merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it works and only one critical step is missing (.qm file), I‘ll approve it.
57fbd63
to
611e11a
Compare
I have squashed all the commits except for the first one by @jardous. I'll wait until the checks are complete (looks like they may need to be rerun) and merge tomorrow. |
I think you should use @jardous E-Mail or jardous@users.noreply.github.com to link his GitHub account to the first commit. This would add him to the contributor entry on GitHub. |
Not exactly sure how to do that. |
To set the values:
You'd need to do that during either a |
Note that it is backwards compatible with IPv4. Co-authored-by: Tony Mountifield <tony@mountifield.org>
Reworked ParseNetworkAddress() to use regex to validate format. Allows literal IP address (IP4 or IP6) between [ ], or else IP4 address or hostname without [ ]. Optional :port follows. Add code to determine routable IPv6 interface address. Uses Cloudflare's IPv6 DNs resolver address (no traffic sent). Use LocalHostIPv6 if no local IPv6 address Add command option and flag for enabling IPv6 Reworked sockaddr handling in OnDataReceived() Change in_port_t to uint16_t for Windows compatibility Allow IPv4 only for communicating with Directory Servers Rework dual-stack socket handling for Windows compatibility Move sockaddr union definition into socket.h
OK, that seems to have worked. Just waiting for the Checks to run and then I'll merge. |
Well although Android and Windows failed this time, they have previously worked with identical code (I diffed the before and after of the rebases to be sure), so I'll go ahead and merge anyway. |
hi. Feel free to use my real email: ***@***.***
J.
…On Tue 10. Aug 2021 at 16:42, Tony Mountifield ***@***.***> wrote:
I think you should use @jardous <https://github.com/jardous> E-Mail or
***@***.*** to link his GitHub account to the first
commit. This would add him to the contributor entry on GitHub.
OK, that seems to have worked. Just waiting for the Checks to run and then
I'll merge.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1938 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACU74J3TCBUEETO47F6EY3T4E3DTANCNFSM5BM5NUNA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email>
.
|
I already used your generic Github address jardous@users.noreply.github.com, which was enough to link the rebased version of your original commit to your Github ID. Thanks! |
This implementation of IPv6 on Jamulus is based on #1017 by @jardous, with further enhancements by @softins. It is an alternative to #1455 by @mstolle629.
It has been tested on Linux, Mac and Windows. It is currently running on jamminthejazz, at
privjam.softins.co.uk:22123
(IPv4) andprivjam6.softins.co.uk:22123
(IPv6). There is also a private instance atprivjam.softins.co.uk
andprivjam6.softins.co.uk
, which may be used for testing.Servers running this version can accept a mix of IPv4 and IPv6 connections.
Server addresses for direct connection can be specified in the following formats:
[v6addr]
[v6addr]:port
[v4addr]
[v4addr]:port
v4addr
v4addr:port
hostname
hostname:port
A literal IPv6 address must always be enclosed in
[ ]
, to avoid ambiguity with a port.Phase 2 will be the addition of Directory Server support, which will require some
protocol enhancements. Phase 1 is worth adding on its own before Phase 2 is ready.
Potential ChangeLog entry
Add support for direct connections using IPv6
Documentation needed
-6
and--enableipv6
Status of this Pull Request
Working implementation
What is missing until this pull request can be merged?
More testing is always good!
Checklist