# # # patch "ChangeLog" # from [9db6a7ef69afbce9b8e915455f82a8be359c5842] # to [e890f4b921a48dff2378a4867338e5e644923d71] # # patch "netsync.cc" # from [4762b64c8b2098ee894c3798934fdcdfc4c80bdd] # to [4d15f2c47aed8bb45b5dc8267ab60c35703d49e9] # ============================================================ --- ChangeLog 9db6a7ef69afbce9b8e915455f82a8be359c5842 +++ ChangeLog e890f4b921a48dff2378a4867338e5e644923d71 @@ -1,5 +1,10 @@ 2006-02-11 Richard Levitte + * netsync.cc (serve_connections): Enclose more or less everything + in a try-catch block to catch if using IPv6 failed, and to try + with just IPv4 in that case. This is important for those who + copy a IPv6-enabled binary to a system that doesn't use IPv6. + * po/sv.po: Adapt translation to the newly changed messages. 2006-02-10 Derek Scherger ============================================================ --- netsync.cc 4762b64c8b2098ee894c3798934fdcdfc4c80bdd +++ netsync.cc 4d15f2c47aed8bb45b5dc8267ab60c35703d49e9 @@ -2575,102 +2575,138 @@ #else bool use_ipv6=false; #endif - Netxx::Address addr(use_ipv6); + // This will be true when we try to bind while using IPv6. See comments + // further down. + bool try_again=false; - if (!app.bind_address().empty()) - addr.add_address(app.bind_address().c_str(), default_port); - else - addr.add_all_addresses (default_port); + do + { + try + { + try_again = false; + Netxx::Address addr(use_ipv6); - Netxx::StreamServer server(addr, timeout); - const char *name = addr.get_name(); - P(F("beginning service on %s : %s\n") - % (name != NULL ? name : "all interfaces") - % lexical_cast(addr.get_port())); + if (!app.bind_address().empty()) + addr.add_address(app.bind_address().c_str(), default_port); + else + addr.add_all_addresses (default_port); + + // If se use IPv6 and the initiasation of server fails, we want + // to try again with IPv4. The reason is that someone may have + // downloaded a IPv6-enabled monotone on a system that doesn't + // have IPv6, and which might fail therefore. + // On failure, Netxx::NetworkException is thrown, and we catch + // it further down. + try_again=use_ipv6; + + Netxx::StreamServer server(addr, timeout); + + // If we came this far, whatever we used (IPv6 or IPv4) was + // accepted, so we don't need to try again any more. + try_again=false; + + const char *name = addr.get_name(); + P(F("beginning service on %s : %s\n") + % (name != NULL ? name : "all interfaces") + % lexical_cast(addr.get_port())); - map > sessions; - set armed_sessions; + map > sessions; + set armed_sessions; - shared_ptr guard; + shared_ptr guard; - while (true) - { - probe.clear(); - armed_sessions.clear(); + while (true) + { + probe.clear(); + armed_sessions.clear(); - if (sessions.size() >= session_limit) - W(F("session limit %d reached, some connections " - "will be refused\n") % session_limit); - else - probe.add(server); + if (sessions.size() >= session_limit) + W(F("session limit %d reached, some connections " + "will be refused\n") % session_limit); + else + probe.add(server); - arm_sessions_and_calculate_probe(probe, sessions, armed_sessions); + arm_sessions_and_calculate_probe(probe, sessions, armed_sessions); - L(FL("i/o probe with %d armed\n") % armed_sessions.size()); - Netxx::Probe::result_type res = probe.ready(sessions.empty() ? forever - : (armed_sessions.empty() ? timeout - : instant)); - Netxx::Probe::ready_type event = res.second; - Netxx::socket_type fd = res.first; + L(FL("i/o probe with %d armed\n") % armed_sessions.size()); + Netxx::Probe::result_type res = probe.ready(sessions.empty() ? forever + : (armed_sessions.empty() ? timeout + : instant)); + Netxx::Probe::ready_type event = res.second; + Netxx::socket_type fd = res.first; - if (!guard) - guard = shared_ptr(new transaction_guard(app.db)); + if (!guard) + guard = shared_ptr(new transaction_guard(app.db)); - I(guard); + I(guard); - if (fd == -1) - { - if (armed_sessions.empty()) - L(FL("timed out waiting for I/O (listening on %s : %s)\n") - % addr.get_name() % lexical_cast(addr.get_port())); - } + if (fd == -1) + { + if (armed_sessions.empty()) + L(FL("timed out waiting for I/O (listening on %s : %s)\n") + % addr.get_name() % lexical_cast(addr.get_port())); + } - // we either got a new connection - else if (fd == server) - handle_new_connection(addr, server, timeout, role, - include_pattern, exclude_pattern, - sessions, app); + // we either got a new connection + else if (fd == server) + handle_new_connection(addr, server, timeout, role, + include_pattern, exclude_pattern, + sessions, app); - // or an existing session woke up - else - { - map >::iterator i; - i = sessions.find(fd); - if (i == sessions.end()) - { - L(FL("got woken up for action on unknown fd %d\n") % fd); - } - else - { - shared_ptr sess = i->second; - bool live_p = true; + // or an existing session woke up + else + { + map >::iterator i; + i = sessions.find(fd); + if (i == sessions.end()) + { + L(FL("got woken up for action on unknown fd %d\n") % fd); + } + else + { + shared_ptr sess = i->second; + bool live_p = true; - if (event & Netxx::Probe::ready_read) - handle_read_available(fd, sess, sessions, - armed_sessions, live_p); + if (event & Netxx::Probe::ready_read) + handle_read_available(fd, sess, sessions, + armed_sessions, live_p); - if (live_p && (event & Netxx::Probe::ready_write)) - handle_write_available(fd, sess, sessions, live_p); + if (live_p && (event & Netxx::Probe::ready_write)) + handle_write_available(fd, sess, sessions, live_p); - if (live_p && (event & Netxx::Probe::ready_oobd)) + if (live_p && (event & Netxx::Probe::ready_oobd)) + { + P(F("got OOB from peer %s, disconnecting\n") + % sess->peer_id); + sessions.erase(i); + } + } + } + process_armed_sessions(sessions, armed_sessions, *guard); + reap_dead_sessions(sessions, timeout_seconds); + + if (sessions.empty()) { - P(F("got OOB from peer %s, disconnecting\n") - % sess->peer_id); - sessions.erase(i); + // Let the guard die completely if everything's gone quiet. + guard->commit(); + guard.reset(); } } } - process_armed_sessions(sessions, armed_sessions, *guard); - reap_dead_sessions(sessions, timeout_seconds); - - if (sessions.empty()) + catch (Netxx::NetworkException &e) { - // Let the guard die completely if everything's gone quiet. - guard->commit(); - guard.reset(); + // If we tried with IPv6 and failed, we want to try again using IPv4. + if (try_again) + { + use_ipv6 = false; + } + // In all other cases, just rethrow the exception. + else + throw; } } + while(try_again); }