Skip to content

IP2Country: swap libGeoIP for libmaxminddb (.dat → .mmdb) - #502

Merged
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:pr-a-ip2country-maxminddb
Apr 29, 2026
Merged

IP2Country: swap libGeoIP for libmaxminddb (.dat → .mmdb)#502
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:pr-a-ip2country-maxminddb

Conversation

@got3nks

@got3nks got3nks commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Swaps the IP2Country backend from libGeoIP v1 (GeoIP.dat) to libmaxminddb v2 (GeoLite2-Country.mmdb). MaxMind discontinued the v1 product in 2019 and distros are increasingly dropping libGeoIP. Public API of CIP2Country is unchanged — no caller in ListenSocket, GenericClientListCtrl, etc. is affected.

Why

  • MaxMind's only currently-maintained free dataset is GeoLite2-Country in the .mmdb format.
  • Debian / Ubuntu / Fedora / Arch / Homebrew / MSYS2 all ship libmaxminddb and have been moving away from libGeoIP.
  • Without this change, building IP2Country support on a current distro increasingly requires installing the legacy libGeoIP from third-party packages or building it from source.

What's in the PR

src/geoip/MaxMindDBDatabase.{h,cpp} — new thin wrapper (~90 LoC)

Tiny RAII class around the libmaxminddb C API:

class CMaxMindDBDatabase {
public:
    bool        Open(const wxString& path);    // MMDB_open, MMAP mode
    void        Close();                       // MMDB_close
    bool        IsOpen() const;
    wxString    GetCountryCode(const wxString& ip) const;  // lowercase ISO 3166-1
};

No abstract interface, no factory, no singleton, no manager class — just the one wrapper that replaces the GeoIP_* calls. The whole production scope of MaxMindDB integration that someone might be tempted to build (pluggable backends, format detection, auto-update scheduler, retry policy) is intentionally absent. A second backend, if it ever appears, can introduce abstraction at that point with a concrete second use case.

src/IP2Country.{h,cpp} — backend swap

CIP2Country holds a CMaxMindDBDatabase* via a forward-declared raw pointer (so the ENABLE_IP2COUNTRY=OFF build path stays trivial — no header dependency on <maxminddb.h> from the #else branch). The five public methods (GetCountryData / Enable / Disable / IsEnabled / Update / DownloadFinished) keep their existing signatures.

Database filename is now GeoLite2-Country.mmdb.

src/Preferences.cpp — auto-download URL default

The default value of /eMule/GeoLiteCountryUpdateUrl is empty:

  • MaxMind's official download URL requires a per-account license key.
  • Their archive is .tar.gz with a date-stamped subdirectory, which UnpackArchive does not handle (it understands .gz and .zip only).

Forcing a "best-effort" auto-download that always 404s or fails to extract is worse UX than asking the user to drop the file manually once. When the URL is empty and the file is missing, Update() now logs a clear instruction (path + free-account note) instead of trying to fetch.

Users who want auto-update can edit GeoLiteCountryUpdateUrl in amule.conf directly — there is no GUI field for it. A third-party mirror that serves a plain .mmdb.gz works with the existing decompress flow.

Build system

  • cmake/ip2country.cmakefind_path(maxminddb.h) + find_library(maxminddb). Matches the existing libGeoIP probe pattern. Upstream libmaxminddb does not ship a CMake config file in the common distros / Homebrew / MSYS2, so a manual probe is needed.
  • cmake/source-vars.cmake — adds geoip/MaxMindDBDatabase.cpp to the IP2COUNTRY source list.
  • src/CMakeLists.txtMaxMindDB::Shared replaces GeoIP::Shared as the imported target. The IP2COUNTRY source-files compile flags get -I${CMAKE_CURRENT_SOURCE_DIR} added so geoip/*.cpp finds Logger.h.
  • Top-level CMakeLists.txt — status print updated.

docs/IP2Country.md — new setup guide

Covers build prerequisites for each platform (Debian / Fedora / Arch / Homebrew / MSYS2), the per-platform path where the .mmdb should be dropped, three ways to obtain the database (MaxMind direct, third-party mirrors, generate from CSV with mmdbctl / geolite2legacy), the GUI enable step, the auto-update limitation, and diagnostics.

docs/INSTALL — corrected references

The optional dependency entry and the ENABLE_IP2COUNTRY description both said libGeoIP; updated to libmaxminddb with a pointer to docs/IP2Country.md for the runtime setup.

Backward compatibility

  • CIP2Country's public API is unchanged — every call site keeps working.
  • ENABLE_IP2COUNTRY=OFF build path keeps the no-op stubs and adds no dependency.
  • No wire protocol changes.
  • No .met / on-disk format changes.
  • The previous GeoIP.dat config setting is not migrated. Users moving from a libGeoIP build need to drop a GeoLite2-Country.mmdb at the same config directory; the old .dat file is ignored. This matches what the migration off libGeoIP requires anyway.

Tested

  • macOS Apple Silicon (Release build, Homebrew libmaxminddb 1.13.3): country flags render correctly in the search results, transfers pane, and shared-files-peers list.
  • Windows ARM64 in UTM (MSYS2 CLANGARM64, Release build): same.

Smoke-test recipe: download GeoLite2-Country.mmdb from MaxMind (free signup), drop it into the platform-specific config directory documented in docs/IP2Country.md, tick Show country flags for clients in Preferences → GUI Tweaks, restart aMule, observe flags rendering for peers.

Files changed

11 files / +384 / -87.

File Purpose
src/geoip/MaxMindDBDatabase.h / .cpp NEW. Thin libmaxminddb wrapper. ~90 LoC.
src/IP2Country.h / .cpp Replace GeoIPTag* with CMaxMindDBDatabase*. Public API unchanged.
src/Preferences.cpp Default GeoLiteCountryUpdateUrl to empty.
cmake/ip2country.cmake find_path + find_library for libmaxminddb; export MaxMindDB::Shared.
cmake/source-vars.cmake Add geoip/MaxMindDBDatabase.cpp to IP2COUNTRY sources.
src/CMakeLists.txt Link MaxMindDB::Shared. Add -I${CMAKE_CURRENT_SOURCE_DIR} to IP2COUNTRY compile flags so geoip/*.cpp resolves cross-tree includes.
CMakeLists.txt Top-level status print: libmaxminddb instead of libGeoIP.
docs/INSTALL Optional dependency listing + ENABLE_IP2COUNTRY build-option description: libGeoIPlibmaxminddb, pointer to docs/IP2Country.md.
docs/IP2Country.md NEW. Build prereqs per platform, db location, three ways to obtain the .mmdb, GUI step, auto-update note, diagnostics.

MaxMind discontinued the GeoLite v1 .dat databases in 2019; the
distros that still ship libGeoIP are increasingly few, and
libmaxminddb v2 with .mmdb is what's currently maintained.

* Add CMaxMindDBDatabase, a thin RAII wrapper around libmaxminddb
  that opens an .mmdb in MMAP mode and looks up an IP's ISO 3166-1
  alpha-2 country code.  ~90 lines, no abstract interface, no
  factory, no manager — just the wrapper that replaces the GeoIP_*
  calls.
* CIP2Country holds one CMaxMindDBDatabase via a forward-declared
  raw pointer (so the no-IP2Country build path stays trivial).  The
  public API (GetCountryData / Enable / Disable / IsEnabled / Update)
  is unchanged, so no caller in ListenSocket / GenericClientListCtrl
  / etc. is affected.
* Database filename is now GeoLite2-Country.mmdb (was GeoIP.dat).
* Auto-download URL defaults to empty.  MaxMind requires a (free)
  license key for GeoLite2 downloads, and the official URL returns
  .tar.gz which the existing UnpackArchive does not handle — so the
  default behaviour is "drop the .mmdb at the config directory
  manually" rather than a broken auto-download.  Users who want
  auto-update can edit GeoLiteCountryUpdateUrl in amule.conf
  directly (no GUI field for this).  When the URL is empty and the
  file is missing, Update() now logs a clear instruction (path +
  free-account note) instead of trying to fetch.
* cmake/ip2country.cmake: find_path + find_library for libmaxminddb
  (matches the existing libGeoIP probe pattern; libmaxminddb does
  not ship a CMake config file in the common distros / Homebrew /
  msys2).
* MaxMindDB::Shared replaces GeoIP::Shared as the link target.
* docs/IP2Country.md: setup guide covering build prereqs per
  platform, database location, three ways to obtain the .mmdb
  (MaxMind direct, third-party mirrors, generate from CSV), GUI
  enable step, the auto-update limitation, diagnostics.
@got3nks
got3nks force-pushed the pr-a-ip2country-maxminddb branch from c27c4b3 to 4637f5a Compare April 29, 2026 13:28
@mrjimenez
mrjimenez merged commit 1ba110d into amule-project:master Apr 29, 2026
9 checks passed
got3nks added a commit to got3nks/amule that referenced this pull request Apr 30, 2026
Previously commented out citing windows-11-arm runner stability;
the CLANGARM64 build is verified locally on the dev VM (amule-dev-
windows) and produces a clean ~19 MB portable .zip. Better to have
both archs covered on every PR and add continue-on-error if the
runner proves flaky.

Parameterized the package-prefix (${{ matrix.pkg_prefix }}) so the
install list works for both archs:
  x64    -> mingw-w64-x86_64-...
  arm64  -> mingw-w64-clang-aarch64-...

Also dropped mingw-w64-*-geoip from the install list — IP2Country
migrated to libmaxminddb in PR amule-project#502, libgeoip is no longer used.
got3nks added a commit to got3nks/amule that referenced this pull request May 1, 2026
Follow-up to amule-project#502 which migrated aMule from libGeoIP to libmaxminddb
(GeoIP-1 .dat → GeoIP-2 .mmdb). The CI workflow's apt / brew /
pacman deps lists kept the old libGeoIP packages, which left
ENABLE_IP2COUNTRY silently off on every CI run:

* Ubuntu had `libgeoip-dev` (unused since amule-project#502) but no
  `libmaxminddb-dev`, so cmake/ip2country.cmake's find_path on
  maxminddb.h fell through the soft-fail and disabled the feature.
* Windows MSYS2 had the same gap (`mingw-w64-x86_64-geoip` instead
  of `mingw-w64-x86_64-libmaxminddb`).
* macOS hardcoded `cmake_macos_config_flags: -DENABLE_IP2COUNTRY=NO`
  with a comment claiming "Homebrew dropped legacy libgeoip; only
  libmaxminddb is available, which aMule doesn't use" — outdated
  since amule-project#502, libmaxminddb is in Homebrew and aMule does use it.

This patch:

* Replaces `libgeoip-dev` -> `libmaxminddb-dev` on Ubuntu
* Replaces `mingw-w64-x86_64-geoip` -> `mingw-w64-x86_64-libmaxminddb`
  on Windows
* Adds `libmaxminddb` to the macOS Homebrew install list
* Flips macOS `-DENABLE_IP2COUNTRY=NO` -> `=YES` and drops the stale
  comment

Net effect: PR builds now exercise the IP2Country code path on all
three platforms instead of silently skipping it. No source-code
changes; runtime behaviour for users is unchanged (the database file
is still user-supplied, see docs/IP2Country.md).
mrjimenez pushed a commit that referenced this pull request May 1, 2026
Follow-up to #502 which migrated aMule from libGeoIP to libmaxminddb
(GeoIP-1 .dat → GeoIP-2 .mmdb). The CI workflow's apt / brew /
pacman deps lists kept the old libGeoIP packages, which left
ENABLE_IP2COUNTRY silently off on every CI run:

* Ubuntu had `libgeoip-dev` (unused since #502) but no
  `libmaxminddb-dev`, so cmake/ip2country.cmake's find_path on
  maxminddb.h fell through the soft-fail and disabled the feature.
* Windows MSYS2 had the same gap (`mingw-w64-x86_64-geoip` instead
  of `mingw-w64-x86_64-libmaxminddb`).
* macOS hardcoded `cmake_macos_config_flags: -DENABLE_IP2COUNTRY=NO`
  with a comment claiming "Homebrew dropped legacy libgeoip; only
  libmaxminddb is available, which aMule doesn't use" — outdated
  since #502, libmaxminddb is in Homebrew and aMule does use it.

This patch:

* Replaces `libgeoip-dev` -> `libmaxminddb-dev` on Ubuntu
* Replaces `mingw-w64-x86_64-geoip` -> `mingw-w64-x86_64-libmaxminddb`
  on Windows
* Adds `libmaxminddb` to the macOS Homebrew install list
* Flips macOS `-DENABLE_IP2COUNTRY=NO` -> `=YES` and drops the stale
  comment

Net effect: PR builds now exercise the IP2Country code path on all
three platforms instead of silently skipping it. No source-code
changes; runtime behaviour for users is unchanged (the database file
is still user-supplied, see docs/IP2Country.md).
mrjimenez pushed a commit that referenced this pull request May 2, 2026
* docs/TODO is 29 bytes of 'Lots of stuff. Ask a dev.' Useless.

* docs/ABOUT-NLS is 24KB of generic FSF gettext boilerplate from the
  autotools era — installed by gettextize into every gettext-using
  package. aMule moved to CMake and uses gettext only at build time
  to compile .po → .mo; the upstream 'how to use gettext' tour
  doesn't apply. Anyone wanting it can read it at the gettext
  upstream. Distros that still ship aMule with this file are
  duplicating their gettext package's copy.

* docs/README duplicates content already in the root README.md
  (which was also touched in this PR to fix a broken icon URL),
  with stale extras: 56k modem references, dead 'Update server.met
  from URL' addresses pointing at ocbmaurice.dyndns.org, file-type
  list missing modern formats, and a closing 'Last modified Thu Apr 7
  18:06:32 CEST 2016' timestamp. The user-guide content here belongs
  on the wiki, which the README already links at.

Also wire docs/IP2Country.md into the install list — it was added by
PR #502 (libgeoip → libmaxminddb migration) but never reached
docs/CMakeLists.txt's FILES list, so distro packages have been
shipping without it. The list stays alphabetised.
@got3nks
got3nks deleted the pr-a-ip2country-maxminddb branch May 3, 2026 15:19
got3nks added a commit to got3nks/amule that referenced this pull request Jun 5, 2026
CMaxMindDBDatabase::GetCountryISOCode returns a lowercased copy of
the ISO 3166-1 alpha-2 code from the .mmdb. The result feeds
CamuleArtProvider's "flag_<cc>" embedded-bitmap lookup, so the
lowercase has to be ASCII.

Under a Turkish locale (tr_TR), wxString::Lower() folds 'I' to
U+0131 (dotless i) rather than 'i'. "IT" becomes "ıt" and the
flag bitmap is not found.

This is the same Turkish-I bug class as amule-project#852 but a different code
path. SVN r10697 fixed the original instance in the libGeoIP path
in 2011; the fix was lost when GeoIP was replaced by libmaxminddb
in PR amule-project#502.

Wrap the Lower() call with CCtypeAsciiScope (introduced in the
previous commit) so the case fold runs under LC_CTYPE=C regardless
of the user's UI language.

Forum thread: http://forum.amule.org/index.php?topic=19398.0
mrjimenez pushed a commit that referenced this pull request Jun 5, 2026
CMaxMindDBDatabase::GetCountryISOCode returns a lowercased copy of
the ISO 3166-1 alpha-2 code from the .mmdb. The result feeds
CamuleArtProvider's "flag_<cc>" embedded-bitmap lookup, so the
lowercase has to be ASCII.

Under a Turkish locale (tr_TR), wxString::Lower() folds 'I' to
U+0131 (dotless i) rather than 'i'. "IT" becomes "ıt" and the
flag bitmap is not found.

This is the same Turkish-I bug class as #852 but a different code
path. SVN r10697 fixed the original instance in the libGeoIP path
in 2011; the fix was lost when GeoIP was replaced by libmaxminddb
in PR #502.

Wrap the Lower() call with CCtypeAsciiScope (introduced in the
previous commit) so the case fold runs under LC_CTYPE=C regardless
of the user's UI language.

Forum thread: http://forum.amule.org/index.php?topic=19398.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants