diff --git a/docs/manual.html b/docs/manual.html
index 6dde7a9be..c8d5939e4 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -37,7 +37,7 @@
-
load_asnum_db()
+
+
load_asnum_db() load_country_db()
bool load_asnum_db(char const* file);
+bool load_country_db(char const* file);
-
This function is not available if TORRENT_DISABLE_GEO_IP is defined. This
-expects a path to the MaxMind ASN database. This will be used to look up
-which AS peers belong to.
+
These functions are not available if TORRENT_DISABLE_GEO_IP is defined. They
+expects a path to the MaxMind ASN database and MaxMind GeoIP database
+respectively. This will be used to look up which AS and country peers belong to.
load_state() state()
diff --git a/docs/manual.rst b/docs/manual.rst
index 889ae7944..d21b22fed 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -133,6 +133,7 @@ The ``session`` class has the following synopsis::
int num_connections() const;
bool load_asnum_db(char const* file);
+ bool load_country_db(char const* file);
void load_state(entry const& ses_state);
entry state() const;
@@ -420,18 +421,20 @@ their turn to get connected.
``max_half_open_connections()`` returns the set limit. This limit defaults
to 8 on windows.
-load_asnum_db()
----------------
+load_asnum_db() load_country_db()
+---------------------------------
::
bool load_asnum_db(char const* file);
+ bool load_country_db(char const* file);
-This function is not available if ``TORRENT_DISABLE_GEO_IP`` is defined. This
-expects a path to the `MaxMind ASN database`_. This will be used to look up
-which AS peers belong to.
+These functions are not available if ``TORRENT_DISABLE_GEO_IP`` is defined. They
+expects a path to the `MaxMind ASN database`_ and `MaxMind GeoIP database`_
+respectively. This will be used to look up which AS and country peers belong to.
.. _`MaxMind ASN database`: http://www.maxmind.com/app/asnum
+.. _`MaxMind GeoIP database`: http://www.maxmind.com/app/geolitecountry
load_state() state()
--------------------
diff --git a/examples/client_test.cpp b/examples/client_test.cpp
index 5960645e8..89d9fda75 100644
--- a/examples/client_test.cpp
+++ b/examples/client_test.cpp
@@ -810,6 +810,7 @@ int main(int ac, char* av[])
session ses;
#ifndef TORRENT_DISABLE_GEO_IP
ses.load_asnum_db("GeoIPASNum.dat");
+ ses.load_country_db("GeoIP.dat");
#endif
// UPnP port mapping
ses.start_upnp();
diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp
index 3664e0e3a..dd7f882c4 100644
--- a/include/libtorrent/aux_/session_impl.hpp
+++ b/include/libtorrent/aux_/session_impl.hpp
@@ -295,7 +295,11 @@ namespace libtorrent
int as_for_ip(address const& a);
std::pair* lookup_as(int as);
bool load_asnum_db(char const* file);
- bool has_asnum_db() const { return m_geoip_db; }
+ bool has_asnum_db() const { return m_asnum_db; }
+
+ bool load_country_db(char const* file);
+ bool has_country_db() const { return m_country_db; }
+ char const* country_for_ip(address const& a);
#endif
void load_state(entry const& ses_state);
@@ -591,7 +595,8 @@ namespace libtorrent
#endif
#ifndef TORRENT_DISABLE_GEO_IP
- GeoIP* m_geoip_db;
+ GeoIP* m_asnum_db;
+ GeoIP* m_country_db;
// maps AS number to the peak download rate
// we've seen from it. Entries are never removed
diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp
index 280c32a2b..63dae16e7 100755
--- a/include/libtorrent/session.hpp
+++ b/include/libtorrent/session.hpp
@@ -204,6 +204,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_GEO_IP
bool load_asnum_db(char const* file);
+ bool load_country_db(char const* file);
#endif
void load_state(entry const& ses_state);
diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index 44d8b91fe..9ed399cef 100755
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -133,6 +133,17 @@ namespace libtorrent
TORRENT_ASSERT(peerinfo == 0 || peerinfo->banned == false);
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
std::fill(m_country, m_country + 2, 0);
+#ifndef TORRENT_DISABLE_GEO_IP
+ if (m_ses.has_country_db())
+ {
+ char const *country = m_ses.country_for_ip(m_remote.address());
+ if (country != 0)
+ {
+ m_country[0] = country[0];
+ m_country[1] = country[1];
+ }
+ }
+#endif
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
m_logger = m_ses.create_log(m_remote.address().to_string() + "_"
@@ -218,6 +229,17 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
std::fill(m_country, m_country + 2, 0);
+#ifndef TORRENT_DISABLE_GEO_IP
+ if (m_ses.has_country_db())
+ {
+ char const *country = m_ses.country_for_ip(m_remote.address());
+ if (country != 0)
+ {
+ m_country[0] = country[0];
+ m_country[1] = country[1];
+ }
+ }
+#endif
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
diff --git a/src/session.cpp b/src/session.cpp
index c17a6602d..538ae47d5 100755
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -180,6 +180,11 @@ namespace libtorrent
{
return m_impl->load_asnum_db(file);
}
+
+ bool session::load_country_db(char const* file)
+ {
+ return m_impl->load_country_db(file);
+ }
#endif
void session::load_state(entry const& ses_state)
diff --git a/src/session_impl.cpp b/src/session_impl.cpp
index a12d906ef..f3f95b7c0 100755
--- a/src/session_impl.cpp
+++ b/src/session_impl.cpp
@@ -174,7 +174,8 @@ namespace aux {
, m_logpath(logpath)
#endif
#ifndef TORRENT_DISABLE_GEO_IP
- , m_geoip_db(0)
+ , m_asnum_db(0)
+ , m_country_db(0)
#endif
{
m_tcp_mapping[0] = -1;
@@ -265,10 +266,16 @@ namespace aux {
};
}
+ char const* session_impl::country_for_ip(address const& a)
+ {
+ if (!a.is_v4() || m_country_db == 0) return 0;
+ return GeoIP_country_code_by_ipnum(m_country_db, a.to_v4().to_ulong());
+ }
+
int session_impl::as_for_ip(address const& a)
{
- if (!a.is_v4() || m_geoip_db == 0) return 0;
- char* name = GeoIP_name_by_ipnum(m_geoip_db, a.to_v4().to_ulong());
+ if (!a.is_v4() || m_asnum_db == 0) return 0;
+ char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
if (name == 0) return 0;
free_ptr p(name);
// GeoIP returns the name as AS??? where ? is the AS-number
@@ -277,8 +284,8 @@ namespace aux {
std::string session_impl::as_name_for_ip(address const& a)
{
- if (!a.is_v4() || m_geoip_db == 0) return std::string();
- char* name = GeoIP_name_by_ipnum(m_geoip_db, a.to_v4().to_ulong());
+ if (!a.is_v4() || m_asnum_db == 0) return std::string();
+ char* name = GeoIP_name_by_ipnum(m_asnum_db, a.to_v4().to_ulong());
if (name == 0) return std::string();
free_ptr p(name);
char* tmp = std::strchr(name, ' ');
@@ -301,9 +308,17 @@ namespace aux {
bool session_impl::load_asnum_db(char const* file)
{
mutex_t::scoped_lock l(m_mutex);
- if (m_geoip_db) GeoIP_delete(m_geoip_db);
- m_geoip_db = GeoIP_open(file, GEOIP_STANDARD);
- return m_geoip_db;
+ if (m_asnum_db) GeoIP_delete(m_asnum_db);
+ m_asnum_db = GeoIP_open(file, GEOIP_STANDARD);
+ return m_asnum_db;
+ }
+
+ bool session_impl::load_country_db(char const* file)
+ {
+ mutex_t::scoped_lock l(m_mutex);
+ if (m_country_db) GeoIP_delete(m_country_db);
+ m_country_db = GeoIP_open(file, GEOIP_STANDARD);
+ return m_country_db;
}
#endif
@@ -1985,7 +2000,8 @@ namespace aux {
abort();
#ifndef TORRENT_DISABLE_GEO_IP
- if (m_geoip_db) GeoIP_delete(m_geoip_db);
+ if (m_asnum_db) GeoIP_delete(m_asnum_db);
+ if (m_country_db) GeoIP_delete(m_country_db);
#endif
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " waiting for main thread\n";