Branch: Tag:

2011-07-14

2011-07-14 12:13:32 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Keep track of when specific IP numbers have been superseded by ANY ports.
Open ports on the specific IPs if the corresponding ANY port goes away.
Fixes [bug 5982 (#5982)].

Rev: server/base_server/roxen.pike:1.1082

6:   // Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.   // ABS and suicide systems contributed freely by Francesco Chemolli    - constant cvs_version="$Id: roxen.pike,v 1.1081 2011/06/15 15:11:08 grubba Exp $"; + constant cvs_version="$Id: roxen.pike,v 1.1082 2011/07/14 12:13:32 grubba Exp $";      //! @appears roxen   //!
2638:   //!   //! In both cases the same set of data is stored:   //! @mapping - //! @member mapping(string:Configuration|Protocol|string|array(Protocol)) url + //! @member mapping(string:Configuration|Protocol|string|array(Protocol)|array(string)) url   //! @mapping   //! @member Protocol "port"   //! Representative open port for this URL.
2650:   //! Path segment of the URL.   //! @member string "host"   //! Hostname segment of the URL. + //! @member array(string) "skipped" + //! List of IP numbers not bound due to a corresponding + //! ANY port already being open.   //! @endmapping   //! @endmapping - mapping(string:mapping(string:Configuration|Protocol|string|array(Protocol))) + mapping(string:mapping(string:Configuration|Protocol|string|array(Protocol)|array(string)))    urls = ([]);      array sorted_urls = ({});
2771:    mapping(string:mixed) shared_data = urls[url];    if (!shared_data) return; // Strange case, but URL not registered.    +  int was_any_ip; +  if (!data->skipped && data->port) { +  if (!data->port->ip || (data->port->ip == "::")) { +  was_any_ip = data->port->port; +  report_debug("Unregistering ANY port: %O:%d\n", +  data->port->ip, data->port->port); +  } +  } +     foreach(data->ports, Protocol port) {    shared_data->ports -= ({ port }); -  int was_main_port = (shared_data->port == port); +     port->unref(url);    m_delete(shared_data, "port");    }
2783:    shared_data->port = shared_data->ports[0];    }    sort_urls(); +  +  if (was_any_ip) { +  foreach(urls; string url; mapping(string:mixed) url_info) { +  if (!url_info->skipped || !url_info->conf || +  (url_info->port && (url_info->port->port != was_any_ip))) { +  continue;    } -  +  // Re-register the ports that may have bound to the removed ANY port. +  register_url(url, url_info->conf); +  } +  } + }      array all_ports( )   {
2879:    return 0;    }    -  if (!urls[ourl]) +  // FIXME: Do we need to unref the old ports first in case of a reregister?    urls[ ourl ] = ([ "conf":conf, "path":path, "hostname": host ]);    if (!urls[url]) {    urls[ url ] = urls[ourl] + ([]);
2919:    array(string) ipv4 = required_hosts - ipv6;    if (m[0][port] && sizeof(ipv4 - ({ 0 }))) {    // We have a non-ANY IPv4 IP number. +  // Keep track of the ips in case the ANY port is removed. +  urls[ourl]->skipped = ipv4;    ipv4 = ({ 0 });    }   #if constant(__ROXEN_SUPPORTS_IPV6__)    if (m["::"][port] && sizeof(ipv6 - ({ "::" }))) {    // We have a non-ANY IPv6 IP number. -  +  // Keep track of the ips in case the ANY port is removed. +  urls[ourl]->skipped += ipv6;    ipv6 = ({ "::" });    }    required_hosts = ipv6 + ipv4;