From: <sv...@ww...> - 2004-12-18 11:05:38
|
Author: mkrose Date: 2004-12-18 03:05:26 -0800 (Sat, 18 Dec 2004) New Revision: 1406 Modified: trunk/CSP/IndexServer/IndexServer.cpp trunk/CSP/SimCore/Battlefield/GlobalBattlefield.h Log: Part of a significant simplification of ip address specifications for the index server and clients. The global battlefield and IS now use the inbound ip address to infer the remote external ip rather than forcing the client to specify it explicitly. Improve the error checking and correctly handle peer-peer introductions for both local and remote peers. NOTE: in IndexServer.ini, you must specify ExternalIp=x.x.x.x to receive connections from external clients (assuming you are running on a LAN behind a NAT router). If unspecified, the Bind parameter will now default to the primary ethernet interface, port 3160. If in doubt, just delete the entire [Network] section, rerun IS to regenerate the default fields, and add ExternalIp = {your external ip}. If you have a dynamic ip assignment, the latter must be updated whenever your ip changes. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1406 Modified: trunk/CSP/IndexServer/IndexServer.cpp =================================================================== --- trunk/CSP/IndexServer/IndexServer.cpp 2004-12-18 11:00:39 UTC (rev 1405) +++ trunk/CSP/IndexServer/IndexServer.cpp 2004-12-18 11:05:26 UTC (rev 1406) @@ -42,7 +42,9 @@ void IndexServer::initPrimaryInterface() { assert(m_NetworkServer.isNull()); - const std::string server_interface = g_Config.getString("Network", "Bind", "127.0.0.1:4999", true); + simnet::NetworkNode default_node; + const std::string server_interface = g_Config.getString("Network", "Bind", default_node.getIpString() + ":3160", true); + const std::string external_ip = g_Config.getString("Network", "ExternalIp", "", false); const std::string::size_type colon = server_interface.find(':'); std::string address; simnet::Port port = 0; @@ -55,11 +57,32 @@ std::cerr << "Should be of the form www.xxx.yyy.zzz:port\n"; ::exit(1); } - CSP_LOG(APP, INFO, "binding to interface " << address << ":" << port); - simnet::NetworkNode local(address, port); + simnet::NetworkNode local_node(address, port); + CSP_LOG(APP, INFO, "binding to interface " << local_node); + const int incoming_bw = g_Config.getInt("Network", "IncomingBandwidth", 12000, true); const int outgoing_bw = g_Config.getInt("Network", "OutgoingBandwidth", 12000, true); - m_NetworkServer = new simnet::Server(local, incoming_bw, outgoing_bw); + m_NetworkServer = new simnet::Server(local_node, incoming_bw, outgoing_bw); + + if (external_ip.empty()) { + if (!local_node.isRoutable()) { + CSP_LOG(APP, WARNING, "no external ip address specified; accepting only local (LAN) connections"); + } + } else { + if (!local_node.isRoutable()) { + simnet::NetworkNode external_node(external_ip, port); + CSP_LOG(APP, INFO, "external interface is " << external_node); + if (external_node.isRoutable()) { + m_NetworkServer->setExternalNode(external_node); + } else { + CSP_LOG(APP, ERROR, "external interface is not routable; ignoring ExternalIp and accepting only local (LAN) connections"); + } + } else { + if (external_ip != address) { + CSP_LOG(APP, ERROR, "binding to a routable interface that does not match the specified external ip (" << external_ip << "); ignoring ExternalIp"); + } + } + } } void IndexServer::initialize() { Modified: trunk/CSP/SimCore/Battlefield/GlobalBattlefield.h =================================================================== --- trunk/CSP/SimCore/Battlefield/GlobalBattlefield.h 2004-12-18 11:00:39 UTC (rev 1405) +++ trunk/CSP/SimCore/Battlefield/GlobalBattlefield.h 2004-12-18 11:05:26 UTC (rev 1406) @@ -186,7 +186,7 @@ dispatch->registerHandler(this, &GlobalBattlefield::onRegisterUnit); } - PlayerJoin::Ref makeJoin(const PeerId id) { + PlayerJoin::Ref makeJoin(const PeerId id, bool local) { PlayerJoin::Ref join = new PlayerJoin(); join->setRoutingType(ROUTE_COMMAND); join->setReliable(); @@ -197,29 +197,23 @@ join->set_outgoing_bw(static_cast<int>(peer_info->outgoingBandwidth())); join->set_incoming_bw(static_cast<int>(peer_info->incomingBandwidth())); join->set_port(peer_info->getNode().getPort()); - // default to the external ip (overridden in announceJoin) - join->set_ip_addr(data.external_ip_addr); + join->set_ip_addr(local ? data.internal_ip_addr : data.external_ip_addr); return join; } void announceJoin(const PeerId id) { - //ClientData &new_client_data = m_ClientData[id]; - PlayerJoin::Ref join = makeJoin(id); + ClientData &new_client_data = m_ClientData[id]; + PlayerJoin::Ref local_join = makeJoin(id, true); + PlayerJoin::Ref remote_join = makeJoin(id, false); for (ClientDataMap::const_iterator iter = m_ClientData.begin(); iter != m_ClientData.end(); ++iter) { // don't announce to ourself if (iter->first == id) continue; // if the external ips match, these hosts are probably on a LAN and should communicate via their // internal interfaces; otherwise use the external ip. - /* XXX broken since join is shared for all outbound messages - if (iter->second.external_ip_addr == new_client_data.external_ip_addr) { - join->set_ip_addr(new_client_data.internal_ip_addr); - } else { - join->set_ip_addr(new_client_data.external_ip_addr); - } - */ - - m_NetworkServer->queue()->queueMessage(join, iter->first); + PlayerJoin::Ref join; + bool local = (iter->second.external_ip_addr == new_client_data.external_ip_addr); + m_NetworkServer->queue()->queueMessage(local ? local_join : remote_join, iter->first); } } @@ -234,12 +228,14 @@ } - // FIXME sends one message for each existing player. + // FIXME sends one message for each existing player (should be batched into one, or a few, messages). void announceExistingPlayers(const PeerId new_id) { + ClientData &new_client_data = m_ClientData[new_id]; for (ClientDataMap::const_iterator iter = m_ClientData.begin(); iter != m_ClientData.end(); ++iter) { const PeerId id = iter->first; if (id == new_id) continue; - PlayerJoin::Ref join = makeJoin(id); + bool local = (iter->second.external_ip_addr == new_client_data.external_ip_addr); + PlayerJoin::Ref join = makeJoin(id, local); m_NetworkServer->queue()->queueMessage(join, new_id); } } @@ -258,35 +254,39 @@ PeerId id = msg->getSource(); simnet::PeerInfo const *peer_info = m_NetworkServer->getPeer(id); + uint32 inbound_ip_addr = peer_info->getNode().getIp(); uint32 internal_ip_addr = msg->has_internal_ip_addr() ? msg->internal_ip_addr() : inbound_ip_addr; - uint32 external_ip_addr = msg->has_external_ip_addr() ? msg->external_ip_addr() : inbound_ip_addr; - ost::InetAddress decode_addr; - CSP_LOG(BATTLEFIELD, INFO, "join request from " << (decode_addr = inbound_ip_addr).getHostname()); - CSP_LOG(BATTLEFIELD, INFO, " internal ip " << (decode_addr = internal_ip_addr).getHostname()); - CSP_LOG(BATTLEFIELD, INFO, " external ip " << (decode_addr = external_ip_addr).getHostname()); + CSP_LOG(BATTLEFIELD, INFO, "join request from " << peer_info->getNode()); + CSP_LOG(BATTLEFIELD, INFO, " internal ip " << simnet::NetworkNode::ipToString(internal_ip_addr)); // basic sanity checking on ip addresses - if (simnet::NetworkNode::isRoutable(internal_ip_addr) && (internal_ip_addr != external_ip_addr)) { + if (simnet::NetworkNode::isRoutable(internal_ip_addr) && (internal_ip_addr != inbound_ip_addr)) { CSP_LOG(BATTLEFIELD, ERROR, "join rejected: internal ip routable, but does not match external ip"); response->set_details("internal ip routable, but does not match external ip"); response.send(queue); return; } - if (simnet::NetworkNode::isRoutable(inbound_ip_addr) && (external_ip_addr != inbound_ip_addr)) { - CSP_LOG(BATTLEFIELD, ERROR, "join rejected: inbound ip routable, but does not match external ip"); - response->set_details("inbound ip is routable, but does not match external ip"); - response.send(queue); - return; - } if (!simnet::NetworkNode::isRoutable(inbound_ip_addr) && (internal_ip_addr != inbound_ip_addr)) { CSP_LOG(BATTLEFIELD, ERROR, "join rejected: inbound ip unroutable, but does not match internal ip"); response->set_details("inbound ip is unroutable, but does not match internal ip"); response.send(queue); return; } + if (simnet::NetworkNode::isRoutable(inbound_ip_addr) && (!m_NetworkServer->getExternalNode().isRoutable())) { + CSP_LOG(BATTLEFIELD, ERROR, "join rejected: inbound ip routable, but server is not configured to accept remote connections (no external ip set)."); + response->set_details("server not configured to accept remote connections"); + response.send(queue); + return; + } + // the correct "external" ip for remote clients is the ip the packets come from. for clients + // on the same lan, use the server's "external" ip address. this simplifies the configuration, + // since only the server needs to specify an external ip address; the clients can just bind to + // their local interfaces and the server will decide which ip to use when introducing two peers. + uint32 external_ip_addr = simnet::NetworkNode::isRoutable(inbound_ip_addr) ? inbound_ip_addr : m_NetworkServer->getExternalNode().getIp(); + ClientData &data = m_ClientData[id]; response->set_success(true); response->set_details("welcome " + msg->user_name()); |