#
#
# 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);
}