wiki:MapGuideRfc118

Version 6 (modified by wuma, 13 years ago) ( diff )

--

MapGuide RFC 118 - Support IPv6

This page contains a change request (RFC) for the MapGuide Open Source project. More MapGuide RFCs can be found on the RFCs page.

Status

RFC Template Version(1.0)
Submission Date04 July 2011
Last Modified04 July 2011
AuthorMars Wu
RFC Statusdraft
Implementation Statuspending
Proposed Milestone2.3
Assigned PSC guide(s)Bruce Dechant
Voting History(vote date)
+1
+0
-0
-1
no vote

Overview

This RFC proposes a solution to make MGOS work with both IPv4 and IPv6.

Motivation

IPv6 is the trend of network. Supporting IPv6 will be a must-have for MGOS in the future.

Proposed Solution

To make MGOS support IPv6, couple things need be done:

  1. Enable IPv6 for ACE.

ACE supports both IPv4 and IPv6. But by default, ACE is compiled without IPv6 support. To change this, one compiler predriective should be defined:

#define ACE_HAS_IPV6

It should be defined in config.h so that it could be effective for both Windows and Linux

  1. Port the IP address validation logic.

There is existing logic to validate if the IP address specified in the configuration file is valid. But the logic always assumes the IP address is in v4 format. We need port the logic to consider both v4 format and v6 format. One example is like below in in \Common\MapGuideCommon\Util\IpUtil.cpp.

void MgIpUtil::ValidateAddress(CREFSTRING address, bool strict)
{
...

    if (STRING::npos != address.rfind(L':'))
    {
        MgStringCollection arguments;
        arguments.Add(L"1");
        arguments.Add(address);

        MgStringCollection whyArguments;
        whyArguments.Add(L":");

        throw new MgInvalidArgumentException(L"MgIpUtil.ValidateAddress",
            __LINE__, __WFILE__, &arguments,
            L"MgStringContainsReservedCharacters", &whyArguments);
    }
...
}

It treats the character ":" as invalid. But for IPv6, ":" is used as a splitter for the address segments.

  1. Make MapGuide Server listen to IPv6 address

When the service of MapGuide Server starts, it uses following code to listen to the client, site and admin ports: Server\src\Core\Server.cpp

ACE_INET_Addr clientAddr((u_short)pServerManager->GetClientPort));
ACE_INET_Addr adminAddr((u_short)pServerManager->GetAdminPort());
ACE_INET_Addr siteAddr((u_short)pServerManager->GetSitePort());

But this way it always listens to IPv4 address no matter if IPv6 is available. Then the 3 ACE_INET_Addr instances need be created by another constructor:

ACE_INET_Addr (u_short port_number,
               const wchar_t host_name[],
               int address_family = AF_UNSPEC);

by passing in an IPv6 address as host_name, MapGuide Server can listen to the IPv6 address instead of IPv4 address. But if the given host_name is a specific IP Address, the Client (Web Extension, Support Server, Admin etc.) has to connect to the Server through the given IP Address. E.g. if there is a computer whose IP Addresses are:

IPv4	127.0.0.1
	192.168.0.10
IPv6	::1
	fe80::9c4b:2cb5:5cda:5c3f%11

MapGuide Server should be able to be connected with either 127.0.0.1 or 192.168.0.10 for IPv4 and either ::1 or fe80::9c4b:2cb5:5cda:5c3f%11 for IPv6. But if we pass 127.0.0.1 as the host_name, MapGuide Server will NOT listen to 192.168.0.10. The same for IPv6. The solution is: we don’t pass in a specific IP Address, instead:

  • For IPv4, we pass in 0.0.0.0. Then it will listen to all IPv4 addresses.
  • For IPv6, we pass in ::. Then it will listen to all IPv6 address.
  1. Add the IPv6 / v4 configuration in serverconfig.ini

We need a way to determine we should pass in 0.0.0.0 or :: as the host_name parameter when instantizte the ACE_INET_Addr objects. Although passing the ip address seems to be the right way to determine the protocol version at runtime, adding a new configuration parameter in serverconfig.ini is a much simpler and more reliable solution – the machine IP is specified by the MachineIp parameter, but it can happen that the user doesn’t input any ip address at all in serverconfig.ini. So adding one more parameter is a better idea. The parameter will be added into GeneralProperties section following the MachineIp parameter.

[GeneralProperties]
# *****************************************************************************
# G E N E R A L
#
# Property Name                    Description
# -----------------------------------------------------------------------------
# MachineIp	IP address of this server
# Ipv6		Specify if the server will listen to Ipv6 addresses. 
#		Possible values: 1, 0 or empty.
#		0 or empty means it’s Ipv4. 1 (or non-zero values) means Ipv6
  1. Change the way encoding Site IpAddress into SessionId

MapGuide Server encodes the IP address of site server into the Session Id so that it could pick the right site server from the list by comparing the IP address. The encoding logic currently is: (INTERNAL_API)

STRING MgSiteInfo::ToHexString()
{
    STRING hexString;
    UINT32 n1, n2, n3, n4;
    wchar_t buffer[30];
    if (4 == ::swscanf(m_target.c_str(), L"%u.%u.%u.%u", &n1, &n2, &n3, &n4))
    {
        swprintf(buffer, 30, L"%.2X%.2X%.2X%.2X%.4X%.4X%.4X", n1, n2, n3, n4, 
                 m_sitePort, m_clientPort, m_adminPort);
        hexString = buffer;
    }

    return hexString;
} 

Then it works for only IPv4. And for IPv6, because the valid format is really complicated, then convert it to a hex string is difficult. The solution is: encode the IP as Base64 string. The port numbers will still be converted to hex string so that they could be easily decoded. Then the new method will be like:

STRING MgSiteInfo::ToHexString()
{
    STRING hexString;
    
    char buf[100] = {0};
    char* target = ACE_Wide_To_Ascii(m_target.c_str()).char_rep();
    Base64::Encode(buf, (unsigned char*)target, (unsigned long)strlen(target));
    
    wchar_t buffer[100] = {0};	
    swprintf(buffer, L"%s%.4X%.4X%.4X", ACE_Ascii_To_Wide(buf).wchar_rep(),     
             m_sitePort, m_clientPort, m_adminPort);
    hexString = buffer;

    return hexString;
}

One thing that needs attention is: A Base64 string might have “=” appended at the end for alignment. But “=” is treated as a reserved character. The solutions is: we remove all appending “=” when doing encoding, and then append them back when doing decoding

Implications

Since it just makes MGOS work with IPv6, it doesn't change any existing functions.

Test Plan

Since it doesn't change any existing functions, so no new test cases need be added.

Funding / Resources

Autodesk supplied.

Note: See TracWiki for help on using the wiki.