From 2c414a237da0df74a094089a526416639c50c822 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Wed, 25 Jan 2017 14:20:49 -0500 Subject: [PATCH] Migrate old docs --- docs/about/community.md | 7 + docs/about/contributing.md | 12 ++ docs/about/history.md | 3 + docs/about/license.md | 5 + docs/devs/api/BOB.md | 4 + docs/devs/api/I2CP.md | 5 + docs/devs/api/I2PControl.md | 5 + docs/devs/api/SAM.md | 4 + docs/devs/api/index.md | 3 + docs/devs/api/libi2pd.md | 4 + docs/devs/building/android.md | 65 +++++++ docs/devs/building/cross.md | 74 ++++++++ docs/devs/building/index.md | 15 ++ docs/devs/building/ios.md | 85 +++++++++ docs/devs/building/unix.md | 136 +++++++++++++++ docs/devs/building/windows.md | 159 +++++++++++++++++ docs/devs/hacking.md | 114 +++++++++++++ docs/index.md | 35 ++++ docs/media/i2pd-logo.png | Bin 0 -> 37177 bytes docs/tutorials/filesharing.md | 12 ++ docs/tutorials/http.md | 40 +++++ docs/tutorials/irc.md | 65 +++++++ docs/tutorials/retroshare.md | 21 +++ docs/user-guide/FAQ.md | 42 +++++ docs/user-guide/config_opts_after_2.3.0.md | 43 +++++ docs/user-guide/configuration.md | 190 +++++++++++++++++++++ docs/user-guide/family.md | 36 ++++ docs/user-guide/install.md | 57 +++++++ docs/user-guide/run.md | 55 ++++++ docs/user-guide/tunnels.md | 177 +++++++++++++++++++ mkdocs.yml | 51 ++++++ 31 files changed, 1524 insertions(+) create mode 100644 docs/about/community.md create mode 100644 docs/about/contributing.md create mode 100644 docs/about/history.md create mode 100644 docs/about/license.md create mode 100644 docs/devs/api/BOB.md create mode 100644 docs/devs/api/I2CP.md create mode 100644 docs/devs/api/I2PControl.md create mode 100644 docs/devs/api/SAM.md create mode 100644 docs/devs/api/index.md create mode 100644 docs/devs/api/libi2pd.md create mode 100644 docs/devs/building/android.md create mode 100644 docs/devs/building/cross.md create mode 100644 docs/devs/building/index.md create mode 100644 docs/devs/building/ios.md create mode 100644 docs/devs/building/unix.md create mode 100644 docs/devs/building/windows.md create mode 100644 docs/devs/hacking.md create mode 100644 docs/index.md create mode 100644 docs/media/i2pd-logo.png create mode 100644 docs/tutorials/filesharing.md create mode 100644 docs/tutorials/http.md create mode 100644 docs/tutorials/irc.md create mode 100644 docs/tutorials/retroshare.md create mode 100644 docs/user-guide/FAQ.md create mode 100644 docs/user-guide/config_opts_after_2.3.0.md create mode 100644 docs/user-guide/configuration.md create mode 100644 docs/user-guide/family.md create mode 100644 docs/user-guide/install.md create mode 100644 docs/user-guide/run.md create mode 100644 docs/user-guide/tunnels.md create mode 100644 mkdocs.yml diff --git a/docs/about/community.md b/docs/about/community.md new file mode 100644 index 0000000..74cdb5d --- /dev/null +++ b/docs/about/community.md @@ -0,0 +1,7 @@ +PurpleI2P team and community +============================ + +Community IRC channel [i2pd-dev@freenode](https://webchat.freenode.net/?channels=i2pd-dev) + +Twitter hashtag [#i2pd](https://twitter.com/hashtag/i2pd) + diff --git a/docs/about/contributing.md b/docs/about/contributing.md new file mode 100644 index 0000000..cf4bf00 --- /dev/null +++ b/docs/about/contributing.md @@ -0,0 +1,12 @@ +Contributing +============ + +Coding guideline +---------------- + +1. Files from libi2pd must not depend on files from libi2pdclient and i2pd. Files from libi2pdclient can depend on files from libi2pd but not on i2pd. You can find it in the fileslist.mk +2. You can use C++11, but make sure code is buildable by gcc 4.6 +3. Don't reinvent a wheel. Try to find appropriate solution in std or boost. If a feature is presented in both, use std. +4. Don't bring any additional dependency without discussion. However boost, openssl and zlib can be used in any amount. +5. No requirements for formatting or coding style. You can do whatever you like. +6. When you work with binary data, mind endianess. Use functions from I2PEndian.h diff --git a/docs/about/history.md b/docs/about/history.md new file mode 100644 index 0000000..e0766c3 --- /dev/null +++ b/docs/about/history.md @@ -0,0 +1,3 @@ +History +======= + diff --git a/docs/about/license.md b/docs/about/license.md new file mode 100644 index 0000000..5dcceac --- /dev/null +++ b/docs/about/license.md @@ -0,0 +1,5 @@ +License +======= + +This project is licensed under the BSD 3-clause license, which can be found in +the file LICENSE in the root of the project source code. diff --git a/docs/devs/api/BOB.md b/docs/devs/api/BOB.md new file mode 100644 index 0000000..15a553a --- /dev/null +++ b/docs/devs/api/BOB.md @@ -0,0 +1,4 @@ +BOB interface +============= + +BOB interface is documented [here](https://geti2p.net/en/docs/api/bob) diff --git a/docs/devs/api/I2CP.md b/docs/devs/api/I2CP.md new file mode 100644 index 0000000..9310f71 --- /dev/null +++ b/docs/devs/api/I2CP.md @@ -0,0 +1,5 @@ +I2CP interface +============== + +I2CP interface is documented [here](https://geti2p.net/en/docs/protocol/i2cp) + diff --git a/docs/devs/api/I2PControl.md b/docs/devs/api/I2PControl.md new file mode 100644 index 0000000..d6be341 --- /dev/null +++ b/docs/devs/api/I2PControl.md @@ -0,0 +1,5 @@ +I2PControl interface +============= + +I2PControl interface is documented [here](https://geti2p.net/en/docs/api/i2pcontrol) + diff --git a/docs/devs/api/SAM.md b/docs/devs/api/SAM.md new file mode 100644 index 0000000..6dff255 --- /dev/null +++ b/docs/devs/api/SAM.md @@ -0,0 +1,4 @@ +SAM interface +============= + +SAM interface is documented [here](https://geti2p.net/en/docs/api/samv3) diff --git a/docs/devs/api/index.md b/docs/devs/api/index.md new file mode 100644 index 0000000..c8b1f5c --- /dev/null +++ b/docs/devs/api/index.md @@ -0,0 +1,3 @@ +Choosing API for your project +============================= + diff --git a/docs/devs/api/libi2pd.md b/docs/devs/api/libi2pd.md new file mode 100644 index 0000000..1ad28df --- /dev/null +++ b/docs/devs/api/libi2pd.md @@ -0,0 +1,4 @@ +libi2pd +======= + +i2pd can be built in any application with libi2pd diff --git a/docs/devs/building/android.md b/docs/devs/building/android.md new file mode 100644 index 0000000..3e9ab08 --- /dev/null +++ b/docs/devs/building/android.md @@ -0,0 +1,65 @@ +Building on Android +=================== + +There are two versions: with QT and without QT. + +Pre-requesties +-------------- + +You need to install Android SDK, NDK and QT with android support. + +- [SDK](https://developer.android.com/studio/index.html) (choose command line tools only) +- [NDK](https://developer.android.com/ndk/downloads/index.html) +- [QT](https://www.qt.io/download-open-source/)(for QT only). + Choose one for your platform for android. For example QT 5.6 under Linux would be [this file](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-linux-x64-android-5.6.1-1.run) + +You also need Java JDK and Ant. + +QT-Creator (for QT only) +------------------------ + +Open QT-creator that should be installed with QT. +Go to Settings/Anndroid and specify correct paths to SDK and NDK. +If everything is correct you will see two set avaiable: +Android for armeabi-v7a (gcc, qt) and Android for x86 (gcc, qt). + +Dependencies +-------------- + +Take following pre-compiled binaries from PurpleI2P's repositories. + + git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git + git clone https://github.com/PurpleI2P/android-ifaddrs.git + +Building the app with QT +------------------------ + +- Open `qt/i2pd_qt/i2pd_qt.pro` in the QT-creator +- Change line `MAIN_PATH = /path/to/libraries` to an actual path where you put the dependancies to +- Select appropriate project (usually armeabi-v7a) and build +- You will find an .apk file in `android-build/bin` folder + +Building the app without QT +--------------------------- + +- Change line `I2PD_LIBS_PATH` in `android/jni/Application.mk` to an actual path where you put the dependancies to +- Run `ndk-build -j4` from andorid folder +- Create or edit file 'local.properties'. Place 'sdk.dir=' and 'ndk.dir=' +- Run `ant clean debug` + +Creating release .apk +---------------------- + +In order to create release .apk you must obtain a Java keystore file(.jks). Either you have in already, or you can generate it yourself using keytool, or from one of you existing well-know ceritificates. +For example, i2pd release are signed with this [certificate](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/certificates/router/orignal_at_mail.i2p.crt). + +Create file 'ant.propeties': + + key.store='path to keystore file' + key.alias='alias name' + key.store.password='keystore password' + key.alias.password='alias password' + +Run `ant clean release` diff --git a/docs/devs/building/cross.md b/docs/devs/building/cross.md new file mode 100644 index 0000000..fc884ca --- /dev/null +++ b/docs/devs/building/cross.md @@ -0,0 +1,74 @@ +Cross compilation notes +======================= + +Static 64 bit windows binary on Ubuntu 15.10 (Wily Werewolf) +------------------------------------------------------------ + +Install cross compiler and friends + + sudo apt-get install g++-mingw-w64-x86-64 + +Default is to use Win32 threading model which lacks std::mutex and such. So we change defaults + + sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix + +From now on we assume we have everything in `~/dev/`. Get Boost sources unpacked into `~/dev/boost_1_60_0/` and change directory to it. +Now add out cross compiler configuration. Warning: the following will wipe out whatever you had in there. + + echo "using gcc : mingw : x86_64-w64-mingw32-g++ ;" > ~/user-config.jam + +Proceed with building Boost normal way, but let's define dedicated staging directory + + ./bootstrap.sh + ./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \ + --build-type=minimal --with-filesystem --with-program_options --with-date_time \ + --stagedir=stage-mingw-64 + cd .. + +Now we get & build OpenSSL + + git clone https://github.com/openssl/openssl + cd openssl + git checkout OpenSSL_1_0_2g + ./Configure mingw64 no-rc2 no-rc4 no-rc5 no-idea no-bf no-cast no-whirlpool no-md2 no-md4 no-ripemd no-mdc2 \ + no-camellia no-seed no-comp no-krb5 no-gmp no-rfc3779 no-ec2m no-ssl2 no-jpake no-srp no-sctp no-srtp \ + --prefix=~/dev/stage --cross-compile-prefix=x86_64-w64-mingw32- + make depend + make + make install + cd .. + +...and zlib + + git clone https://github.com/madler/zlib + cd zlib + git checkout v1.2.8 + CC=x86_64-w64-mingw32-gcc CFLAGS=-O3 ./configure --static --64 --prefix=~/dev/stage + make + make install + cd .. + +Now we prepare cross toolchain hint file for CMake, let's name it `~/dev/toolchain-mingw.cmake` + + set(CMAKE_SYSTEM_NAME Windows) + set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) + set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) + set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) + set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +Download miniupnpc, unpack and symlink it into `~/dev/miniupnpc/`. +Finally, we can build i2pd with all that goodness + + git clone https://github.com/PurpleI2P/i2pd + mkdir i2pd-mingw-64-build + cd i2pd-mingw-64-build + BOOST_ROOT=~/dev/boost_1_60_0 cmake -G 'Unix Makefiles' ~/dev/i2pd/build -DBUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=~/dev/toolchain-mingw.cmake -DWITH_AESNI=ON -DWITH_UPNP=ON -DWITH_STATIC=ON \ + -DWITH_HARDENING=ON -DCMAKE_INSTALL_PREFIX:PATH=~/dev/i2pd-mingw-64-static \ + -DZLIB_ROOT=~/dev/stage -DBOOST_LIBRARYDIR:PATH=~/dev/boost_1_60_0/stage-mingw-64/lib \ + -DOPENSSL_ROOT_DIR:PATH=~/dev/stage + make + x86_64-w64-mingw32-strip i2pd.exe + +By now, you should have a release build with stripped symbols. diff --git a/docs/devs/building/index.md b/docs/devs/building/index.md new file mode 100644 index 0000000..1bb163e --- /dev/null +++ b/docs/devs/building/index.md @@ -0,0 +1,15 @@ +Build requirements +================== + +In general, for building i2pd you need several things: + +* compiler with c++11 support (for example: gcc >= 4.7, clang) +* boost >= 1.49 +* openssl library +* zlib library (openssl already depends on it) + +Optional tools: + +* cmake >= 2.8 (or 3.3+ if you want to use precompiled headers on windows) +* miniupnp library (for upnp support) +* [websocketpp](https://github.com/zaphoyd/websocketpp/) (for websocket ui) diff --git a/docs/devs/building/ios.md b/docs/devs/building/ios.md new file mode 100644 index 0000000..c175356 --- /dev/null +++ b/docs/devs/building/ios.md @@ -0,0 +1,85 @@ +Building on iOS +=================== + +How to build i2pd for iOS 9 and iOS Simulator 386/x64 + +Prerequisites +-------------- + +XCode7+, cmake 3.2+ + +Dependencies +------------ + +- precompiled openssl +- precompiled boost with modules `filesystem`, `program_options`, `date_time` and `system` +- ios-cmake toolchain from `https://github.com/vovasty/ios-cmake.git` + +Building +-------- + +Assume you have folder structure + + lib/ + libboost_date_time.a + libboost_filesystem.a + libboost_program_options.a + libboost_system.a + libboost.a + libcrypto.a + libssl.a + include/ + boost/ + openssl/ + ios-cmake/ + i2pd/ + +```bash +mkdir -p build/simulator/lib build/ios/lib include/i2pd + +pushd build/simulator && \ +cmake -DIOS_PLATFORM=SIMULATOR \ + -DPATCH=/usr/bin/patch \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=../../ios-cmake/toolchain/iOS.cmake \ + -DWITH_STATIC=yes \ + -DWITH_BINARY=no \ + -DBoost_INCLUDE_DIR=../../include \ + -DOPENSSL_INCLUDE_DIR=../../include \ + -DBoost_LIBRARY_DIR=../../lib \ + -DOPENSSL_SSL_LIBRARY=../../lib/libssl.a \ + -DOPENSSL_CRYPTO_LIBRARY=../../lib/libcrypto.a \ + ../../i2pd/build && \ +make -j16 VERBOSE=1 && \ +popd + +pushd build/ios +cmake -DIOS_PLATFORM=OS \ + -DPATCH=/usr/bin/patch \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=../../ios-cmake/toolchain/iOS.cmake \ + -DWITH_STATIC=yes \ + -DWITH_BINARY=no \ + -DBoost_INCLUDE_DIR=../../include \ + -DOPENSSL_INCLUDE_DIR=../../include \ + -DBoost_LIBRARY_DIR=../../lib \ + -DOPENSSL_SSL_LIBRARY=../../lib/libssl.a \ + -DOPENSSL_CRYPTO_LIBRARY=../../lib/libcrypto.a \ + ../../i2pd/build && \ +make -j16 VERBOSE=1 && \ +popd + +libtool -static -o lib/libi2pdclient.a build/*/libi2pdclient.a +libtool -static -o lib/libi2pd.a build/*/libi2pd.a + +cp i2pd/*.h include/i2pd +``` + +Include into project +-------------------- + +- add all libraries in `lib` folder to `Project linked frameworks`. +- add `libc++` and `libz` libraries from system libraries to `Project linked frameworks`. +- add path to i2p headers to your `Headers search paths` + +Alternatively you may use swift wrapper `https://github.com/vovasty/SwiftyI2P.git` diff --git a/docs/devs/building/unix.md b/docs/devs/building/unix.md new file mode 100644 index 0000000..b5c38ae --- /dev/null +++ b/docs/devs/building/unix.md @@ -0,0 +1,136 @@ +Building on Unix systems +============================= + +First of all we need to make sure that all dependencies are satisfied. + +This doc is trying to cover: + +* [Debian/Ubuntu](#debian-ubuntu) (contains packaging instructions) +* [Fedora/Centos](#fedora-centos) +* [Fedora/Centos](#mac-os-x) +* [FreeBSD](#freebsd) + +Make sure you have all required dependencies for your system successfully installed. +See [this](requirements.md) page for common requirements. + +If so then we are ready to go! +Let's clone the repository and start building the i2pd: + + git clone https://github.com/PurpleI2P/i2pd.git + +Generic build process looks like this (with cmake): + + cd i2pd/build + cmake . # see "CMake Options" section below + make # you may add VERBOSE=1 to cmdline for debugging + +..or with quick-and-dirty way with just make: + + cd i2pd/ + make + +After successfull build i2pd could be installed with: + + make install + +CMake Options +------------- + +Available CMake options(each option has a form of `=`, for more information see `man 1 cmake`): + +* `CMAKE_BUILD_TYPE` build profile (Debug/Release) +* `WITH_BINARY` build i2pd itself +* `WITH_LIBRARY` build libi2pd +* `WITH_STATIC` build static versions of library and i2pd binary +* `WITH_UPNP` build with UPnP support (requires libminiupnp) +* `WITH_AESNI` build with AES-NI support (ON/OFF) +* `WITH_HARDENING` enable hardening features (ON/OFF) (gcc only) +* `WITH_PCH` use pre-compiled header (experimental, speeds up build) +* `WITH_I2LUA` used when building i2lua +* `WITH_WEBSOCKETS` enable websocket server + + +Also there is `-L` flag for CMake that could be used to list current cached options: + + cmake -L + +Debian/Ubuntu +------------- + +You will need a compiler and other tools that could be installed with `build-essential` package: + + sudo apt-get install build-essential + +Also you will need a bunch of development libraries: + + sudo apt-get install \ + libboost-date-time-dev \ + libboost-filesystem-dev \ + libboost-program-options-dev \ + libboost-system-dev \ + libssl-dev + +If you need UPnP support miniupnpc development library should be installed (don't forget to rerun CMake with needed option): + + sudo apt-get install libminiupnpc-dev + +You may also build deb-package with the following: + + sudo apt-get install fakeroot devscripts + cd i2pd + debuild --no-tgz-check + +Fedora/Centos +------------- + +You will need a compiler and other tools to perform a build: + + sudo yum install make cmake gcc gcc-c++ + +Also you will need a bunch of development libraries + + sudo yum install boost-devel openssl-devel + +If you need UPnP support miniupnpc development library should be installed (don't forget to rerun CMake with needed option): + + sudo yum install miniupnpc-devel + +Latest Fedora systems using [DNF](https://en.wikipedia.org/wiki/DNF_(software)) instead of YUM by default, you may prefer to use DNF, but YUM should be ok + +Centos 7 has CMake 2.8.11 in the official repositories that too old to build i2pd, CMake >=2.8.12 is required. +But you can use cmake3 from the epel repository: + + yum install epel-release -y + yum install make cmake3 gcc gcc-c++ miniupnpc-devel boost-devel openssl-devel -y + +...and then use 'cmake3' instead 'cmake'. + +MAC OS X +-------- + +Requires [homebrew](http://brew.sh) + + brew install boost libressl + +Then build: + + make HOMEBREW=1 + +FreeBSD +------- + +For 10.X use clang. You would also need devel/boost-libs, security/openssl and devel/gmake ports. +Type gmake, it invokes Makefile.bsd, make necessary changes there is required. + +Branch 9.X has gcc v4.2, that is too old (not supports -std=c++11) + +Required ports: + +* `devel/cmake` +* `devel/boost-libs` +* `lang/gcc47`(or later version) + +To use newer compiler you should set these variables(replace "47" with your actual gcc version): + + export CC=/usr/local/bin/gcc47 + export CXX=/usr/local/bin/g++47 diff --git a/docs/devs/building/windows.md b/docs/devs/building/windows.md new file mode 100644 index 0000000..7cc09cb --- /dev/null +++ b/docs/devs/building/windows.md @@ -0,0 +1,159 @@ +Building on Windows +========================= + +There are two approaches available to build i2pd on Windows. The best +one depends on your needs and personal preferences. One is to use +msys2 and [unix alike infrastructure](unix.md). Another +one is to use Visual Studio. While there might be no difference for +end users of i2pd daemon, developers, however, shall be wary of +differences in C++ name mangling between the two compilers when making +a choice to be able to link their software against libi2pd. + +If you are a stranger to C++ with no development tools installed on +your system and your only goal is to have i2pd up and running from the +most recent source, consider using msys2. Although it relies on +command line operations, it should be straight forward. + +In this guide, we will use CMake for both approaches and we will +assume that you typically have your projects in C:\dev\ as your +development location for the sake of convenience. Adjust paths +accordingly if it is not the case. Note that msys uses unix-alike +paths like /c/dev/ for C:\dev\. + +msys2 +----- + +Get install file `msys2-$ARCH-*.exe` from `https://msys2.github.io` + +Where $ARCH is `i686` or `x86_64` (matching your system). + +- Open MSYS2 Shell (from Start menu). +- Install all prerequisites and download i2pd source: + + export ARCH='i686' # or 'x86_64' + export MINGW='mingw32' # or 'mingw64' + pacman -S mingw-w64-$ARCH-boost mingw-w64-$ARCH-openssl mingw-w64-$ARCH-gcc git make + mkdir -p /c/dev/i2pd + cd /c/dev/i2pd + git clone https://github.com/PurpleI2P/i2pd.git + cd i2pd + # we need compiler on PATH which is usually heavily cluttered on Windows + export PATH=/$MINGW/bin:/usr/bin + make + +### Caveats + +It is important to restrict PATH as described above. +If you have Strawberry Perl and/or Mercurial installed, +it will pick up gcc & openssl from the wrong places. + +If you do use precompiled headers to speed up compilation (recommended), +things can go wrong if compiler options have changed for whatever reason. +Just delete `stdafx.h.gch` found in your build folder, note the file extension. + +If you are an Arch Linux user, refrain from updating system with `pacman -Syu`. +Always update runtime separately as described on the home page, +otherwise you might end up with DLLs incompatibility problems. + +### AES-NI + +If your processor has [AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set), +use `make USE_AESNI=1` instead just `make`. No check is done however, it will compile, +but it might crash with `Illegal instruction` if this feature is not supported by your processor. + +You should be able to run ./i2pd . If you need to start from the new shell, +consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* +as it adds `/minw32/bin` to the PATH. + +### UPnP + +You can install it through the MSYS2 and build with `USE_UPNP` key. + + export ARCH='i686' # or 'x86_64' + pacman -S mingw-w64-$ARCH-miniupnpc + make USE_UPNP=yes + +Using Visual Studio +------------------- + +Requirements for building: + +* [CMake](https://cmake.org/) (tested with 3.1.3) +* [Visual Studio Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) (tested with VS2013 Update 4) +* [Boost](http://www.boost.org/) (tested with 1.59) +* Optionally [MiniUPnP](http://miniupnp.free.fr) (tested with 1.9), we need only few client headers +* OpenSSL (tested with 1.0.1p and 1.0.2e), if building from sources (recommended), you'll need as well + * [Netwide assembler](http://www.nasm.us/) + * Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work + +### Building Boost + +Open a Command Prompt (there is no need to start Visual Studio command +prompt to build Boost) and run the following: + + cd C:\dev\boost + bootstrap + b2 toolset=msvc-12.0 --build-type=complete --with-filesystem --with-program_options --with-date_time + +If you are on 64-bit Windows and you want to build 64-bit version as well + + b2 toolset=msvc-12.0 --build-type=complete --stagedir=stage64 address-model=64 --with-filesystem --with-program_options --with-date_time + +After Boost is compiled, set the environment variable `BOOST_ROOT` to +the directory Boost was unpacked to, e.g., C:\dev\boost. + +If you are planning on building only particular variant, e.g. Debug only and static linking, +and/or you are out of space/time, you might consider `--build-type=minimal`. +Take a look at [appveyor.yml](../appveyor.yml) for details on how test builds are done. + +### Building OpenSSL + +Download OpenSSL, e.g. with git + + git clone https://github.com/openssl/openssl.git + cd openssl + git checkout OpenSSL_1_0_1p + +Now open Visual Studio command prompt and change directory to that with OpenSSL + + set "PATH=%PATH%;C:\Program Files (x86)\nasm" + perl Configure VC-WIN32 --prefix=c:\OpenSSL-Win32 + ms\do_nasm + nmake -f ms\ntdll.mak + nmake -f ms\ntdll.mak install + +You should have it installed into C:\OpenSSL-Win32 by now. + +Note that you might consider providing `-DOPENSSL_ROOT_DIR` to CMake and/or +create a symlink (with mklink /J) to C:\OpenSSL if you plan on maintain +multiple versions, e.g. 64 bit and/or static/shared. +See `C:\Program Files (x86)\CMake\share\cmake-3.3\Modules\FindOpenSSL.cmake` for details. + +### Get miniupnpc + +If you are behind a UPnP enabled router and don't feel like manually configuring port forwarding, +you should consider using [MiniUPnP](http://miniupnp.free.fr) client. +I2pd can be built capable of using miniupnpc shared library (DLL) to open up necessary port. +You'd want to have include headers around to build i2pd with support for this. +Unpack client source code to subdir, e.g. `C:\dev\miniupnpc`. +You may want to remove version number from folder name included in downloaded archive. + +### Creating Visual Studio project + +Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options. + +Alternatively, if you feel adventurous, try that from the command line + + mkdir i2pd\out + cd i2pd\out + cmake ..\build -G "Visual Studio 12 2013" -DWITH_UPNP=ON -DWITH_PCH=ON -DCMAKE_INSTALL_PREFIX:PATH=C:\dev\Debug_Win32_stage + +If necessary files are not found `WITH_UPNP` will stay off. + +### Building i2pd + +You can open generated solution/project with Visual Studio and build from there, +alternatively you can use `cmake --build . --config Release --target install` or +[MSBuild tool](https://msdn.microsoft.com/en-us/library/dd293626.aspx) + + msbuild i2pd.sln /p:Configuration=Release diff --git a/docs/devs/hacking.md b/docs/devs/hacking.md new file mode 100644 index 0000000..163575f --- /dev/null +++ b/docs/devs/hacking.md @@ -0,0 +1,114 @@ + +# Hacking on I2PD + +This document contains notes compiled from hacking on i2pd + +## prerequisites + +This guide assumes: + +* a decent understanding of c++ +* basic understanding of how i2p works at i2np level and up + +## general structure + +Notes on multithreading + +* every compontent runs in its own thread + +* each component (usually) has a public function `GetService()` which can be used to obtain the `boost::asio::io_service` that it uses. + +* when talking between components/threads, **always** use `GetService().post()` and be mindfull of stack allocated memory. + + +### NetDb + +#### NetDb.h + +The `i2p::data::netdb` is a `i2p::data::NetDb` instance processes and dispatches *inbound* i2np messages passed in from transports. + +global singleton at `i2p::data::netdb` as of 2.10.1 + +#### NetDbRequests.h + +For Pending RouterInfo/LeaseSet lookup and store requests + + +### ClientContext + +#### ClientContext.h + +`i2p::client::ClientContext` spawns all destinations used by the i2p router including the shared local destination. + +global singleton at `i2p::client::context` as of 2.10.1 + + + +### Daemon + +File: Daemon.cpp + +`i2p::util::Daemon_Singleton_Private` subclasses implement the daemon start-up and tear-down, creates Http Webui and i2p control server. + + + + +### Destinations + +#### Destination.h + +each destination runs in its own thread + +##### i2p::client::LeaseSetDestination + +Base for `i2p::client::ClientDestination` + +##### i2p::client::ClientDestination + +Destination capable of creating (tcp/i2p) streams and datagram sessions. + + +#### Streaming.h + +##### i2p::stream::StreamingDestination + +Does not implement any destination related members, the name is a bit misleading. + +Owns a `i2p::client::ClientDestination` and runs in the destination thread. + +Anyone creating or using streams outside of the destination thread **MUST** be aware of the consequences of multithreaded c++ :^) + +If you use streaming please consider running all code within the destination thread using `ClientDestination::GetService().post()` + + +#### Garlic.h + +Provides Inter-Destination routing primatives. + +##### i2p::garlic::GarlicDestination + +sublcass of `i2p::client::LeaseSetDestination` for sending messages down shared routing paths. + +##### i2p::garlic::GarlicRoutingSession + +a point to point conversation between us and 1 other destination. + +##### i2p::garlic::GarlicRoutingPath + +A routing path currently used by a routing session. specifies which outbound tunnel to use and which remote lease set to use for `OBEP` to `IBGW` inter tunnel communication. + +members: + +* outboundTunnel (OBEP) +* remoteLease (IBGW) +* rtt (round trip time) +* updatedTime (last time this path's IBGW/OBEP was updated) +* numTimesUsesd (number of times this path was used) + +### Transports + +each transport runs in its own thread + +#### Transports.h + +`i2p::transport::Transports` contains NTCP and SSU transport instances diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..3539206 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,35 @@ +i2pd +==== + +![Logo](media/i2pd-logo.png) + +i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. + +I2P (Invisible Internet Protocol) is a universal anonymous network layer. +All communications over I2P are anonymous and end-to-end encrypted, participants +don't reveal their real IP addresses. + +I2P client is a software used for building and using anonymous I2P +networks. Such networks are commonly used for anonymous peer-to-peer +applications (filesharing, cryptocurrencies) and anonymous client-server +applications (websites, instant messengers, chat-servers). + +I2P allows people from all around the world to communicate and share information +without restrictions. + +* [Website](http://i2pd.website) +* [Documentation](https://i2pd.readthedocs.io/en/latest/) +* [Wiki](https://github.com/PurpleI2P/i2pd/wiki) +* [Tickets/Issues](https://github.com/PurpleI2P/i2pd/issues) +* [Specifications](https://geti2p.net/spec) +* [Twitter](https://twitter.com/hashtag/i2pd) + +Features +-------- + +* Distributed anonymous networking framework +* End-to-end encrypted communications +* Small footprint, simple dependencies, fast performance +* Rich set of APIs for developers of secure applications + + diff --git a/docs/media/i2pd-logo.png b/docs/media/i2pd-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9a2f7404a20eef22adc6da0fb1538b6c507c97f4 GIT binary patch literal 37177 zcmV*QKwrO!P)+0Ht zRaESi-jQBYNbmjLgGJWcdAp>$_ z`J?w6we1@u)>=cfJ8!n|?6j;k58iiE3;;|!Wg_VtsXqBlNzvc}V$_{NM-}yd=Ye~S z{2vcm6q7EFzw^3*a|P;kS2?*s&c6l#^0PC9|K+g|`_$pb%isb1$+lg)`2htRQb0Cs z-NApY*W+@z;0uEIyj|H7Cn(%(RH&kGWM!&=2$q--6#OBd699sN0Orwvwp)A0O0U}wzkPINXBlz0_gSn z|LL3C7i9e?5d;9-W*RnNK>olx`(<@Mn3`Dl=dmM45AXyOo}Hfgs~g{&Z@!hRTDP79 z;B78n;sH|!^9swCvOe;S0(hfi`7i00Ggt(GwB%9K zr%p<3zU%@Uzvm7!zveP4ACQ+-dBgk*QUH*%X3hB3xFDBbe&qq6bMjJewVL9!M8|kF zJ1vRdI6sPCc0p`sZbs_5+>9YpdK?g;PZRp&zhvUL(G&nKx#+_9VS`d?UV2*3Z@AhP zdg>8Vh;xK4InT;R45MbZ5CDL4PGjTk_t?xSJk@c5mK*&CZZ*bt zXQq$7KQVgv?7QxmAKT}i_sJ0@FDqRF0E;o_&kx;e4i;|{`OIk%{N6h)Jmez$Kd%~; z)Wobe03bg*^<{Dg5b0BqgRY;(p~p0=B^czVR8YJSYEEX8paH<-lj2L)XqzZuKX zHwzqx1pIy){yWrvKz~h6P1W$slWrLF9FmQ*4I2e&wHh}9fL^CRsRQ-A{A~To6{`Z* z&A%gI+N_+Xm?w31lztSKMYEtXAKbxxN>WnN2c;#I$j;0#?q@SNTP`_u0Uno2=I!wcV6H4C;(yTu;GD^KL48cX+WPGQ6`KY zB?7>-$){W~d`KL7<#_|&v{KR@{;Ppc9-G=RZ1DKe05Ga(+(|hBEqVV_0zd}@dh0H8PA@cX`&l0G?x;7t&8000BtxXL+COP~onJw1QY zfjIUgl#wHgL;&ENlbAT$19npeOLJVv^I~q{xjk^?MBl*kV{T?9IYk>fbnssQAUiwj zHyf+=#URHaG0teJYFaQMHL)O($BfH2q*9dzkd_x$-}9D}&QDKEPZHO!-=yAg+kH`S z@y_>^u9W|C8crp8$qCNYo>S%^py&>kGrh%AyLt20zXA|TOUu+gK>FmU#q0Bl08rmt zchdw*QIe4u6iwo&>a1@%S?_aYMXfsdl<|XJdiklViIfM~7W zRYHD#{_hAO>hR%3zv)VOA0WplsVOOf$Lk5D4$K&wEu@W2mEz&nx``+YUFF-0LnrBJ zvwj1z&)U4PWQ`mgnHy~x$-`jq@4&$zP(5qvS|%i=M7_Iu_3AG&Gc$#a8#na<(kDkR zZ7ppS0IJH$FCS{iPmhzLS+mkEf{-dmIO&w>nrkoAXJn?{Rl7g9*eOq!ErxWi@gO-k zOyZzK;@$oVaJjB?;^cAH7z_rwfB$~%w|>9-3WdiKd&I@i=Ei2loE4Fm&}f^OB*Z|b z5^GaCDG16zPcA@4jP4ir@dvA(?QS!lnP5LH$ho59Tm?C3UgQ7>7z=4_{*~g0(F3mB zvSnL`-|z2hLOc-`3U7=Ei0U0G@`9^9LBR`^C%A;GCgV>3}Fp`w>fjQKc#z zHt4{;$jVI|R$kn-F3^#BW^%-tA;yBbu+{kQ+a(a4+R*itn3Nj%!t&)SKiIN)YabjZ z0+2!d2a&Iquk3MTr`RLxGpxO@&7D2-e+rz`^fU@UjTxSlnnhEmB#{`1L|_6Dc$?Y@ zDhnk8{%`6pr&t7Z^Ecc1C09+?XJw~f+|eX$(yJqrW9_5Vkm{DnA=;C`#8SBEUk_BAAp`%>~h-+q>)H&wi=&E(Hh6 zD~O6&`suFQye{L-QHDv1Bh4401Xz%B z=FBFWw||2N@B4$@)lt7NE2HM|5yM*MUO2D*{E9hEfz2xuV^l2p_NnyP>9^O|?=T-xI^v8+6MfxF4N(BBzz zbDVjmB2Yf{57k#Ztuh41OZZ2RVe~s3m2~YQ&C~pSYmwRg%ih3xP${*b#>*hzBQV1fdW8qQ`eMiIb~|DAst@krxF!e zQ>axEB%x8M^ZI|za~fJWK>W|5#S8#X&4@bF)fD+De7O_jtdmv715y~AL(NSbl!(wY zMQih~BoWbgeBYk^Zvw#VIkWrPNlpYHiW(9CpwksR?dmIoh;cG8F+mmU8;K}OpqE?} zB9#^H834c-`&9!nY2swk+|sPkv!mpAQ|xJpLM$~4MpfgCNDz6W+DcTW?t&4@&vj0b zPP4pa^DcG8iqG_MiO$=*Tbzqc7!~g@_16^U6OY{KLO>uW9sUiXZ0`7U{KUdP6GF7i ztTg)md++yk>Yj)ggsB=25495L>Y|u6$B$`KgAk?g`12VLPm}pC9Yq; z?pN8aux$BK0)Vp>ZKG3Y!JL8mEO<1ZKtLc8kvA#rpt7(JQ3%2Hvz(IL-s%aBo{$kY z@0`mYWd78PBXot31e2z*fIyA_2M32p^h&#Ln-mhtb`=$7-tfvx?|A^w{biMXnX40J zK}1p10Kgfg`}dSpb>yWq5^9QwE+^@^Yq@uKdA+|`szzb&x95lFeG+J=`Q7c8t8X% zq<%Cc!N?d72{V0f<~+9dJW2@x9lRxj&hEGGXFK`oasZ0Dzj2XM7G)rKM%Xm6eqYfIM^N43w0Vp0s|ir`rPnFq_RYvw8C6W6VPoFY}8O6oe42aFwhH zZl`r>{eAHLG!9lyZYtffc{c-q^vr}mxEk%x+2zrZ1~HCtXcS=Nhv1+@-irIXA7X!fLQzp@+UoY#k9zP`@N0On#`j4)zX#Y$M z6qurIg$O7vsxdzTS{>Sb8$Gfixay({uD<)3XP?*%fQ}kH3hUOcJLztiG1)r0z?Z(} z3ey~=i+e;0N*EZ7)S!Oj*)4vhZup=^sJ{g5IH5(h)U+g0Rawg~ynK%Fi;vbWr2d?l z4&z`DP|l%|qrG*UbM6jqBYwJVg{!lBDj_74o0mn4_m%a*@l(YhM0hhU(vtsGysOo?ZtXgjot=GhrG#@JJG-sZ zQ+Rx@K9aD~0U{B3i_!*7V5KzA7C4cI9Xxmtsj95ymtKBu{O2F6TP+6*XGR!@0wA3K zpi6bIc$Es`VOxst`qTaA5kf+#X-R!>oD6^fz`i{dODqxEmEC-k=n2#@N+b{h2-FC> zzJMfI&eyj$7%m$zHnVc_OwcoOZ_SAuB4kGaE){orA~@1#&UBqH!u)ddgt z?`3P;!4q}JY15{WZQHi%4O=y!e&{ zzi%om93oUz*7m`1vH$`AmF0~u*`3P&b%s_80i~T2A^~9Gauqcq!FIY}<`W`TuiWrX zc6Ro{#qTUO;Urn7V$d6MMQA3&qWwxArw6o=ku|{O}_L z0IDmSA9BP59&;({iK2P=xBWo`92(5JRGR9zh}Bnx&b{oi%eJ3$&fLOZdSLY9BF+7h za&H){%Y~N*L`uFLDuD>xrMN{+;0QK*+fT&t;$qUt(q&8e@Zm)hcWkX%8>gRTkpwdd zTa9DmgL4gyp3hi%X8c1dS1$igzkdCs&6_u?ed>Oa0dm`I3;3-IZYKaxRnh!s!BD@j z)4z#u&c3r~hXCLpM4~B8FS`2YNG2S1VCvKe#T}eE(3GPDSnz=L z2v?&8-l}#AL?pGa!FM8(C5_D$e9+*6Gm3Y&d>v~zQ=n89aoB#U!=eFz@D}e%L^#R2 zd-v}Bi`{P3?b)+O=~MNS)W!PyBMZ!4QN4Sxke|v1+V?jDp7eY)a z2jD&4<4m71=|E7EmzOiAvZVWiSmR7i2oVprxasg{Fi;|~PTzJy^tIb+YHH61AiG>$ z!9F!Vi2(tC4?kR@4IDT?dgb+}>Jk%@?)0+l4ZdJ4Aw)Q+_CY|Q@er}<(~xMH!>TLX z*WGmUjql!c^Y5KMCnT%Hm!!_tjthsI2g1(+0wo8p-xi6$JJc>{0i=pi6ch)!~lB%j$*X zu0P-NlY)}nKPTF#=q9A-;uVFf2Q>h44hRsqOY4FnsCBcio_EZEoPXhLvgExl0Dx!b zrk~qVC%zG5n%Z*^a*Wp&ZeI_o-CBEK1qurbuXyYq4^+;-=2|{#OkrPl?ym(90O;!S z1pvrR4elodW77v+!M)&z2tvc|mO=!60$*RLNLvS2*X1*GYjJP8UE{C9V3*n+q<4+1n)zvy@WJf>Otu6q`cx88W40N`mE zv9sIibT3C4CJB^?>{!#d-?@#UR^L)FCC&NJs?{q$I{oz1>2uFN+n3J$wE+SE=bv|h z1^`!IcH95?u(K|p9(u1e0t&_zP%28XmMJ0TOU~J_e%rgJOc^%@0RHihNBR8u*PT#E z6h*<-M^T3{g!WKJ{jnb7-g_Pq0I<{y=d|ut$7_-Lae9I3 zd-|%5JzFITCbh}EN;W(EtDb-9fxDM~v4ed2>8E{g{8|BdYvG$(Y^+m$@b7n*q^8B+ z-|k<}`C--?^+G}jm18ZFLZX_TzU7;pZ%;mD>?8nq?zw09@2BM=Kf_{XQUsQ24a~WdaAh%mn~~ARO&Ehyc`-4C|=wwuo14(kQbim^IGTP}7dM4y{&Oyw$9 z4+4Y(5I}j5h3K|W32#>0o`;HhtJO+^!QfHBky{Yizq>j59jh=RQ71-eoGZfd+SzGVsM&Hh}QTIEOI)MYb6OLrOCZoXRrp|JA2-=*8m_tKeum9 z`Tq(a3l}cb5)xyjf4%tZ-jp=wv&~(rArO)C!)}ZouDXLW$!Q*?NNT=w_3CvC=ggTk z5dhE4&Hho>;t(wq0HSpfXC+FpOoK)a6@O4r_*oDP+zl}dh#(x^5Dy#PpSHL9wCo`; zch<)ILsIjG8N?)w2gcN2L7F-G6+-4}k35TioYf{jUH50M}f7 zg9Ir!+D01C9j;0|%3$Eu&Of&5Qivi?83AHEZU`;^I;^Z{ED)x}J=* zG;+Ni`^+=Rpn?LDpO;5dQc`GAQW8x}NT3-R8G_U4 zq}kcoG$|>GW@cv43FF6;1-IPttG8&s_yvp|J4RT&dW|+_%&4)GbBjO@WAxbEdue>dRYixZ(Hosi&SirYuf&R<=-DR;p!XXWcovz2D!4 znDg29n-hCyZ#~s%`+OC`m)iO*#kz{K(ZDOCqoYYnOUq#uG(97IURSeqk<&N{0An1C z9-sAKkOVVp>DoxSVb6}j;r-6}?2~1sR;!tGb$Na?Ao+QDq`keJgcOCUs!BNHFcAZ> ziYC(OYUiEk)-J~o_AhMZM?TNbh#jX9H$Y<$AqZ9pUgqa2Q@J3D+-k9KQIfb`r{l#X zC5Qa3J8oM*mM>i@1Ok4dC<;VTWQD^=vX@?dh5x1i0RWrbCb(U0Ejl`8l@J&@+HS}p zoNGV0loTK!gz~1YrG&{@m3P(fEm>ZVu(LGD=z zNRIPnQK-zvTK!9@F{1VQhFbSC=xt^@Mj1G8AZcuDq=8_Nn5lt;Ts~ZiG3ui@{O*v8 zzI@yI^pnq6I@>y|9i5$eRa0fAGQngr3hf;op_rH$?(_M)R-45;Y5WB5bANx%MF=@; zohS#%VyDGVyHyVl1pJH;${Azq{CTs;TmSih;(Obm+Vl{LMoz?6%a?1vDL~FTYYut$ z-S_zPGfpd9{`EKCq*yOe7(x;`N)M0#yrKImLUaxFciwULnA>i@spio~|G{s$<)))j zoCGOas#jW+IN8~DXWUg03fBld#LzHs7^z;{?kN_QvQ6vDEDh(PI#?4M8%vs+n*Qrp z5%F+Hq4dv<+UO#^9DUpwt6n@sYGTdZ8>p(=w(j)PreE~tn{QU+_sb`H_w4<_>zq1e z3fZx9CkgrkL~t`Q1O2s^vF@PH4IEyOR#R1-7Yv266h%$v8c#J-L%dzG#?t^yCTbuC zA`>0eQHh8Ui4cy{2mu2FV+s>7s-zZ`3MmZQa!9oT|;&D=Krg!Zhr_zv1N}l+DU@#ene>$ z73ex}js-&o<<-^JjtvBZ!}VMqY-g67XkypJh*5CL4iYKah+VJ}iAZ4s#d{;5?`zGs zi^zKI7(ZZdzkQ3w8QfYIZ&%&CP3h##N;_-TI*3d1xZI(xt)XCO9e{7ZvHF~|PS4%E zY1d~HCv@9$b5xp=tYX(5iG1>@z0+z201j>)#t@Nq_B@~=SIqBBPc=1yI9ptNL$uiHC50+un>GHN+Z9*I;_ zBAk*Plu*tOxkg){FxSd=-dVgA0Nt=*!=bH*4KfJy1#tsMwzamM)$nEI z)Kn=xd73l=+4dCJMXRQ9O=Dn0q(lEHx|A9G>PUJ0EpLdNGZcI`Fo(q&f}=XSQf{f5JNPW!oY=a5B<-{Zd- zK-R4+2@M;O`FLAP(|o_uAySuyC-ko(17L=`nj=n7X4Jy zFl0Cr87EK_u2Pk&#K-(XF9hHIIlKsjf`CBbDgrEkAXCu6+^7yU1Sp+1{Myx*P96EqyI+1XYevA4pQoZ= zgnGc35da3g=J@kni<|)3o0^)AD@pOI1q1*JhZi+@Ts!V>tXh9>qGN`lXx$PyhHy!w zCd8SiqrP^@^sKCmf0dP$U$uVy1~z;4Z2JED?;iw-PxEsCNR(r;3C9n1n=>$CAbLoG z6a#@80R}-3F|Z(??%c7L4I12ULT#yVRjegPQJL=qSdZ{I1=V)=c>Ug)GwxfxZR_nQ zE-ntc7Ljlmm@zrd7d1y`mVcMvamEZb<|134sxt6UkcR{h_fx_l9UTr~ZKEI%iNG0W z#I1VJ#k^?J+OW@8-mx!K+2IkqyX_H&(!VdMS^6Y@XWTZuIyTazbFv@a zUi14pMY$(XM_L1)vAllif8Dlq=RE*$*=3iLmtX!j2LMqJs4`OJWDQ9eX)4%zcH~qG zJ%U1Wa8N=KQbWpXfls7eTJd-VwkBP*9mgS$AUtLD+1vlg#0iN-@QHo z6f%{$PxF%|r43D5JBmXUoqIwRHD1xX&S8sO(ox&C{CnwJNtPsPb2vC>j5+LfF3B<< zGGqvU3 z^uGJAd3efcmvsK=|8AxCJ^1&Zv~&5S1%z`hWM*alzN69fSc2t@kixo;Inbpjz4`{f_>v2GTx_h+*wmz16YMii^%uT9#ynL2L(0U!VWGz0 zKU!bY?bXU>Ab^h}BOOwEd#93;l5khBqyJwV#{3^u@A!W9DyX>8&DO!-aQ(&S4m>Oi z`YWBxeo3Ti9Wqp(hb&{7qH+a378JlidtIWVPXUD8N(0riZp}-p0`;iS>aaVse}7G& zVPj%O@{-!(>JJGay}pp3*XzZ|$Vg_;>)C{f6WNO|zIa02oJr$G3CmWkgm?)*uLe# zNs}g2EnBu?`Nfx9NCEI*C`14t5C~*Mi4nrlC>7@ndO=5YOoq{F&hz@aKOuxD7hQ5r z+{f>2xi!|=TRCN^A`jZ*$AtUymIz_N|()8@AV#)PN8|?GbjJPLS2n zqerp#mMjU@*N2zG>@P1r;X1Hv)jDn7+}Wgf?_MbwY@@~H?HU2-$f80F8eE|K9B`b} z7Nl3AV;u7}Z_2Z==F>vzF{ev82n29&rNz5Kg1)kB$|=*&SoEK_O2e@yrJOMZz$1T* z|J_Ya(eZ;{u5pG4(W)+N`$XJjs(RCz9((i7b=z8EW1|=8LzBnmo&pSaYO%@@4hJhND%2J)e)kt^hWy8)eO^_8b)NxL^_JE>App2D#&R9;=R6%{n4~fu5RY%y4;_L^r`G8GM2Jt8 zUn(oDzLpT80$@=l$L3oiE*)wldhj2}820Roh4zqJdD*i>5{lweyLMDOWaZQ6$%5lV z#a|$Vz+eiZTiXbVX3QKMfpZEYk>HRaPy&Gx(4GXR#sQ6SC>lp)TM+MWZO5lOJ7K3z zoMs#ahsOrSIY>{@&LSFleV|$UxNDVILaR433whAj(EV=jq?wYE!mF#R``2mn$ZFQg9=%+5`kOM>M9xX&bzO5{(bg4o8RC3 z3X2pRcMLQ3w@XAks_#;{hG;nw>pQnocd#)=2xOdQ5;OFKoS5Mxgg`deqf1$eQ}PI& zz90jq4{#vDBtaG^1WG{2w?6_U5CsCgND*U|FfrGLIfapE4|L=0s%;1wG$hklfB`1K zpzZXQ(*JaSPOIdmSM!JTn_s=FasvQFIwPsy=VxxWyKh~|uK|$uwhjQG)fH_W21~#Q zW}2p_2^`?ZoIec*yDBlrPOc~*&F#gL8?b$IO>KQ?f*gJOAVaR@XaMQ8NO~&M7PXTX zyUGVR^yBn0wcgFB}u;nryh5W^4I4LgiHYy}wW{df4Nyr+ytN%;Rd zkzz_eJH}*K@oD*fZ1mS5Tc6CfcI*`vd%t2qJO4{}t9!xkF1y+VfQ%hGmK5*nTX6NO z3(^M-E}+}D?O^9#bZYAI&&n5x!Ghs-Qx?-$;5aiy90JvA^{%f4s;_D(oK$#5=T{By z&b3WR(o^}URGfiBCNhfsrFhR%0)ue`WNHBakxw(D6yW+&nDx7G|Lk;3$hE-bS0M=m zA(f-HJ&09hZfvdgqO#2oPk@0Fz@ih75~;_aBooGETagl_gHEJ9scs;o0{4Dcg)jE{ z(d`c~QzE0{|iml!vrFck0(@K>(nsshI;1cJHj{G+6vLf!n9ZBs%Pe9Ji0J zQHw5}xw&EPt<@g<{quS}{#891T?z`4O*o?<0y76i;?#UQ3X;uWjAMC;8~83Gc=7OpfIo=b4LlFlPE-yprqc9 zm)11l;~gCsl5ECxljG1o!Gw^?U^9yRz7K2o!mV9Oa(epgufJY?xSdd_Ga_BkxSJbI zMxKqL3SBAn}-h(ui? zs!1!l#STzC12h8a*TKo65GO<+n%clL1`{=5rF#|DGZ~UD3*q*Z<2w(|IRud*Abf#y zhv{+OSt)S)R1`P)aqovU=niPOe@-gKW?SJ2XwVpkEK*3qw`(4IGgv{Dff53{NknfDYe^eJMX*i zue;~WKDY7UGc^dYu?|R*$OjE7;2(YT5$^-!B$CmiN7J=y*Rp%>`@fh+AA03On=r1( ztV`yMD?j2I7zjitq#W(a2J}m^A>OPZE5-=BK|o03sCR`>)2X1nTR?;-1^t8+Wb-7v z(Eb5xg)}&HX<%GAZb$(F$+8Dgrcx}qp+7hnwp4j=$9vW27iYvnXQ#q$6cJJx2!NW- zAZpu#X!oiJsT=|UtOfzmRvD>LIylV|x_VqQgG}+t+GafVMLo_O9EAnb5x9oO+W2lU1uJp5xke_=XCXIiki%7dH# zQ-Se0Hrz8S83G|-oMTUe4C4db$HNQu`@+62|A)Ff_%ClqemHGKI>3=B^M*8vWQ%(T%Ou9@q>b<`zcc%ps8w zDS<2y?5OqO>Q~D!Ip2;uPESOnS;GAv)!~&5e(2O`P?X+>8XYv*a01E+5g0(BvViCf z*21q<17dr#tmjLjqMYxjq+x4iQlc*rigKi-rOGe7@S-O&hD7m@eY`{> zC?UsM7GWTSLN@J()mVk+FV2Ed7fz*00>wL<+wkW47Hq2UKokfvV+`;s3_eA}@C+*o z5{;;Fbz*;8BW%WaC?W9}AqmGndZPasMm z(9g`3$YC8Fu8aL%?RRF`o}QML-mQ>E-_*0MO7ZsK0n3t;n@if;+WG+bIb__}Nvx!F zA6@$SrX4T7`si$fkm3}n;TYVk@Oo*Zk)p-F5`Q`)9)priU>wjm$2}ibW69PISPTMc zI)YfTtpi)CJQ$KHs@526XvU_<|Zh5DwPGuoZFp zHF$#>5*;!os`fPV2t=p+H3?JkFr z=0Vk1PvHOk#kakkT!a9OGOh?5DrC{ZEOLfw6!P_2&@!~Gt?d$lnC7~gqM{s5*=3CA zQo1|f>xCmK(n)-NUmqYprIeKJLtb8v^uR-Z^Tj0^B7#1{c$r3$qqia)giwgadg!GZ z+%qc)y_-HP-qMamo7(W~MVUBjXe1`&*pMA-z^XDg-dNv){s|_eIrZ=aG}w#+hNoH4 z>2+g6bp>J^i3s{-fM_`KhLsG22r${}KxjE0IVTM@9YNgjZWSIpI~5}{tf+1e;+D57 zAqfQkyeJdN5i+_08WfE~76>98G8BcQxY39GEdeMRM_QB)I*G#NQ=w`=MzjHw@@yz? z3E-J!jmU{LAl@z`H_ixeh~e4gjTn|@#)xz)7H@6>s2!SOJqpkJ05D-#pa>iakwu$k z)8{C9ni1vcQpN`T>eZqaRS@a4LlruFK_7SBe*0~`vlyK-XEyfjEA9j2r;yy7!K|jX zLMq$oUH|YCx148|vmz*wkJ`NgD1vl1Cglq_HQx?O0KdX<=X+JSVoVI?6gr_O99DyX z>=*-1$+M%fHHfE{H6Sm}h%~1jK{cE*9hPQ6Nb_MuSt(*1u?YGN;81bsw)}AY#b{7b z=UIt6PmjUaY#aWts1mucM%*$r0ZncNk9=8=nzkTbyetcmW(l6428{tui-bB?2oHQ* zhrfJKgU@z%VpC-|-rUfN_qMh}7AOi+E%1jJLMnq9c>;3Pk!Bi{CFc0>@r5A zTd=*xi~b2lBsp|&`7~^~@ET2j^r$cdDi+6v_4W{J1|@%O>>Y-g0Gla7;x zDDuO_b>34Er|43);=JKDIGI2;HDtl(Vjsl0!CPK;|Hgu*9mz^IH6ZagI( zOZU03Xj3cxeOWd*fG>A<;`Mbcc;>qo7VakH4NI1U7L4NCoF|G;>K|vNRnpKyjQZ3pU3~Cc~G~&E9%W7iuW*58T!800` ze^weQEh&RD$|;T>GlEx?SM~vNqU6Tw7qI0kmWr({u5a%B+k%VCQm*Z2x@ifaFk3h} z{CjZe=m;c5=)gGe!S;4&47g-$EIa`XBK_9u)>ycpH!;_SMt2BLEp5bvTpR305uAq` z0|zCW5Njj&WY-?ptTNPK6gUrOOnc#=M1;;#0!ggELuaKRDN>K$y|y3ckBGtKJR54; zgSg|pDqJ)w8fOiSM5j;dDF_nWy`%=Ot!u%8sR_7YavTbhOo+9~h%}3cx9c!8)r=7t z7QC^c4Vx;uamJuX@Saw9#yKYC*|D#|kJr|6Vf%o`SkXD>{F#&-awwXj&#o*@ozN2Irw zp*y$}f190z0f{EOy{Qd>5X0qTqT%wXcx` z!sSQe`|B%qetz38;BBWa~~S zx-Y@86VG0lhS6CzfB?_0XvC$Xqah0vP3{oh-`b7^Qxl*v29Xj3RgSxs)S#>-fafpH z#LyHoLMj70#8Xr_2ZAa?Zkz#k&qzjnhl1LUAmpB|-rhF($Ineeaf1(wHnu`z{D74l zm}Ek?zxBX(o%n(q1puNjuLz=Xn=wzd2t#E98+w)$D013lk zYSidoTtEMd)VZ@}&#kQ)(_?5yYv5F)E}jEN z+GvhIZ_v=`E5(H)B49U)&=~OSibkAW7=?Jd+_UqamR3{5rn zxKm+8H0uPMJ}?5O=G$P9yl`5&Fr&bTduAphBU%qxBzS*o2UZlj@VB#4ArRo1Wlaz$ z!5_~^LYH5IKnNcBvH|P&cj4&^GLRobVGEr_*cBXrDlonx~p00`#_C4_Lj7|jIk(1|1}Uk#ck z3p!U}Mov^+Q$t5}ZEY=2PfwFNJ6*q++jYR*EH0g)YZ{F zd-kamMse}$J0Bf8IrA3I3nBo1$X(QXZ@JH_0Gz|^*AC3Y;nb}NjUQeydaVfO91$iF z56w-*wQualurvz>C7F7H;_!PFjUgjOk3YmEfD!_YbA(iekj9~xDV|y0fD1-MLoZUe z0~$Ws(SfHfNQWn&K`&9fzM&N#Y-`7p=cl6}$pn{Ag+PyTe=8n7KK&j|0wwT;G)x=d z00%)zgnVF3OuF!DL`FOS>_5Yu3y-G8{Q{*DHwzg&q((*S5kIfFqGV)Lbk`S`Uv}l6 zAAacZW&rZ2QKPkW>(>74Z7l~(SZYFyuw}SG z{e~LVn0U+I+P&KZLL}`_u2!$Q$g%~L3TW+C0N(RR8wQwkLU_hKWN?oje?9E8hg6OU zxi(xpIvO`EEQialLJW7Oga?*{m-Yo!2EU>~(ZcQN5hf8YtZYU|<(NAx3Ob46?Qhx; zXO}QJ&khb?eR(&Y`l=qcPD{Y#JR3T^M-NBuxzfX!8i5jc0~#jh*`Sl?LBEf)3Gj!y zPH-G@G@x+8cz{ZRksHJmZr2qho3vA|dj9Em)}*947XS#YTenuT+061U21r$Xvo@+| z*fWb3zP>&uXV=T0fBNahjN}1N^6<{gdZ5B%hZ zo?SI~JscDSH61~40D+z$R}yeY-(H{uon947wsoN16$-Dt5D2;h8g7}Ah%~1G*S}c~ zl>s6p2OuE?2R2yX95Bfg)$KvNu(A=?PKbj=Cm^UYEZW$LE62u#yN5f2c=+==OdH_9 z#Uo?T+8tg|h{IG>dSjqtQD;gC6z$+oP(l!87Que8b}9l6MmSfAELyoiNQF~BH8a%N z?{7wvdHtBNBgVPio)7?e>a;1s&ko4=(Iam(>MO6k@p^aEsG@-Vt=C#2PCu>ThFIso zhXC*e3m(wL$Hj?Jk&!}NTpS%eYSc*uOm1!(|Kp$T3`Rv;?rQUH5-8DY|GfnE+t9?I zv!bFc5Uz{#{*oVB2?YvtcvZZ#stJGns1{Xi0T|@)nv9^z@YuO&aQjp&c)Jpc#$b>r z7~=<&S7RJ{DI5>nyr=>NNhX{&zyX^50R+7)`VMJ8+-x(}Q!YR^%Bokh_A{$+P4L2>Uz&Dj1 zm~{dKN?_3oc>012lr;MBheZ`=aD`wsiZJRZ^b&=`BqF48{9#cA+Py0NI6Vn^iNfX6 z@chaq+<0m{2noAZi#NC7ud`ENH3;E&h=g50AiQeOZWLfQ3J9qTm2ClRsOZL$?Hzb+ zT??Arp>TWQae7CjXSb9ef}%GoMTo#Dk+?u)CJ>oXA~FKX2n0rn$iDr3&uc{B1e72A zUHk|~>uD+#BN1bqViEl#uCYZ#?if5|;PmFEHU)ri_BnHYQoR$u9UPi5aG;9pEDt$l zQUIA5DzREQaywU{O7;CJvr=?!jd#p zEB?WQoPVq?S^s97?Uazpya(;Z*gKjciNyYv5_I`B7-a!Ljl&aU2QpFQdwzR&KtoET z4zFI3jXU10#7zq;u;8==%pM$xfWnXxslyAGWa75PmALZNGF&j+iTrpIbP_>>D~MOu zw4kX=!K3ri5Mz^J(F?fa-73UdCCn&@Ky#OZzkgPT^NO4pmt#YdD+F025GjGhBqF46 zl(+a%((K3nWI zWX;DhvCfw+zx28V4?K8}Ys{FjWX+n@{3iv3F}{86I(g8{*+HI=pb_YS_67oPw?Ibe z`b7>Pagj}=V^Dj@g(hDcc5m2;UE6jc(jHO9fwi(hUK^PZwR%tW?i$fx(Ej}BJ<8o@ z-~NlFiT9Ro{>WiY-yTrf2g#y|asJ(>%95T7kAub-HdlEtAt&5&@~ykY4^kRYAZYg} zc=)q$Z1BRRS$N=+I^6qVEs7icxO#jnqRbMKB4oUDNfw@6(TIhc+F;TBKYQODCS`TE zeV_BR=`-7VUsx7cdY7Vth>DG9tg*#(6O))2)7~%fO^hZnro3u2u_Pw8SWyJTLQ{G# zyUXsfz3=q$%+t>K{+QjR2nyKnef?e6UR(+cGtZp+{Q7+dQ-3#Zpd!nLJ1;FkzE6hB zCg82w5T4sMfJbi}2~i;U_r^XL7RUD%=A$R1!>I^x+XZw5b-cDai1m#Tv|0KF4*H*jTwg_hPP$Cj;|U7ek6 zS z!hw;jbi{ey*)(6u<_eK502nZXyhZC0o3##dQ0qXiIRKl>;U^+_8wy>iWI5Kh?`rND zclKm$_gmYvPZA{K#!Xt>(a2uO_nh}02{g{F6l=P?0vC)E@T*IUvA;8cl1v+%GCkr> zOU3&@Bx&K-ueM`La}2kgTY#(PkCxFHJ^y-^)cZtTbEx(H&L ziIPkkCKWp|sn~_Fg-)brD2Ey^jN@48ma3XaokBm zw%1A;VXH@r5OQRG;C8!-%jH6MclSr)b-X$7c!g2V5OvZbr<`vxt{+BOnwsb(_B{~A z16cjTv9QSmrj^~3^JS{Da=j7z@^73*}O2IitBoaYGLjxHY7=Ws(Bp#2GL?S_Au^1T`7~lYo zSmwX_s;jGa?b&)!cTeY{L{uE%Rz{>b#1e-GAfpdD{Xr%&KQaU%dNlb2mfIy}aSBS(UB3XVjguRIdd4Hl2U92BmA-YD5 zl?h2(m8AM+W?7wAFZyEe$$vc+Kl*(YkY8;B)M#B~dXnd-F| zR;v52n-;(sZe3J?+ZR{BsZcQX{=!*=q^fi?epL&Pt(-S@tRud3PyP5YQ~$7f?Hhj^ zyv&4(ib^3bFV{Nbj5F9h_uTWLFS1387SX1rCQ1mQ2M!znaHz)o{BujQfBe&1F6r&- zz1U28tKD){zD>+iD0f2B(CzyL!$Ozy0s0RGgxQ z{Bb?VoS8GkbtxUcA%{)IkEs@R?W;8liwotBwhjw`HDltmnvM0F|7(meV&P0>oM)7+ z98S^BlT0Igkc@zXLm(6im6?Oun8tMLK%!OLpKKDElI=)JI&{I@n~=5j2_d=8Olk)T za*KOA-e~G2MUws=z!Ve^LI`|5AK$xo?+JbA8S@oqS6%tNR;==CY4$OO!Q#V`XhVAs zmVG4_i~@dtMLAU6g2{lcpoXN$U=1EDNg(h!L}WN6WOyY&rs(KQ;D6rg#)~`rm@~qI z+s-XONrnyU8zOjhR{*;^;_%0e!M+HGA_=I>vf<}xf6cpqLBpo&}3nEpR$rDthb}Okz zt&qN6mYjiyv+{&{_Uvpw_+dfvo+o$Bm6wz5&Mtv529M9jmM&X99Nk{E$j(yU+2}%`4+RH4R8-mF#(7`P|4i3gsdkHd;xSiS<1+_Y~9#Wrd zmKu}o@FN6WG_@E}w}ge*R!*^lo9tj&UTJ6J{)UdDfR|Q!CnN@nS9^tdUQrYo=R>@{gJG6!KZvjwYi}P9MIxx}QE~ns_o6J*mU;nB zkTe;R27@FJxD<-=EIVdaxG^fv0f$WR%w|7U9|&PYwjGPdr>92IJrdf3I{G386p13k zDI&`yBHJUwWE|FD=~ko!vPALCCmPY%tK#2Z8wGz<$2T6^gB>j)s5$^age(cE5&WUS zs-wH(2^At?_}iDq;lfEd5C)rpC)$92yDo%p{IdnuN#~9fWx-nDDrVy9F(*G|i-2}^@rEPyE3EDnCQd7L;(5=zk9;7VybN{&y>?x)QSs73q}rs1>lgV1ck`VMimw|qgHdWLut`E(P8u=O5#uj zJ?dxS-7y~94OysDM5Vbjr?}&Wh1azH_zyonRx&1LW@f@>vvHfv#uqL;hd=PZgB$?z za*J=L$r1PXlxe!jhZ6Rbr;}|O!sd&(@5&0CGscI6Zebv5!Y)&ogUvpRrRJ#mq6V7! zlV}-8qOmuLx*in*1xDvPF{#7}&0yHl9K-(Z1V-mM@ZE(4IIGG7)nLQjZqqulLPiMi zpREJyz@m?IGdX3a4BVwM2AJGVh%)iDokojP)GLf`WXhv$IR98ZQ+^yQ^N1jqy{QN`Yyyl*Y)AHlO8Kh1um69=fg)k)(;H zJ{4>0gDB3hLy;)F4hdOq86LZU45tVJKs6Xt-NN?P7~ZT6W7WP8Ksc_PmW}z(L*x;IP|=lkH=NMFij`;&Byc zR%hVvH%~x@`{bL;L*pv$cTM9 z^C;I`^CePSyI0u0eFqsz@bCHUojJew@BdotRtlC7Gv|C_X2PXZaHo=^N7NQ2YHkH} zbpGYKYrk^W@9+I>PhNhe(%m(neIft>fcbOJB5$sJTNpw%GKA}M)bwwRQ$|joXP?CK zY&k4sghl#3ntA*%$P8A+AQO?xL}DDA`;9Pq^#QTp45Hr%z|X>nQ569*)Z?d-PQ%oj zA)?vs@;2tB=N!0T+&Q)PJ#&BW;s1uqLoaq<>We;kI-!&dw!>1t5PJgzVF%v)!FV_n zg2vtizVzS@>}`)g5>m5OgaD!-KokUIdli&r*)cNLg;Dt~)D*chF-J> zG<He{83*B^ zG9v6#o$@~a{PXE+uf0Zx&fR@~yeIR{yY5&(joeFYV%`;|nuc`8M3aD^UtKG5+rif> zDhqzJX~WK)02Bb)CjyWm%goHA0|NsL0K_6&xe&(9l_>iDM4?JK(>pb(a$V7wPQ(*f zi{*zwhJZjI0wf}GiHMv4JZ7mpV1$K$6(RvMf&nv#AfgB%X7!o=&X6AN07bW8lNzfk zs@g?O*!k@Je>!;8Ew}$T+*9;zn^3_SQu=Fvf=GI%G-08C4m$U_v%TQNYHg7;c)KjWb92@b!N-qC2eP zk5`tXFkK#Q<_&)VgMEmz@7joFzYax_hsR5fHp?<$=sHH`IPkZd$D^j$eNy4nu>fLm zj?3?_$2em)$`ggd02%rtGLgt0^#E2R-(A-%w_k$+v^(=WQoK82;8V6abLNr${vM&O zuHFQIZ-4J5-_uY1a~@^+*H}sCDJVoD zKp+AaiNFnR@~9anAu~!NRt#Y)iaslVAc-PGVp?0Gvp>nTHb_Xb^TO(U`ywc!7mORJ zSLGa*V>M=$CGq%8RTzlr@Yp3hzP1hDcx(?O#Rf%^hC`kq?x<95z`+@VWm!n-2EZ98 z6>!z8LVR;UF~$|T5K>KC`?q?WJ2nm9o}UlPN?id%IgTO{gcBx;Z+!zUmvfL(^zcK> zVVDer>2OFC-&s_K+s>~5kV^LHsVhOGO4y8J=AC1d5V0DvxBaF!V88{oR3!RJe})^6BzgzNrD$A$y`K-CuEpuW<+)-^S*C?UX;0B>5NG~(A$#;0tZ-K$&CegV;EY7G*CE^ub zJXg*{iIT_5l|o)F7LiI?C{D0dd8(!IqB2^PMXe~0a-9fb76=3or1}S(as(1>xM)Hq z6p6sF7$%kZ;8X;x+T8;N3Q-i^JG(T97%GTR6d8)5fD&N)K|dZ{(*aIIESa1I-DG%e zcMwy{+{koE5CwwgxB0QDIf^NzZX|SuKdv|kyG=={M==h=V$gIGlpF9Wz-80&@YF4n zuy{faR3p`Q`Y_-adbnL71COom!93d}5JMOodOqTH2?yr|ayAhyq4HpNOMcNgBVRxG zZhdmhv>Mvq+4re$p6;*R2XOF-6Q>Zj%R%2=zatU!C+f#d$zEk5vVoCMd0g!;5UdiL zp)2!!*}5|lR##tl{S8J}Zy)O&@UzyAPF^!=wAeS$&psA_42J=xb?EW;8mg{po3$Li zv_tL5*c)q@kSk=6JUQFYxFK-hq(twJ1)AXs85l9RNepfg0zzzp46o=$rj*X}GS*Xpan(XUe#0W+5KBc|2~KTLg}jHi#$?d{}G@RnfM!MzL~#6eG1_IH(QBy14k@ zE@iQtPc%)hscoxM;%ef}Z+-Qf?8+OiCVO}8IUO7cdV0DL2n6_y88b;oM+e$l1BswN zR#!d2`-&i1yEHQ}F%e5<=?UAM2mX3@(Zq3+9I&#laXZqcU3<;+&Sfj#34ClG5AZz<^z*s3~+p76~>qMiJF4EE<~z)8eS>j)5}^V+&olXi_%5 zzo-ItU0IC_C+7m3BbGEFPz3bre?V8Y&3kw5IqjC|IyyRztQ59|;{Ji)?y(aypK-fA{zNh`I~35SmKKH2 zz5YwRb8BiMXDoZQ|LYayHP(|)-Lmnq$KT+e2tZ8zP>9;IzSa88KkjMx&p-e3u$IR7 z+WyUFx~Y>C+wv^N8R6g`5lr6a{lJ2gI*~>t)Fx`d#Y~7q0U>|^4IDkVa#}V_#vqVX z2ou*VoH;rZ6HC143aM!AizBJ&Fd2a)5(qR!Bt7&)02ro)M8be&ngAHCn30E;fB^zv zTA2$DMZmg-2!e4F=hdVG1ei4<9XFp@j9V91V$ry46ld6w&@IH&L126YUgPLu2nEGc zn+DJuEX3Ym3nn{C;H38BUOp`K9q~$AG3kx>pVQ?GY)6tEz-L4$ptC&?>+S1V@3NP7 zUa-ixWX|lcynekx&s(HQKe;0+y|PR{=lSObHud(mHw?}!e6sePCEwxzVqHC5Kbty# z#^@(w%UAuS=Sd-8hKK;l`NzBqO+k=kNsMuf!c^G}O>2O~4FD7pNk>BGsOwUph;(>$ zRu(Dx!W!m|O2;$bo`TF}Mx%&EV}n0Y#9}cJW?)pFjLWCx;PJ0d z#Kn_yAktJ~ZXLF_e)tZ1VY&?-yNJGkivDmCi9s(Wi}WJ}#^E8BAOQQjRS3k3bjM`8 z8`}-`K6;A;1QskJ5|LftnJ126<$r|-WASm(pnSwul$#|0Kz|@iE6U@z=N+u zt9E2(arWgKLh!l+Umfl~e_C&J-=XB9RfV= zTtCo-PbI`U+S=RNtywc>QbGs`^!b1F_xt}g@?~rFWB2v_Ggz-RBhC`T2m0dxiN-YC zoOKyUViOD=fn{amK#vOZIEzLEsSQKMfN;XVKq!eoR3DtE1ysYrKrjh^L_adIL2UOtQG|11A|?G z2=JR>`O>trlZATb&y&CFKKFF@AX|3q<^X70=bAnH>vA9X{@~ARyHk z{Aj~10+CSMl(`sM>|Jonjh=84wVg@W4$DK{0~C^?&k-pZ_5?$>v^Yrhb99e_^VD?h zP??wza@^NH6%WBUKkn-t=ur_&Si=>tArG>rGX{}l4#S2*K$v>aZS)OJWWT?OL_mne zlqIeOW_Hr|sI$ad@)^k0835YSzU6`5zM`wHxF&zk*oir9U%IKFDZg;?jV~?z_tMh} zAVcQ&`^|ICUC7;Tx4d!fhDJTCT@uJw&wnKG;_~N0uls9_gCt}`iA*FW5|JO8-uiH5 zVF2(6Zd{)>A7-KsDwnajISji@Pxyu>Cy=2YA>PDOA=U6m$tir0A^B(1;t**ncM)i6 zx$AIlE&#Y^MF%!CMN*$>5Kxjpv7;>x5t)PUPXOa4((N_a5ZeWjNZ=FAz6w+w^pApk>^ecYZmwv!|(Y>9W@zA6YS#o|XUsfK@AB z=h0|XFD@&gnVA{NKvVCgWLQ1FE~De>zeitK`f7ZQe@C*G28}RrP&<={fx(Jso{P3tL;GfIv^0LTBjk9q;$RkMv%rVirq*!ZxUE>#>Vy3uxHY9!GE3K!!_% zNHI)K%{kB!(2>v>L_&tWM_V9?fv64vIl~tL2Zv3{MXlbO>U^9~Wso9asp53cIIT31 zbMc%1TyZl1K5AU`X-$qERXfc&GpCC-K&l$`)jj~y+*z~415I1lr=FyLkhL|pG5}gy zW}4uZ-9lSi+v@;c-%?P2!S3*Z>&FXKb1SvtoJyq#`Erh>bDe11paiGZnWrEyxrvcV z1t#!rH1sy2sYgYgSAuEr6ECy!RETA9jt^p(5(rMZ{4hj9Cs2Zw`$BkO+W@w;#*ow* zY!XFWw=g!}iJx6qgmFcw9Tm;ugXLl}2w)DINU^m!2Aj=;c$5z6D-NpMat2GxL7Ucv zd^vYek(Ycxs3js`gq2IZ^R);2|MMpZSX#HcwxgoDf;82hz9i`DHf%D#dh<;r5)RXX zflpI`N0syAG=r9Tj37os*n^3mF1OC}HA?hwAXqnjU<4P7YRle++)MxEN=R z@*>+U!RruEk!8pC&dG;J37*>A55+AZoJfiB*kw9MUCJSf6q^o4!HukA`Zrlj#{s<; z5)n=!4>-9VP&)peSDeKoG!MUDa;e zZ0)&vg|Xphuc_;HJsVyrwI;iSbm}n_Dw`GXkzlU@;C+plBILqCaXtK;AI`kP1}e#D$<4 z0wux;Uo!%sNHA4cN zEcxpl=Kd>JCg1()3Uk9dkB45C>f#4QA9YzyYBv}dw>bNN6e4vLN@+HF{R-AMhOlyP z2v2P2gF47+NXa3I0fDBZ5T4&QfO}u>z@3BPj(VK++9N}(V?rpkF~~UjqsDNUMhK8J zIVKi42gmXG5nF_kK+qf3asOLgC`wasW|bHHF$2*gLvT>e&0`Z_vQ+-@Zetjd;)SM4 z$IwPk{kJ0J<3O?*A`wr{6N5q~B0X20mHyW!AO14{>z~j3Oa2@npMv%F^e_NCBO^Wa zSz@T;s`aZOi(AM1(uabnOr&81DMNja ziiM-ov7seo%r>VQd~449TC+!f|dPfYz(PA zRc6^RccgbvdG}C%!XXRT(H6(ek2hjZM;s1WNU2^8R>&wJM=*RzgC5~W&$lAoC1Kv= zOhl6w>=I2;3q^FuB8Ar>!mv0LnPOc-1kA{L-*FN}%0si(28oC#)zBQA{6&?$6l1i~ z#c-1Ov2aw&$;06|3fyNz=5?fV@qV|Gdn-@ZTkOzS`VFU!5!fZ!F}hMn5Xq44YQb<=Ds z1JmtQc5eb_66S(}(+rT-;ZvPoBt!IJp>x)F_~?%S z=vlehpQ%tw!2eQLcx(dle0ESm zQu-pt$U8U(95w;}ezy;0nKn!y&jhe!!RaTC`(upNzkNj!PWWRzy6sDg$Rq!{Pu4C;7sdjNAscrdZV1yL06 zx3yhp=+B0!=7W5|9ho!-;N&W+w3l#$8-yQ6;Pm+Y5eg@1Z;1KVQXs?3&;3SkgmWqf#0v}KsYuE#PohZ*_$G1 zg|IHPoYbkUBwx<5vZQos3^F{ONNINzcs!#vZbI~?N3vvOfsc3xGWd;8jaY|6~^d%X9^^71Jf#e z7+>tc9SP0kM`#&x z&f&C+cx`t8Eq)D`Psu`tOTyavFjnl3LW|dc@DENwsX%piPVXxrD_OrTxTU&N>$S?2 zLgEx0gq=W#J=G%;xWok#)nb|c?C840K)fS6J4=Yi6Z~_4dBFr=#oVW!i zr$k8G5v{W`-FiulCj<_#&jIoouwW>Nq^|KvbLWzd&Q8i0<6Rw{Jr|vGUb4NXeMuy4 zOUw6M$bGg7(jIQZ=H>yMQRzXNQ-nD<=d^fI4zfH7?puBk%Xaia76nW!^`^XuX2D<_ zBXb?_$4tDoCy4b8QB>vH@!fL@QUul_fyq)sgmiFJKBbS7Dk(b@0ir;0*UOE#^Th)Y zL>V`qU51-x=fGrmk6eQyQ8f0ccxi_p^QydN zFiq`Wt?g|GP2GI3vZ6A!KCo?CYrMl&qU6IPxIQp_Cxk%eBGF7ez0KLZldCxBa5@CT zF!<*H`HWagYbzLI{A*wTijNX@%f>C+pVp$;X(bsKb3mk)CBkPfMr-IGIzusBFfKiH zhzD=@*(1|2rQC;=dj{~-yB%oiOQ1N@j_N`W;+h2lU}~8gV+x#@QQ^k*v$ApT>s@&K zoj%MT?SpMlw>-t%nEFv90qJRW)OW=2!>4NTz#Gl5$r45sWZ(~1R=^>@cV9i_X#}i2 z5W&WSQCvAK3x!!WytJ(!Z`T_z5>=o$5guOx#&sB^%SdYB`;nsTqyqu}`X63@>q~Do zt{=5IxVt=E^deWv8eFnE_IYPuBu(%z1BS2B>=3l1_M%}JA6mcTbAWsTCW#VZEamOz zojG&-u3ftyZmjS5hFh4D%=euwSWF{?(A1QxB_qR=hTWa@D9w~HGRKipmIYv#3|09q z%&X2seUFOeJA3f<{sDA_G@LOq1L@8bfpuZJf_$G0hb-XMrw<~bTL>mBoIA#cm}bFg z6XEmN;B+Y1)e^#QUaZ62ue4xIT|Y9@(?BIV{(DI&rj@ymIgU>UJ4_JeWY=DE3` zp!nm;b~N;sKtVn@Cno?8fH4CJts|uB1NZ;(m%n6x`SYKxJ-heF%h$Z#rziC%a`LkI zI{&sQBBM&Nk_V9r$8ErJ!eQeINtnruR=IN*G#pINOc&II%0CClX=oECPNY3OJ)ALy z%f4`VJ|pUN?JfQP>FY#Qp>MI~u~phkD^3UzQ(rNm;M{_#yP?=4*wEC4C6h8Bi-)!c z4T~esr{L@{ndpx(tg9QqmZl(H-Ps4-Vwhf;2A5ri#eleO;?Z@zxOq-4*3?IE^SnIR z6d7ylg82Q5d-2`BZ^5(M!r0v_psjZRS-x_(ooSdqTEW-mS*9EsuPwHA)nNkReO2-5V10xxt&kC6lZ(Y1OVp-O5bx@c6bAX&i zHh1nk+S=MmdU|@88s+xqU;5|#*0$C^cef?KA(~aRIO9AekGR;F! zt4BvDfr}<&42so|;e^_27jRZ}1`?KtO${ORMO3V=_2WOAy0EdX7p?vz%5%N=>byKm zEpuVXlx#e=xf>VWwHi;n(}Dbn3o-rdix4w7np>KX;iy4gRv9ebj$d6;h_Xx@%;Rik z*=33~^YLR2^Wb#j^#xxSj0)}#E`6_*39lL2=i8_ z%RvqO^vp%*|0Q7j<`c_4n#4{GFaTd9DkMT+b|GnyLV> z<5YQ4(#VD`!Yfb3n|nieaeE*|C?8LXv zP6=}w#{q{(3Hl-i-mFcPq$gCkv8OSDo$U#5qX^78ISrB27>+D-c6GS`AQFij@%x5h zsv}2?us!nf6Ps?k_*++Oru)~u5LiVR7(131F}OwYv z#jq*G_|0qW=#LsWdjBKEybk>0qGH@QuNb-6Iq0 zTr?paOrTh~H-H1ZZrFv)!ve7rh6pGmAsUUj0YKBba>NNRxPyVUtj?2G$ z?Pk93otFY{Qkh8B(bLlefXb7!N-9N}mA@EHR0BY9X)*mAAfJL=aKQxv0HM9T-Q=9x z#?(}O^Tk&le->Kq@9k`2X`$~TGu>GYizNik%@gPi9F}x)2F03zgf8OtXIo&CgyB7q zp~Enw;PlIjOR->-3%OYpNVC=8ySM%bS6_W4sz#2)v(G+@`|i6Bk3RYcuKUuBD9=3~ zSs3SpcjB3(mPTBh&GG`@!J- zqCRd$w&Pru<(|$6sA#ezIWb<6qmB+CFmwu+JP$kCqquKX7u?EwL6SPW9KXAw5@WK1 zFn9oC3U5T3G#7t+@CBT8)Z-1a@~cV^p3KBXaD}50hUWDg%p@V8NIS>}u^sN2~)9M!_SGL%MS^%Jb&JCr(31 z4WKu=2Gi^gl%%=PF1O<67v$rDap{OBEzsl8FH(}44*u)v9;gPxuP-mdwuT5Ed1nCr zPz8vYjguWT90HVuupu}*S4G3d?zFTt8jVJen=|zF^|A7ba-p`auDhtBq<&X#?bTy# zBXm1e#Gy&)LF!UcAZPP>y`{RXr|T7%XcM_WR89RHARmW4_~3)2y}ez0?z!hkFc>o1 z8j~4IU;Ec@-h6Atozy6r?G~oleU2JtlheVtK{+hoBNAKyI0Tjr6+PJ6(u)PvX-IR5 zM^v^Bfdsf{VisEZ0_aj3k+dj8?nP7$qf1?bTm&)OQ-YWyhM=Pv|FyUnmrTq+M6=#k z_COQ}c6TQ5hm~FU^`)gK_9=LDeGgvUsUXuf9;Qi;vpM*|05MrukF)*Dk_oW1ayX)A-XzXT5YJ#%z({d!0%~C zNnQeXEvdllDmOw2^N2yjWBu!WQ4>FTp#>9*o%q&yg;=%6kNe;1g~)1P>b^nho>Pga zISdxkO|fa28fUv*E*Fi*;~!Xc(v1|6N!j!fJA3>4CMM#EQIlMwEtMtd5J)U=*dWt( z)}!<~2Ua10$mw>zKC>Hz7hilaX=`g2?!NnOU{L9F#*CTYPD^)xTT95rX|}nFLoS0P zI5R0cLyGzn;-yLi`dqT3B=Exb;N-2Or<2tRd6`M9qnvDeV0d#m3 zHwkOe(yy-!JUnzaKq4-4^FuS-yP5_u`4jlkIK(FL;D0*_n>n zqFu^^Ko#(mD$*zSCM^d<$$`CH4G<~CjB*bc=fhLI!w;SkB#qQXJhsqZCt^7s31^M+BHt_H$&LMZbbTCo&KWQb`4mH|L*b*&0veN=Ux`Pp zy>7Rg#$vIP>RagHWS^9&gu8=%i|4o}8!Af*lu&TaiCs|44z))}DEh958r`B<`e}9M zPJ4hXS+a!KY&K$=CVk_LH_+MH$t}xbH{NjbIMdXBb^GnNJ<{8yUEmd`rDZwi3U(b9n8--2WYd|mGIkwtB^$UbAX(L)z;Rcr>6&rM1tRO#~oF%SnOs1 zk8Itt?Psx|XHus9EL)~yI#I;T!Lg7}uTq%mjilHW9AZAgS}(S?cB4Go&PV0iiGBXVad6Hu3DU z<~WOsDyP{L$E`NI{o&Pbzwy&YeTHF}yVUSM*5QikE85q|wsMe08*_VuK%}L08 zZB92|Rx_^R#WkxtwhaWpzI?^S1+T2x^y&|uZJzL_D=RRy%!Q}DS&K$b@WXB=Vm z#8$Qqi^FRd`JGGK$jbe(=+x20*H%xN*S~Y`Uv3B{YMIYoO&K>&z1PDzI5(Kfu~n*%gIFXxiDDZcae8!KbQrKJ_E z9kmlOT~jQ^bb4x4ECR+2sAfmFv`Tuoxv^&;KR=)J_V%8%2hlW*1Hd_7I5*JN(pnf?ku^x1KHOO+?Lp3-JBPfrb{z)*kDZcPXPkuQW<&%T>c4)}lQDc43?LK)gmca*<2p>1Bo@~|1q&8SXi2j- zsPn$C&N}NMsOxhJbJjH0^==+|rQhBCSNPodipxt`PEL-sZQC{-02VDg*SBHEruifF z0w5{yZ~VK7JakZ2kv45byP!`h0>q%uUx1_mh!pJu@1$HSPb}Y_CmI4If+!_qN zhrUko5rAO$?GJecp2`sk7&EBF6EK+yh9s!KV6k{iHTwE=tABt5?LkIe!2G0K7UcC8(vDncT$K9{BV<55mU@%@gju273^2#gu(@#Hr zN;$~*vE#|Ey}S6xGe&2rdqR&dlxLhj!!_QDvN!=J^nb!n)gDya=D>jev+6;3QU3I5 zW*KKHHrdp0H)>d4eY^p?yLFzCowsoFmMyD}emI?{?2zZ)Air7aa~_P_NFbd04|`XXjJ z=4lBL4zUPMrNppFnI?xWFs@U^48p<4vHw|qf^U@|Rkk9-+kF7#1Val;Ot6?nET+O_ zDlC=&;|WlSfe@2fEYWSSXt!a7I*A=C)yR=>VsCaWpGG~@rbcje(#R%iZq&bQq)xi@=4h^&E-g)JS&&)Gz9p~w2t<|3 zknJY9x%={c-#KUgxB)jdJFyb-{hlY!eUc~l-t)cZ{LXpb_q@w>yw?m-nMg=z2L2RZ zi!ce`-{u$M_G#JBnZWVx1R6RM`0Av-0@%_g?>J?NU`2H|`{lc*qy+3ov$C^q-mz=f z(Q|$O)M?`#J>Ai5?agG;$eg8IH$(LEogx%WgwbuRtL+W6RRA6h2>id)pYh|z(*p+% z@Um+sPE-!+uUv!5al;*j+({hfFM3~6YlBA%0kjSnf?Rv`RbzrL! zFiJbs){yL{bthbzu4lhOXMby!V={M8oBp`(Wm{r6#vQFYa(KX~SUuf66aahY?cG=3 zert5}l3U{V`D5wo-Wrgv-5kdwk3@`Bt2Hezci4x9VfvY9BB8a^LPv2*3=6uaG$y z=Ng60tvm6p=bMo2kuZI@8$-MbRGA`_U}*3qu(vs4gyPK1^tdGY|UWasYca}t;kBIeDXUFGpQy8OY~tbEUGVX(;OxED!nOfkK;6#&9ff4_t#+E(#5xQ$AfqJjex^tD}W*-P+9Q|sCy96m*~PwQ*qcK<>hhw_rpPA7yzXL&;VJX zs3>!Ozp3TJMz<^7jKvL>;dK*9lF-%d6RN67hMpuzJxKu~g~LHY2$f}7kxbK&bX}*+ z1d(m3Vj2caCSVxgiUJ~~4i=`WGE2QG2K0EmXlS81Vd8jwWQiPl@V-@_*h%AI07&8# zlBlcM+P7m#QeJ*GAc%0eoT8$lLabc5(&*^u006YKoa$G>7UmBb6K)P%d!2W>9^o-n z`jnehA`+P37^xRxq_hOh+9@0}Ph$HapXiLX5k`eymZY%TW^TM`!Gsqd``s%i zKRnimv7<)FM;e;Uox7_qIF1Lu_n%$gd+;BhJLYTpVZNAU0H06CXFSOXWgS4@eD?=I zvT|8RTL+eYb;+8|&#tc??JSx-(q1G~qTobZr#her;?2kq05E^y=)IdZcb{CeP%61* zp_%M^FZySzSXO$Hl*Is-S^Imxe(Pa@cYMMe&V&Y@f3D!`NX0oHpNRdJ7BY` zP!vU|stT9OB@P}uC;(=5w0E5O=Z1!cFZ6zihuN}Rk%5u+A{sQqkj|p}ON6G{3J8uN zMjpzf;^d2=x3vy8{XzGs&PNF$q|=vr;OYZ)WY~~=bxdigx#8W7=EV+V-VJm0lCq+A zoNn^NaN;B!TAuhQy!b z5$%it>GIZ7dgtAKGng$A3Q8}n@TZG%^Ul6zj##mBCHCz5_h%-Q{m-$#yz9HOYP&hS z(}(?rk^b_|nyvc)V9(x~|8M!0i=Ke?_I6xqC>}YQ?%A`456Lh1egVxUrS{P@!lGwA zJx;?ACcJW*vC+RnJ*YIU$tubJmzgtXCZ|oChWqcoU(_Axb5b3x|EtGUv-eQf*m1*F z_jI;ba={tF#k#TtOcpjX)6!dk9@y>nej~_;;lr7)(}!JKcW#_N@!I3p*r($xN>008P6kCFK|%pbaW z)28o!C-Y7-DRlXK)z6t=a7j*99j;ThWB|O%;!n2 z({r630s<;kc$?lu-i&VS4P_?37H;Z2_C<`XwzgIP!14!v+OG4!wj}EYA@W74!UD3Y z8-$Pq;Fe!|?X`X-NN#Q}2Y}M6CT%&EIMEU0VGzSOWf9~uLPbS6IrQNnDukeQ#}57O z#?x%0YHzwPh{;!6b{d>RYaW1~~rkKmE9srHOU@?ACfuDqc z%JEhJ$n-k;eN59TD+K^jx3bz7bcY$qNw?c_5F60woJONPi zL~5n5e$QWCx8~0>05NuS>5~)6jfsyx8p7Xyv#TH;^KUCJ8J|-;qJUTg8NiV2vJ~tM zm?K7wSR85(+|-L*|`(}zOio(zR=|Pq@FSrGrUXM&7C{9q_w5>>91$rq`4*6S;;{_pb!}+^fvNF zctiJ5-n1mq9$kx6!rB*J**rHl7XVN>dAg6#WP`y%AdrQ)pn)D_gpm3(f9OYW&L{wM zbw{rJ%8f?Rs8I&O5ki`psPv7y6CxH1&H;dMI7lpl48X&K$4z#_b@MWI?B2QJCfC(j zqqQqO)3Zqcpddmf5)Q>0urju(r6WId7h-r9sgRGqiO;{fIu)<=`{!Qi5hT`Z@CXQ@ z7gVtf9$-TYhc*L1R#sNO62#E;K5@k}oDSxgJxj;$f7gqO@g{O|m;gu~aPBJh7C|mi z5RJ+J*smXb!d10v+Z!{a^3s{kNuMdPkTS-pprB-Tv=*!4n`;{N6E}yC`QJsV*PrpX z9y%e!6eM|)N(MML#rba21q5`XmoHwtqzM2iEiLWWrD~d|OVk@NUl-BcZeYrl2Amlj z^~Yp@kahr|61502fFO$`H(z_|1?|C~{P6h+D8BYa&m7Rcn5vI2E|nZn6K}L-#*3jtyUW zOZxRti6WR_XZB(a0SC1+pYErtBU|tn{r$&pUh=iO8}}S-AZ}Sh{L3kf=5nPn6g8VI zNT>kg2?;n?cy20l*XBq?@fPF{?e}%EV8J2|fF7)?+OfAL{nbZ)o{mQ!w#&;N$k5*3 zne~2I#mpB~;v)NNKjdHbq+7U1a{T zI@zwsL3uAf+*M;9`Y|GS=7m2zkHXPK@~LAdzqH5$RZT^ayIt;RB*BBsOr{g0L7XFj z%3vWdBx?a6k&N{FBK^t3|0TY0_hRzmD{tY}JKg{B)*H&Hb?f;Ax0|-!c1QV>PyOb( z(4{i*7S0Ddl@aIWoOyGdKYHZH&rYIa?^x`)4lc>b6GEpH1g2ncNH%70ldKGGlIzKd zjSZyvrwF480G%*p687(@F~7{mINj!&3m!6=(JRA92gq62AplU3G`pcWZHIv{G|l#f zs5vjb@)mz!*}e3aPd*<4@R$%nB80G~esc)ZE2oj2)w{m*BG#6Qb>3|k65`yPI`_(q z-8*)#m@bvwajW-+GvokLrQ@;`Z?ZntEWI3jhwh-YKj|rqe-k~Z>f3<${yjBcdXvi2 z=>m3}Ee^0~DjoXVM!L@Y!t3=O27t7*v@dL-{_@G^`Jx-H@2kK{7yvqJ#x!~WJ#17H37({>U_+JJpz5#ptkc%B5B5}}?uOnT|9|uz z>}>VsW~BNBTp~DK&&uQV>XafW#JO7;5D>)mEg(&kOBW70+@_7L-uLc!J185?NBZzB^p2 zZB6c_or?d*-R{s!XhsVF6ptw;^+)S3t-J;~HPsG>!vKjS#d+^1iIBA@fBLu2)B;de zu3Y&yaY?`M;>(v@BTtJUpF&Pfj^y+CSaC`5?BfR;-?%Mpe(nVO7{MV(k|*Jj(~NH2 zPoM66Lu-}0-wS6YejGU7vm5@8KBN9<{UtZir<-pk5^=+1rhcBpZ()iAQ8cq2VIU_v z7rw5}LG7Kf(1-l|e7U{7-5fJ^%w4{wj%WYDv&243%NHgXQHjcB$mW{fE$TjYq=R|L z_XER>)zNJ|(E;IWu%}YJ)6+dvmO>Q9**GjfKtTGynuPqM0?3L-J;$T1lj_|4NADqdhG>y(xuifcP8w+`KlM zCP|Vkad8d+f%c5?c&ai|AkYhD3UanvbkTQ$#Ef>#m@#7) z05W;-DZL2xZ*+Pq}vs2@>fv{dlhXE&f#aPn*-mWL9?h zx|SY4b-cB>bPV}m`}+fK(S*Zc06<$uD=|$@D3SWQVVy;-u!W;9yzqzpHq9;dcNU?g zVhtdyeEls^F@8eE!dn)tpDLGDF3h?b?PeF*9NLrEov7WH?nwJVGL)#=wRgAV$@EBp zo&c*qbaX&JvtV4MRJIW=;giw40+dKRu6IZtk8@Wr)Ppu|@?*v0Z*lads z>clB#)sAfgeJ3RVgkhRCN+bs*@@Ld53Ykar6BP0IpZnCZL4A5$_5>MOG?Fx)Y!pHW zGQD!<0#$ALXS+?zbJ+J`@&pC@kHk=(94Qh)_dnA4+~FZ3hyEs6pL{hLO~S6(Rhz1r zz2SgSwPV|WmxZpUs#Zp$QB8XS;UMJVBx?z8yQWyx{h&+AeS*3Pd27P zs>fY<-^dZoPtTklKyN_S^Ku2h|JzYoRb^xU@XyWmFi-n60{HjV`W66C^K$c8M`wo~ zPsT4BS(s+(Qa_nY+GQa*DNz83Gqte@h%k9nHbqZk(nvPT((y|u4!|sz6_1asduXR2GOGA^8ObYle?>k}IwlX0hXPK0y+RRN6(SFXSFl zpbznSg)wB5DX-bkgFfrj+`og`qH#NN3i9e#uU%(c&J%q)?us$)B1DoUqHzI6KQho& z9%siyYC)qtPey~fcYQ%baoHK?EW8Or9_;>7d>orc{^vXHyquz!@?6)8vb-M{W3s<1O7oVR`L0D`SW)r1(G_r7 zt7VX>SO5@=cJZrcUP*$%AmN-rq7w4+^ToRNHu0DL_|j$n{E%Ru`#S_a7F)5e?!!Sd$)QlH{=xC%%`VP{WUG<` zLNFpx8xKT}s!lhrrnX?UMTgJAisl^zIGrpN4oBQVNVzg~q}pXeHDls1G)MgL1G{}b zOHvj=2InMG+V?7XWJ%4Jh+R;kia_kJs@fBKG^f7Jl9EM`L5rRqKLLPf)O4GsfFij} z!8wnMddQBzuaDGrw^&lL2r_74ng#~|PntI`5jUYJ>1I##fTB6$TSko@_P+p7Qc^-J zNm&FLv=BlNiMaA5;(%_3B$Kv4vh_T(Wn)bX0CM>7VPQ$hBFLb{8*l&0smjhPWRebl zY@f>H_LuLw_rbLQFn|6+OF$L|H%iJXio9us8!{c`B0GItY)DbwQfrgEFeFO^mp|sr zx-D0R|H;uK12;~a?lZEobd8GK{F0J6?>8Mk)SYJYkffQg1Z83H!Q)z>U0GT3+q;*h zi{Cuvh_7F17b1$}vis7+m=R@93n3IsN)`q!vNPrv-!#8K9NkZ2*Uie}^X6oVK%2zs z_E52CUQvU`b!9mKOe!z6yjW*}RXFZ4N4nSTG?{_o@tpkZCn4f=2)NyxxLknOgN#H{ z*ey%s+_1!QnWLfcXm>c`FzTuyPn)BgWm64Mmq>o_fsBSm`NPukyfy%^+3c3EEF*pJ z;lbq(#hQ*C(|7OY*DFZSP>&EB)+x&CD{|1Hhf`z{o{tsn$Y#O-W RE#UwF002ovPDHLkV1gi%A?yGE literal 0 HcmV?d00001 diff --git a/docs/tutorials/filesharing.md b/docs/tutorials/filesharing.md new file mode 100644 index 0000000..2d6e429 --- /dev/null +++ b/docs/tutorials/filesharing.md @@ -0,0 +1,12 @@ +Anonymous filesharing +===================== + +You can share and download torrents with [Transmission-I2P](https://github.com/l-n-s/transmission-i2p). + +Alternative torrent-clients are [Robert](http://en.wikipedia.org/wiki/Robert_%28P2P_Software%29) and [Vuze](https://en.wikipedia.org/wiki/Vuze). + +Robert uses BOB protocol, i2pd must be run with parameter --bob.enabled=true. + +Vuze uses I2CP protocol, i2pd must be run with parameter --i2cp.enabled=true. + +Also, visit [postman tracker](http://tracker2.postman.i2p). diff --git a/docs/tutorials/http.md b/docs/tutorials/http.md new file mode 100644 index 0000000..6875a62 --- /dev/null +++ b/docs/tutorials/http.md @@ -0,0 +1,40 @@ +Anonymous websites +================== + +## Browse anonymous websites + +To browse anonymous websites inside Invisible Internet, configure your web browser to use HTTP proxy 127.0.0.1:4444 (available by default in i2pd). + +In Firefox: Preferences -> Advanced -> Network tab -> Connection Settings -> choose Manual proxy configuration, Enter HTTP proxy 127.0.0.1, Port 4444 + +In Chromium: run chromium executable with key + + chromium --proxy-server="http://127.0.0.1:4444" + +Note that if you wish to stay anonymous too you'll need to tune your browser for better privacy. Do your own research, [can start here](http://www.howtogeek.com/102032/how-to-optimize-mozilla-firefox-for-maximum-privacy/). + +Big list of Invisible Internet websites can be found at [identiguy.i2p](http://identiguy.i2p). + +## Host anonymous website + +If you wish to run your own website in Invisible Internet, follow those steps: + +1) Run your webserver and find out which host:port it uses (for example, 127.0.0.1:8080). + +2) Configure i2pd to create HTTP server tunnel. Put in your ~/.i2pd/tunnels.conf file: + + [anon-website] + type = http + host = 127.0.0.1 + port = 8080 + keys = anon-website.dat + +3) Restart i2pd. + +4) Find b32 destination of your website. + + Go to webconsole -> [I2P tunnels page](http://127.0.0.1:7070/?page=i2p_tunnels). Look for Sever tunnels and you will see address like \.b32.i2p next to anon-website. + + Website is now available in Invisible Internet by visiting this address. + +5) (Optional) Register short and rememberable .i2p domain on [inr.i2p](http://inr.i2p). diff --git a/docs/tutorials/irc.md b/docs/tutorials/irc.md new file mode 100644 index 0000000..f627858 --- /dev/null +++ b/docs/tutorials/irc.md @@ -0,0 +1,65 @@ +Anonymous chat servers +====================== + +## Running anonymous IRC server + +1) Run your IRC server software and find out which host:port it uses (for example, 127.0.0.1:5555). + + For small private IRC servers you can use [miniircd](https://github.com/jrosdahl/miniircd), for large public networks [UnreadIRCd](https://www.unrealircd.org/). + +2) Configure i2pd to create IRC server tunnel. + + Simplest case, if your server does not support WebIRC, add this to ~/.i2pd/tunnels.conf: + + [anon-chatserver] + type = irc + host = 127.0.0.1 + port = 5555 + keys = chatserver-key.dat + + And that is it. + + Alternatively, if your IRC server supports WebIRC, for example, UnreadIRCd, put this into UnrealIRCd config: + + webirc { + mask 127.0.0.1; + password your_password; + }; + + Also change line: + + modes-on-connect "+ixw"; + + to + + modes-on-connect "+iw"; + + And this in ~/.i2pd/tunnels.conf: + + [anon-chatserver] + type = irc + host = 127.0.0.1 + port = 5555 + keys = chatserver-key.dat + webircpassword = your_password + +3) Restart i2pd. + +4) Find b32 destination of your anonymous IRC server. + + Go to webconsole -> [I2P tunnels page](http://127.0.0.1:7070/?page=i2p_tunnels). Look for Sever tunnels and you will see address like \.b32.i2p next to anon-chatserver. + + Clients will use this address to connect to your server anonymously. + +## Connect to anonymous IRC server + +To connect to IRC server at *walker.i2p*, add this to ~/.i2pd/tunnels.conf: + + [IRC2] + type = client + address = 127.0.0.1 + port = 6669 + destination = walker.i2p + #keys = walker-keys.dat + +Restart i2pd, then connect to irc://127.0.0.1:6669 with your IRC client. diff --git a/docs/tutorials/retroshare.md b/docs/tutorials/retroshare.md new file mode 100644 index 0000000..49830c5 --- /dev/null +++ b/docs/tutorials/retroshare.md @@ -0,0 +1,21 @@ +Using RetroShare with i2pd +========================== + + +Retroshare is I2P capable. +Their [configuration instructions](https://retroshare.readthedocs.io/en/latest/tutorial/i2p-hidden-rs-node/) for Java I2P. +In order to do it for i2pd, you must create a new server tunnels in tunnels.conf like this + +[Retroshare] +type=server +host=127.0.0.1 +port="port you wish to use" +keys=retroshare.dat + +You can specify [more options](https://github.com/PurpleI2P/i2pd/wiki/tunnels.conf) +Also keep SOCKS proxy enabled. It's enabled by default. + +Start i2pd with this new tunnels, and get it's .b32.i2p address from http://127.0.0.1:7070/?page=i2p_tunnels. +Now you are ready to create hidden profile for Retroshare. +Mark it as hidden and enter your .b32.i2p and port you specified for tunnel. + diff --git a/docs/user-guide/FAQ.md b/docs/user-guide/FAQ.md new file mode 100644 index 0000000..bbbcb50 --- /dev/null +++ b/docs/user-guide/FAQ.md @@ -0,0 +1,42 @@ +Frequently asked questions +========================== + +## What is I2P? + +## How exactly I2P works? Is I2P better than Tor? + +Learn more at https://geti2p.net + +## How i2pd differs from original I2P implementation? + +## What can I use i2pd for? + +## Why is network so slow and unstable sometimes? + +## What is good tunnel creation success rate value? + +Average values are 15% - 40%. Larger is better. + +## Can use i2pd as a proxy for regular Internet? + +Not out of the box. You better use [Tor](https://www.torproject.org/) for that. + +## Are there any alive I2P websites? + +Sure, there is a list of alive websites [here](http://identiguy.i2p.xyz/) + +## How can I better integrate my router to the network? + +Edit your settings: set correct bandwidth and share rate. + +Run i2pd for a long time, download and seed some popular torrents. + +## What browser should I use to browse I2P websites? + +Use any opensource browser - for example, Firefox or Chromium based. Create separate profile for I2P ([firefox instructions](https://support.mozilla.org/en-US/kb/profile-manager-create-and-remove-firefox-profiles)), try not to mix clearnet browsing with I2P. Learn how to configure your browser for better privacy and security. + +Good idea is to configure [privoxy](https://wiki.archlinux.org/index.php/Privoxy) for I2P/onion/clearnet browsing at the same time. + +i2pd socks proxy has an option to pass all non-i2p traffic to Tor socks proxy. Make sure you know what are you doing! + +## What is floodfill mode? diff --git a/docs/user-guide/config_opts_after_2.3.0.md b/docs/user-guide/config_opts_after_2.3.0.md new file mode 100644 index 0000000..1b2adcd --- /dev/null +++ b/docs/user-guide/config_opts_after_2.3.0.md @@ -0,0 +1,43 @@ +Изменения обработки параметров в релизах > 2.3.0 +------------------------------------------------ + +Система параметров отличается от того, что было ранее и достаточно сильно: + +* изменения имён и стиля параметров + +Все параметры теперь в виде --help (gnu-style), у некоторых есть шорткаты в виде -h (unix-style). +Это касается всех систем, в том числе винды. + +--daemon=1 и подобное -> просто --daemon, без параметра. Нет опции - false, есть - true +--notransit=1 -> --notransit, то же что и выше: есть опция - false, нет - true +--v6 -> --ipv6 (первое было похоже на версию какого-то своего протокола, типа socksproxy --v5) +--tunnelscfg -> --tunconf (имя параметра было слишком длинным, cfg переделан на conf - единообразно с --conf) +--sockskeys -> разделён на два, для socks и httpproxy по-отдельности + +* поддержка секций в основном конфиге + +Выглядит это так: + + # основные опции + pidfile = /var/run/i2pd.pid + # + # настройки конкретного модуля + [httproxy] + address = 1.2.3.4 + port = 4446 + keys = httproxy-keys.dat + # и так далее + [sam] + enabled = no + addresss = 127.0.0.2 + # ^^ переопределяется только адрес, остальное берётся из дефолта + +Точно так же сейчас работает конфиг туннелей: секция до точки - имя, после - параметр + +* поддержка выключения отдельных сервисов "на корню" см sam.enabled и подобное + +Это позволило задать дефолт для номера порта и не писать его руками для включения. + +* добавлен --help (см #110) + +* присутствует некая валидация параметров, --port=abcd - не прокатит, --port=100500 - тоже diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md new file mode 100644 index 0000000..92d313b --- /dev/null +++ b/docs/user-guide/configuration.md @@ -0,0 +1,190 @@ +i2pd configuration +================== + +i2pd can be configured via command-line arguments and config files. +Options are the same, for example, running i2pd with argument `--port=10123` and setting +option `port = 10123` in config file will have same effect. + +There are two separate config files `i2pd.conf` and `tunnels.conf`. `i2pd.conf` is main configuration file, where +you configure all options. `tunnels.conf` is I2P tunnel configuration file, where you configure I2P hidden services +and client tunnels for you needs. `tunnels.conf` options are documented [here](tunnels.md). + +INI-like, syntax is the following : = . +Comments are "#", not ";" as you may expect. See [boost ticket](https://svn.boost.org/trac/boost/ticket/808) +All command-line parameters are allowed as keys, but note for those which contains dot (.). + +For example: + +i2pd.conf: + + # comment + log = true + ipv6 = true + # settings for specific module + [httpproxy] + port = 4444 + # ^^ this will be --httproxy.port= in cmdline + # another comment + [sam] + enabled = true + +See also commented config with examples of all options in ``docs/i2pd.conf``. + +Options specified on the command line take precedence over those in the config file. +If you are upgrading your very old router (< 2.3.0) see also [this](config_opts_after_2.3.0.md) page. + +Available options +----------------- + + +Run `./i2pd --help` to show builtin help message (default value of option will be shown in braces) + +### General options + +Option | Description +------------- | -------------------------------------- +conf | Config file (default: ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf). This parameter will be silently ignored if the specified config file does not exist. +tunconf | Tunnels config file (default: ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf) +pidfile | Where to write pidfile (dont write by default) +log | Logs destination: stdout, file (stdout if not set, file - otherwise, for compatibility) +logfile | Path to logfile (default - autodetect) +loglevel | Log messages above this level (debug, info, warn, error) +datadir | Path to storage of i2pd data (RI, keys, peer profiles, ...) +host | Router external IP for incoming connections +port | Port to listen for incoming connections (default: auto) +daemon | Router will go to background after start +service | Router will use system folders like '/var/lib/i2pd' +ipv6 | Enable communication through ipv6. false by default +notransit | Router will not accept transit tunnels at startup. false by default +floodfill | Router will be floodfill. false by default +bandwidth | Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000) +family | Name of a family, router belongs to +netid | Network ID, router belongs to. Main I2P is 2. + +### Windows-specific options + +Option | Description +------------- | -------------------------------------- +svcctl | Windows service management (--svcctl="install" or --svcctl="remove") +insomnia | Prevent system from sleeping +close | Action on close: minimize, exit, ask + +All options below still possible in cmdline, but better write it in config file: + +### HTTP webconsole + +Option | Description +------------- | -------------------------------------- +http.enabled | If webconsole is enabled. true by default +http.address | The address to listen on (HTTP server) +http.port | The port to listen on (HTTP server) 7070 by default +http.auth | Enable basic HTTP auth for webconsole +http.user | Username for basic auth (default: i2pd) +http.pass | Password for basic auth (default: random, see logs) + +### HTTP proxy + +Option | Description +------------- | -------------------------------------- +httpproxy.enabled | If HTTP proxy is enabled. true by default +httpproxy.address | The address to listen on (HTTP Proxy) +httpproxy.port | The port to listen on (HTTP Proxy) 4444 by default +httpproxy.keys | optional keys file for HTTP proxy local destination +httpproxy.inbound.length | Inbound tunnels length if keys is set. 3 by default +httpproxy.inbound.quantity | Inbound tunnels quantity if keys is set. 5 by default +httpproxy.outbound.length | Outbound tunnels length if keys is set. 3 by default +httpproxy.outbound.quantity | Outbound tunnels quantity if keys is set. 5 by default + +### Socks proxy + +Option | Description +------------- | -------------------------------------- +socksproxy.enabled | If SOCKS proxy is enabled. true by default +socksproxy.address | The address to listen on (SOCKS Proxy) +socksproxy.port | The port to listen on (SOCKS Proxy). 4447 by default +socksproxy.keys | optional keys file for SOCKS proxy local destination +socksproxy.inbound.length | Inbound tunnels length if keys is set. 3 by default +socksproxy.inbound.quantity | Inbound tunnels quantity if keys is set. 5 by default +socksproxy.outbound.length | Outbound tunnels length if keys is set. 3 by default +socksproxy.outbound.quantity | Outbound tunnels quantity if keys is set. 5 by default +socksproxy.outproxy | Address of outproxy. requests outside i2p will go there +socksproxy.outproxyport | Outproxy remote port + +### SAM interface + +Option | Description +------------- | -------------------------------------- +sam.address | The address to listen on (SAM bridge) +sam.port | Port of SAM bridge. Usually 7656. SAM is off if not specified +sam.enabled | If SAM is enabled. false by default + +### BOB interface + +Option | Description +------------- | -------------------------------------- +bob.address | The address to listen on (BOB command channel) +bob.port | Port of BOB command channel. Usually 2827. BOB is off if not specified +bob.enabled | If BOB is enabled. false by default + +### I2CP interface + +Option | Description +------------- | -------------------------------------- +i2cp.address | The address to listen on or an abstract address for Android LocalSocket +i2cp.port | Port of I2CP server. Usually 7654. Ignored for Andorid +i2cp.enabled | If I2CP is enabled. false by default. Other services don't require I2CP + +### I2PControl interface + +Option | Description +------------- | -------------------------------------- +i2pcontrol.address | The address to listen on (I2P control service) +i2pcontrol.port | Port of I2P control service. Usually 7650. I2PControl is off if not specified +i2pcontrol.enabled | If I2P control is enabled. false by default +i2pcontrol.password | I2P control authentication password. itoopie by default +i2pcontrol.cert | I2P control HTTPS certificate file name. i2pcontrol.crt.pem by default +i2pcontrol.key | I2P control HTTPS certificate key file name. i2pcontrol.key.pem by default + +### UPNP + +Option | Description +------------- | -------------------------------------- +upnp.enabled | Enable or disable UPnP, false by default for CLI and true for GUI (Windows, Android) +upnp.name | Name i2pd appears in UPnP forwardings list. I2Pd by default + +### Cryptography + +Option | Description +------------- | -------------------------------------- +precomputation.elgamal | Use ElGamal precomputated tables. false for x64 and true for other platforms by default + +### Reseeding + +Option | Description +------------- | -------------------------------------- +reseed.verify | Request SU3 signature verification +reseed.file | Full path to SU3 file to reseed from +reseed.urls | Reseed URLs, separated by comma + +### Addressbook options + +Option | Description +------------- | -------------------------------------- +addressbook.defaulturl | AddressBook subscription URL for initial setup +addressbook.subscriptions | AddressBook subscriptions URLs, separated by comma + +### Limits + +Option | Description +------------- | -------------------------------------- +limits.transittunnels | Override maximum number of transit tunnels. 2500 by default +limits.openfiles | Maximum size of corefile in Kb (0 - use system limit) +limits.coresize | Maximum size of corefile in Kb (0 - use system limit) + + +Local addressbook +----------------- + +There is also a special addressbook config file in working directory `addressbook/local.csv`. +It is used to map long I2P destinations to short, human readable domain names. The syntax is csv. + diff --git a/docs/user-guide/family.md b/docs/user-guide/family.md new file mode 100644 index 0000000..bb92517 --- /dev/null +++ b/docs/user-guide/family.md @@ -0,0 +1,36 @@ +Family configuration +==================== + +Your might want to specify a family, your router belongs to. +There are two possibilities: create new family or joing to existing. + +New family +----------- + +You must create family self-signed certificate and key. +The only key type supposted is prime256v1. +Use the following list of commands: + + openssl ecparam -name prime256v1 -genkey -out .key + openssl req -new -key .key -out .csr + touch v3.ext + openssl x509 -req -days 3650 -in .csr -signkey .key -out .crt -extfile v3.ext + +Specify .family.i2p.net for CN (Common Name) when requested. + +Once you are done with it place .key and .crt to /family folder (for exmple ~/.i2pd/family). +You should provide these two files to other members joining your family. +If you want to register you family and let I2P network recorgnize it, create pull request for you .crt file into contrib/certificate/family. +It will appear in i2pd and I2P next releases packages. Dont place .key file, it must be shared between you family members only. + +How to join existing family +--------------------------- + +Once you and that family agree to do it, they must give you .key and .crt file and you must place in /certificates/family/ folder. + +Publish your family +------------------- + +Run i2pd with parameter 'family=', make sure you have .key and .crt in your 'family' folder. +If everything is set properly, you router.info will contain two new fields: 'family' and 'family.sig'. +Otherwise your router will complain on startup with log messages starting with "Family:" prefix and severity 'warn' or 'error'. diff --git a/docs/user-guide/install.md b/docs/user-guide/install.md new file mode 100644 index 0000000..1cd3ac6 --- /dev/null +++ b/docs/user-guide/install.md @@ -0,0 +1,57 @@ +Installing +========== + +Building from source +-------------------- + +See [build documentation](../devs/building/index.md) for how to build +i2pd from source on your OS. + + +Windows, Android, Mac OS X +-------------------------- + +The easiest way to install i2pd is by using precompiled binaries. +Go to [latest release page](https://github.com/PurpleI2P/i2pd/releases/latest) and choose a file for your operating system. + + +Linux x86/x64 +------------- + +### Docker images + +You can use [prebuilt docker image](https://hub.docker.com/r/meeh/i2pd/) by community member [Meeh](https://twitter.com/mikalv). + + +### Ubuntu + +You can install binary packages from [latest release page](https://github.com/PurpleI2P/i2pd/releases/latest). + +Alternatively, you can use [PPA repository](https://launchpad.net/~purplei2p/+archive/ubuntu/i2pd) run by community member [R4SAS](https://twitter.com/i2pr4sas). + + sudo add-apt-repository ppa:purplei2p/i2pd + sudo apt-get update + sudo apt-get install i2pd + + +### Debian + +Look for Debian packages at [latest release page](https://github.com/PurpleI2P/i2pd/releases/latest). + + +### ArchLinux + +[AUR stable](https://aur.archlinux.org/packages/i2pd/) + +[AUR trunk](https://aur.archlinux.org/packages/i2pd-git/) + +### Gentoo Linux + +[packages](https://packages.gentoo.org/packages/net-misc/i2pd) + + +FreeBSD +------- + +You can install i2pd from [ports](https://www.freshports.org/security/i2pd/). + diff --git a/docs/user-guide/run.md b/docs/user-guide/run.md new file mode 100644 index 0000000..601631f --- /dev/null +++ b/docs/user-guide/run.md @@ -0,0 +1,55 @@ +Running i2pd +============ + +Starting, stopping and reloading configuration +---------------------------------------------- + +This chapter explains how to start and manage i2pd daemon under \*nix operation systems. + +After you have built i2pd from source, just run a binary: + + ./i2pd + +To display all available options: + + ./i2pd --help + +i2pd can be controlled with signals. Process ID by default is written to file `~/.i2pd/i2pd.pid` or `/var/run/i2pd/i2pd.pid`. +You can use `kill` utility to send signals like this: + + kill -INT $( cat /var/run/i2pd/i2pd.pid ) + +i2pd supports the following signals: + +* INT - Graceful shutdown. i2pd will wait for 10 minutes and stop. Send second INT signal to shutdown i2pd immediately. +* HUP - Reload configuration files. + + +### systemd unit + +Some Linux packages have a systemd control unit, so it is possible to managage i2pd with it. + +Start/stop i2pd: + + sudo systemctl start i2pd.service + sudo systemctl stop i2pd.service + +Enable/disable i2pd to be started on bootup: + + sudo systemctl enable i2pd.service + sudo systemctl disable i2pd.service + + +Recommended way to run i2pd built from source +--------------------------------------------- + +This way all i2pd-related files will be stored at `$HOME/dist`. + + mkdir $HOME/dist + cp i2pd $HOME/dist + cp -R contrib/certificates $HOME/dist + cp docs/i2pd.conf $HOME/dist + cd $HOME/dist + ulimit -n 4096 # only on Linux, increasing open file limit + ./i2pd --datadir . + diff --git a/docs/user-guide/tunnels.md b/docs/user-guide/tunnels.md new file mode 100644 index 0000000..b9f28ab --- /dev/null +++ b/docs/user-guide/tunnels.md @@ -0,0 +1,177 @@ +I2P tunnel configuration +======================== + +Overview +-------- + +tunnels.conf is designed to support multiple I2P tunnels. Must be located in ``~/.i2pd`` (per-user) or ``/var/lib/i2pd`` (system-wide). + +This file uses .ini file format. It consists of multiple sections with unique name each. + +Section type is specified by *type* parameter with possible values *client*, *server* or *http*. Each *client* specifies I2P client tunnel and each *server* specifies I2P server tunnel. *http* is special type of server tunnel for eepsites. + +Client tunnels +-------------- + +Mnemonic: we can connect to someone as client + +Must contain few mandatory parameters, some optional parameters might be also presented. + +Example of client tunnel: + + [irc-out] + type = client + address = 127.0.0.1 + port = 6668 + destination = irc.echelon.i2p + keys = irc.dat + +If *keys* is empty, transient keys will be created on every restart. If keys file is not found, new keys will be created and stored into specified file. +Client tunnels might share same local destination, if keys file contains same identity. + +Optional parameters: + +* address -- local interface tunnel binds to, '127.0.0.1' for connections from local host only, '0.0.0.0' for connections from everywhere. '127.0.0.1' by default. +* signaturetype -- signature type for new keys. 0 (DSA), 1 (ECDSA-P256), 7 (EDDSA). 1 by default +* destinationport -- connect to particular port at destination. 0 by default + +So, with example above, if you telnet to 127.0.0.1:6668 on localhost, i2pd will connect to irc.echelon.i2p:6668 + +Server/generic tunnels +---------------------- + +Mnemonic: we serving some service to others in network + +Example of server tunnel: + + [smtp-in] + type = server + host = 127.0.0.1 + port = 25 + keys = smtp-in.dat + +*keys* must be presented, LeaseSet of address from keys file will be published. Server tunnel must use its own local destination. + +Optional parameters: + +* inport -- what port at local destination server tunnel listens to. Same as *port* by default. +* accesslist -- list of comma-separated of b32 address (without .b32.i2p) allowed to connect. Everybody is allowed by default. +* gzip -- turns internal compression off if set to false. true by default. +* signaturetype -- means signature type for new keys. 0 - DSA, 1- ECDSA-P256, 7 -EDDSA. 1 by default. +* enableuniquelocal -- if true, connection to local address will look like 127.x.x.x where x.x.x is first 3 bytes of incoming connection peer's ident hash. true by default. + +Server/http tunnels +------------------- + +*http* tunnel works same way as server tunnel, but replace 'Host:' field in HTTP header to address provided in configuration. +Also resolves it if necessary. + +Example of http tunnel: + + [http-in] + type = http + host = ourwebsite.com + port = 80 + keys = our-website.dat + +Optional parameters: + +* hostoverride -- value to send in 'Host:' header, default: the same as *host* parameter +* gzip -- should we compress contents at i2p level. default: true + +Server/IRC tunnels +------------------- + +IRC tunnels are supposed to connect to an IRC server through WEBIRC. +It replaces IP address (usually 127.0.0.1) to user's .b32 I2P address. + +Optional parameters: + +* webircpassword -- password to send with WEBIRC command + +UDP Tunnels +----------- + +There are 2 types of UDP tunnels: `udpclient` and `udpserver` + + +`udpclient` forwards 1 local udp endpoint to 1 remote i2p destination + + + [openvpn-client-simple] + type = udpclient + destination = something.b32.i2p + port = 1194 + + +* destination -- the i2p destination of a udpserver tunnel, required parameter +* address -- ip address to bind local udp endpoint to, defaults to `127.0.0.1` +* port -- port to bind local udp endpoint to, required parameter + +`udpserver` forwards traffic from N i2p destinations to 1 local udp endpoint + + [openvpn-simple-server] + type = udpserver + keys = openvpn.dat + port = 1194 + +* address -- ip address to use for local udp endpoints, defaults to `127.0.0.1` +* host -- ip address to forward traffic to, defaults to `127.0.0.1` +* port -- udp port to forward traffic on, required parameter + + +I2CP parameters +--------------- + +I2CP parameter are common for all tunnel types and specify setting for a local destination. + +* inbound.length -- number of hops of an inbound tunnel. 3 by default; lower value is faster but dangerous +* outbound.length -- number of hops of an outbound tunnel. 3 by default; lower value is faster but dangerous +* inbound.quantity -- number of inbound tunnels. 5 by default +* outbound.quantity -- number of outbound tunnels. 5 by default +* crypto.tagsToSend -- number of ElGamal/AES tags to send. 40 by default; too low value may cause problems with tunnel building +* explicitPeers -- list of comma-separated b64 addresses of peers to use, default: unset + + +Other examples +-------------- + + # outgoing tunnel sample, to remote service + # mandatory parameters: + # * type -- always "client" + # * port -- local port to listen to + # * destination -- i2p hostname + # optional parameters (may be omitted) + # * keys -- our identity, if unset, will be generated on every startup, + # if set and file missing, keys will be generated and placed to this file + # * address -- local interface to bind + # * signaturetype -- signature type for new destination. 0 (DSA/SHA1), 1 (EcDSA/SHA256) or 7 (EdDSA/SHA512) + [IRC] + type = client + address = 127.0.0.1 + port = 6668 + destination = irc.postman.i2p + keys = irc-keys.dat + # + # incoming tunnel sample, for local service + # mandatory parameters: + # * type -- "server" or "http" + # * host -- ip address of our service + # * port -- port of our service + # * keys -- file with LeaseSet of address in i2p + # optional parameters (may be omitted) + # * inport -- optional, i2p service port, if unset - the same as 'port' + # * accesslist -- comma-separated list of i2p addresses, allowed to connect + # every address is b32 without '.b32.i2p' part + [LOCALSITE] + type = http + host = 127.0.0.1 + port = 80 + keys = site-keys.dat + # + [IRC-SERVER] + type = server + host = 127.0.0.1 + port = 6667 + keys = irc.dat + diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..09e9d2d --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,51 @@ +site_name: i2pd documentation +site_url: https://i2pd.readthedocs.io +site_description: i2pd documentation +site_author: PurpleI2P Team + +repo_url: https://github.com/PurpleI2P/i2pd_docs_en + +site_favicon: media/i2pd-logo.png + +pages: +- Home: index.md +- User Guide: + - Installation: user-guide/install.md + - Running: user-guide/run.md + - Configuring: user-guide/configuration.md + - I2P tunnels configuration: user-guide/tunnels.md + - Family configuration: user-guide/family.md + - FAQ: user-guide/FAQ.md +- How-To / Tutorials: + - Anonymous websites: tutorials/http.md + - Anonymous IRC chats: tutorials/irc.md + - Filesharing: tutorials/filesharing.md + - Using RetroShare with i2pd: tutorials/retroshare.md +- Developer Section: + - Building from source: + - Unix: devs/building/unix.md + - Windows: devs/building/windows.md + - Android: devs/building/android.md + - Cross-platform: devs/building/cross.md + - iOS: devs/building/ios.md + - API: + - Choosing API for your project: devs/api/index.md + - SAM: devs/api/SAM.md + - BOB: devs/api/BOB.md + - I2CP: devs/api/I2CP.md + - I2PControl: devs/api/I2PControl.md + - libi2pd: devs/api/libi2pd.md + - Hacking the code: devs/hacking.md +- About: + - Community: about/community.md + - History: about/history.md + - License: about/license.md + - Contributing: about/contributing.md + +copyright: CC-BY-SA 4.0, Maintained by the PuprleI2P team +theme: readthedocs + + +markdown_extensions: + - toc: + permalink: 