Author Topic: IPv6 support?  (Read 4603 times)

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
IPv6 support?
« on: June 05, 2016, 08:13:09 PM »
TNet had issue with parsing IPv6 addresses in the past (see: http://www.tasharen.com/forum/index.php?topic=13794). However, even with the parsing fixed - in TNet2 - Sockets are created with AddressFamily.InterNetwork (see TcpProtocol::ConnectToTcpEndPoint()), which, as far as I can tell, only supports IPv4. In .NET 4.5 Sockets support dual mode, but I don't think Unity has caught up to that yet.

If I change AddressFamily.InterNetwork to tcpEndPoint.AddressFamily, will this introduce incompatibilities? Has IPv6 support been more thoroughly planned out in TNet3?

I know this is something I could test myself, but I thought I might check here before potentially breaking the whole game :P


edit: Here's all the changes I've made in TNet2. I think this should solve IPv6 problems when using TCP. Not sure though. The Lobby code (client and server) should be fine already.
TNManager::Connect (string address) [full function]:
  1. string parsedAddress = address;
  2. string[] split = address.Split(new char[] { ':' });
  3. int port = 5127;
  4. if (split.Length == 2)
  5. {
  6.    int.TryParse(split[1], out port);
  7. }
  8. else if (split.Length == 9)
  9. {
  10.    parsedAddress = address.Substring(0, address.Length - split[8].Length - 1);
  11.    int.TryParse(split[8], out port);
  12. }
  13. Connect(parsedAddress, port);
  14.  

TcpProtocol::ConnectToTcpEndPoint():
Change:
  1. mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  2.  
To:
  1. mSocket = new Socket(tcpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  2. if (tcpEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
  3.         mSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
  4.  

TNTools.cs -
Tools::ResolveExternalIP (string url):
Change:
  1. string[] split1 = text.Split(':');
  2.  
  3. if (split1.Length >= 2)
  4. {
  5.    string[] split2 = split1[1].Trim().Split('<');
  6.    mExternalAddress = ResolveAddress(split2[0]);
  7. }
  8. else mExternalAddress = ResolveAddress(text);
  9.  
To:
  1. mExternalAddress = ResolveAddress(text);
  2.  

Tools::IsValidAddress (IPAddress address):
Change:
  1. if (address.AddressFamily != AddressFamily.InterNetwork) return false;
  2.  
To:
  1. if ((address.AddressFamily != AddressFamily.InterNetwork) && (address.AddressFamily != AddressFamily.InterNetworkV6)) return false;
  2.  

Tools::ResolveEndPoint (string address):
Change:
  1. if (split.Length > 1)
  2. {
  3.    address = split[0];
  4.    int.TryParse(split[1], out port);
  5. }
  6.  
To:
  1. if (split.Length == 2)
  2. {
  3.    address = split[0];
  4.    int.TryParse(split[1], out port);
  5. }
  6. else if (split.Length == 9)
  7. {
  8.    address = address.Substring(0, address.Length - split[8].Length - 1);
  9.    int.TryParse(split[8], out port);
  10. }
  11.  

Sorry for ugly formatting. I tried :(
« Last Edit: June 06, 2016, 11:00:46 PM by cmifwdll »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: IPv6 support?
« Reply #1 on: June 06, 2016, 10:28:13 PM »
You missed some key changes there to make the socket listen to both IPv4 and IPv6. If you want to give the latest TNet 3 beta a shot, it should already handle everything correctly, accepting both 4 and 6 connections. Toss me an email to support [at] tasharen.com and I'll hook you up with a copy.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: IPv6 support?
« Reply #2 on: June 06, 2016, 11:31:03 PM »
Oh, I see I did. I don't have the ability to test, so this is needlessly hard. Additional changes:
TcpProtocol::ConnectToTcpEndPoint():
Change:
  1. mSocket = new Socket(tcpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  2.  
To:
  1. mSocket = new Socket(tcpEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  2. if (tcpEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
  3.         mSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
  4.  

GameServer::Start():
Change:
  1. mListener = new TcpListener(IPAddress.Any, tcpPort);
  2.  
To:
  1. mListener = new TcpListener(IPAddress.IPv6Any, tcpPort);
  2. mListener.Server.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
  3.  

TcpLobbyServer::Start():
Change:
  1. mListener = new TcpListener(IPAddress.Any, tcpPort);
  2.  
To:
  1. mListener = new TcpListener(IPAddress.IPv6Any, listenPort);
  2. mListener.Server.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
  3.  

Are there more changes I'm missing? Specifically for TCP, as I'm not worried about UDP. I'm a little wary that SocketOptionName.IPv6Only doesn't exist. I think mono supports it though. If not, then it seems you'd have to create two TcpListener's instead of one.

I'd love to sink my teeth into TNet3, but I'm not ready for the transition yet. Thanks though.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: IPv6 support?
« Reply #3 on: June 07, 2016, 06:18:43 PM »
So, bad news, mSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false); throws an exception because the specified SocketOptionName isn't found. So that means you'd have to have two sockets (and TcpListeners): one for ipv4 and one for ipv6. Right?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: IPv6 support?
« Reply #4 on: June 09, 2016, 02:50:13 PM »
I didn't do any SocketOptions. According to the docs I was reading mListener = new TcpListener(IPAddress.IPv6Any, port); was enough. IPv6Any will accept both 4 and 6.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: IPv6 support?
« Reply #5 on: June 10, 2016, 06:26:48 PM »
Finally got a chance to test it out.
Testing with TNTcpLobbyServer,
  1. mListener = new TcpListener(IPAddress.IPv6Any, listenPort);
  2.  
will only accept IPv6 addresses. Project is built using .NET Framework 3.5 (standalone, not Unity) on Windows 10. Similarly, IPAddress.Any will only accept IPv4 addresses.
Tested with online port scanners:
IPv6: http://www.ipv6scanner.com/cgi-bin/main.py
IPv4: http://www.canyouseeme.org/
If the listener accepted both IPv4 and IPv6, both port scanners should report a success; however, only the IPv6 scanner will report a success. Encourage use of Wireshark to verify the incoming connection is IPv6 or IPv4.

Additionally, with the changes made to TNTools.cs, localAddresses returns a bunch of invalid IPv6 addresses (Teredo Tunneling Pseudo-Interface, Temporary IPv6 Address, and Link-local IPv6 Address). This messes up local connections as localAddress will often return one of the invalid addresses. This much, at least, should be an easy fix.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: IPv6 support?
« Reply #6 on: June 12, 2016, 03:56:33 AM »
Yeah, you're right. I just had a chance to test the changes and it fails to establish an IPv4 connection on an IPv6 socket. Oh well. I'll just add a #define to TNet and the end user can decide if they want to use 4 or 6.

cmifwdll

  • Global Moderator
  • Sr. Member
  • *****
  • Thank You
  • -Given: 0
  • -Receive: 149
  • Posts: 285
  • TNet Alchemist
    • View Profile
Re: IPv6 support?
« Reply #7 on: June 12, 2016, 10:19:29 PM »
I need to study OS level networking again, but couldn't you bind two TCPListener's to the same port? If they're listening on different local addresses (IPAddress.Any, IPAddress.IPv6Any) there shouldn't be issues, right?

Supporting one or the other means a fraction of players won't be able to host / connect, even with ISP's supporting dual stack.

Anyway, I guess it isn't a big deal, thanks for confirming it's a problem with TNet and not on my end.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: IPv6 support?
« Reply #8 on: June 12, 2016, 10:42:40 PM »
No, you can't even bind TCP and UDP to the same port.

What I ended up doing with 3.0.2 yesterday is simply have a boolean on the example script that effectively switches from IPv4 to IPv6. Seems to work well. The only tricky thing was that I had to keep UDP broadcasting/multicasting (server discovery) as IPv4 as it didn't work with IPv6.