diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml
index dbc4028c..4e31bed7 100644
--- a/.github/workflows/build-freebsd.yml
+++ b/.github/workflows/build-freebsd.yml
@@ -10,7 +10,7 @@ jobs:
- uses: actions/checkout@v2
- name: Test in FreeBSD
id: test
- uses: vmactions/freebsd-vm@v0.0.9
+ uses: vmactions/freebsd-vm@v0.1.2
with:
usesh: true
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index bb995219..a776df92 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,19 +19,3 @@ jobs:
sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
- name: build application
run: make USE_UPNP=${{ matrix.with_upnp }} -j3
-
- build_qt:
- name: With QT GUI
- runs-on: ubuntu-16.04
- steps:
- - uses: actions/checkout@v2
- - name: install packages
- run: |
- sudo add-apt-repository ppa:mhier/libboost-latest
- sudo apt-get update
- sudo apt-get install build-essential qt5-default libqt5gui5 libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
- - name: build application
- run: |
- cd qt/i2pd_qt
- qmake
- make -j3
\ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
index bc9b28df..94c21562 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,42 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
+## [2.36.0] - 2021-02-15
+### Added
+- Encrypted lookup and publications to ECIES-x25519 floodfiils
+- Yggdrasil transports and reseeds
+- Dump addressbook in hosts.txt format
+- Request RouterInfo through exploratory tunnels if direct connection to fllodfill is not possible
+- Threads naming
+- Check if public x25519 key is valid
+- ECIES-X25519-AEAD-Ratchet for shared local destination
+- LeaseSet creation timeout for I2CP session
+- Resend RouterInfo after some interval for longer NTCP2 sessions
+- Select reachable router of inbound tunnel gateway
+- Reseed if no compatible routers in netdb
+- Refresh on swipe in Android webconsole
+### Changed
+- reg.i2p for default addressbook instead inr.i2p
+- ECIES-x25519 (crypto type 4) for new routers
+- Try to connect to all compatible addresses from peer's RouterInfo
+- Replace LeaseSet completely if store type changes
+- Try ECIES-X25519-AEAD-Ratchet tag before ElGamal
+- Don't detach ECIES-X25519-AEAD-Ratchet session from destination immediately
+- Viewport and styles on error in HTTP proxy
+- Don't create notification when Windows taskbar restarted
+- Cumulative SSU ACK bitfields
+- limit tunnel length to 8 hops
+- Limit tunnels quantity to 16
+### Fixed
+- Handling chunked HTTP response in addressbook
+- Missing ECIES-X25519-AEAD-Ratchet tags for multiple streams with the same destination
+- Correct NAME for NAMING REPLY in SAM
+- SSU crash on termination
+- Offline signature length for stream close packet
+- Don't send updated LeaseSet through a terminated session
+- Decryption of follow-on ECIES-X25519-AEAD-Ratchet NSR messages
+- Non-confirmed LeaseSet is resent too late for ECIES-X25519-AEAD-Ratchet session
+
## [2.35.0] - 2020-11-30
### Added
- ECIES-x25519 routers
diff --git a/README.md b/README.md
index ec7548f0..d21df6e7 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
[![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions)
[![Docker Pulls](https://img.shields.io/docker/pulls/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd)
+*note: i2pd for Android can be found in [i2pd-android](https://github.com/PurpleI2P/i2pd-android) repository and with Qt GUI in [i2pd-qt](https://github.com/PurpleI2P/i2pd-qt) repository*
+
i2pd
====
@@ -53,6 +55,8 @@ Building
See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build
i2pd from source on your OS.
+note: i2pd with Qt GUI can be found in [i2pd-qt](https://github.com/PurpleI2P/i2pd-qt) repository and for android in [i2pd-android](https://github.com/PurpleI2P/i2pd-android) repository.
+
Build instructions:
@@ -70,7 +74,7 @@ Build instructions:
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
* Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/)
-* Snap - [![Snap Status](https://build.snapcraft.io/badge/PurpleI2P/i2pd-snap.svg)](https://build.snapcraft.io/user/PurpleI2P/i2pd-snap)
+* Snap
* FreeBSD
* Android
* iOS
diff --git a/Win32/Win32App.cpp b/Win32/Win32App.cpp
index 1785ffd6..15157355 100644
--- a/Win32/Win32App.cpp
+++ b/Win32/Win32App.cpp
@@ -80,18 +80,19 @@ namespace win32
DestroyMenu(hPopup);
}
- static void AddTrayIcon (HWND hWnd)
+ static void AddTrayIcon (HWND hWnd, bool notify = false)
{
NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.hWnd = hWnd;
nid.uID = ID_TRAY_ICON;
+ nid.uFlags = notify ? NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO : NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
strcpy (nid.szTip, "i2pd");
- strcpy (nid.szInfo, "i2pd is starting");
+ if (notify) strcpy (nid.szInfo, "i2pd is starting");
Shell_NotifyIcon(NIM_ADD, &nid );
}
@@ -195,7 +196,7 @@ namespace win32
case WM_CREATE:
{
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
- AddTrayIcon (hWnd);
+ AddTrayIcon (hWnd, true);
break;
}
case WM_CLOSE:
@@ -380,7 +381,7 @@ namespace win32
default:
{
if (uMsg == s_uTaskbarRestart)
- AddTrayIcon (hWnd);
+ AddTrayIcon (hWnd, false);
break;
}
}
diff --git a/android/.gitignore b/android/.gitignore
deleted file mode 100644
index 57a0a6cd..00000000
--- a/android/.gitignore
+++ /dev/null
@@ -1,18 +0,0 @@
-gen
-tests
-bin
-libs
-log*
-obj
-.cxx
-.gradle
-.idea
-.externalNativeBuild
-ant.properties
-local.properties
-build.sh
-android.iml
-build
-*.iml
-*.local
-*.jks
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
deleted file mode 100755
index 8b011b8e..00000000
--- a/android/AndroidManifest.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/README.md b/android/README.md
deleted file mode 100644
index e0850b15..00000000
--- a/android/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# how to compile?
-## Install the gradle + NDK or use android-studio
-[https://gradle.org/install/](https://gradle.org/install/)
-
-## Install the depencies
-```
-git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
-git clone https://github.com/PurpleI2P/android-ifaddrs.git
-git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
-git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
-```
-## Set libs in jni/Application.mk on 24 line:
-```
-# change to your own
-I2PD_LIBS_PATH = /home/user/i2pd/android/
-```
-
-## compile apk file
-gradle clean assembleRelease
diff --git a/android/assets/addressbook/addresses.csv b/android/assets/addressbook/addresses.csv
deleted file mode 100644
index 97a43dfc..00000000
--- a/android/assets/addressbook/addresses.csv
+++ /dev/null
@@ -1,693 +0,0 @@
-00.i2p,zmzpltxslembpaupg3srh4bbhv5txgh5jmms6sfj4hzsvlv3xugq
-0ipfs.i2p,cdii3ou5mve5sfxyirs6kogt4tbvivk2d6o25awbcbazjrlhjeza
-0xcc.i2p,gawouxh2sg32cluwlqsnpy3dwedvoqtfroi4evvdvm2pfv7tdadq
-1.fcp.freenet.i2p,cuxbeputgxn75ak4nr7ltp7fjktnzl5sul3wstwnsoytbbpb4ixq
-102chan.i2p,xxu3lso4h2rh6wmrxiou3ax7r7la7x6dhoepnku3jvrlwp35pefq
-1st.i2p,rduua7bhest6rwsmmyttzssfdw3p4eu6bgl3mb4hin32qo3x5zfq
-2.fcp.freenet.i2p,ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
-333.i2p,ctvfe2fimcsdfxmzmd42brnbf7ceenwrbroyjx3wzah5eudjyyza
-55cancri.i2p,b4iqenefh2fr4xtuq6civfc6nhnia6e2yo36pf7vcgdvrwmh7xua
-adab.i2p,pxjr6f2cig6v7v7ekam3smdnkqgmgseyy5cdwrozdyejm7jknkha
-alice.i2p,iq26r2ls2qlkhbn62cvgb6a4iib7m5lkoulohdua5z6uvzlovjtq
-always.i2p,wp43sdtuxum6gxbjvyeor35r5yvgtkp3dcu7dv47lx22zeb3relq
-amazone.i2p,e6kq73lsxaeyiwpmykdbdo3uy4ppj64bl7y3viegp6mqrilqybqa
-amiga.i2p,edy2xappzjjh7bxqounevji4wd2binqkv7gft4usrkan45xhbk5q
-amobius.i2p,rj6432agdprun5baai2hj62xfhb4l75uvzl55dhj6z5zzoxv3htq
-anarchistfaq.i2p,xosberjz2geveh5dcstztq5kwew6xx2brrqaorkjf2323bjzcd3q
-animal.i2p,5iedafy32swqq4t2wcmjb4fvg3onscng7ct7wb237jkvrclaftla
-anodex.i2p,25cb5kixhxm6i6c6wequrhi65mez4duc4l5qk6ictbik3tnxlu6a
-anoncoin.i2p,nmi3loretkk4zbili32t2e5wyznwoxcsgzmd2z4ll3msgndyqpfa
-anongw.i2p,owrnciwubb3f3dctvlmnaknb6tjdxtlzvv7klocb45mmhievdjhq
-anonsfw.i2p,ir6hzi66izmvqx3usjl6br3nndkpazonlckrzt3gtltqcy5ralyq
-anonymnet.i2p,77ouyl2ane7ffgydosd4ye42g67aomtc4jrusmi76lds5qonlffa
-anonynanny.i2p,l2lnhq2dynnmf3m46tcbpcmbbn4kifjgt26go6n2hlapy4drhyja
-anonyradio.i2p,cbobsax3rhoyjbk7ii2nd2fnl5bxh3x7bbearokyxgvmudn7o5bq
-antipiracyagency.i2p,by4kcmklz7xnkai6ndfio47kts3rndm6wwleegtxghllimikdapq
-antipiratbyran.i2p,y2qbhrvuciifbszaqqwxd5t75bomp7kzdqx4yxsrkaq542t75k3a
-aosp.i2p,ly7raldsh2na2cgw5yvueyvqqjgx3vbqinecjrqdldgya76i2p2q
-arc2.i2p,rnmosuwvtftfcrk5sk7zoyhyadh2g4dhe2mif5ml7qjisgkyw2na
-archaicbinarybbs.i2p,t7o2tw36cffedgfr6kahewpkrntofnliuapji2e4rucl3os55epa
-archiv.tutorials.i2p,lldr2miowq6353fxy44pnxfk37d6yn2f6kaivzecbmvvnnf5exyq
-archive.i2p,x54d5st3dl6mwgfxj6raiekqkypo5pdvuex3n62szwju7hgefiyq
-archive.syndie.i2p,abbyu5n3mh3nj7pe3b6byldrxswvva5ttxcafsnnseidanurq3kq
-ardor-wallet.i2p,tm23k5ny3umhf6vf3kghnnwacli5zywq5wrr3xcqowbcofuyr4gq
-ardvark.i2p,jcmw2sol3hruwc6rfinonx4e23pjkukkg7lg7xt7xb2gpiyyraiq
-arf.i2p,o46lsq4u7udxg3qqlidrmpj4lb4nr7ldxmbb2x53nftndaeyxqeq
-arkan.i2p,7o5y2lyyrjx5tf6l4fyumywui7msjv5azaaheatvw5sqj7mxbuvq
-asciiwhite.i2p,itbzny5ktuenhjwjfqx3jravolhlj5wullhhr2m4qr6k2emnm5dq
-aspnet.i2p,tsb7zqru57p4q2a7cto2lko4w5cg4lieglwm6t27c44fkphqmf2a
-asylum.i2p,p45ejjw4p2q6nq3mzi6cm6ep35grtzshboidj2lojmrmic22noha
-auchan.i2p,6vxz4yp3vhjwbkmxajj7wiikxafwujig63gkhjknbq6xh4rqpm5a
-aum.i2p,ohdfneqxapfd3fwfbum4tut7z6k3rnr7rrguoxdrrfe2tln2kpbq
-awup.i2p,v6g32duzrkacnrezfbll3pza5u37h7lnukr2wbsk6rqen6prhbga
-b.i2p,272kt3gcx6wjurunzaiiwld7s5p4mpjewfubzmlcvw2vie62ckpq
-bacardi.i2p,hivhnx2v47vh234c7coi2urj5cyvbl4bu3ypjr7snklortyqeljq
-backup.i2p,kepphem42whle3rkfv26wcksmnegdbg6rdp6t3oobdkc2fmzrdkq
-badfish.i2p,f6v26gyr4eipy3a7pi2voulw5qvob6dg7zij6xpo2ywbi5tvbu6a
-badtoyz.i2p,3qz6ubtwlt2c4iasofjirkckq43u5fgkzyg7mlutcsym5gzhijna
-barry.i2p,4kyahq53ol52n23l44tefgeaxqpp3cbb632t5k3umdvqcooevdzq
-bash.i2p,s3wouoilbl3mrefxjhp4qoyujgok34e7y6vmpbu6hx4342ivqo4q
-bdl.i2p,kp6fnuulenbjm7r26pfbmjcq3u7c7kvxeajodvgr5flcnskdgi5a
-bdsm.i2p,pa7fxql5jljegg7j5tglhnnaod2sptq3gxvdn3ji6muqyhgn3poq
-betaguru.i2p,d7cduwwhrcc2voameqfkvd66u3advu4jw2p6pysgax35vq6ovriq
-beyond.i2p,uaicfqlrpjtitqbqkpfujanj5dollzfzee5glsuls67ekw6hlpoa
-bible.i2p,pypz7ca24n3lyp4tm3kvncg3ltp3gd5pgnacc6zltoeffiyyegda
-bible4u.i2p,xs6lr2g5jiaajtb3nkno2zmy34eipitrggooxb7wtey7uko7bqmq
-bigbrother.i2p,tnxiifs6uticzyg6ac4lhv2l5luwi6xra7yngocro56ive5e4jsq
-bitlox.i2p,lqw5khxcdntlv3u4vhn53upcqirplvnc4etjlmoytrzs66ytettq
-bittorrent.i2p,pgax2vz572i4zsp6u6paox5xubmjrkqohq6g4hvlp6ruzzy56l5q
-bk1k.i2p,nlyegmtyfffo5jfgg5h4dxxnlmqko2g36gpaye5a7vd3is35xxfq
-bl.i2p,e73d6uhnfbylza6wqkhxejmqeyfb7thkzw35gn5ojmna64jzyk2a
-black.i2p,sjwueu62qpe6dtv5b322k3f23fl4uz3w6qe6wcrwauiwpnymypfq
-blackbox.i2p,7josyf7zjieoib3ovmr5a4dh5w64kmfh45lv5h436eljtgfegtqa
-blackexchange.i2p,ztgr5kghkyn43fhhkuycroxgfti6cojo3vg4wdd3usqonyvrla5q
-blog.curiosity.i2p,yiz6jec5k7ccxdgnh7msqa4ze52bqqmf6rpq6bqdyojra2erd4ta
-blog.polecat.i2p,orlccceubewvxo3fbdyydq6e4uuidbs4xd5u2gyqbculnowo3ehq
-blog.tinlans.i2p,ylkch2nkrwehakx4z6wiyjbeqwlgasknukdkex6r6yq4xusrjnda
-bluebeam.i2p,lvxp3cbcfwtol57d5pmrsck32t7ndutlxubjb4smaf32bynhlk6a
-blueheron.i2p,anfb5jrhixjmvkyxctqwkezqer7dbob22wge2bh6wsewbhgnftfa
-bnc.i2p,fr4zbcygmx2vdct6nrabakfys4b4derm6jqu2ovppkgqillvlqxa
-bob.i2p,i76m7dwm5hnapljendbie6fc5y3mjlkdlduo3tvbwiwmvhxbpyaa
-bobcat.i2p,ftuukjtcquuvppt726w37boit7gp5hf2yxwfop35prx3grzzzxlq
-bobthebuilder.i2p,qlahgthqhr4uojkkwahnper2cl3ro5f5gtzy5t4lzapbzo4osy6q
-boerse.i2p,7633w56hd53sesr6b532r5qlbdnvyl5bnvama6ign6xryaxol4rq
-bofh.i2p,auvuinzogu6gc4pwsgbjijuszxgcjygciu2wy53pfz7mo5nfpc5a
-boing.i2p,bgsq33bh74j66hn4oh7oovlvuhhdyw22lq2qi2fnv3jyh2ryap3a
-books.manveru.i2p,eb2tisc2vr5jvjqrixrozcujiucwxg4m722stxwho5666ipl67zq
-bote.i2p,bhjhc3lsdqzoyhxwzyrd63kvyg4br6n2337d74blyintae66mr2a
-bozo.i2p,7a2d23h6htprhzrol36vgwgklsbqrnuya4tbaaaspmaeaodt57iq
-brittanyworld.i2p,e76umhhic3474sdxiuax25ixyfg7y3z7oojj4fmxvhgv3ruet6aa
-bt.i2p,uhkuu54pg47zey76h45tnvsdtpkf5bthbtrjgnaloi5m54h4hlaq
-bugfuzz.i2p,ubszn4gsf22vga67rvzzlg4qj2bfcq6o52fmxz46xruawqm6z7rq
-burntout.i2p,lkep3fd7tjvxrs25crr2c3jy7xm4s7bqiua5r327zgpw37sgyerq
-bytepay.i2p,7amc4ztwkzu3cgsaaaw3223ohuihn5hlsqc6gpf2rxdyptdkyugq
-ca.i2pd.i2p,u5safmawcxj5vlrdtqrsqbsndkr5cfenpicgg5euu4xqm73yicba
-cases.i2p,kmpmk2fmineaiwublteqlifg4fkmewnhmxqlcgg7qwecz6daj43a
-cathugger.i2p,vq43xjjcnejqpzfprws5qzrea2siieshu4tglpdepql2w3w3bpba
-cbs.i2p,u3lp7wazvq6opodzwjg5sc5w5kwxehmxd4wcdpt4s4j2k4dx4apq
-cerapadus.i2p,zroed2cxga5zeuu6rcvmp2yfi77nzduw7yhdplbeuqkuyxwbrzaq
-cerebrum.i2p,u5gtsfn267udwfh2uq35jiabkufifvcbgv456zz34cydutsiw2eq
-cgan.i2p,43z65gdr52xe3fxmkumwp3dzhedu4tu4rdtzr24hz5b4awcpfbqa
-chat.i2p,ollpwnp6yidc3obbb3famgt6rw5jg5w3k3a6z7hhaegj6gcohiuq
-chess.fillament.i2p,tv6wbanei647yf5bie4dhg2wmybkjurezlpdfwftc5ajqlfswwya
-chess.i2p,sbnoqznp5yzxals3vs6nzyqaj2fetvonys4e3b3x4ktmfeus54sa
-china.i2p,wit6f2zx6dtuqqze6nhbykrds3idppfirxvhf2f7ydqoqf4xdzeq
-chitanka.i2p,u4s3jneepk3akoez46kqiwikoezi6zyj2ibjkjyi4uuvsbcojzba
-ciaran.i2p,2r3645eete6xwbfu62ogonudcrcgqq25sbnij5v4geru74yrscna
-ciphercraft.i2p,7s5pkqbpbfdkxtwuu2e2iwstbikyewvvscy76lij4x5pfbygbjca
-closedshop.i2p,6fg67mbw2okopzyonsck4bsy3cy7l2fame56uiysr2cezhjhzdbq
-cneal.i2p,g4za73ffigv3ht4jnhzy4dae52djjq7lqcguqsfg3w5cxzqm7nba
-co.i2p,3mvo5eifcwplcsoubtvqkzdahwo2sdhfygfdde7lj2glybk4q22q
-codevoid.i2p,2mukrqwtinsw27uoejtrz74zxtilyhnnfdyso7j3yo6vaa6nzlaa
-colombo-bt.i2p,cyr75zgiu2uuzap5zeosforbgvpfbqos2g6spe4qfulvzpyhnzxa
-complication.i2p,x2av6rwj5e5tp64yhdmifdyleo4wblw4ncrrcrabxwscuevpdv7a
-comwiz.i2p,6p7zqfotzbd66etl5xqy3p6xvr5ijucru3am2xqa7wmnj6vf3djq
-confessions.i2p,lh5vitshufxpmyr44zgyymebo5elc42eda7pxvn5lmtes47c7rxa
-connelly.i2p,5yrris3nigb3fapvzrlrcaew6cdmzdknzvgrc7y2jpn3ntqurweq
-costeira.i2p,abhty5xlmnyab2kqdxcd56352kcescxoux3p6dbqdrghggyygnxa
-cowsay.i2p,q4ghzfpah4ffvm3bhc6fdkrznk5f6jxfjm2daytlparznai5d54q
-crstrack.i2p,mm3zx3besctrx6peq5wzzueil237jdgscuvn5ugwilxrwzyuajja
-crypthost.i2p,zywhrxtnkjc3rxxvxbocom7ml4hnutomgtuvqrwyf3rhuupnq5ca
-crypto.i2p,vffax5jzewwv6pfim55hvhqyynafkygdalvzoqd74lkib3hla3ta
-cryptostorm.i2p,mlu7mswyirjf53usqq7gyamvqc6rqihezgdbevov3dkxmkfo57aq
-curiosity.i2p,eomeif4xrykxlzhawc3icdilje5iammijos6tyizwhrfh3j7qdvq
-cvs.i2p,yd6k7dzpsa2tnlzx4q7xqkmd4qsjk5xk5hbiqpiarwbeyvxaxgba
-danwin1210.i2p,eoqdf4no5dxn4tw5n256kkd4lzz3uk4p47np4mepsykpsdzrnvba
-darknetnow.i2p,gkx3o5fy7mv7l4psqqnhp35d5iun7rt3soci6ylf3rgb7a5a655q
-darknut.i2p,2mk37gtvpk2i63o6vl7vna4dr46rqexxetupgn5efuuins7x3qya
-darkrealm.i2p,gbh4eerxdsph7etxsxznfhvmuiz54trlkenakqep343u4xcoekzq
-darrob.i2p,hz2xhtpeo6btgiwi6od4qj2575ml5o2246rd5orarruyjhd63zja
-dashninja.i2p,dzjzoefy7fx57h5xkdknikvfv3ckbxu2bx5wryn6taud343g2jma
-davidkra.i2p,nq7ca2egm563nir3xegfv52ocgmxstpz56droji4jgnzfoosk45a
-dcherukhin.i2p,qa4boq364ndjdgow4kadycr5vvch7hofzblcqangh3nobzvyew7a
-de-ebook-archiv.i2p,6mhurvyn6b6j6xa4a3wpuz7ovpsejbuncvyl6rnhepasfgdgmn7q
-de-ebooks.i2p,epqdyuuhtydkg5muwwq47n7jvr66pq4jheve7ky5euls6klzwuyq
-dead.i2p,7ko27dxvicr2sezvykkrfiktlghx5y5onup3f2bas5ipocy6ibvq
-deadgod.i2p,63bveyh7wefb44hlia7wtxxb3jal3r67thd6jekmwrtq4ulaaksa
-debian-multimedia.i2p,cylxxz2y35x6cvyrl57wu3brckurtexatyi2i5awz3eeamqwjspq
-decadence.i2p,pw5ys7k2grjb5myydpv6ohikm6nna7y6u2dro44i4rucgulu3ikq
-deepwebradio.i2p,2nait2gdeozkgf6gyhzjfij6mwldwkxxwcvtxobb4b5q5cvtm5la
-def2.i2p,cepsrw27kdegwo7ihzouwvgcvw2obswwjs23ollgj7hk2yrce3da
-def3.i2p,xbf3ots2purqun7orn72ypkpjmrzbfrkj3u654zfe77hbrbow6la
-def4.i2p,yyzdq4fwwmnlojp23drfpfqujln2vcjozjrfzfeuriuqzdq7g4mq
-deploy.i2p,ujzspsqkbz5z272eozsrdv4ukl434h3fuliwrfxxnab74jmd7e6a
-det.i2p,y6d4fs3rpqrctuv77ltfajf5m4tl4kzcu7rtwhxgiohylfxxow4q
-detonate.i2p,nykapdsjjswdkjov7x3jzslhg4ig3cpkhmshxqzijuhbisx25jja
-dev.i2p,cfscxpnm3w3qxnlv3oikewxm4qrot4u6dwp52ec2iuo6m7xb5mna
-di.i2p,3irnooyt5spqiem66upksabez4f3yyrvvjwkmwyzlbealg64mgxa
-diasporg.i2p,edvccoobtjukjgw2os5eetywanbb2mpag5aknkrpia5qx2koksua
-diftracker.i2p,m4mer767ipj7mq6l7gdrmrq37yzvsj3kzezd7n7nsfuctntjseka
-dm.i2p,heysbdivyeugdbggpscco5wje3dsvwgcpp5ot4sopooebnmiqvtq
-docs.i2p,ato242wckzs4eaawlr5matzxudt6t5enw73e4p6r3wajwkxsm3za
-docs.i2p2.i2p,las5l45ulwwf5i72nht6vk33sfkidcpr2okpf5b6mvgbk3a2ujna
-downloads.legion.i2p,xpmxdpuuptlekyhs7mmdwkvry7h2jbvpqpzsijqe3a5ctxgodesq
-dox.i2p,vk27cjdrtegfdnrjqutebgxkpyrfj42trdfbsupl5zn2kp34wb3a
-dropbox.i2p,omax2s5n4mzvymidpuxp2yqknf23asvu54uon6cxl6gdrlblnuiq
-duck.i2p,3u2mqm3mvcyc27yliky3xnr4khpgfd4eeadhwwjneaqhj25a65ua
-dumpteam.i2p,2fwlpuouwxlk2nj4xklvm43m52tqyhqnu2fcfiuv7clvf3wd5nwa
-dust.i2p,u6xgh6zhhhvdvefbqksfljfs3nyjvqcrmyamp5bryz5f4injmniq
-dvdr-core.i2p,fg6l2ej6qrk5rkyfzdptxx5xkcm4kvdla4gg2tun7z7fm5cxxw5q
-dyad.i2p,7n2ljphvp2dep7imoujvydxp4myuxfld3axwfgcny5xc5x6jj6ka
-e-reading.i2p,z54dnry6rxtmzcg7e6y3qtsig5yf5fmehuvakcg5wnuahx3iafuq
-easygpg2.i2p,bwxry5alzx5ihgrd3glah4eotddblzhalvpheppnw4zcajzqoora
-eboochka.i2p,ou7g64d5in4sugv5fgmmzwnunuw5hloixio7puthmrvrkwrp6egq
-ebooks.i2p,bvpy6xf6ivyws6mshhqmdmr36pruh2hvoceznzeag52mpu647nzq
-echelon.i2p,afvtspvugtd32rsalxircjglh3fhcjzk7gxrm3gw4s2yrpvzk6wq
-echo.baffled.i2p,bfr3lyicr72psxvt2umqfb562rtex66w6q3hi3tktzkoyane2iha
-eco.i2p,2dq2o5h6c6a674qaduipp55mid5iktumjbswuwmpsrcqaeowdvwa
-eddysblog.i2p,ieac3ub4g5sy3wuhsbqfembnpp7f3a37xgcx537ytzsmgfzexnbq
-edge.i2p,aknsl5wmzjmwyc4wxutfdwy2w5vgd3vcx52mqx647hcgvyurmqta
-eepdot.i2p,t6edyotbxmxvy56fofdvmragvsj65te2gkhvzv5qnblicutyvgoa
-eepshare-project.i2p,sn26kom4qyuzouppv4lwnk6bqabdydcegtrilybviibwiq2s4nfq
-eepsites.i2p,isskhl4ak3g7qevrarlmblddgr4ugnn3ckalwpjcvxafk5rjgypq
-elf.i2p,duz6ey27ohpcp3llylklzdb63lylolzcixad6bh7rt5tkq42qqpa
-elgoog.i2p,z6hrgkg2ajmuzlrddjlffrgctx7x7fkipm6c4hdzmohyn5wkr4ya
-ems.i2p,734zw4jsegdf55zl3z6s22tqkbxcghu4qvk6q2wevjfmx7xhbn6q
-epub-eepsite.i2p,yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
-es.hiddenanswers.i2p,cw7ge5ey4ekp5iep2kaw6j54boebtqytpcbnvio2bfpccd5ejzfa
-eschaton.i2p,xe75f5hzmrq6rkhsef2geslmi2v2yfngdiysmlmxvh7b4pyyjk4q
-esuwiki.i2p,cwxuiwcpymb72vm5vluba66ofhugyf5qeevvwo7e2fqrxl243coa
-evil.i2p,ljfl7cujtmxfffcydq77pgkqfxhgbikbc6qxjgkvcpn4wzd73a4a
-evilchat.i2p,s5b7l3hzs3ea535vqc5qe2ufnutyxzd63ke5hdvnhz24ltp3pjla
-evilgit.i2p,mx5vyoqhg77yuhthwznsxrepjsemq4uwitx4lxdzetk36ryl5rla
-exch.i2p,vsyjsbbf2pyggtilpqwqnhgcc7mymjxblamarmxe5hmbxaxvcndq
-exchange.gostcoin.i2p,n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
-exchanged.i2p,ylmulgfskl6uiwac4hw4ecwqdzd3oxtwaemzj25zc6k5q4rkexra
-exitpoint.i2p,5zmjurq3enudcenegnxu5hqmfmayz4lxvnik6ulch4xssa2ithta
-exotrack.i2p,blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva
-explorer.gostcoin.i2p,ktoacmumifddtqdw6ewns3szxths2hq2fat2o7xnwq4y3auga3za
-fa.i2p,6n6p3aj6xqhevfojj36dixwbl4reopkhymxmatz7ai5sroh75rka
-falafel.i2p,djpn5cbcgmpumwcriuzqistbae66txca2j4apjd2xesfgb7r5zmq
-false.i2p,77mpz4z6s4eenjexleclqb36uxvqjtztqikjfqa4sovojh6gwwha
-false2.i2p,j5i2tfumh3ti5sdtafwzzbpupmlcbg5drysfay2kxbdpsaljrosa
-fantasy-worlds.i2p,62a4xcyyhvfrcq2bkckb7ia37fmrssrgx467tlkxp32fjpq577wq
-fcp.entropy.i2p,de6h6ti5z3mcbdcwucu45vplikqyoeddsu3rqy7s2zy5i47j3peq
-fcp.i2p,ndsznnipoeyapnsg3gj3yi2dzsqduxwalmujm5mzjm7e6x374tta
-fedo.i2p,zoamh7e3k2vf2g6pfy46ho4taujk2f4mxqqsv3gbg554fxbvyfqq
-feedspace.i2p,kvtnpx4jylgeyojfhix4x462sqn5uork3roml4sfzotkxx62i4wa
-ferret.i2p,kkqie5qmja7bkf3iad4zxhrdarwj7kbrx2m3etn5kmba3shgwj4q
-fido.r4sas.i2p,i522xmu63hfbaw2k54cthffcoqmeao6urjyq3jg4hddf6wf57p3q
-fifi4all.i2p,v2stz6bsot7sbjzix5tky5dm5ej7gidmjnkvzqjju5xvz5sz6fwa
-files.hypercubus.i2p,qfglq25jwieszgyt7muz6dambzqsrmjhhszygzzx2ttubc77sffa
-files.i2p,w2sy74xe6oqnuz6sfh5fhkzu7boholgzd5f3anhj47srxwpj2vaa
-files.nickster.i2p,yil7dp2hg5pbqyovsiwb2ig6zjsq4tize3fnwemmqdrr6j5itdtq
-fillament.i2p,udj2kiino4cylstsj4edpz2jsls77e32jvffn2a4knjn4222s2oq
-firerabbit.i2p,awqh7n3wskzl3epyvkdwgarmfybsncm7vye6psg4tpkmplh3mj2q
-flibs.i2p,ocdm33e3h5tdml3yyholj4objdwsrhlugfqjnqgdkslmgdzb6b3a
-flibusta.i2p,zmw2cyw2vj7f6obx3msmdvdepdhnw2ctc4okza2zjxlukkdfckhq
-flipkick.i2p,aso5rzc4ym6g2bcbxjy2n573bmbenkjawva2jg7fhyqhwtwgu6lq
-flock.i2p,hflpi33ko5bi2655lx6bpzstdnjqgzrz23inovqjx5zpntyzyb3q
-floureszination.i2p,vitpvfb25sikuk3crgcvtcdi7hajxnnq2t6weay3no7ulur2wwwq
-forum.fr.i2p,onvelkowkbuwrglhw2cnocggvbdudi75sll5mfirde3cbopjqivq
-forum.i2p,33pebl3dijgihcdxxuxm27m3m4rgldi5didiqmjqjtg4q6fla6ya
-forum.rus.i2p,zd37rfivydhkiyvau27qxwzmerlzbqtthsa5ohtcww62zrygjaga
-forums.i2p,tmlxlzag7lmkgwf6g2msygby3qttxvm6ixlfkq6s6cpgwubp33ya
-fproxy.i2p,keknios3gm6kh6onez6x2bm2t7stv54oanvltuagphgdfjdw5e2a
-fproxy.tino.i2p,fpaituvuvyxp6xdjnv3i27alnj2ifzcvqdweqb6yj5uybotzvyha
-fproxy2.i2p,r4lgw4wmza25g7j5fjocjbwzwthfg4ymcbm52ref3hh2hogskcza
-fr.i2p,ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
-freeciv.nightblade.i2p,rluupsgxbvw5t7jno3apyzlrdirjkljft4gdoy4mxxh4fmd4xzta
-freedomarchives.i2p,4ck6oliqfjz3sccpya2q4rh5xkj5xdxkqs76ieml37537nfhwd2q
-freedomforum.i2p,abzmusjcm3p3llj4z7b5kkkexpsxcnsylikokouk5txfim3evqua
-freefallheavens.i2p,giqnkltyugfmsb4ot5ywpvf3ievuswfurk6bjie4hxi2hh2axajq
-freenet.eco.i2p,2kf7ovb35ztqkrurkm76y34jfpwi6go25xj7peznnmxrl7aieo7a
-freshcoffee.i2p,sscuukigp6alcb3ylhkcugoejjfw5jqgtqbsbafw4hyku42lgc3q
-frooze.i2p,m6ofa5dmyse4b4jg7kfmluuuc4pw5jqu6zh4qnboin4vropxepja
-frosk.i2p,63naq7zb3hvbcppj2ng7qwf6ztusp4kwpyrzbt4ptafcdbu4pfjq
-frostmirror.i2p,ycz3imuz6yte2zhlapmsm3bsvc46senvc2jxzwsbfdct5c72qulq
-fs.i2p,ah4r4vzunzfa67atljlbrdgtg3zak5esh7ablpm6xno6fhqij35q
-fsoc.i2p,vaqc4jm2trq7lx2kkglve7rkzxhhaptcwwl32uicx4ehf5k3hx6q
-galen.i2p,4weo7zkxscxbcouiqx4mlnb35uwl2lromikzk33er3fljktyvi2q
-gaming.i2p,rfxberwod6st2zc6gblqswxjl57nucgc3xrbwss43pe3dvqqzj4q
-garden.i2p,qkk2dqx6nocycgt3vinsoc76cxkb4jreybcpgz3fcps2dbe4rowq
-gaytorrents.i2p,fnggbr2t2aulr6rvlo4aehotx6wecfob7u3k2nxsnvtm4xex424q
-general.i2p,5fklrsztdqpl3hkkwwrrw2rdowrq7wwhwb6h7avvk4fhansp4vvq
-gernika.i2p,wpzqv3lxpecdsvcaadvbmrhhwlc7kp4n2mijdv2qjw3zr3ye232a
-ginnegappen.i2p,kbhfkzx5jeqhfgss4xixnf4cb3jpuo432l3hxc32feelcmnr3yja
-git-ssh.crypthost.i2p,llcp7jvz3hgtt3yzkdgjolwobisgvhv4xqa5a4oddejllyozur5a
-git.crypthost.i2p,7frihhdcisdcyrzdbax6jzvx5gvtgwsm7m6kcem2tlaw4jtahbqa
-git.psi.i2p,em763732l4b7b7zhaolctpt6wewwr7zw3nsxfchr6qmceizzmgpa
-git.repo.i2p,vsd2vtgtuua2vwqsal2mpmxm2b2cpn3qzmqjoeumrrw2p4aot7uq
-git.volatile.i2p,gwqdodo2stgwgwusekxpkh3hbtph5jjc3kovmov2e2fbfdxg3woq
-glog.i2p,ciaqmqmd2wnws3hcpyboqymauyz4dbwmkb3gm2eckklgvdca4rgq
-gloinsblog.i2p,zqazjq6ttjtbf2psrtmmjthjeuxaubi742ujrk2eptcsaoam4k7a
-go.i2p,ll6q4lsirhwkln4dqxwqkh2xu4mu3jiy546b4uhe4fypyb4vvx2q
-gonzo2000.i2p,nogsv7okydhbvrewv6hb4xdojncvhkusnyib4lglluc4uw67a37a
-google.i2p,4p3ajq4cotnflmuv7fhef3ptop5qpm3uzzgp5bahxif3nc4w3ffq
-gostcoin.i2p,4gzcllfxktrqzv3uys5k4vgkzbth4gqednwhfpt755yivm3davuq
-gott.i2p,dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
-greenflog.i2p,zny5ftmhzxulxzyczmeat53qjnue2xtqv2clisc7dg76lwfceecq
-gstbtc.i2p,n33uthzyqsbozl2qh5zii2bq2nnvbz6g6c4ew3mwp6uukk6u7wva
-gusion.i2p,4qyfdhizjixe2psu7wcvqufix5wlijocehpb2futurcmlhlktrta
-guttersnipe.i2p,kizkhzes2bzp45widihremo6geepfk7dl6juourkvzuvlc6y3spq
-hack8.i2p,un63fgjgi3auvi7zscznwqfol7ka4johgthvqf635mg3fefsjgpq
-hagen.i2p,e2t6rqd2ysbvs53t5nnaf7drllkgk6kfriq3lfuz6mip6xfg644q
-heisenberg.i2p,jz4quyw7zt63tmw65jfp76fblwadjss4iyi4puqdg3dye7oaqlvq
-heligoland.i2p,gzrjm62ektpqjfsem3r3kwvg6zpjvvhvpjvwfxkm2ay4zu7sp6oq
-hidden.i2p,iqodhhqo473qv5gwhjcs2bsrbhlqtpzgpnuumpastfiyhuwb2kyq
-hiddenanswers.i2p,kj2kbzt27naifij4ki6bklsa2qfewxnkzbkgvximr4ecm7y4ojdq
-hiddenbooru.i2p,zma5du344hy2ip5xcu6xmt4c7dgibnlv5jm4c2fre5nxv44sln3q
-hiddenchan.i2p,6y4tltjdgqwfdcz6tqwc7dxhhuradop2vejatisu64nwjzh5tuwa
-hiddengate.i2p,rvblcu54jvkkfffp3fobhunsvpgfc6546crcgzielzwe2s5m5hbq
-home.duck.i2p,jsh7yfvm2t5urdcnmfzdy4n6vegqskdtlwem53chgxli4ipfmuma
-hopekiller.i2p,kcaelbgsvrkiwpx36b4wxofebrl3njx7rgm5amzfmqwbomt44cxa
-hotline.i2p,6cczi27iuxkm3aivazaemzltdqgh42ljzurqp43uclbz2lid2uqq
-hq.postman.i2p,27ivgyi2xhbwjyqmnx3ufjvc2slg6mv7767hxct74cfwzksjemaq
-http.entropy.i2p,ytu7kz5bdoc26nkpw2hajwt3q7n5rcbg2eokyefhmkxmmslimbdq
-human.i2p,nrtcelq3humyfvoxmzmngpka6tmyifweouku5mbi5av4lc43hzaa
-i2host.i2p,awdf3nnmxxup5q2i6dobhozgcbir7fxpccejwruqcde2ptld443q
-i2jump.i2p,633kqgmwzzu6vhkevwvbf2pfyejt3gkes34i6upa4og57fgdfcxa
-i2p-bt.postman.i2p,jeudwnx7mekjcowpqo6xpkwn7263c57y5piurrjrdzinjziu4fla
-i2p-epub-eepsite.i2p,yxvzjwd4vin6pnjauekdufh7lxaijal3kqe2bhakuf47g5zkb6xa
-i2p-javadocs.i2p,icgmr6hhjudl4yxhtuq4pxvss2pzypwddzowajgs5rdz6f55novq
-i2p-projekt.i2p,udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna
-i2pbote.i2p,tjgidoycrw6s3guetge3kvrvynppqjmvqsosmtbmgqasa6vmsf6a
-i2pbuggenie.i2p,bioq5jbcnfopqwvk7qssaxcl7avzeta6mu72jmxjeowflpcrhf6q
-i2pchan.i2p,tduxyvfs7fzi26znvph3mu2d2ewaess7emomfci22wvownajphuq
-i2pd.i2p,4bpcp4fmvyr46vb4kqjvtxlst6puz4r3dld24umooiy5mesxzspa
-i2pdocs.str4d.i2p,yfvbtrhjac3jutdsqzugog6mbz3jtyhpwovrt2mqc5mzv534y7cq
-i2peek-a-boo.i2p,qgv64klyy4tgk4ranaznet5sjgi7ccsrawtjx3j5tvekvvfl67aa
-i2pforum.i2p,tmipbl5d7ctnz3cib4yd2yivlrssrtpmuuzyqdpqkelzmnqllhda
-i2pjump.i2p,2mwcgdjvfvd3xwumzqzqntual3l57h3zo7lwdmkjboeraudpkyka
-i2plugins.i2p,bb63kmnmbpitsdu45ez54kmogvvljn3yudksurcxiyq7dn5abt7a
-i2pmetrics.i2p,v65p4czypwxrn35zlrfkar2w77vr42acd7gbszegsrqq4u7sip5a
-i2pnews.i2p,tc73n4kivdroccekirco7rhgxdg5f3cjvbaapabupeyzrqwv5guq
-i2podisy.i2p,3c2jzypzjpxuq2ncr3wn3swn5d4isxlulqgccb6oq5f6zylcrvcq
-i2push.i2p,mabdiml4busx53hjh4el5wlyn4go5mgji2dxsfyelagi4v5mzjxq
-i2pwiki.i2p,nrbnshsndzb6homcipymkkngngw4s6twediqottzqdfyvrvjw3pq
-iamevil.i2p,au7jhslyt4cxkjp365bvqvend3hhykrrhbohtjqlgoqrlijbezja
-icu812.i2p,bxgqwfsnr3bgnr6adn62anjcin5nuthqglotb3wn3dgynsfofeva
-id3nt.i2p,ufuqdzsxltiz224vq5gnuslt3a3t72dhy5kq6i2xway53m6pzv6q
-identiguy.i2p,3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva
-ilcosmista.i2p,6u2rfuq3cyeb7ytjzjxgbfa73ipzpzen5wx3tihyast2f2oeo24q
-ilita.i2p,isxls447iuumsb35pq5r3di6xrxr2igugvshqwhi5hj5gvhwvqba
-illuminati.i2p,syi6jakreatlm2z22u76izyqvbm4yi4yj7hr7jb63lgru5yhwwla
-imhotep.i2p,qegmmhy52bdes2wqot4kfyqyg7xnxm5jzbafdb42rfoafadj2q7a
-in.i2p,r5vbv2akbp6txy5amkftia757klgdy44s6cglqhmstpg65xycyjq
-infosecurity.i2p,v3gkh5kqzawn2l3uzhw6xnszsh6w3nztjmlwil7p4kyrwrsm2dba
-infoserver.i2p,jd3agbakybnhfvkeoxrx7t33iln6suzomv3kxkxf77j7rkonch6q
-inproxy.tino.i2p,ex5yf6eqqmjkrzxnkn6cgvefgne24qxsskqnpmarmajoit43pgma
-inr.i2p,joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq
-instantexchange.i2p,5wiyndm44bysev22kxvczxt37p6o6qroiqykytrvn2yzi55aqfxq
-investigaciones.i2p,n7hqd4asxrdwf3zwo7rzv27y2qkcfmakmz6mjar6aw6hlc4c7mha
-invisible-internet.i2p,jnpykdpp46zenz4p64eb3opadl5g42dls3rurk2cvq6a3g3rvbvq
-io.i2p,tx22i6crnorzuti3x6va4mijsbhoqswy2cfdxjbvprgsq4eerg7q
-irc.00.i2p,bvcja52pppgfspp2ueuipoysjnvvoyblz2h6smpxcmanjquogirq
-irc.arcturus.i2p,5nywlbn35p2nwsymwpfmicu6fxono6g64vwusxbsvmm2qwz6vupq
-irc.baffled.i2p,5zmtoopscym6qagkvpgyn7jnkp6dwnfai745xevkxlou77c2fsjq
-irc.carambar.i2p,hxzbpivxqxy6nuae4t6fnkhcgnhs4c72vt6mmsqfmfhrkn2ca6gq
-irc.cerapadus.i2p,e4ckznxcxvgyikzjmjsu72i2dbj2d76ogexyukklbjvpcnhp6zzq
-irc.dg.i2p,fvp3pkcw4uvijqabwtekcdilklp73gyasuek67wdcs2mucep4caq
-irc.duck.i2p,chdpmm4gxffyn24xx5dhxvfd5httu42i5gtoe6cctjlsf4mbofeq
-irc.echelon.i2p,ez2czsvej5p3z5bquue5q3thujcodfze7ptybctqhnqc7hms5uzq
-irc.freshcoffee.i2p,ubiu2ehtfnrleemgpzsqkahwnvzuaifqa3u4wmaz5maaisd5ycfa
-irc.i2p,l3ohmm4ccxvyuxuajeaddiptci5lsrnxtvtyq7iohphrt3oj2evq
-irc.ilita.i2p,5xeoyfvtddmo5k3kxzv7b3d5risil6333ntqrr3yvx3yubz5tk3a
-irc.ircbnc.i2p,4rqcsqd7xif6r4v55blqvmqu5er6due4eyene3mjorfkts4o3rxa
-irc.killyourtv.i2p,wre4majmg2vnbi6id27et7yw6lnpf56wkbm6ftnlwpvxnktq73hq
-irc.nickster.i2p,dhq3fhd5scw3jqhj5ge7kqfpprfolcgxfjbaw24obohaiqjtdu7a
-irc.orz.i2p,7gifacog4aoons3syybojbbnyqqaaqijhngrehn2xlq3eucuyjcq
-irc.postman.i2p,mpvr7qmek2yz2ekegp5rur573z7e77vp3xqt2lfbco5i6nkfppcq
-irc.r4sas.i2p,hodhusp73gltozgrnianlbploon3rrvhrzfn5mf2g46o7aaau5la
-ircssl.cerapadus.i2p,4x2i745i4w52ss3he2kse6tzwt64pr62yvrcb72lgvrb63fup6ea
-irongeeks.i2p,ecduxoion5uc5hnvzjxff6iiwhdwph6gse3dknyvlo7e6gaeho7a
-iscofsi.i2p,enjgdxs4um2dmhdb2ajff2egrdijkjji3g47m6unb74swbrqsddq
-isotoxin.i2p,wue3ycaccf4texikza3fh6p5yrmtgnooisuypnepo5mo67lmpcqq
-itemname.i2p,o35ut7hgywy35okvgkjkv3ufzv2ejv4luap4oytwbyy2jqy6u4vq
-ivorytower.i2p,fpwrfvidfexsz7dspofkwtkmmizm7lyralfz5kvykffk7gubvxsq
-j.i2p,kjxvohlsf5sdrzxzfcrmvquccnoevi6ytbl63mstsru5wt2dx3ea
-jabber-2.i2p,pvnmzgemetkwcuvt45omgowmeznwk5xw3nc3ygeoz7yekqxy57na
-jabber.duck.i2p,rhdzvvzraqzzm67zpyegb7knpfrjeffitixqzeyymdoz56uh2rtq
-jake.i2p,v2axvy6pqefnla7gun5fmqs4lqe4xfyqovgzcundhxrpcdvfd7cq
-jar.i2p,2fthkmujup3xiiu3yple24n6g4emzdiiimbuqwvpdddtsr3c4nrq
-jazzy.i2p,ha5c3zafwkt6mwqwjcf4oqwvbwz473652ljjadiwrj4gfkfkjofa
-jdot.i2p,kw4jr5qw4bhnj33avkwankjdh3zi7wtahlmgkjwvsv2isskkzgpq
-jhor.i2p,c6rnm7oemydhuwzmhwwwxphkzanez5rnn7fkcs3lpgu6gkgtssoa
-jikx.i2p,aazr55itvyns4lwppvx5njyx5tjdwemw4w6jbmpegdunznod2ieq
-jisko.i2p,jxgfvr663uhr6m65hrgkscshysfshkq32ywdubc4ed7zda3e2pca
-jmg.i2p,oglpnq7zungdukmk6gk5fzj5jp6wibuoihqgks453wztrwos4ggq
-jnymo.i2p,nbfplxgykyfutyadlfko2rmizdsxox2pee2ahboj5mju4s3putda
-jrandom.dev.i2p,htynimemonyzqmn76gworxyfkmqtsa7zcprbrd3i5cxqqm75tuzq
-jrandom.i2p,dqows7dpftxxl2bd4bgcpkck6knrysdun6mtqy4ms5dxobbvg3ja
-jrrecology.i2p,qxi24gpbum3w3kesuxvheyu3p5u5o6tuvoypaolub2gnvbld57xq
-jwebcache.i2p,xdffxnxtjd6ji2zig3cgva7igvl2tiapyjoc7ylbzwqhxudbmvfa
-k1773r.i2p,zam7u6vslhemddz347uusuzjdk5wma4h5hcmcqlng4ybbpdbjhnq
-kaji.i2p,z5ic7gvm2k4doczphtrnrspl2w5sfbss2de4z3ihjijhtjw67ydq
-kaji2.i2p,4lscgc6napekfx7ay5fdcjofeja4fnl7tqcd3fek63t4saavur2a
-keys.echelon.i2p,mwfpkdmjur5ytq4og36ym3ychinv36b2a57f4rmgqmtrwepq3fva
-keys.i2p,6qv4x7ltaxckd4vbay5s4ntqqflq4efk6oke2d5yzicqrmk443ba
-keyserver.sigterm.i2p,isoxvnflrdn7cm76yjlfg5tbcugoito2hur7eidbqmo33xmwz5ga
-killyourtv.i2p,aululz24ugumppq56jsaw3d7mkbmcgo7dl2lgeanvpniyk2cbrda
-knijka.i2p,knjkodsakcxihwk5w5new76hibywia5zqcgoqgjttzsausnd22oa
-knotwork.i2p,2yocdbcjiyfaqgxb4l6oenrrrrie6nydgmbnbfulqg7cik6bozxq
-kohaar.i2p,qchpjehbhqjbxdo7w3m55jbkrtsneb7oqoxcr24qttiq6j5g3z5q
-krabs.i2p,3yamyk5bgfgovg6zpvtvpdjk37ivjj2wog2w7wha5agzgxxkqaca
-kuroneko.i2p,wbit2huhhwlyqp2j4undccuyrodh6qcmzdeyuaoy5o4ym7g5gdgq
-kycklingar.i2p,gctswdhp4447yibxfbqg3uq2bvx63qjeqnaoaux75zw73leakyva
-lazyguy.i2p,ia6xlsnygorllplx2owokahtrkospukvsmysz7i7bzw3vejc4hdq
-legion.i2p,5oirascyhwfy2tr2horw6mixozsre7z6s7jfq7qbnj523q3bkebq
-legwork.i2p,cuss2sgthm5wfipnnztrjdvtaczb22hnmr2ohnaqqqz3jf6ubf3a
-lenta.i2p,nevfjzoo3eeef3lbj2nqsuwj5qh3veiztiw6gzeu2eokcowns3ra
-libertor.i2p,7gajvk4dnnob6wlkoo2zcws7nor3gunvoi7ofalcps5lc76wruuq
-library.i2p,brqqaq44vbeagesj5o3sxcnkc5yivkwouafyxa77ciu7l644ei2a
-lifebox.i2p,pyqjnycm55cuxow22voqj62qysrjdnb6nbyladaiaiirqi7vp2yq
-linuxagent.i2p,ap5riaikrjq2uv5qvy7klzhhqywvqi7wqscyipsewcun7w2eynlq
-lists.i2p2.i2p,vmfwbic2brek2ez223j6fc6bl5mmouzqvbsch45msvyyzih3iqua
-lm.i2p,yeyar743vuwmm6fpgf3x6bzmj7fxb5uxhuoxx4ea76wqssdi4f3q
-lodikon.i2p,u3f67staiwhqxpacya3clmvurdwd2kp7qcthzhstqnhrmlwc2g4a
-lolicatgirls.i2p,a4lzmjyba7aq7hl6okqpds7znnwymolqnr7xhvno2wraqb7uhfla
-lolifox.i2p,7fd2clkiotjnaoeigdtxlkkb24eik675ovezjf67x26ysham4zca
-longhorn.i2p,pohcihzxzttjclrazhs3p76wt3ih737egb5bovqb6ym3du6z3o7a
-lp.i2p,jiklbujn3cbfikf4pca526jgmorx6mxhil3twqmfoteaplx6ddwq
-lucky.i2p,wx36m3wnpt2y6bngdpg3ifrarvtkpwnluarx377bllpgvkuhybaa
-luckypunk.i2p,y4t6cujjxnnrtln3rgmfbgbh46hic7wkef57krd7opitbgngohka
-lunokhod.i2p,3yc6sp7xic4grmpfecbwuij6z3dp5kdgoo362pszaco7io42mnwa
-m16.i2p,ucsr3eveuc4mx5y6gxnoaywd4ojvbel5q3ynns6s5yfw3vusmfva
-mac7.i2p,3yjowssqzydciwa5zx55kazgf7q7w6g7rkocr7bngy35ii44t34q
-madman2003.i2p,a2sam2xbhxbzmeyobphbxrkdwlppoerewq5qvibbyk3ftsr643qq
-magix.i2p,cgfnyxv62msfynsfbv3kju22j2mt6tfnopshhmrcmpcrxyts6xwq
-magnets.i2p,snz46nez6hrrpg6336neinflw56l3vwatk6bzzytwu77xmsfsoca
-manas.i2p,6qolj62ikkoq6wdn3hbvcbdmlvf2rcyv432kgi5uy7mvrczmjtba
-manveru.i2p,pbmbofs76wpjnxi55eqtwg4y6ltyij72o4fm4sxfjol3y57ze5sq
-marcos.i2p,vpo36bsil2voqaou53zshuegssqaroa5mbrzxfmhjywlbojckalq
-marshmallow.i2p,svdqd6j3y3gwryufcl4fkzpmcujgvrvphvk2oy4r7m75xs327e2q
-marxists.i2p,lepah55qyp2fhuwxlz7bwrhzckn4gkuofivnofoeuyfpmke5x2hq
-mattermost.i2p,x5oovnhnuli5fnwtgkbd5z5jvrvdvprqyuofywx6uoxkk4bie6ya
-me.i2p,dbpegthe42sx2yendpesxgispuohjixm4bds7ts5gjxzni5nu6na
-meeh.i2p,4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa
-mesh.firerabbit.i2p,3x5wokr4bjy5z3ynji4fyhvwzv4fvgry3xafi5df5h75doezjytq
-messageinabottle.i2p,avfhe3kvrrv7utxn2vre65lg7damxzzsewq3vukwie4llitd254a
-metrics.i2p,z45ieamhex2ihqv7oowk5fz4qq47rbvxhhhbaaiinpajbhuevtpq
-mhatta.i2p,o4rsxdeepfrnncsnjq675xogp5v5qkbfgbt6ooqeyfvlifobrjxq
-microbleu.i2p,mtapervgibruizniems2yyr47pin2wpysyh7m632rigl26vjc6qa
-microsoft.i2p,hvaqr5idszdyrjph34amb4mjosqd3ynggoxlnj7ciqhnx7q6plza
-mindisl0st.i2p,u7rnqhvsuyxd3fabm4kyzn7brgz3i3cporj2emk2jmbpcmltyf7a
-mindspore.i2p,uuh5dd3y2rqa7x2jpggm4p2pg6znarm5uanwsvybe4tk36ymwr4q
-modulus.i2p,ctz3o6hdefrzwt3hlg6rjhdcbjk6irppbndq32u6jnn4lz72f62a
-monerotools.i2p,5bal7dngxde2ddmhuzbtfken6w5nmxmixtjlrlmxt3wbhnemv73q
-monerujo.i2p,puri6y5dtwh6zr4u77ep6ozatun6iz7v4wai2dzxppz7654corlq
-morph.i2p,iovyp2dao5rta6g5v6hke2s4ugx2btkpcljddak2yhxfrx3l4dqa
-mosbot.i2p,5bhmrp43mjwlzf4x64xgdrkwmw4luvng6eq5waa663a7vnkp732a
-mosfet.i2p,s5ynkgagndmpxpf2kmnenv4x72io664gzd2x3qef54ilammnte3q
-moxonom.i2p,gcjdrvnlobgexh7ebv276pwmnoj3yoyaqm3w4vmmdha4lgxfinqq
-mp3.aum.i2p,n7bmu5dwux7f6gedmdik6zrm77bnls4lkzo2vo3bf4bwegk7vkjq
-mp3.tc.i2p,w3ied5s7ldjcvnhxu2gyofe3oogzbplkyxshzfkhspiy2526snsa
-mpaa.i2p,m6cqnglo7xlytwxkdsmwf3d23d6lq5r446c3tktb2tdmuah36zya
-mrbamboo.i2p,tmpmkx6wlbbrgsnexrqlrib7laoegpbfeop7bnyezegii7hecpxa
-mrflibble.i2p,u7k2qcmkrril6yvudvwxjqz7k3dzgp3jdejjjeapej7liselj3eq
-mrplod.i2p,fjn5hxtybxyfyvdf6u5v5seg2sjd47hb5by6sa6ais4w3xnrxwyq
-mtn.i2p,xisk3h6sku3iqj52uriogaajmnku7pwjux7wa4omx2zloamuw6eq
-mtn.i2p-projekt.i2p,f52x5fp6uhq53f5zle5d6rq5un34xgmxgazvilvmzcby37xcmsfa
-mtn.i2p2.i2p,l6kuhtmgvbp57d7jwalj5nksi6nr4gfzbz4oit62lxgipb3llt5a
-mtn.meeh.i2p,h7ylrsuzzynrxp3jql7anoozyqblavj7eqces6o3wngvuuxhs2la
-mudgaard.i2p,yz32lk42gtoesknesfolq3tt4erxxcejcote5pontaeqev3bj2kq
-mush.zeit.i2p,dk3sg23kljawxqp3cb6xz5mnzjlyckzvq5jhqs5gnvdsv7wqn6ha
-music.i2p,akamh76yi6p7xxbvl3qv3yhaockne57yfuh77acogbgpjmwypvia
-mysterious.i2p,p66g2a4nzfkvidd3l7nwphcnfa3ttyu5kiolcb4czec2rn2kvwsq
-mywastedlife.i2p,ceumy3puvvsrru5bmfmtgsajsx5qyehqac7l7a23xpwtfs2bvcgq
-nacl.i2p,bm2fib3tumer72lopjh4nmqomwvqu2sdfyb2hmr6lnk7jbw3vvia
-nano.i2p,ex5ssv7s3hj6jp7hvadxfw3wvbjbvnczxr4pbk7qw26ihiorjmba
-nassai.i2p,v653cocvn3i6bgjdm3ciwbdnu32supglv6gn4fh23bohemsp545q
-neodome.i2p,5hkhjehj3ct2pvcah7dcylwef2oti3xij5myxbv3pd7rocio5vkq
-news-i2pn.i2p,wwcqkwfo5yhe6uribv5tzylk25j5hkdk6gdnyftzd3k7dawlzwca
-news.neodome.i2p,trhwcnygfkeqjj6g4xhmrdp4gsjqsye47lsxshbmwbten4ywt5oq
-news.underscore.i2p,rl7t3kspoktuatjcu7gf7xleu7y6biibs4fspzo24kll6n7hbq4q
-newsbyte.i2p,gsk3rgsejxxrfabjxu5w5plplxsu47aoeoke22vvhlwwllzosnxq
-nibble.i2p,jmdxcpdzqafedn3clc4y7u6o56qocfiffrzbzncmtggqtio5qjpa
-nic.i2p,vzu5ymab6klevpcdudv4ypisjqaznmt44e6lcg7dwiuza4saibxq
-nickster.i2p,zkwsa6kvq2wdhovw5g5wqakpb7rlaylyhfriwmurots5pvwbqauq
-nickster2.i2p,eofzi7npzpk4p5gb4qper4hmwgxo6kepo3dheeblakewedxj2bwq
-nickyb.i2p,gmpxk4tje7mnud32kg2kjmf36f6cpwqakzc2dxuzjnnz4qr5w4sa
-nightblade.i2p,p4gkon7ytswxrbwkl7vruw6mg7kfw5aofovqjgt4c7tnqmbq6lha
-ninja.i2p,q6dg6hlb3egzdqz352ri5rc4fx4gcrdeu3tpiyfxlv73yfjgrhya
-nm.i2p,3itdpqzyn3ii7sivppo4sxxwhvgtpskzkbokrdibim6gqpvlw5ya
-nntp.baffled.i2p,kc6muo2tih5mttbpzecteegvtonuysjidk3emcy4cm4yifzild2a
-nntp.duck.i2p,gvzzor4utsqxswvf6jaglfks7yxudlz2s326ftrk56i4lpd2s47q
-nntp.fr.i2p,npoztnqadfnu4vrokoh6rusoi3yne47s6jurc3lzhcrzzia5eqva
-nntp.i2p,wwdzmeyler4djegvyt2bxmkwrckfgg3epkkwowyb75s47he6df6q
-no.i2p,lpsg4x4gdrf7antxcdy47cl6abcqei5ommgzt55retq7go5ku3ba
-noname56.i2p,oiyoslismzyxuw7ehxoigmtkdj35idim6flmlplddxuiiif6msfa
-nop.i2p,ssag45lathm4gqp46si7c4w4tioyvjpcza5uvz5x2zuljnplylca
-normal.i2p,j5fex634r2altzb3kjvu35qekt2r3hgsqzg5qxoy7dp53heu5pma
-normanabcd.i2p,si2vh43gvxjnw2shwr24j76xyanow4oa6gbu4idookbraoxl3s3a
-nothingburger.i2p,tesfpn757ysc7nih7mxher2b3jstkc3l5fhfcyb5kxhzhvv52trq
-nothingspecial.i2p,wzrwqrp52bilqijrlboclynuev4kzpjzfzlvzl5aqxqt5fdnpbga
-novospice.i2p,ukqap24nwac4gns77s4zy7j5cagt7l7syb5zo7eukfg3zn5gg5qq
-nsa.i2p,nsetvbclpomqxfcit4mghn6z7vdhnza6jdzczby4crnto32uykga
-nvspc.i2p,anlncoi2fzbsadbujidqmtji7hshfw3nrkqvbgdleepbxx3d5xra
-nxt-wallet.i2p,33pp74k4ivy67z332qpyl3qlcqmi6gxqumrow4bldkblxxlxqq5a
-obmen.i2p,vodkv54jaetjw7q2t2iethc4cbi4gjdrmw2ovfmr43mcybt7ekxa
-obscuratus.i2p,i4j37hcmfssokfb6w3npup77v6v4awdxzxa65ranu34urjs4cota
-ogg.aum.i2p,wchgsx6d6p3czloeqvna2db5jr7odw4v4kqrn4gr4qiipfyrbh5q
-ogg.baffled.i2p,tfbvj2xal6lcuxv3hzuw7cw4g3whguombcv2zuotzvul4qtrimgq
-ol.i2p,bnb46culzbssz6aipcjkuytanflz6dtndyhmlaxn3pfiv6zqrohq
-onboard.i2p,qwlgxrmv62mhdu6bgkh4ufnxowxsatfb6tbs2zr666qyunwqnecq
-onelon.i2p,irkvgdnlc6tidoqomre4qr7q4w4qcjfyvbovatgyolk6d4uvcyha
-onhere.i2p,vwjowg5exhxxsmt4uhjeumuecf5tvticndq2qilfnhzrdumcnuva
-oniichan.i2p,nnkikjorplul4dlytwfovkne66lwo7ln26xzuq33isvixw3wu3yq
-onionforum.i2p,yadam2bp6hccgy7uvcigf5cabknovj5hrplcqxnufcu4ey33pu5q
-ooo.i2p,iqp5wt326fyai5jajsa3vkkk5uk56ofn4anocgpe5iwlpisq6l7a
-opal.i2p,li5kue3hfaqhhvaoxiw2ollhhkw765myhwcijgock5rs4erdqdaa
-open4you.i2p,ice6ax5qrzwfwzsy64bctffj6zlzpuzdr5np65zsxlbt7hztyc6a
-opendiftracker.i2p,bikpeyxci4zuyy36eau5ycw665dplun4yxamn7vmsastejdqtfoq
-openforums.i2p,lho7cvuuzddql24utu7x6mzfsdmxqq7virxp5bcqsxzry2vmwj5q
-opentracker.dg2.i2p,w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa
-orion.i2p,5vntdqqckjex274sma3uqckwqep2czxs5zew25zlntwoofxk3sga
-orz.i2p,oxomqkekybmyk6befjlouesit5mhstonzvzd2xnvsk7i6uyrqsfq
-os3.i2p,s7x4ww5osrrfein3xgwyq67wnk6lgliw4mzt7shtu66wrb2zdojq
-osiristomb.i2p,t3slf77axkv3qm7c3gzpv3jgmkraoqqe2bojr6h66eipibofsyzq
-ot.knotwork.i2p,cxhvvfkbp2qbv5qojph7zb46molpe2ffanghnerjag3xdmy6ltxq
-outproxy-tor.meeh.i2p,77igjr2pbg73ox5ngqy5ohzvrnur3ezqcogtl4vpuqtrcl3irsqq
-outproxy.h2ik.i2p,nwgvfpfarpnyjjl4pwsxr2zdsppcx5we3kos2vlwicbiukopgaza
-outproxyng.h2ik.i2p,v32zse2zczzgegelwxbx7n5i2lm2xhh2avltg76h6fz5tb53sfxq
-overchan.oniichan.i2p,g7c54d4b7yva4ktpbaabqeu2yx6axalh4gevb44afpbwm23xuuya
-p4bl0.i2p,lkgdfm4w6e2kkjhcdzr4ahhz26s3aunhrn6t2or436o73qh4z7ga
-pants.i2p,xez3clscjfafkqwk6f473ccp3yvac4kh6rdp6dptwxa2lhixizgq
-papel.i2p,mxskjqntn2d34q4ovsnd5mud7cgde734tdjldd3lt4hczh2645zq
-pasta-nojs.i2p,dkkl3ab6iovxfqnp44wsjgqaabznvu7u3hugpzyagbeqlxgvx3la
-paste.crypthost.i2p,2zaj4u4s4l3lgas2h5p6c6pvzr2dckylkrh5ngabursj4oh25ozq
-paste.i2p2.i2p,b2gizskfea4sjxlw6ru2tb6kdrj47dsjc77cijsf5mzh4ogbmfvq
-paste.r4sas.i2p,csen43keji3qiw6uobsgzysxyjd225g6446ylq5uuz6ur2glkzaa
-pastebin.i2p,mnicncxrg2qqi55qftigiitaheugnj4rpysbk7zabdrirgktelqa
-pastethis.i2p,erkqiwnjl7vtysqd3wvddv6tfvnhswarqkbn4blhdlhfxn7cf2ha
-pdforge.i2p,wzeg3ehf6d2mqjqji3sd3rns776thvhe2vam2r6gjlmsqis2dctq
-perv.i2p,f3k3wm4ae7t7ottfjd4hu6is7zsls73izl2gm2qynzficxcdsiwq
-pgp.duck.i2p,wujajyxj3cgsfsbtr3g7g7npv5ft3de6pcstxlav26zq6cxdjmha
-pharos.i2p,vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
-pharoz.i2p,vathk2pyvaskeie63yyg4tshjkx5xt6zfvhwhgr3de67q46ob3sa
-phonebooth.i2p,noxia7rv6uvamoy2fkcgyj4ssjpdt4io6lzgx6jl6wujpufxedrq
-photo.i2p,fqhuy77ugd5htnubzkyy5guvwboqn6goahtmn2g7feewvdj7k3iq
-piespy.i2p,vzusfjzcu5ntnvobcvyzc4dcu4j6ommtnpmba2puk3kexgdzrl7a
-pisekot.i2p,7yzdwhy723fodqz4onp6k3nyvixra2sa6dl45tcblhmyoa7i36nq
-pizdabol.i2p,5vik2232yfwyltuwzq7ht2yocla46q76ioacin2bfofgy63hz6wa
-planet.i2p,y45f23mb2apgywmftrjmfg35oynzfwjed7rxs2mh76pbdeh4fatq
-plugins.i2p,wwgtflbaa7od2fxbw4u7q7uugmdclxf56alddvizugwcz5edjgia
-polecat.i2p,het5jrdn35nhkanxmom5mjyggyvmn2wdj2agyqlrv4mhzhtmavwq
-politguy.i2p,6dkkh3wnlwlr6k7wnlp4dbtf7pebjrph5afra2vqgfjnbihdglkq
-pomoyka.i2p,omt56v4jxa4hurbwk44vqbbcwn3eavuynyc24c25cy7grucjh24q
-pool.gostcoin.i2p,m4f4k3eeaj7otbc254ccj7d5hivguqgnohwelkibr4ddk43qhywa
-pop.mail.i2p,bup6pmac7adgzkb5r6eknk2juczkxigolkwqkbmenawkes5s5qfq
-pop.postman.i2p,ipkiowj7x4yjj7jc35yay3c6gauynkkl64gzzyxra3wmyhtfxlya
-pravtor.i2p,2sr27o5x2v2pyqro7wl5nl6krrsbizwrzsky5y7pkohwh24gn6xq
-pris.i2p,ahiwycgzuutdxvfqu3wseqffdnhy675nes57s4it2uysy5pxmz6a
-project-future.i2p,ivqynpfwxzl746gxf376lxqvgktql2lqshzwnwjk2twut6xq7xta
-projectmayhem2012-086.i2p,ehkjj4ptsagxlo27wpv4a5dk4zxqf4kg4p6fh35xrlz4y6mhe4eq
-protokol.i2p,f4xre35ehc5l6ianjvt3zcktxkjlyp2iwdje65qnu2j6vurhy6nq
-proxynet.i2p,7gar5a3n4hzvsgi73iizo65mjza4kujf7feopfxuwu5p6wtwog5a
-psi.i2p,avviiexdngd32ccoy4kuckvc3mkf53ycvzbz6vz75vzhv4tbpk5a
-psy.i2p,s3elzoj3wo6v6wqu5ehd56vevpz2vrhhjc5m6mxoazicrl43y62q
-psyco.i2p,eoilbrgyaiikxzdtmk2zeoalteupjrvcu3ui23p4wvfqo25bb73q
-pt.hiddenanswers.i2p,o5jlxbbnx3byzgmihqye3kysop5jgl3unsrkmurbtr2nrnl2y74a
-ptm.i2p,7dna5745ynxgogpjermnq26hwrqyjdlsibpjfmjxlwig247bjisa
-ptt.i2p,q7r32j7lc3xgrcw2ym33wv4lfgqbez7vtm4lts7n34qfe3iygeha
-pull.git.repo.i2p,3so7htzxzz6h46qvjm3fbd735zl3lrblerlj2xxybhobublcv67q
-push.git.repo.i2p,jef4g5vxnqybm4zpouum3lzbl6ti6456q57nbyj5kfyldkempm3a
-pycache.awup.i2p,w45lkxdnqhil4sgzanmxce62sv3q4szeowcjb2e72a5y5vbhm4ra
-r4sas.i2p,2gafixvoztrndawkmhfxamci5lgd3urwnilxqmlo6ittu552cndq
-radio.r4sas.i2p,cv72xsje5ihg6e24atitmhyk2cbml6eggi6b6fjfh2vgw62gdpla
-ragnarok.i2p,jpzw6kbuzz3ll2mfi3emcaan4gidyt7ysdhu62r5k5xawrva7kca
-ransack.i2p,mqamk4cfykdvhw5kjez2gnvse56gmnqxn7vkvvbuor4k4j2lbbnq
-rasputin-sucks.i2p,fdozdbyak4rul4jwpqfisbkcx4xbrkuvf2o5r6fd3xryyrjgvjiq
-rebel.i2p,nch2arl45crkyk6bklyk2hrdwjf5nztyxdtoshy6llhwqgxho5jq
-red.i2p,fzbdltgsg7jrpz7gmjfvhpcdnw5yrglwspnxqp4zoym3bglntzfa
-redpanda.i2p,3wcnp6afz4cikqzdu2ktb5wfz7hb3ejdbpn7ocpy7fmeqyzbaiea
-redzara.i2p,ty7bt62rw5ryvk44dd3v5sua6c7wnbpxxqb6v4dohajmwmezi7va
-reefer.i2p,4cde25mrrnt5n4nvp5tl62gej33nekfvq2viubmx4xdakhm5pfaa
-relatelist.i2p,utrer5zgnou72hs4eztmk37pmzdtfw3d6s23wwl7nk3lkqpzbdiq
-repo.i2p,uxe3lqueuuyklel23sf5h25zwgqgjwsofrqchhnptd5y6pedzbxa
-repo.r4sas.i2p,ymzx5zgt6qzdg6nhxnecdgbqjd34ery6mpqolnbyo5kcwxadnodq
-reseed.i2p,j7xszhsjy7orrnbdys7yykrssv5imkn4eid7n5ikcnxuhpaaw6cq
-retrobbs-nntp.i2p,fkyzl24oxcxvjzkx74t3533x7qjketzmvzk6bwn3d6hj5t7hlw6q
-retrobbs.i2p,mnn77stihntxdoade3ca2vcf456w6vhhvdsfepdvq5qggikvprxq
-retrobbs2.i2p,ejff7jtyaus37slkwgeqrrcmyhpj26carp7n27f5h6s5vlbeiy6q
-revo-ua.i2p,hpojpumki22xjwhmhe6zkiy44oanyn7u4ctcfe3in2ibwm5l32hq
-riaa.i2p,lfbezn7amkzhswnx7lb4lxihyggl2kuqo5c7vwkcv6bwqmr4cuoa
-rideronthestorm.i2p,xrdc2qc7quhumhglpbcuiqxr42nuffv4xj4a73jbr4ygepitibqq
-romster.i2p,eaf2stdqdbepylt53egvixdi34g2usvgi7a4oixsja6atkran43a
-rootd.i2p,mzbe5wofwn7eaqq4yefrmxizqaxoslwqxrv5qcv2opx5lnhg64dq
-rospravosudie.i2p,z55khrnlj6bzhs5zielutm6ae6t2bbhfuiujwlrp3teubqyc4w7q
-rotten.i2p,j4bm3rvezlejnb44elniagi5v2gazh7jaqrzhbod2pbxmgeb2frq
-rpi.i2p,56p5qxsrvo5ereibevetw2qbj5bronmos7wxunku27g2s4kpbnlq
-rslight.i2p,bitag46q3465nylvzuikfwjcj7ewi4gjkjtvuxhn73f6vsxffyiq
-rsync.thetower.i2p,w4brpcdod7wnfqhwqrxyt4sbf2acouqfk5wyosfpq4mxq4s35kqa
-ru.hiddenanswers.i2p,o6rmndvggfwnuvxwyq54y667fmmurgveerlzufyrhub6w3vkagva
-ru.i2p,m7fqktjgtmsb3x7bvfrdx4tf7htnhytnz5qi2ujjcnph33u3hnja
-rufurus.i2p,7msryymfdta3ssyz34qur6gi4jyfkvca5iyfmnceviipwu7g2wca
-rus.i2p,gh6655arkncnbrzq5tmq4xpn36734d4tdza6flbw5xppye2dt6ga
-ruslibgen.i2p,kk566cv37hivbjafiij5ryoui2ebxnm7b25gb3troniixopaj6nq
-rutor.i2p,tro5tvvtd2qg34naxhvqp4236it36jjaipbda5vnjmggp55navdq
-salt.i2p,6aflphlze6btsbez5cm4x53ydrmwhqrkxsud535d3qjh4wq62rxq
-sasquotch.i2p,p6535uyfk2y6etc3t47vd3oqxydznqior5jxcvq5bdxe5kw5th6q
-schwarzwald.i2p,4gokilzy73mmudufy3pohgatm42fcstx7uzg5hjvnfyphxpnphuq
-sciencebooks.i2p,ypftjpgck75swz3bnsu4nw7rmrlr2vqsn4mwivwt3zcc3rxln5cq
-scp.duck.i2p,ghbpsolpnveizxu4wbs7jbs2vj3kntnsexfcdleyhpqdhfpxleda
-search.i2p,nz4qj6xaw5fda3rsmsax6yjthqy4c7uak2j3dzcehtkgyso4q46q
-secretchat.i2p,cl3j2zxhpw6u6jevny45i557ojhwfxn4g375nnuqhy6lp27mry2q
-secure.thetinhat.i2p,4q3qyzgz3ub5npbmt3vqqege5lg4zy62rhbgage4lpvnujwfpala
-seeker.i2p,ipll7sit24oyhnwawpvokz5u7dabq6klveuqpx3sbi6o5qemy2bq
-seomon.i2p,5mvpsy4h45w4fx7upen7ay3vkrs5klphz5nptmtcqvc3fsajsm4q
-septu.i2p,5lqvih7yzbqacfi63hwnmih57dxopu5g2o5o4e2aorq7bt4ooyra
-serien.i2p,3z5k3anbbk32thinvwcy4g5al7dmb75fagcm3zgh4rzrt3maphda
-ses.i2p,5qfoz6qfgbo7z5sdi26naxstpi2xiltamkcdbhmj6y6q2bo4inja
-shiftfox.i2p,wpvnuzslu7hjy4gujvnphtyckchdoxccrlhbyomsmjizykczyseq
-shoieq3.i2p,3fjk4nfk3mccch4hdreghnyijcvovsi3yucjz3qzj5sxngqk5j6q
-shoronil.i2p,7shqzgmb6tabiwrnwlasruq7pswy2d3emvfhaitehkqgod7i62sa
-short.i2p,z5mt5rvnanlex6r3x3jnjhzzfqpv36r4ylesynigytegjmebauba
-sion.i2p,lcbmmw2tvplvqh2dq5lmpxl3vnd5o4j3bdul5moa23deakjrso5q
-sirup.i2p,aohdp4yajnkitrtw7v2mo3sp7swuqhjfwlsi5xwd7dudzftumsma
-site.games.i2p,zeuczucfxeev3k7tvqlfcdpfbnqggheiknyyb5r2q4utn3d2auja
-skank.i2p,qiii4iqrj3fwv4ucaji2oykcvsob75jviycv3ghw7dhzxg2kq53q
-slack.i2p,gfcsh2yrb2tx7hyvmobriv52skz7qoobn7n7y7n6xaehhh4rpbja
-slacker.i2p,wq7m2wdguzweleb666ygv3bmfhha63zj74rub76vfesbyhsyk6iq
-smeghead.i2p,ojf4czveeuekxqkjvkszvv7eiop5dg7x2p6rgfzl4ng4xrjk6lja
-smtp.mail.i2p,kdn7zx7fgoe4bn5abaaj5cb3e4ql22fklb5veui5yajpj4cxapya
-smtp.postman.i2p,jj7pt6chsziz6oxxnzpqj7mzhxm2xfhcrbh7dl3tegifb577vx5q
-socks1.tor.i2p,sifawcdexgdmoc3krv46pvvz74nzd6fkju2vzykjxsx3egqsb6wq
-sonax.i2p,jmuxdhlok5ggojehesfjlit2e2q3fhzwwfxjndts7vzdshucbjjq
-sponge.i2p,o5hu7phy7udffuhts6w5wn5mw3sepwe3hyvw6kthti33wa2xn5tq
-squid.i2p,r4ll5zkbokgxlttqc2lrojvvey5yar4xr5prnndvnmggnqzjaeoq
-squid2.i2p,hum4wlwizbsckbudcklflei66qxhpxsdkyo4l2rn256smmjleila
-sqz.i2p,3jvbwc7sy4lnhj25nj7yepx7omli4ulqirnawv3mz6qlhgokjgzq
-ssh.i2p,xpvdadaouc4qr75pteymyozc7mcsynjfkuqqkkla542lpcsqionq
-stasher.i2p,6ilgpudnba4kroleunc2weh5txgoxys5yucij5gla6pjyki4oewa
-stats.i2p,7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq
-status.str4d.i2p,ycyyjo3psqbo45nuz243xvgvwnmzlanzqbzxv3kh6gyjztv7425q
-sto-man.i2p,rg4eilfpe24ws6nctix63qw2dlvd2tqgwdcgdxzji6l5bc4dc7aa
-str4d.i2p,wrrwzdgsppwl2g2bdohhajz3dh45ui6u3y7yuop5ivvfzxtwnipa
-stream.i2p,prmbv3xm63ksoetnhbzqg4nzu2lhqdnqytgsydb7u3quxfrg7rna
-streams.darkrealm.i2p,ud3gcmvysjch4lbjr2khmhqpf7r2x5if4q43xkqdptl4k7lc4muq
-striker.i2p,4gswsrfpbd44hwjoj33jbqfbwzxfkwpuplb3ydq5zm7nfu2pxvdq
-subrosa.i2p,g3lnglrnoual7wyabnwwv37uwhadgbxiqz36pf3f5cwfuxsx4mxq
-subterra.i2p,vdmhe4u26unzgd7ysq6w36ubjncms5wzbhzr2gq576sq4xut5zwq
-sugadude.i2p,yzjn76iyqard64wgggfrnywkxi7tbfkw7mjhpviqz3p2dguey4yq
-suicidal.i2p,yfamynllow5xiqbbca7eh5xn733wtnuti5bi4ovc7dwycntqmiuq
-sungo.i2p,h67s3jw56rwfyoxqxj3fngrluybsgxc2meendngkehzqowxnpj3q
-surrender.adab.i2p,jgz7xglgfgnjfklrytyn427np2ubipztlm5bxrtbiucayglukrta
-susi.i2p,qc6g2qfi2ccw7vjwpst6rwuofgzbeoewsb2usv7rubutf4gzqveq
-syncline.i2p,5kcqmhislu3lmr7llgmdl72yu3efhyriljdc6wp774ftpwlcs5ra
-syndie-project.i2p,xa63tpfoaqt3zru2ehxjjfbpadwj4ha6qsdvtcqtyr3b7hmt4iaq
-syndie.echelon.i2p,vwrl2qmcif722fdkn3ldxcgz76df5cq4qypbndzthxwgmykyewta
-syndie.i2p,7lm3yzpuejhpl4tt4l7o4ndqlu7hgijohofh7oaydx7q7kelenbq
-syndiemedia.i2p,4lrbbblclodhobn3jadt5bf2yab2pxzoz4ey4a2cvrl44tdv3jma
-tabak.i2p,y5o2vwb6kart7ivpnbpk4yte3i7kf2dsx7fy3i6w7htqtxhmbzia
-tahoeserve.i2p,yhs7tsjeznxdenmdho5gjmk755wtredfzipb5t272oi5otipfkoa
-tc.i2p,qkv2yk6rof3rh7n3eelg5niujae6cmdzcpqbv3wsttedxtqqqj7a
-telegram.i2p,i6jow7hymogz2s42xq62gqgej2zdm4xtnmpc6vjcwktdxpdoupja
-templar.i2p,zxeralsujowfpyi2ynyjooxy222pzz4apc2qcwrfx5ikhf64et7q
-terror.i2p,wsijm6aqz4qtuyn2jedpx6imar5uq4yuhjdgtfqumxbqww47vbnq
-thebland.i2p,oiviukgwapzxsrwxsoucpqa47s3wt6nfuhfjxvgbqsyrze2mwrda
-thebreton.i2p,woutbsflcrlgppx4y7ag2kawlqijyenvlwrhbbvbkoaksuhf2hkq
-thedarkside.i2p,fxt3z33nzkrg5kjrk7bp5vvmu7w2vsn4i6jo6cily3hsm6u664ca
-theland.i2p,26ppxbseda6xmim37ksarccdb4q5ctdagfmt2u5aba6xjh452zsa
-thetower.i2p,3xqa5nype64y6fxgqjq6r5w2qpiqftoraj2niebumseat4cj654a
-thornworld.i2p,vinz4ygmodxarocntyjlfwk2wjpvzndlf4hxss2w2t3fk52oplva
-tino.i2p,e4bfnhvaofu4s67ztcgiskos2mqyhskid64dvlqexxs2c2bno3iq
-tinyurl.i2p,mc4oxv3v7dnyzpvok7v5qxkwtgjprgyz6w7x3tag4fipsen6rdwa
-tome.i2p,qktkxwawgixrm5lzofnj5n24zspbnzxy4pvjm7uvaxvmgwrsuvgq
-tor-gw.meeh.i2p,ounrqi7cfemnt66yhnhigt2u27fkctbvct527cp2522ozy3btjza
-tor-www-proxy.i2p,xov45rvjks5fe4ofmpblkj23bnwxgslbypbgvchbr7yul2ujej2q
-torapa.i2p,eejqjtpko6mdd4opvntbpsuandstrebxpbymfhix7avp5obrw5ta
-torrentfinder.i2p,mpc73okj7wq2xl6clofl64cn6v7vrvhpmi6d524nrsvbeuvjxalq
-torrfreedom.i2p,nfrjvknwcw47itotkzmk6mdlxmxfxsxhbhlr5ozhlsuavcogv4hq
-trac.i2p,kyioa2lgdi2za2fwfwajnb3ljz6zwlx7yzjdpnxnch5uw3iqn6ca
-trac.i2p2.i2p,i43xzkihpdq34f2jlmtgiyyay5quafg5rebog7tk7xil2c6kbyoa
-tracker-fr.i2p,qfrvqrfoqkistgzo2oxpfduz4ktkhtqopleozs3emblmm36fepea
-tracker.awup.i2p,dl47cno335ltvqm6noi5zcij5hpvbj7vjkzuofu262efvu6yp6cq
-tracker.crypthost.i2p,ri5a27ioqd4vkik72fawbcryglkmwyy4726uu5j3eg6zqh2jswfq
-tracker.fr.i2p,rzwqr7pfibq5wlcq4a7akm6ohfyhz7hchmy4wz5t55lhd7dwao5q
-tracker.i2p,lsjcplya2b4hhmezz2jy5gqh6zlk3nskisjkhhwapy3jjly4ds5q
-tracker.lodikon.i2p,q2a7tqlyddbyhxhtuia4bmtqpohpp266wsnrkm6cgoahdqrjo3ra
-tracker.mastertracker.i2p,tiwurhqvaaguwpz2shdahqmcfze5ejre52ed2rmoadnjkkilskda
-tracker.postman.i2p,jfcylf4j3gfmqogkltwy7v5m47wp4h7ffrnfsva6grfdavdn7ueq
-tracker.psi.i2p,vmow3h54yljn7zvzbqepdddt5fmygijujycod2q6yznpy2rrzuwa
-tracker.thebland.i2p,s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq
-tracker.welterde.i2p,cfmqlafjfmgkzbt4r3jsfyhgsr5abgxryl6fnz3d3y5a365di5aa
-tracker2.postman.i2p,ahsplxkbhemefwvvml7qovzl5a2b5xo5i7lyai7ntdunvcyfdtna
-traditio.i2p,wkpjjloylf6jopu2itgpktr45t2xvpjijxilxd5tq4i7wkqgwhhq
-trevorreznik.i2p,wc2z6o5fxm2saqzpfcawr63lejwccvzkysmgtfudkrigqopzfdma
-true.i2p,pdilhl5vmefyzrrnmak5bnmxqxk2pmw7rpy4f7wbaeppqu2vvugq
-trwcln.i2p,evml6jiiujhulsgxkdu3wcmkwbokxlv4is6w5qj46tp3ajz3hqzq
-trypanom.i2p,tgv5acj4khwvr6t44cmryohybd2e5o2kndysnzae6qwcr4hzda3q
-ts.i2p,nebcjgfx3f7q4wzihqmguwcdeopaf7f6wyk2dojw4bcuku472zxq
-ttc.i2p,wb4tsfyvfv4idgrultsq6o7inza4fxkc7dijsfpncbx7zko4cdlq
-ttp.i2p,uuczclxejmetohwf2vqewovx3qcumdfh5zecjb3xkcdmk6e5j72a
-tumbach.i2p,u6pciacxnpbsq7nwc3tgutywochfd6aysgayijr7jxzoysgxklvq
-tutorials.i2p,zy37tq6ynucp3ufoyeegswqjaeofmj57cpm5ecd7nbanh2h6f2ja
-ugha.i2p,z3f3owc72awbywk4p6qb5l2mxgitvs6ejztggbpn2a3ddmymfjda
-uk.i2p,vydbychnep3mzkzhg43ptewp242issy47whamfbxodc4ma6wc63a
-underground.i2p,dlnuthb6tpw3kchlb7xoztyspy4ehlggjhl44l64vbcrulrfeica
-underscore.i2p,3gmezyig6gvsjbpkq2kihoskpuqpkfrajmhhm7hpyrjuvtasgepa
-unqueued.i2p,3gvn4kwd7z74jxc2sn4ucx52dpvpscxbzjluux3ul4t3eu5g64xq
-up.i2p,25it5olgdo7pht25z6buzd32sw7jvc65oziqeuocfozfhgua655q
-update.dg.i2p,iqj6ysfh3wl26m4buvyna73yhduifv523l7bwuexxak4mgldexja
-update.killyourtv.i2p,gqdfg25jlqtm35qnmt4b7r53d6u2vep4ob23fwd42iyy4j6cvdqq
-update.postman.i2p,u5rbu6yohfafplp6lgbbmmcuip34s7g3zqdd63cp27dl3nbd7gtq
-utansans.i2p,u2oyre7ygqv4qs5xjjijfg3x7ddwtod6nqwgbomuuzljzvnq4rda
-v2mail.i2p,4gg7fykcqe7oaqt4w5fmlarnia7vtmwkv3h45zzgoj6o6crryg5a
-vadino.i2p,aalttzlt3z25ktokesceweabm5yyhhvml2z3rfotndgpfyh6myra
-visibility.i2p,pwgma3snbsgkddxgb54mrxxkt3l4jzchrtp52vxmw7rbkjygylxq
-volatile.i2p,q6rve733tvhgyys57jfw4fymqf3xsnza6dqailcdjcq7w4fa5m3a
-vpnbest.i2p,ov5f74ndsy5rfkuyps56waf42vxncufqu5rzm3vsnxkdtogccaea
-vudu.i2p,3zlwci7pvgep2igygzyjej24ue7mjsktlhaff6crpsr75yquak2q
-w.i2p,j2xorlcb3qxubnthzqu7lt4fvxqn63it4ikwmze55yjkzeeampuq
-wa11ed.city.i2p,7mxwtmala3ycg2sybjwwfil7s6dqck2fbemeutghhwu73rznmqoa
-wahoo.i2p,vqe5vkpe5wbda7lwekcd2jaj44ar3rawgv54u5rcolezbg5f5vwa
-wallet.gostcoin.i2p,reuvum7lgetglafn72chypesvto773oy53zumagrpigkckybrwda
-wallsgetbombed.i2p,tzhea5d65fllm4263wztghgw4ijdgibsca5xsecp6lk4xlsbdeuq
-web.telegram.i2p,re6cgwg2yrkgaixlqvt5ufajbb3w42fsldlq7k5brpvnd5gp6x5a
-wiht.i2p,yojmpj3sh76g3i6ogzgsf7eouipdgdij5o2blcpdgmu5oyjk5xca
-wiki.fr.i2p,lrqa7hw52uxjb5q3pedmjs6hzos5zrod4y6a4e25hu7vcjhohvxq
-wiki.ilita.i2p,r233yskmowqe4od4he4b37wydr5fqzvj3z77v5fdei2etp2kg34a
-wintermute.i2p,4gvlfrdy2rkmem33c342tjntpvqik65wekcvm4275qbkuwotoila
-wspucktracker.i2p,ubd2txda3kllumx7ftg4unzgqy536cn6dd2ax6mlhodczfas7rgq
-www.aum.i2p,3xolizygkzkqrldncjqsb734szznw2u36lliceuacqnbs2n65aeq
-www.baffled.i2p,lqrsfslwu4xnubkk2hofhmuvvr4dia2zevxefinbzdsjurvehtqq
-www.fr.i2p,rmkgvlfwo3vkb3xrr6epoypxasdzzuilv3sckcqbo6c4os5jo2ea
-www.i2p,ojxyenivrrqvycgbxbm3phgisu5abspzq4g2us4fjlwz4tx222va
-www.i2p2.i2p,rjxwbsw4zjhv4zsplma6jmf5nr24e4ymvvbycd3swgiinbvg7oga
-www.imule.i2p,657xcllunctawyjtar5kgh3wpt6z4l7ba6mmam5rf7hev5w2lsvq
-www.infoserver.i2p,fq7xhxkdcauhwn4loufcadiiy24zbei25elnup33a3gfrdzrtlyq
-www.janonymous.i2p,vosqx5qw22hwrzcgsm4ib7hymf5ryovsbtaexqrzmnzshy5bhakq
-www.mail.i2p,nctas6ioo7aaekfstv3o45yh6ywzwa3vznrdae52ouupzke5pyba
-www.nntp.i2p,kly3o7zmetuwyz7xonnhttw4lj2244pkbibjz26uflyfte3b3dka
-www.postman.i2p,rb3srw2gaooyw63q62cp4udrxxa6molr2irbkgrloveylpkkblhq
-www.syndie.i2p,vojgy5ep4wffmtpjmpnbpa4gq64bgn4yicuw6qmhbm6nqa2ysrva
-www1.squid.i2p,vbh3bltd2duwbukafgj6f6vfi6aigwso7snucp5zohnf66a2hkpa
-xc.i2p,mt45a2z3sb2iyy2mwauj4rwa2lwu4peanfy6gx6ybidwnbasusyq
-xeha.i2p,oartgetziabrdemxctowp7bbeggc7ktmj7tr4qgk5y5jcz4prbtq
-xilog.i2p,eoc5i5q52hutnmsmq56edvooulutaxfikddgdz27otmgtsxmiloq
-xmpp.crypthost.i2p,ittkqpjuliwsdewdugkhvgzstejr2jp5tzou7p332lxx4xw7srba
-xmpp.rpi.i2p,3yv65pfwiwfuv4ciwtx34clqps6o2mc3vtyltcbqdkcki6untbca
-xn--l2bl5aw.i2p,d2epikjh5crt2l5xjmtceqw2ho44hzp6x3u7hgjrd4mi4wywikwa
-xolotl.i2p,rwr6rrlmrotxfkxt22mah42cycliy2g5k7hgxyxkpcyyxkd2bgwq
-xotc.i2p,gqgvzum3xdgtaahkjfw3layb33vjrucmw5btyhrppm463cz3c5oq
-z-lab.i2p,s6g2pz3mrwzsl4ts65ox3scqawfj7mzvd7hn2ekiiycawopkriba
-zab.i2p,n4xen5sohufgjhv327ex4qra77f4tpqohlcyoa3atoboknzqazeq
-zcash.i2p,zcashmliuw3yd2ptfyd5sadatcpyxj4ldiqahtjzg73cgoevxp4q
-zener.i2p,mcbyglflte3dhwhqyafsfpnqtcapqkv2sepqd62wzd7fo2dzz4ca
-zerobin.i2p,3564erslxzaoucqasxsjerk4jz2xril7j2cbzd4p7flpb4ut67hq
-zeroman.i2p,gq77fmto535koofcd53f6yzcc5y57ccrxg3pb6twhcodc7v5dutq
-zeronet.i2p,fe6pk5sibhkr64veqxkfochdfptehyxrrbs3edwjs5ckjbjn4bna
-znc.i2p,uw2yt6njjl676fupd72hiezwmd4ouuywowrph6fvhkzhlnvp7jwa
-znc.str4d.i2p,ufkajv3stxpxlwgwwb2ae6oixdjircnbwog77qxpxv7nt67rpcxq
-zzz.i2p,ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq
diff --git a/android/assets/certificates b/android/assets/certificates
deleted file mode 120000
index 01b21e5d..00000000
--- a/android/assets/certificates
+++ /dev/null
@@ -1 +0,0 @@
-../../contrib/certificates
\ No newline at end of file
diff --git a/android/assets/i2pd.conf b/android/assets/i2pd.conf
deleted file mode 100644
index 14254248..00000000
--- a/android/assets/i2pd.conf
+++ /dev/null
@@ -1,92 +0,0 @@
-## Configuration file for a typical i2pd user
-## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
-## for more options you can use in this file.
-
-#logfile = /sdcard/i2pd/i2pd.log
-loglevel = none
-#tunnelsdir = /sdcard/i2pd/tunnels.d
-
-# host = 1.2.3.4
-# port = 4567
-
-ipv4 = true
-ipv6 = false
-
-# ntcp = true
-# ntcpproxy = http://127.0.0.1:8118
-# ssu = true
-
-bandwidth = L
-# share = 100
-
-# notransit = true
-# floodfill = true
-
-[ntcp2]
-enabled = true
-
-[http]
-enabled = true
-address = 127.0.0.1
-port = 7070
-# auth = true
-# user = i2pd
-# pass = changeme
-
-[httpproxy]
-enabled = true
-address = 127.0.0.1
-port = 4444
-inbound.length = 1
-inbound.quantity = 5
-outbound.length = 1
-outbound.quantity = 5
-signaturetype=7
-i2cp.leaseSetType=3
-i2cp.leaseSetEncType=0,4
-keys = proxy-keys.dat
-# addresshelper = true
-# outproxy = http://false.i2p
-## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
-
-[socksproxy]
-enabled = true
-address = 127.0.0.1
-port = 4447
-keys = proxy-keys.dat
-# outproxy.enabled = false
-# outproxy = 127.0.0.1
-# outproxyport = 9050
-## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
-
-[sam]
-enabled = false
-# address = 127.0.0.1
-# port = 7656
-
-[precomputation]
-elgamal = true
-
-[upnp]
-enabled = true
-# name = I2Pd
-
-[reseed]
-verify = true
-## Path to local reseed data file (.su3) for manual reseeding
-# file = /path/to/i2pseeds.su3
-## or HTTPS URL to reseed from
-# file = https://legit-website.com/i2pseeds.su3
-## Path to local ZIP file or HTTPS URL to reseed from
-# zipfile = /path/to/netDb.zip
-## If you run i2pd behind a proxy server, set proxy server for reseeding here
-## Should be http://address:port or socks://address:port
-# proxy = http://127.0.0.1:8118
-## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
-# threshold = 25
-
-[limits]
-transittunnels = 50
-
-[persist]
-profiles = false
diff --git a/android/assets/subscriptions.txt b/android/assets/subscriptions.txt
deleted file mode 100644
index 8f4afb03..00000000
--- a/android/assets/subscriptions.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-http://inr.i2p/export/alive-hosts.txt
-http://stats.i2p/cgi-bin/newhosts.txt
-http://i2p-projekt.i2p/hosts.txt
diff --git a/android/assets/tunnels.conf b/android/assets/tunnels.conf
deleted file mode 100644
index c39a0220..00000000
--- a/android/assets/tunnels.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-#[IRC-IRC2P]
-#type = client
-#address = 127.0.0.1
-#port = 6668
-#destination = irc.postman.i2p
-#destinationport = 6667
-#keys = irc-keys.dat
-
-#[IRC-ILITA]
-#type = client
-#address = 127.0.0.1
-#port = 6669
-#destination = irc.ilita.i2p
-#destinationport = 6667
-#keys = irc-keys.dat
-
-#[SMTP]
-#type = client
-#address = 127.0.0.1
-#port = 7659
-#destination = smtp.postman.i2p
-#destinationport = 25
-#keys = smtp-keys.dat
-
-#[POP3]
-#type = client
-#address = 127.0.0.1
-#port = 7660
-#destination = pop.postman.i2p
-#destinationport = 110
-#keys = pop3-keys.dat
-
-# see more examples at https://i2pd.readthedocs.io/en/latest/user-guide/tunnels/
diff --git a/android/assets/tunnels.d b/android/assets/tunnels.d
deleted file mode 120000
index ff262031..00000000
--- a/android/assets/tunnels.d
+++ /dev/null
@@ -1 +0,0 @@
-../../contrib/tunnels.d
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
deleted file mode 100644
index dbe75759..00000000
--- a/android/build.gradle
+++ /dev/null
@@ -1,104 +0,0 @@
-buildscript {
- repositories {
- mavenCentral()
- jcenter()
- google()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.4.2'
- }
-}
-
-apply plugin: 'com.android.application'
-
-repositories {
- jcenter()
- maven {
- url 'https://maven.google.com'
- }
- google()
-}
-
-dependencies {
- implementation 'androidx.core:core:1.0.2'
-}
-
-android {
- compileSdkVersion 29
- buildToolsVersion "28.0.3"
- defaultConfig {
- applicationId "org.purplei2p.i2pd"
- targetSdkVersion 29
- minSdkVersion 14
- versionCode 2350
- versionName "2.35.0"
- setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
- ndk {
- abiFilters 'armeabi-v7a'
- abiFilters 'x86'
- //abiFilters 'arm64-v8a'
- //abiFilters 'x86_64'
- }
- externalNativeBuild {
- ndkBuild {
- arguments "-j3"
- }
- }
- }
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = ['src']
- res.srcDirs = ['res']
- jniLibs.srcDirs = ['libs']
- assets.srcDirs = ['assets']
- }
- }
- splits {
- abi {
- // change that to true if you need splitted apk
- enable true
- reset()
- //include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
- include "armeabi-v7a", "x86"
- universalApk true
- }
- }
- signingConfigs {
- orignal {
- storeFile file("i2pdapk.jks")
- storePassword "android"
- keyAlias "i2pdapk"
- keyPassword "android"
- }
- }
- buildTypes {
- release {
- minifyEnabled false
- signingConfig signingConfigs.orignal
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
- }
- }
- externalNativeBuild {
- ndkBuild {
- path './jni/Android.mk'
- }
- }
- compileOptions {
- sourceCompatibility = '1.8'
- targetCompatibility = '1.8'
- }
-}
-
-ext.abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'arm64-v8a': 3, 'x86_64': 4]
-import com.android.build.OutputFile
-
-android.applicationVariants.all { variant ->
- variant.outputs.each { output ->
- def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
-
- if (baseAbiVersionCode != null) {
- output.versionCodeOverride = baseAbiVersionCode + variant.versionCode
- }
- }
-}
diff --git a/android/build.xml b/android/build.xml
deleted file mode 100644
index ed8196c3..00000000
--- a/android/build.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/gradle.properties b/android/gradle.properties
deleted file mode 100644
index 6678daaf..00000000
--- a/android/gradle.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-android.enableJetifier=true
-android.useAndroidX=true
-org.gradle.parallel=true
\ No newline at end of file
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index f6b961fd..00000000
Binary files a/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 3b803211..00000000
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Tue Aug 20 14:39:08 MSK 2019
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/android/gradlew b/android/gradlew
deleted file mode 100755
index cccdd3d5..00000000
--- a/android/gradlew
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env sh
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=$((i+1))
- done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
deleted file mode 100644
index f9553162..00000000
--- a/android/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
deleted file mode 100755
index 07dc7080..00000000
--- a/android/jni/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := i2pd
-LOCAL_CPP_FEATURES := rtti exceptions
-LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(DAEMON_SRC_PATH)
-LOCAL_STATIC_LIBRARIES := \
- boost_system \
- boost_date_time \
- boost_filesystem \
- boost_program_options \
- crypto ssl \
- miniupnpc
-LOCAL_LDLIBS := -lz
-
-LOCAL_SRC_FILES := DaemonAndroid.cpp i2pd_android.cpp $(IFADDRS_PATH)/ifaddrs.c \
- $(wildcard $(LIB_SRC_PATH)/*.cpp)\
- $(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
- $(DAEMON_SRC_PATH)/Daemon.cpp \
- $(DAEMON_SRC_PATH)/UPnP.cpp \
- $(DAEMON_SRC_PATH)/HTTPServer.cpp \
- $(DAEMON_SRC_PATH)/I2PControl.cpp
-
-include $(BUILD_SHARED_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := boost_system
-LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
-LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := boost_date_time
-LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
-LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := boost_filesystem
-LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
-LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := boost_program_options
-LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
-LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := crypto
-LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
-LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/include
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := ssl
-LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
-LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1d-clang/include
-LOCAL_STATIC_LIBRARIES := crypto
-include $(PREBUILT_STATIC_LIBRARY)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_MODULE := miniupnpc
-LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
-LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
-include $(PREBUILT_STATIC_LIBRARY)
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
deleted file mode 100755
index 0c291661..00000000
--- a/android/jni/Application.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#APP_ABI := armeabi-v7a x86
-#APP_PLATFORM := android-14
-
-# ABI arm64-v8a and x86_64 supported only from platform-21
-#APP_ABI := arm64-v8a x86_64
-#APP_PLATFORM := android-21
-
-NDK_TOOLCHAIN_VERSION := clang
-#APP_STL := c++_shared
-APP_STL := c++_static
-
-# Enable c++17 extensions in source code
-APP_CPPFLAGS += -std=c++17 -fexceptions -frtti
-
-APP_CPPFLAGS += -DANDROID -D__ANDROID__ -DUSE_UPNP
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-APP_CPPFLAGS += -DANDROID_ARM7A
-endif
-
-# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
-# 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
-# change to your own
-I2PD_LIBS_PATH = /path/to/libraries
-BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
-OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
-MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
-IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
-
-# don't change me
-I2PD_SRC_PATH = $(PWD)/..
-
-LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
-LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
-DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon
diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp
deleted file mode 100644
index 39c06ea0..00000000
--- a/android/jni/DaemonAndroid.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
-*
-* This file is part of Purple i2pd project and licensed under BSD3
-*
-* See full license text in LICENSE file at top of project tree
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-//#include "mainwindow.h"
-#include "FS.h"
-#include "DaemonAndroid.h"
-#include "Daemon.h"
-
-namespace i2p
-{
-namespace android
-{
-/* Worker::Worker (DaemonAndroidImpl& daemon):
- m_Daemon (daemon)
- {
- }
-
- void Worker::startDaemon()
- {
- Log.d(TAG"Performing daemon start...");
- m_Daemon.start();
- Log.d(TAG"Daemon started.");
- emit resultReady();
- }
- void Worker::restartDaemon()
- {
- Log.d(TAG"Performing daemon restart...");
- m_Daemon.restart();
- Log.d(TAG"Daemon restarted.");
- emit resultReady();
- }
- void Worker::stopDaemon() {
- Log.d(TAG"Performing daemon stop...");
- m_Daemon.stop();
- Log.d(TAG"Daemon stopped.");
- emit resultReady();
- }
-
- Controller::Controller(DaemonAndroidImpl& daemon):
- m_Daemon (daemon)
- {
- Worker *worker = new Worker (m_Daemon);
- worker->moveToThread(&workerThread);
- connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
- connect(this, &Controller::startDaemon, worker, &Worker::startDaemon);
- connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon);
- connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon);
- connect(worker, &Worker::resultReady, this, &Controller::handleResults);
- workerThread.start();
- }
- Controller::~Controller()
- {
- Log.d(TAG"Closing and waiting for daemon worker thread...");
- workerThread.quit();
- workerThread.wait();
- Log.d(TAG"Waiting for daemon worker thread finished.");
- if(m_Daemon.isRunning())
- {
- Log.d(TAG"Stopping the daemon...");
- m_Daemon.stop();
- Log.d(TAG"Stopped the daemon.");
- }
- }
-*/
- std::string dataDir = "";
-
- DaemonAndroidImpl::DaemonAndroidImpl ()
- //:
- /*mutex(nullptr), */
- //m_IsRunning(false),
- //m_RunningChangedCallback(nullptr)
- {
- }
-
- DaemonAndroidImpl::~DaemonAndroidImpl ()
- {
- //delete mutex;
- }
-
- bool DaemonAndroidImpl::init(int argc, char* argv[])
- {
- //mutex=new QMutex(QMutex::Recursive);
- //setRunningCallback(0);
- //m_IsRunning=false;
-
- // make sure assets are ready before proceed
- i2p::fs::DetectDataDir(dataDir, false);
- int numAttempts = 0;
- do
- {
- if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
- numAttempts++;
- std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
- }
- while (numAttempts <= 10); // 10 seconds max
- return Daemon.init(argc,argv);
- }
-
- void DaemonAndroidImpl::start()
- {
- //QMutexLocker locker(mutex);
- //setRunning(true);
- Daemon.start();
- }
-
- void DaemonAndroidImpl::stop()
- {
- //QMutexLocker locker(mutex);
- Daemon.stop();
- //setRunning(false);
- }
-
- void DaemonAndroidImpl::restart()
- {
- //QMutexLocker locker(mutex);
- stop();
- start();
- }
- /*
- void DaemonAndroidImpl::setRunningCallback(runningChangedCallback cb)
- {
- m_RunningChangedCallback = cb;
- }
-
- bool DaemonAndroidImpl::isRunning()
- {
- return m_IsRunning;
- }
-
- void DaemonAndroidImpl::setRunning(bool newValue)
- {
- bool oldValue = m_IsRunning;
- if(oldValue!=newValue)
- {
- m_IsRunning = newValue;
- if(m_RunningChangedCallback)
- m_RunningChangedCallback();
- }
- }
-*/
- static DaemonAndroidImpl daemon;
- static char* argv[1]={strdup("tmp")};
- /**
- * returns error details if failed
- * returns "ok" if daemon initialized and started okay
- */
- std::string start(/*int argc, char* argv[]*/)
- {
- try
- {
- //int result;
-
- {
- //Log.d(TAG"Initialising the daemon...");
- bool daemonInitSuccess = daemon.init(1,argv);
- if(!daemonInitSuccess)
- {
- //QMessageBox::critical(0, "Error", "Daemon init failed");
- return "Daemon init failed";
- }
- //Log.d(TAG"Initialised, creating the main window...");
- //MainWindow w;
- //Log.d(TAG"Before main window.show()...");
- //w.show ();
-
- {
- //i2p::qt::Controller daemonQtController(daemon);
- //Log.d(TAG"Starting the daemon...");
- //emit daemonQtController.startDaemon();
- //daemon.start ();
- //Log.d(TAG"Starting GUI event loop...");
- //result = app.exec();
- //daemon.stop ();
- daemon.start();
- }
- }
-
- //QMessageBox::information(&w, "Debug", "demon stopped");
- //Log.d(TAG"Exiting the application");
- //return result;
- }
- catch (boost::exception& ex)
- {
- std::stringstream ss;
- ss << boost::diagnostic_information(ex);
- return ss.str();
- }
- catch (std::exception& ex)
- {
- std::stringstream ss;
- ss << ex.what();
- return ss.str();
- }
- catch(...)
- {
- return "unknown exception";
- }
- return "ok";
- }
-
- void stop()
- {
- daemon.stop();
- }
-
- void SetDataDir(std::string jdataDir)
- {
- dataDir = jdataDir;
- }
-}
-}
diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h
deleted file mode 100644
index 912f6f49..00000000
--- a/android/jni/DaemonAndroid.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
-*
-* This file is part of Purple i2pd project and licensed under BSD3
-*
-* See full license text in LICENSE file at top of project tree
-*/
-
-#ifndef DAEMON_ANDROID_H
-#define DAEMON_ANDROID_H
-
-#include
-
-namespace i2p
-{
-namespace android
-{
- class DaemonAndroidImpl
- {
- public:
-
- DaemonAndroidImpl ();
- ~DaemonAndroidImpl ();
-
- //typedef void (*runningChangedCallback)();
-
- /**
- * @return success
- */
- bool init(int argc, char* argv[]);
- void start();
- void stop();
- void restart();
- //void setRunningCallback(runningChangedCallback cb);
- //bool isRunning();
- private:
- //void setRunning(bool running);
- private:
- //QMutex* mutex;
- //bool m_IsRunning;
- //runningChangedCallback m_RunningChangedCallback;
- };
-
- /**
- * returns "ok" if daemon init failed
- * returns errinfo if daemon initialized and started okay
- */
- std::string start();
-
- // stops the daemon
- void stop();
-
- // set datadir received from jni
- void SetDataDir(std::string jdataDir);
- /*
- class Worker : public QObject
- {
- Q_OBJECT
- public:
-
- Worker (DaemonAndroidImpl& daemon);
-
- private:
-
- DaemonAndroidImpl& m_Daemon;
-
- public slots:
- void startDaemon();
- void restartDaemon();
- void stopDaemon();
-
- signals:
- void resultReady();
- };
-
- class Controller : public QObject
- {
- Q_OBJECT
- QThread workerThread;
- public:
- Controller(DaemonAndroidImpl& daemon);
- ~Controller();
- private:
- DaemonAndroidImpl& m_Daemon;
-
- public slots:
- void handleResults(){}
- signals:
- void startDaemon();
- void stopDaemon();
- void restartDaemon();
- };
- */
-}
-}
-
-#endif // DAEMON_ANDROID_H
diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp
deleted file mode 100755
index c6e309dd..00000000
--- a/android/jni/i2pd_android.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
-*
-* This file is part of Purple i2pd project and licensed under BSD3
-*
-* See full license text in LICENSE file at top of project tree
-*/
-
-#include
-#include "org_purplei2p_i2pd_I2PD_JNI.h"
-#include "DaemonAndroid.h"
-#include "RouterContext.h"
-#include "ClientContext.h"
-#include "Transports.h"
-#include "Tunnel.h"
-
-JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
- (JNIEnv *env, jclass clazz) {
-#if defined(__arm__)
- #if defined(__ARM_ARCH_7A__)
- #if defined(__ARM_NEON__)
- #if defined(__ARM_PCS_VFP)
- #define ABI "armeabi-v7a/NEON (hard-float)"
- #else
- #define ABI "armeabi-v7a/NEON"
- #endif
- #else
- #if defined(__ARM_PCS_VFP)
- #define ABI "armeabi-v7a (hard-float)"
- #else
- #define ABI "armeabi-v7a"
- #endif
- #endif
- #else
- #define ABI "armeabi"
- #endif
- #elif defined(__i386__)
- #define ABI "x86"
- #elif defined(__x86_64__)
- #define ABI "x86_64"
- #elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
- #define ABI "mips64"
- #elif defined(__mips__)
- #define ABI "mips"
- #elif defined(__aarch64__)
- #define ABI "arm64-v8a"
- #else
- #define ABI "unknown"
-#endif
-
- return env->NewStringUTF(ABI);
-}
-
-JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
- (JNIEnv *env, jclass clazz) {
- return env->NewStringUTF(i2p::android::start().c_str());
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
- (JNIEnv *env, jclass clazz) {
- i2p::android::stop();
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
- (JNIEnv *env, jclass clazz) {
- i2p::context.SetAcceptsTunnels (false);
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
- (JNIEnv *env, jclass clazz) {
- i2p::context.SetAcceptsTunnels (true);
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
- (JNIEnv *env, jclass clazz) {
- i2p::client::context.ReloadConfig();
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
- (JNIEnv *env, jclass clazz, jboolean isConnected) {
- bool isConnectedBool = (bool) isConnected;
- i2p::transport::transports.SetOnline (isConnectedBool);
-}
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
- (JNIEnv *env, jclass clazz, jstring jdataDir) {
-
- /*
- // Method 1: convert UTF-16 jstring to std::string (https://stackoverflow.com/a/41820336)
- const jclass stringClass = env->GetObjectClass(jdataDir);
- const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
- const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(jdataDir, getBytes, env->NewStringUTF("UTF-8"));
-
- size_t length = (size_t) env->GetArrayLength(stringJbytes);
- jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
-
- std::string dataDir = std::string((char *)pBytes, length);
- env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
-
- env->DeleteLocalRef(stringJbytes);
- env->DeleteLocalRef(stringClass); */
-
- // Method 2: get string chars and make char array.
- auto dataDir = env->GetStringUTFChars(jdataDir, NULL);
- env->ReleaseStringUTFChars(jdataDir, dataDir);
-
- // Set DataDir
- i2p::android::SetDataDir(dataDir);
-}
-
-JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
- (JNIEnv *env, jclass clazz) {
- return i2p::tunnel::tunnels.CountTransitTunnels();
-}
diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
deleted file mode 100644
index 68935ad1..00000000
--- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-* Copyright (c) 2013-2020, The PurpleI2P Project
-*
-* This file is part of Purple i2pd project and licensed under BSD3
-*
-* See full license text in LICENSE file at top of project tree
-*/
-
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include
-/* Header for class org_purplei2p_i2pd_I2PD_JNI */
-
-#ifndef _Included_org_purplei2p_i2pd_I2PD_JNI
-#define _Included_org_purplei2p_i2pd_I2PD_JNI
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: org_purplei2p_i2pd_I2PD_JNI
- * Method: stringFromJNI
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
- (JNIEnv *, jclass);
-
-JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon
- (JNIEnv *, jclass);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
- (JNIEnv *, jclass);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
- (JNIEnv *, jclass);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
- (JNIEnv *, jclass);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
- (JNIEnv *, jclass);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
- (JNIEnv * env, jclass clazz, jboolean isConnected);
-
-JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
- (JNIEnv *env, jclass clazz, jstring jdataDir);
-
-JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
- (JNIEnv *, jclass);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/android/proguard-project.txt b/android/proguard-project.txt
deleted file mode 100644
index f2fe1559..00000000
--- a/android/proguard-project.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# To enable ProGuard in your project, edit project.properties
-# to define the proguard.config property as described in that file.
-#
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in ${sdk.dir}/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the ProGuard
-# include property in project.properties.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
diff --git a/android/project.properties b/android/project.properties
deleted file mode 100644
index 82181932..00000000
--- a/android/project.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-29
diff --git a/android/res/drawable/icon.png b/android/res/drawable/icon.png
deleted file mode 100644
index 9a2f7404..00000000
Binary files a/android/res/drawable/icon.png and /dev/null differ
diff --git a/android/res/drawable/itoopie_notification_icon.png b/android/res/drawable/itoopie_notification_icon.png
deleted file mode 100644
index fa99e7fc..00000000
Binary files a/android/res/drawable/itoopie_notification_icon.png and /dev/null differ
diff --git a/android/res/layout/activity_perms_asker.xml b/android/res/layout/activity_perms_asker.xml
deleted file mode 100644
index 778c9ef5..00000000
--- a/android/res/layout/activity_perms_asker.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/res/layout/activity_perms_explanation.xml b/android/res/layout/activity_perms_explanation.xml
deleted file mode 100644
index 9129a437..00000000
--- a/android/res/layout/activity_perms_explanation.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/res/layout/activity_web_console.xml b/android/res/layout/activity_web_console.xml
deleted file mode 100644
index 5724b387..00000000
--- a/android/res/layout/activity_web_console.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml
deleted file mode 100644
index f5ea62ab..00000000
--- a/android/res/menu/options_main.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
diff --git a/android/res/values-ru/strings.xml b/android/res/values-ru/strings.xml
deleted file mode 100755
index 91493756..00000000
--- a/android/res/values-ru/strings.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
- i2pd
-
- ะััะฐะฝะพะฒะธัั
- ะะพััะตะบัะฝะฐั ะพััะฐะฝะพะฒะบะฐ
- ะัะผะตะฝะธัั ะบะพััะตะบัะฝัั ะพััะฐะฝะพะฒะบั
- ะะตัะตะทะฐะณััะทะธัั ััะฝะฝะตะปะธ
- ะัะบัััั ะะตะฑ ะะพะฝัะพะปั
-
- ะะพััะตะบัะฝะฐั ะพััะฐะฝะพะฒะบะฐ ัะถะต ะทะฐะฟััะตะฝะฐ
- ะะพััะตะบัะฝะฐั ะพััะฐะฝะพะฒะบะฐ ะทะฐะฟััะตะฝะฐ
- ะะพััะตะบัะฝะฐั ะพััะฐะฝะพะฒะบะฐ ะทะฐะฟััะตะฝะฐ
-
- ะฃะถะต ะพััะฐะฝะพะฒะปะตะฝะพ
- ะัะธะปะพะถะตะฝะธะต ะธะฝะธัะธะฐะปะธะทะธััะตััั
- ะัะธะปะพะถะตะฝะธะต ะทะฐะฟััะบะฐะตััั
- ะะฐะณััะถะตะฝั JNI ะฑะธะฑะปะธะพัะตะบะธ
- ะัะธะปะพะถะตะฝะธะต ะทะฐะฟััะตะฝะพ
- ะะฐะฟััะบ ะฝะต ัะดะฐะปัั
- ะัะธะปะพะถะตะฝะธะต ะฑัะปะพ ะพััะฐะฝะพะฒะปะตะฝะพ
- ะพััะฐะปะพัั
-
- ะะฐะฟัะพั
- ะัะฐะฒะฐ ะดะปั ะทะฐะฟะธัะธ ะฝะฐ SD ะบะฐััั ะพัะบะปะพะฝะตะฝั, ะฒะฐะผ ะฝะตะพะฑั
ะพะดะธะผะพ ะฟัะตะดะพััะฐะฒะธัั ะธั
ะดะปั ะฟัะพะดะพะปะถะตะฝะธั
- ะัะฐะฒะฐ ะฝะฐ ะทะฐะฟะธัั ะฝะฐ SD ะบะฐััั ะฝะตะพะฑั
ะพะดะธะผั ะดะปั ะทะฐะฟะธัะธ ะบะปััะตะน ะธ ะดััะณะธั
ัะฐะนะปะพะฒ ะฒ ะฟะฐะฟะบั I2PD ะฝะฐ ะฒะฝัััะตะฝะฝะตะน ะฟะฐะผััะธ.
- ะะพะฒัะพัะธัั ะทะฐะฟัะพั ะฟัะฐะฒ ะฝะฐ ะทะฐะฟะธัั ะฝะฐ SD ะบะฐััั
-
- ะะฟัะธะผะธะทะฐัะธะธ ะฐะบะบัะผัะปััะพัะฐ
- ะะฟัะธะผะธะทะฐัะธะธ ะฐะบะบัะผัะปััะพัะฐ ะฒะบะปััะตะฝั
- ะะฐัะฐ ะพะฟะตัะฐัะธะพะฝะฝะฐั ัะธััะตะผะฐ ะพัััะตััะฒะปัะตั ะพะฟัะธะผะธะทะฐัะธะธ ัะฐัั
ะพะดะฐ ะฐะบะบัะผัะปััะพัะฐ, ะบะพัะพััะต ะผะพะณัั ะฟัะธะฒะพะดะธัั ะบ ะฒัะณััะทะบะต I2PD ะธะท ะฟะฐะผััะธ ะธ ะฟัะตะบัะฐัะตะฝะธั ะตะณะพ ัะฐะฑะพัั ั ัะตะปัั ััะบะพะฝะพะผะธัั ะทะฐััะด ะฐะบะบัะผัะปััะพัะฐ.\nะ ะตะบะพะผะตะฝะดัะตััั ะพัะบะปััะธัั ััะธ ะพะฟัะธะผะธะทะฐัะธะธ.
- ะะฐัะฐ ะพะฟะตัะฐัะธะพะฝะฝะฐั ัะธััะตะผะฐ ะพัััะตััะฒะปัะตั ะพะฟัะธะผะธะทะฐัะธะธ ัะฐัั
ะพะดะฐ ะฐะบะบัะผัะปััะพัะฐ, ะบะพัะพััะต ะผะพะณัั ะฟัะธะฒะพะดะธัั ะบ ะฒัะณััะทะบะต I2PD ะธะท ะฟะฐะผััะธ ะธ ะฟัะตะบัะฐัะตะฝะธั ะตะณะพ ัะฐะฑะพัั ั ัะตะปัั ััะบะพะฝะพะผะธัั ะทะฐััะด ะฐะบะบัะผัะปััะพัะฐ.\n\nะะฐะผ ัะตะนัะฐั ะฑัะดะตั ะฟัะตะดะปะพะถะตะฝะพ ัะฐะทัะตัะธัั ะพัะบะปััะตะฝะธะต ััะธั
ะพะฟัะธะผะธะทะฐัะธะน.
- ะัะพะดะพะปะถะธัั
- ะะฐัะฐ ะฒะตััะธั ะะฝะดัะพะธะด ะฝะต ะฟะพะดะดะตัะถะธะฒะฐะตั ะพัะบะปััะตะฝะธะต ะพะฟัะธะผะธะทะฐัะธะน ะฐะบะบัะผัะปััะพัะฐ
- ะะฐัะฐ ะฒะตััะธั ะะฝะดัะพะธะด ะฝะต ะฟะพะดะดะตัะถะธะฒะฐะตั ะฟะพะบะฐะท ะดะธะฐะปะพะณะฐ ะพะฑ ะพะฟัะธะผะธะทะฐัะธัั
ะฐะบะบัะผัะปััะพัะฐ ะดะปั ะฟัะธะปะพะถะตะฝะธะน.
-
- ะะปะฐะฝะพะฒะฐั ะพััะฐะฝะพะฒะบะฐ ะพัะผะตะฝะตะฝะฐ
-
- ะะตัะตะทะฐะณััะทะบะฐ ะบะพะฝัะธะณััะฐัะธะธ ััะฝะฝะตะปะตะน...
-
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
deleted file mode 100755
index b3b7e389..00000000
--- a/android/res/values/strings.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
- i2pd
-
- Stop
- Graceful Stop
- Cancel Graceful Stop
- Reload tunnels
- Open Web Console
-
- Graceful stop is already in progress
- Graceful stop is in progress
- Graceful shutdown in progress
-
- Already stopped
- Application initializing
- Application starting
- Loaded JNI libraries
- Application Started
- Start failed
- Application stopped
- remaining
- OK
-
- Prompt
- SD card write permission denied, you need to allow this to continue
- SD card write access is required to write the keys and other files to the I2PD folder on SD card.
- Retry requesting the SD card write permissions
-
- Battery Optimizations
- Battery optimizations enabled
- Your Android is doing some heavy battery optimizations on I2PD that might lead to daemon closing with no other reason.\nIt is recommended to allow disabling those battery optimizations.
- Your Android is doing some heavy battery optimizations on I2PD that might lead to daemon closing with no other reason.\n\nYou will now be asked to allow to disable those.
- Continue
- Your Android version does not support opting out of battery optimizations
- Your Android OS version does not support showing the dialog for battery optimizations for applications.
-
- Planned shutdown canceled
-
- Reloading tunnels config...
-
diff --git a/android/res/values/template-dimens.xml b/android/res/values/template-dimens.xml
deleted file mode 100644
index 36847c97..00000000
--- a/android/res/values/template-dimens.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- 4dp
- 8dp
- 16dp
- 32dp
- 64dp
-
-
-
- @dimen/margin_medium
- @dimen/margin_medium
-
-
\ No newline at end of file
diff --git a/android/settings.gradle b/android/settings.gradle
deleted file mode 100644
index 2a620ef9..00000000
--- a/android/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = "i2pd"
diff --git a/android/src/org/purplei2p/i2pd/DaemonWrapper.java b/android/src/org/purplei2p/i2pd/DaemonWrapper.java
deleted file mode 100644
index 414a3ed1..00000000
--- a/android/src/org/purplei2p/i2pd/DaemonWrapper.java
+++ /dev/null
@@ -1,374 +0,0 @@
-package org.purplei2p.i2pd;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashSet;
-import java.util.Set;
-
-import android.annotation.TargetApi;
-import android.content.res.AssetManager;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Log;
-
-import androidx.annotation.RequiresApi;
-
-public class DaemonWrapper {
- private static final String TAG = "i2pd";
- private final AssetManager assetManager;
- private final ConnectivityManager connectivityManager;
- private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/";
- private boolean assetsCopied;
-
- public interface StateUpdateListener {
- void daemonStateUpdate(State oldValue, State newValue);
- }
-
- private final Set stateUpdateListeners = new HashSet<>();
-
- public synchronized void addStateChangeListener(StateUpdateListener listener) {
- stateUpdateListeners.add(listener);
- }
-
- public synchronized void removeStateChangeListener(StateUpdateListener listener) {
- stateUpdateListeners.remove(listener);
- }
-
- private synchronized void setState(State newState) {
- if (newState == null)
- throw new NullPointerException();
-
- State oldState = state;
-
- if (oldState == null)
- throw new NullPointerException();
-
- if (oldState.equals(newState))
- return;
-
- state = newState;
- fireStateUpdate1(oldState, newState);
- }
-
- public synchronized void stopAcceptingTunnels() {
- if (isStartedOkay()) {
- setState(State.gracefulShutdownInProgress);
- I2PD_JNI.stopAcceptingTunnels();
- }
- }
-
- public synchronized void startAcceptingTunnels() {
- if (isStartedOkay()) {
- setState(State.startedOkay);
- I2PD_JNI.startAcceptingTunnels();
- }
- }
-
- public synchronized void reloadTunnelsConfigs() {
- if (isStartedOkay()) {
- I2PD_JNI.reloadTunnelsConfigs();
- }
- }
-
- public int getTransitTunnelsCount() {
- return I2PD_JNI.GetTransitTunnelsCount();
- }
-
- public enum State {
- uninitialized(R.string.uninitialized),
- starting(R.string.starting),
- jniLibraryLoaded(R.string.jniLibraryLoaded),
- startedOkay(R.string.startedOkay),
- startFailed(R.string.startFailed),
- gracefulShutdownInProgress(R.string.gracefulShutdownInProgress),
- stopped(R.string.stopped);
-
- State(int statusStringResourceId) {
- this.statusStringResourceId = statusStringResourceId;
- }
-
- private final int statusStringResourceId;
-
- public int getStatusStringResourceId() {
- return statusStringResourceId;
- }
-
- public boolean isStartedOkay() {
- return equals(State.startedOkay) || equals(State.gracefulShutdownInProgress);
- }
- }
-
- private volatile State state = State.uninitialized;
-
- public State getState() {
- return state;
- }
-
- public DaemonWrapper(AssetManager assetManager, ConnectivityManager connectivityManager){
- this.assetManager = assetManager;
- this.connectivityManager = connectivityManager;
- setState(State.starting);
- new Thread(() -> {
- try {
- processAssets();
- I2PD_JNI.loadLibraries();
- setState(State.jniLibraryLoaded);
- registerNetworkCallback();
- } catch (Throwable tr) {
- lastThrowable = tr;
- setState(State.startFailed);
- return;
- }
- try {
- synchronized (DaemonWrapper.this) {
- I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
- daemonStartResult = I2PD_JNI.startDaemon();
- if ("ok".equals(daemonStartResult)) {
- setState(State.startedOkay);
- } else
- setState(State.startFailed);
- }
- } catch (Throwable tr) {
- lastThrowable = tr;
- setState(State.startFailed);
- }
- }, "i2pdDaemonStart").start();
- }
-
- private Throwable lastThrowable;
- private String daemonStartResult = "N/A";
-
- private void fireStateUpdate1(State oldValue, State newValue) {
- Log.i(TAG, "daemon state change: " + state);
- for (StateUpdateListener listener : stateUpdateListeners) {
- try {
- listener.daemonStateUpdate(oldValue, newValue);
- } catch (Throwable tr) {
- Log.e(TAG, "exception in listener ignored", tr);
- }
- }
- }
-
- public Throwable getLastThrowable() {
- return lastThrowable;
- }
-
- public String getDaemonStartResult() {
- return daemonStartResult;
- }
-
- public boolean isStartedOkay() {
- return getState().isStartedOkay();
- }
-
- public synchronized void stopDaemon() {
- if (isStartedOkay()) {
- try {
- I2PD_JNI.stopDaemon();
- } catch(Throwable tr) {
- Log.e(TAG, "", tr);
- }
-
- setState(State.stopped);
- }
- }
-
- private void processAssets() {
- if (!assetsCopied) {
- try {
- assetsCopied = true;
-
- File holderFile = new File(i2pdpath, "assets.ready");
- String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
- StringBuilder text = new StringBuilder();
-
- if (holderFile.exists()) {
- try { // if holder file exists, read assets version string
- FileReader fileReader = new FileReader(holderFile);
-
- try {
- BufferedReader br = new BufferedReader(fileReader);
-
- try {
- String line;
-
- while ((line = br.readLine()) != null) {
- text.append(line);
- }
- }finally {
- try {
- br.close();
- } catch (IOException e) {
- Log.e(TAG, "", e);
- }
- }
- } finally {
- try {
- fileReader.close();
- } catch (IOException e) {
- Log.e(TAG, "", e);
- }
- }
- } catch (IOException e) {
- Log.e(TAG, "", e);
- }
- }
-
- // if version differs from current app version or null, try to delete certificates folder
- if (!text.toString().contains(versionName))
- try {
- boolean deleteResult = holderFile.delete();
- if (!deleteResult)
- Log.e(TAG, "holderFile.delete() returned " + deleteResult + ", absolute path='" + holderFile.getAbsolutePath() + "'");
- File certPath = new File(i2pdpath, "certificates");
- deleteRecursive(certPath);
- }
- catch (Throwable tr) {
- Log.e(TAG, "", tr);
- }
-
- // copy assets. If processed file exists, it won't be overwritten
- copyAsset("addressbook");
- copyAsset("certificates");
- copyAsset("tunnels.d");
- copyAsset("i2pd.conf");
- copyAsset("subscriptions.txt");
- copyAsset("tunnels.conf");
-
- // update holder file about successful copying
- FileWriter writer = new FileWriter(holderFile);
- try {
- writer.append(versionName);
- } finally {
- try {
- writer.close();
- } catch (IOException e) {
- Log.e(TAG,"on writer close", e);
- }
- }
- }
- catch (Throwable tr)
- {
- Log.e(TAG,"on assets copying", tr);
- }
- }
- }
-
- /**
- * Copy the asset at the specified path to this app's data directory. If the
- * asset is a directory, its contents are also copied.
- *
- * @param path
- * Path to asset, relative to app's assets directory.
- */
- private void copyAsset(String path) {
- // If we have a directory, we make it and recurse. If a file, we copy its
- // contents.
- try {
- String[] contents = assetManager.list(path);
-
- // The documentation suggests that list throws an IOException, but doesn't
- // say under what conditions. It'd be nice if it did so when the path was
- // to a file. That doesn't appear to be the case. If the returned array is
- // null or has 0 length, we assume the path is to a file. This means empty
- // directories will get turned into files.
- if (contents == null || contents.length == 0) {
- copyFileAsset(path);
- return;
- }
-
- // Make the directory.
- File dir = new File(i2pdpath, path);
- boolean result = dir.mkdirs();
- Log.d(TAG, "dir.mkdirs() returned " + result);
-
- // Recurse on the contents.
- for (String entry : contents) {
- copyAsset(path + '/' + entry);
- }
- } catch (IOException e) {
- Log.e(TAG, "ex ignored for path='" + path + "'", e);
- }
- }
-
- /**
- * Copy the asset file specified by path to app's data directory. Assumes
- * parent directories have already been created.
- *
- * @param path
- * Path to asset, relative to app's assets directory.
- */
- private void copyFileAsset(String path) {
- File file = new File(i2pdpath, path);
- if (!file.exists()) {
- try {
- try (InputStream in = assetManager.open(path)) {
- try (OutputStream out = new FileOutputStream(file)) {
- byte[] buffer = new byte[1024];
- int read = in.read(buffer);
- while (read != -1) {
- out.write(buffer, 0, read);
- read = in.read(buffer);
- }
- }
- }
- } catch (IOException e) {
- Log.e(TAG, "", e);
- }
- }
- }
-
- private void deleteRecursive(File fileOrDirectory) {
- if (fileOrDirectory.isDirectory()) {
- File[] files = fileOrDirectory.listFiles();
- if (files != null) {
- for (File child : files) {
- deleteRecursive(child);
- }
- }
- }
- boolean deleteResult = fileOrDirectory.delete();
- if (!deleteResult)
- Log.e(TAG, "fileOrDirectory.delete() returned " + deleteResult + ", absolute path='" + fileOrDirectory.getAbsolutePath() + "'");
- }
-
- private void registerNetworkCallback(){
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) registerNetworkCallback0();
- }
-
- @TargetApi(Build.VERSION_CODES.M)
- private void registerNetworkCallback0() {
- NetworkRequest request = new NetworkRequest.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
- .build();
- NetworkStateCallbackImpl networkCallback = new NetworkStateCallbackImpl();
- connectivityManager.registerNetworkCallback(request, networkCallback);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- private static final class NetworkStateCallbackImpl extends ConnectivityManager.NetworkCallback {
- @Override
- public void onAvailable(Network network) {
- super.onAvailable(network);
- I2PD_JNI.onNetworkStateChanged(true);
- Log.i(TAG, "NetworkCallback.onAvailable");
- }
-
- @Override
- public void onLost(Network network) {
- super.onLost(network);
- I2PD_JNI.onNetworkStateChanged(false);
- Log.i(TAG, " NetworkCallback.onLost");
- }
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java
deleted file mode 100644
index c97b7f1f..00000000
--- a/android/src/org/purplei2p/i2pd/ForegroundService.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.purplei2p.i2pd;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Build;
-import android.os.IBinder;
-import androidx.annotation.RequiresApi;
-import androidx.core.app.NotificationCompat;
-import android.util.Log;
-
-public class ForegroundService extends Service {
- private static final String TAG="FgService";
-
- private volatile boolean shown;
-
- private static ForegroundService instance;
-
- private static volatile DaemonWrapper daemon;
-
- private static final Object initDeinitLock = new Object();
-
- private final DaemonWrapper.StateUpdateListener daemonStateUpdatedListener =
- new DaemonWrapper.StateUpdateListener() {
-
- @Override
- public void daemonStateUpdate(DaemonWrapper.State oldValue, DaemonWrapper.State newValue) {
- updateNotificationText();
- }
- };
-
- private void updateNotificationText() {
- try {
- synchronized (initDeinitLock) {
- if (shown) cancelNotification();
- showNotification();
- }
- } catch (Throwable tr) {
- Log.e(TAG,"error ignored",tr);
- }
- }
-
-
- private NotificationManager notificationManager;
-
- // Unique Identification Number for the Notification.
- // We use it on Notification start, and to cancel it.
- private static final int NOTIFICATION = 1;
-
- /**
- * Class for clients to access. Because we know this service always
- * runs in the same process as its clients, we don't need to deal with
- * IPC.
- */
- public class LocalBinder extends Binder {
- ForegroundService getService() {
- return ForegroundService.this;
- }
- }
-
- public static void init(DaemonWrapper daemon) {
- ForegroundService.daemon = daemon;
- initCheck();
- }
-
- private static void initCheck() {
- synchronized (initDeinitLock) {
- if (instance != null && daemon != null) instance.setListener();
- }
- }
-
- @Override
- public void onCreate() {
- notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
- instance = this;
- initCheck();
- }
-
- private void setListener() {
- daemon.addStateChangeListener(daemonStateUpdatedListener);
- updateNotificationText();
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.i("ForegroundService", "Received start id " + startId + ": " + intent);
- return START_STICKY;
- }
-
- @Override
- public void onDestroy() {
- cancelNotification();
- deinitCheck();
- instance=null;
- }
-
- public static void deinit() {
- deinitCheck();
- }
-
- private static void deinitCheck() {
- synchronized (initDeinitLock) {
- if (daemon != null && instance != null)
- daemon.removeStateChangeListener(instance.daemonStateUpdatedListener);
- }
- }
-
- private void cancelNotification() {
- synchronized (initDeinitLock) {
- // Cancel the persistent notification.
- notificationManager.cancel(NOTIFICATION);
-
- stopForeground(true);
-
- // Tell the user we stopped.
- //Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show();
- shown = false;
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- // This is the object that receives interactions from clients. See
- // RemoteService for a more complete example.
- private final IBinder mBinder = new LocalBinder();
-
- /**
- * Show a notification while this service is running.
- */
- private void showNotification() {
- synchronized (initDeinitLock) {
- if (daemon != null) {
- // In this sample, we'll use the same text for the ticker and the expanded notification
- CharSequence text = getText(daemon.getState().getStatusStringResourceId());
-
- // The PendingIntent to launch our activity if the user selects this notification
- PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
- new Intent(this, I2PDActivity.class), 0);
-
- // If earlier version channel ID is not used
- // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
- String channelId = Build.VERSION.SDK_INT >= 26 ? createNotificationChannel() : "";
-
- // Set the info for the views that show in the notification panel.
- NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
- .setOngoing(true)
- .setSmallIcon(R.drawable.itoopie_notification_icon); // the status icon
- if (Build.VERSION.SDK_INT >= 16)
- builder = builder.setPriority(Notification.PRIORITY_DEFAULT);
- if (Build.VERSION.SDK_INT >= 21)
- builder = builder.setCategory(Notification.CATEGORY_SERVICE);
- Notification notification = builder
- .setTicker(text) // the status text
- .setWhen(System.currentTimeMillis()) // the time stamp
- .setContentTitle(getText(R.string.app_name)) // the label of the entry
- .setContentText(text) // the contents of the entry
- .setContentIntent(contentIntent) // The intent to send when the entry is clicked
- .build();
-
- // Send the notification.
- //mNM.notify(NOTIFICATION, notification);
- startForeground(NOTIFICATION, notification);
- shown = true;
- }
- }
- }
-
- @RequiresApi(Build.VERSION_CODES.O)
- private synchronized String createNotificationChannel() {
- String channelId = getString(R.string.app_name);
- CharSequence channelName = "I2Pd service";
- NotificationChannel chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
- //chan.setLightColor(Color.PURPLE);
- chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
- NotificationManager service = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
- if(service!=null)service.createNotificationChannel(chan);
- else Log.e(TAG, "error: NOTIFICATION_SERVICE is null");
- return channelId;
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java
deleted file mode 100755
index 9645d4f7..00000000
--- a/android/src/org/purplei2p/i2pd/I2PDActivity.java
+++ /dev/null
@@ -1,486 +0,0 @@
-package org.purplei2p.i2pd;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.PowerManager;
-import android.preference.PreferenceManager;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.TextView;
-import android.widget.Toast;
-
-
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-
-// For future package update checking
-
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-
-import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS;
-
-public class I2PDActivity extends Activity {
- private static final String TAG = "i2pdActvt";
- private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
- public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
- public static final String PACKAGE_URI_SCHEME = "package:";
-
- private TextView textView;
- //private ConfigParser parser = new ConfigParser(i2pdpath); // TODO
-
- private static volatile DaemonWrapper daemon;
-
- private final DaemonWrapper.StateUpdateListener daemonStateUpdatedListener = new DaemonWrapper.StateUpdateListener() {
- @Override
- public void daemonStateUpdate(DaemonWrapper.State oldValue, DaemonWrapper.State newValue) {
- updateStatusText();
- }
- };
-
- private void updateStatusText() {
- runOnUiThread(() -> {
- try {
- if (textView == null)
- return;
- Throwable tr = daemon.getLastThrowable();
- if (tr!=null) {
- textView.setText(throwableToString(tr));
- return;
- }
- DaemonWrapper.State state = daemon.getState();
- String startResultStr = DaemonWrapper.State.startFailed.equals(state) ? String.format(": %s", daemon.getDaemonStartResult()) : "";
- String graceStr = DaemonWrapper.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
- textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
- } catch (Throwable tr) {
- Log.e(TAG,"error ignored",tr);
- }
- });
- }
-
- private static volatile long graceStartedMillis;
- private static final Object graceStartedMillis_LOCK = new Object();
- private Menu optionsMenu;
-
- private static String formatGraceTimeRemaining() {
- long remainingSeconds;
- synchronized (graceStartedMillis_LOCK) {
- remainingSeconds = Math.round(Math.max(0, graceStartedMillis + GRACEFUL_DELAY_MILLIS - System.currentTimeMillis()) / 1000.0D);
- }
- long remainingMinutes = (long)Math.floor(remainingSeconds / 60.0D);
- long remSec = remainingSeconds - remainingMinutes * 60;
- return remainingMinutes + ":" + (remSec / 10) + remSec % 10;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- Log.i(TAG, "onCreate");
- super.onCreate(savedInstanceState);
-
- if (daemon==null) {
- ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- daemon = new DaemonWrapper(getAssets(), connectivityManager);
- }
- ForegroundService.init(daemon);
-
- textView = new TextView(this);
- setContentView(textView);
- daemon.addStateChangeListener(daemonStateUpdatedListener);
- daemonStateUpdatedListener.daemonStateUpdate(DaemonWrapper.State.uninitialized, daemon.getState());
-
- // request permissions
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
- }
- }
-
- // set the app be foreground
- doBindService();
-
- final Timer gracefulQuitTimer = getGracefulQuitTimer();
- if (gracefulQuitTimer != null) {
- long gracefulStopAtMillis;
- synchronized (graceStartedMillis_LOCK) {
- gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
- }
- rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
- }
-
- openBatteryOptimizationDialogIfNeeded();
-
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- textView = null;
- ForegroundService.deinit();
- daemon.removeStateChangeListener(daemonStateUpdatedListener);
- //cancelGracefulStop0();
- try {
- doUnbindService();
- } catch(Throwable tr) {
- Log.e(TAG, "", tr);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
- {
- if (requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
- Log.e(TAG, "WR_EXT_STORAGE perm granted");
- else {
- Log.e(TAG, "WR_EXT_STORAGE perm declined, stopping i2pd");
- i2pdStop();
- //TODO must work w/o this perm, ask orignal
- }
- }
- }
-
- private void cancelGracefulStop0() {
- Timer gracefulQuitTimer = getGracefulQuitTimer();
- if (gracefulQuitTimer != null) {
- gracefulQuitTimer.cancel();
- setGracefulQuitTimer(null);
- }
- }
-
- private CharSequence throwableToString(Throwable tr) {
- StringWriter sw = new StringWriter(8192);
- PrintWriter pw = new PrintWriter(sw);
- tr.printStackTrace(pw);
- pw.close();
- return sw.toString();
- }
-
- // private LocalService mBoundService;
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // This is called when the connection with the service has been
- // established, giving us the service object we can use to
- // interact with the service. Because we have bound to a explicit
- // service that we know is running in our own process, we can
- // cast its IBinder to a concrete class and directly access it.
- // mBoundService = ((LocalService.LocalBinder)service).getService();
-
- // Tell the user about this for our demo.
- // Toast.makeText(Binding.this, R.string.local_service_connected,
- // Toast.LENGTH_SHORT).show();
- }
-
- public void onServiceDisconnected(ComponentName className) {
- // This is called when the connection with the service has been
- // unexpectedly disconnected -- that is, its process crashed.
- // Because it is running in our same process, we should never
- // see this happen.
- // mBoundService = null;
- // Toast.makeText(Binding.this, R.string.local_service_disconnected,
- // Toast.LENGTH_SHORT).show();
- }
- };
-
- private static volatile boolean mIsBound;
-
- private void doBindService() {
- synchronized (I2PDActivity.class) {
- if (mIsBound)
- return;
- // Establish a connection with the service. We use an explicit
- // class name because we want a specific service implementation that
- // we know will be running in our own process (and thus won't be
- // supporting component replacement by other applications).
- bindService(new Intent(this, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE);
- mIsBound = true;
- }
- }
-
- private void doUnbindService() {
- synchronized (I2PDActivity.class) {
- if (mIsBound) {
- // Detach our existing connection.
- unbindService(mConnection);
- mIsBound = false;
- }
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.options_main, menu);
- menu.findItem(R.id.action_battery_otimizations).setVisible(isBatteryOptimizationsOpenOsDialogApiAvailable());
- this.optionsMenu = menu;
- return true;
- }
-
- private boolean isBatteryOptimizationsOpenOsDialogApiAvailable() {
- return android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
- }
-
- @Override
- public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
-
- switch(id) {
- case R.id.action_stop:
- i2pdStop();
- return true;
-
- case R.id.action_graceful_stop:
- synchronized (graceStartedMillis_LOCK) {
- if (getGracefulQuitTimer() != null)
- cancelGracefulStop();
- else
- i2pdGracefulStop();
- }
- return true;
-
- case R.id.action_battery_otimizations:
- onActionBatteryOptimizations();
- return true;
-
- case R.id.action_reload_tunnels_config:
- onReloadTunnelsConfig();
- return true;
-
- case R.id.action_start_webview:
- startActivity(new Intent(getApplicationContext(), WebConsoleActivity.class));
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- private void onActionBatteryOptimizations() {
- if (isBatteryOptimizationsOpenOsDialogApiAvailable()) {
- try {
- startActivity(new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "BATT_OPTIM_DIALOG_ActvtNotFound", e);
- Toast.makeText(this, R.string.os_version_does_not_support_battery_optimizations_show_os_dialog_api, Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- private void onReloadTunnelsConfig() {
- Log.d(TAG, "reloading tunnels");
- daemon.reloadTunnelsConfigs();
- Toast.makeText(this, R.string.tunnels_reloading, Toast.LENGTH_SHORT).show();
- }
-
- private void i2pdStop() {
- cancelGracefulStop0();
- new Thread(() -> {
- Log.d(TAG, "stopping");
- try {
- daemon.stopDaemon();
- } catch (Throwable tr) {
- Log.e(TAG, "", tr);
- }
- quit(); //TODO make menu items for starting i2pd. On my Android, I need to reboot the OS to restart i2pd.
- }, "stop").start();
- }
-
- private static volatile Timer gracefulQuitTimer;
-
- private void i2pdGracefulStop() {
- if (daemon.getState() == DaemonWrapper.State.stopped) {
- Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show();
- return;
- }
- if (getGracefulQuitTimer() != null) {
- Toast.makeText(this, R.string.graceful_stop_is_already_in_progress, Toast.LENGTH_SHORT).show();
- return;
- }
- Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show();
- new Thread(() -> {
- try {
- Log.d(TAG, "graceful stopping");
- if (daemon.isStartedOkay()) {
- daemon.stopAcceptingTunnels();
- long gracefulStopAtMillis;
- synchronized (graceStartedMillis_LOCK) {
- graceStartedMillis = System.currentTimeMillis();
- gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
- }
- rescheduleGraceStop(null, gracefulStopAtMillis);
- } else
- i2pdStop();
- } catch(Throwable tr) {
- Log.e(TAG, "", tr);
- }
- }, "gracInit").start();
- }
-
- private void cancelGracefulStop()
- {
- cancelGracefulStop0();
- new Thread(() -> {
- try {
- Log.d(TAG, "canceling graceful stop");
- if (daemon.isStartedOkay()) {
- daemon.startAcceptingTunnels();
- runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
- } else
- i2pdStop();
- } catch(Throwable tr) {
- Log.e(TAG, "", tr);
- }
- }, "gracCancel").start();
- }
-
- private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
- if (gracefulQuitTimerOld != null)
- gracefulQuitTimerOld.cancel();
-
- if(daemon.getTransitTunnelsCount() <= 0) { // no tunnels left
- Log.d(TAG, "no transit tunnels left, stopping");
- i2pdStop();
- return;
- }
-
- final Timer gracefulQuitTimer = new Timer(true);
- setGracefulQuitTimer(gracefulQuitTimer);
- gracefulQuitTimer.schedule(new TimerTask() {
-
- @Override
- public void run() {
- i2pdStop();
- }
-
- }, Math.max(0, gracefulStopAtMillis - System.currentTimeMillis()));
- final TimerTask tickerTask = new TimerTask() {
- @Override
- public void run() {
- updateStatusText();
- }
- };
- gracefulQuitTimer.scheduleAtFixedRate(tickerTask, 0/*start delay*/, 1000/*millis period*/);
- }
-
- private static Timer getGracefulQuitTimer() {
- return gracefulQuitTimer;
- }
-
- private void setGracefulQuitTimer(Timer gracefulQuitTimer) {
- I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
- runOnUiThread(()-> {
- Menu menu = optionsMenu;
- if (menu != null) {
- MenuItem item = menu.findItem(R.id.action_graceful_stop);
- if (item != null) {
- synchronized (graceStartedMillis_LOCK) {
- item.setTitle(getGracefulQuitTimer() != null ? R.string.action_cancel_graceful_stop : R.string.action_graceful_stop);
- }
- }
- }
- });
- }
-
- @SuppressLint("BatteryLife")
- private void openBatteryOptimizationDialogIfNeeded() {
- boolean questionEnabled = getPreferences().getBoolean(getBatteryOptimizationPreferenceKey(), true);
- Log.i(TAG, "BATT_OPTIM_questionEnabled==" + questionEnabled);
- if (!isKnownIgnoringBatteryOptimizations()
- && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
- && questionEnabled) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.battery_optimizations_enabled);
- builder.setMessage(R.string.battery_optimizations_enabled_dialog);
- builder.setPositiveButton(R.string.continue_str, (dialog, which) -> {
- try {
- startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse(PACKAGE_URI_SCHEME + getPackageName())));
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "BATT_OPTIM_ActvtNotFound", e);
- Toast.makeText(this, R.string.device_does_not_support_disabling_battery_optimizations, Toast.LENGTH_SHORT).show();
- }
- });
- builder.setOnDismissListener(dialog -> setNeverAskForBatteryOptimizationsAgain());
- final AlertDialog dialog = builder.create();
- dialog.setCanceledOnTouchOutside(false);
- dialog.show();
- }
- }
-
- private void setNeverAskForBatteryOptimizationsAgain() {
- getPreferences().edit().putBoolean(getBatteryOptimizationPreferenceKey(), false).apply();
- }
-
- protected boolean isKnownIgnoringBatteryOptimizations() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- final PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
- if (pm == null) {
- Log.i(TAG, "BATT_OPTIM: POWER_SERVICE==null");
- return false;
- }
- boolean ignoring = pm.isIgnoringBatteryOptimizations(getPackageName());
- Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
- return ignoring;
- } else {
- Log.i(TAG, "BATT_OPTIM: old sdk version==" + Build.VERSION.SDK_INT);
- return false;
- }
- }
-
- protected SharedPreferences getPreferences() {
- return PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
- }
-
- private String getBatteryOptimizationPreferenceKey() {
- @SuppressLint("HardwareIds") String device = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
- return "show_battery_optimization" + (device == null ? "" : device);
- }
-
- private void quit() {
- try {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- finishAndRemoveTask();
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- finishAffinity();
- } else {
- //moveTaskToBack(true);
- finish();
- }
- } catch (Throwable tr) {
- Log.e(TAG, "", tr);
- }
- try {
- daemon.stopDaemon();
- } catch (Throwable tr) {
- Log.e(TAG, "", tr);
- }
- System.exit(0);
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java b/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
deleted file mode 100644
index 149a3aa2..00000000
--- a/android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.purplei2p.i2pd;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-
-import java.lang.reflect.Method;
-
-//dangerous perms, per https://developer.android.com/guide/topics/permissions/normal-permissions.html :
-//android.permission.WRITE_EXTERNAL_STORAGE
-public class I2PDPermsAskerActivity extends Activity {
-
- private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
-
- private Button button_request_write_ext_storage_perms;
- private TextView textview_retry;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //if less than Android 6, no runtime perms req system present
- if (android.os.Build.VERSION.SDK_INT < 23) {
- startMainActivity();
- return;
- }
-
-
- setContentView(R.layout.activity_perms_asker);
- button_request_write_ext_storage_perms = (Button) findViewById(R.id.button_request_write_ext_storage_perms);
- textview_retry = (TextView) findViewById(R.id.textview_retry);
-
- button_request_write_ext_storage_perms.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- request_write_ext_storage_perms();
- }
- });
- request_write_ext_storage_perms();
- }
-
- private void request_write_ext_storage_perms() {
-
- textview_retry.setVisibility(TextView.GONE);
- button_request_write_ext_storage_perms.setVisibility(Button.GONE);
-
- Method methodCheckPermission;
- Method method_shouldShowRequestPermissionRationale;
- Method method_requestPermissions;
- try {
- methodCheckPermission = getClass().getMethod("checkSelfPermission", String.class);
- method_shouldShowRequestPermissionRationale =
- getClass().getMethod("shouldShowRequestPermissionRationale", String.class);
- method_requestPermissions =
- getClass().getMethod("requestPermissions", String[].class, int.class);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- Integer resultObj;
- try {
- resultObj = (Integer) methodCheckPermission.invoke(
- this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
-
- if (resultObj != PackageManager.PERMISSION_GRANTED) {
-
- // Should we show an explanation?
- Boolean aBoolean;
- try {
- aBoolean = (Boolean) method_shouldShowRequestPermissionRationale.invoke(this,
- Manifest.permission.WRITE_EXTERNAL_STORAGE);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (aBoolean) {
-
- // Show an explanation to the user *asynchronously* -- don't block
- // this thread waiting for the user's response! After the user
- // sees the explanation, try again to request the permission.
-
- showExplanation();
-
- } else {
-
- // No explanation needed, we can request the permission.
-
- try {
- method_requestPermissions.invoke(this,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- PERMISSION_WRITE_EXTERNAL_STORAGE);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- } else startMainActivity();
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode,
- String permissions[], int[] grantResults) {
- switch (requestCode) {
- case PERMISSION_WRITE_EXTERNAL_STORAGE: {
- // If request is cancelled, the result arrays are empty.
- if (grantResults.length > 0
- && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-
- // permission was granted, yay! Do the
- // contacts-related task you need to do.
-
- startMainActivity();
-
- } else {
-
- // permission denied, boo! Disable the
- // functionality that depends on this permission.
- textview_retry.setText(R.string.permDenied);
- textview_retry.setVisibility(TextView.VISIBLE);
- button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
- }
- }
-
- // other 'case' lines to check for other
- // permissions this app might request.
- }
- }
-
- private void startMainActivity() {
- startActivity(new Intent(this, I2PDActivity.class));
- finish();
- }
-
- private static final int SHOW_EXPLANATION_REQUEST = 1; // The request code
- private void showExplanation() {
- Intent intent = new Intent(this, I2PDPermsExplanationActivity.class);
- startActivityForResult(intent, SHOW_EXPLANATION_REQUEST);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // Check which request we're responding to
- if (requestCode == SHOW_EXPLANATION_REQUEST) {
- // Make sure the request was successful
- if (resultCode == RESULT_OK) {
- // Request the permission
- Method method_requestPermissions;
- try {
- method_requestPermissions =
- getClass().getMethod("requestPermissions", String[].class, int.class);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- try {
- method_requestPermissions.invoke(this,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- PERMISSION_WRITE_EXTERNAL_STORAGE);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- } else {
- finish(); //close the app
- }
- }
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java b/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java
deleted file mode 100644
index 885df75c..00000000
--- a/android/src/org/purplei2p/i2pd/I2PDPermsExplanationActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.purplei2p.i2pd;
-
-import android.app.ActionBar;
-import android.content.Intent;
-import android.os.Bundle;
-import android.app.Activity;
-import android.view.View;
-import android.widget.Button;
-
-public class I2PDPermsExplanationActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_perms_explanation);
- ActionBar actionBar = getActionBar();
- if(actionBar!=null)actionBar.setHomeButtonEnabled(false);
- Button button_ok = (Button) findViewById(R.id.button_ok);
- button_ok.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- returnFromActivity();
- }
- });
- }
-
- private void returnFromActivity() {
- Intent data = new Intent();
- Activity parent = getParent();
- if (parent == null) {
- setResult(Activity.RESULT_OK, data);
- } else {
- parent.setResult(Activity.RESULT_OK, data);
- }
- finish();
- }
-
-}
diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java
deleted file mode 100644
index 582b102b..00000000
--- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.purplei2p.i2pd;
-
-public class I2PD_JNI {
- public static native String getABICompiledWith();
-
- /**
- * returns error info if failed
- * returns "ok" if daemon initialized and started okay
- */
- public static native String startDaemon();
-
- //should only be called after startDaemon() success
- public static native void stopDaemon();
-
- public static native void stopAcceptingTunnels();
-
- public static native void startAcceptingTunnels();
-
- public static native void reloadTunnelsConfigs();
-
- public static native void onNetworkStateChanged(boolean isConnected);
-
- public static native void setDataDir(String jdataDir);
-
- public static native int GetTransitTunnelsCount();
-
- public static void loadLibraries() {
- //System.loadLibrary("c++_shared");
- System.loadLibrary("i2pd");
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java b/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java
deleted file mode 100644
index 437debe8..00000000
--- a/android/src/org/purplei2p/i2pd/NetworkStateChangeReceiver.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.purplei2p.i2pd;
-
-import android.util.Log;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-
-public class NetworkStateChangeReceiver extends BroadcastReceiver {
-
- private static final String TAG = "i2pd";
-
- //api level 1
- @Override
- public void onReceive(final Context context, final Intent intent) {
- Log.d(TAG,"Network state change");
- try {
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
- boolean isConnected = activeNetworkInfo!=null && activeNetworkInfo.isConnected();
- // https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html?hl=ru
- // boolean isWiFi = activeNetworkInfo!=null && (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
-
- I2PD_JNI.onNetworkStateChanged(isConnected);
- } catch (Throwable tr) {
- Log.d(TAG,"",tr);
- }
- }
-}
diff --git a/android/src/org/purplei2p/i2pd/WebConsoleActivity.java b/android/src/org/purplei2p/i2pd/WebConsoleActivity.java
deleted file mode 100644
index 0fcf37fe..00000000
--- a/android/src/org/purplei2p/i2pd/WebConsoleActivity.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.purplei2p.i2pd;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.MenuItem;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import java.util.Objects;
-
-public class WebConsoleActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_web_console);
-
- Objects.requireNonNull(getActionBar()).setDisplayHomeAsUpEnabled(true);
-
- final WebView webView = findViewById(R.id.webview1);
- webView.setWebViewClient(new WebViewClient());
-
- final WebSettings webSettings = webView.getSettings();
- webSettings.setBuiltInZoomControls(true);
- webSettings.setJavaScriptEnabled(false);
- webView.loadUrl("http://127.0.0.1:7070"); // TODO: instead 7070 I2Pd....HttpPort
- }
-
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
-
- if (id==android.R.id.home) {
- finish();
- return true;
- }
- return false;
- }
-}
diff --git a/appveyor.yml b/appveyor.yml
index cc6d130b..4247c5ab 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.35.0.{build}
+version: 2.36.0.{build}
pull_requests:
do_not_increment_build_number: true
branches:
diff --git a/android_binary_only/.gitignore b/contrib/android_binary_only/.gitignore
similarity index 100%
rename from android_binary_only/.gitignore
rename to contrib/android_binary_only/.gitignore
diff --git a/android_binary_only/jni/Android.mk b/contrib/android_binary_only/jni/Android.mk
old mode 100755
new mode 100644
similarity index 100%
rename from android_binary_only/jni/Android.mk
rename to contrib/android_binary_only/jni/Android.mk
diff --git a/android_binary_only/jni/Application.mk b/contrib/android_binary_only/jni/Application.mk
old mode 100755
new mode 100644
similarity index 97%
rename from android_binary_only/jni/Application.mk
rename to contrib/android_binary_only/jni/Application.mk
index bb4afac3..5d54645b
--- a/android_binary_only/jni/Application.mk
+++ b/contrib/android_binary_only/jni/Application.mk
@@ -33,7 +33,7 @@ MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
# don't change me
-I2PD_SRC_PATH = $(PWD)/..
+I2PD_SRC_PATH = $(PWD)/../..
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
diff --git a/contrib/android_binary_pack/build-archive b/contrib/android_binary_pack/build-archive
index c439dd7f..30f5b48d 100755
--- a/contrib/android_binary_pack/build-archive
+++ b/contrib/android_binary_pack/build-archive
@@ -20,7 +20,7 @@ if [ -d archive ]; then
rm -r archive
fi
-if [ -f i2pd_*_android_binary.zip ]; then
+if [ -f ../i2pd_*_android_binary.zip ]; then
rm i2pd_*_android_binary.zip
fi
@@ -28,13 +28,16 @@ fi
mkdir archive
for ABI in "${!ABILIST[@]}"; do
- if [ -f ../../android_binary_only/libs/${ABI}/i2pd ]; then
- cp ../../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
+ if [ -f ../android_binary_only/libs/${ABI}/i2pd ]; then
+ cp ../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
fi
done
cp i2pd archive/i2pd
-cp -rH ../../android/assets/* archive/
+cp -rH ../android/assets/certificates archive/
+cp -rH ../android/assets/tunnels.conf.d archive/
+cp -H ../android/assets/i2pd.conf archive/
+cp -H ../android/assets/tunnels.conf archive/
# Compress files
cd archive
diff --git a/contrib/certificates/reseed/acetone_at_mail.i2p.crt b/contrib/certificates/reseed/acetone_at_mail.i2p.crt
new file mode 100644
index 00000000..13f9f17d
--- /dev/null
+++ b/contrib/certificates/reseed/acetone_at_mail.i2p.crt
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIEctG1gDANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
+WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
+b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEZMBcGA1UEAwwQYWNldG9uZUBtYWls
+LmkycDAeFw0yMTAxMjUxMDMyMjBaFw0zMTAxMjMxMDMyMjBaMHAxCzAJBgNVBAYT
+AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNVBAoMFUkyUCBBbm9u
+eW1vdXMgTmV0d29yazEMMAoGA1UECwwDSTJQMRkwFwYDVQQDDBBhY2V0b25lQG1h
+aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwqF/BRRmvZ54
+5XArgxbytDi7m7MDjFE/whUADruHj/9jXGCxE8DDiiKTt3yhfakV0SNo5xk7AMD+
+wqiSNC5JCHTm18gd2M4cQLIaOVRqucLLge4XVgk2WPX6OT98wfxh7mqA3wlSdEpj
+dY3Txtkf7VfZLicG76/RBtLFW3aBdsn63hZaQqZE4x/5MJyPVZx59+lys5RmMi0o
+LpXJy4HOu1/Gl1iKDJoI/ARFG3y7uP/B+ZtZBitJetTs0HcqycnNJq0tVZf2HiGF
+JNy67AL4foxNYPXP6QsvXvp6LRpGANaBCkFCBlriSF+x1zO2H3uAkRnuLYXuKIfB
+HudejTp4R57VgZGiHYoawHaF17FVAApue9G8O82XYECjhET35B9yFoOBHTvaMxLU
+CKrmayH8KMQon95mfe1qpoO3/YDa8DCxkjAfjdtytat7nt2pGZMH6/cLJxcFiofh
+RtRVvb+omv/X12j/6iCFrwP4NvBnAZsa736igbjpyee5n+CSyYxd9cJkRX1vQVk7
+WFSqL58Pz+g6CKJmdMPvqNOfUQ6mieBeejmx35B4pLzLcoNxw8R3O1+I2l4dg042
+dEydKRQNwdzOec4jYwnKR40iwIyZxpchXWGRbBdyF5RQCbIIo60QBJlfXMJ2svan
+q5lYIeWeY3mlODXu4KH4K09y10KT8FsCAwEAAaMhMB8wHQYDVR0OBBYEFMh+DoIL
+APNiu2o+6I9A49joNYQuMA0GCSqGSIb3DQEBDQUAA4ICAQBFeOJi0rmkqN5/E3IB
+nE2x4mUeLI82tUcN2D3Yu8J81vy4DnH+oMRQFDtYEHW5pfirRmgSZ7MQwYQnqWLp
+iTE7SyCxlqGrmVsYp7PzfS1pUT2QeWPtsNYUDdraG0Zr9BkIGB60VMhjMSa9WUrj
+lbchzr6E/j/EsEOE7IK08JxIDKCDZM2LLwis4tAM6tmiylkMf2RlUBIRBs1TCO+q
+x3yByttNE2P4nQyQVQpjc1qsaOMvJvbxun37dwo+oTQy+hwkA86BWTDRYdN3xwOk
+OfAOtlX6zM/wCKMN0ZRnjZoh59ZCn4JXokt3IjZ4n8qJOuJFRKeKGmGeKA8uaGW8
+ih5tdB99Gu5Z8LOT1FxAJKwQBn5My0JijPoMit4B0WKNC8hy2zc2YvNfflu1ZRj5
+wF4E5ktbtT/LWFSoRPas/GFS8wSXk/kbSB0ArDcRRszb3JHqbALmSQxngz3rfwb3
+SHwQIIg956gjMDueEX5CrGrMqigiK53b9fqtpghUrHDsqtEXqeImpAY65PX1asqo
+metDNuETHF7XrAjP7TGJfnrYQyeK90iS7j1G68ScBGkKY2nsTnFoXkSk5s5D338E
+SUzPaOlh91spmkVY6gQTVQ7BakADBHw+zBgDA1gBN/4JPvgN36hquj63+aG1cKy3
+3ZUnv2ipo2fpr69NtuBnutK6gw==
+-----END CERTIFICATE-----
diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf
index 5ef39bc9..0c2ec5bc 100644
--- a/contrib/i2pd.conf
+++ b/contrib/i2pd.conf
@@ -192,8 +192,8 @@ verify = true
[addressbook]
## AddressBook subscription URL for initial setup
-## Default: inr.i2p at "mainline" I2P Network
-# defaulturl = http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt
+## Default: reg.i2p at "mainline" I2P Network
+# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt
## Optional subscriptions URLs, separated by comma
# subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
@@ -237,4 +237,4 @@ verify = true
# avx = true
## Force usage of CPU instructions set, even if they not found
## DO NOT TOUCH that option if you really don't know what are you doing!
-# force = false
\ No newline at end of file
+# force = false
diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec
index d622ced5..a9f10510 100644
--- a/contrib/rpm/i2pd-git.spec
+++ b/contrib/rpm/i2pd-git.spec
@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
-Version: 2.35.0
+Version: 2.36.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@@ -137,6 +137,9 @@ getent passwd i2pd >/dev/null || \
%changelog
+* Mon Feb 15 2021 orignal - 2.36.0
+- update to 2.36.0
+
* Mon Nov 30 2020 orignal - 2.35.0
- update to 2.35.0
diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec
index d147c269..d8ae9541 100644
--- a/contrib/rpm/i2pd.spec
+++ b/contrib/rpm/i2pd.spec
@@ -1,5 +1,5 @@
Name: i2pd
-Version: 2.35.0
+Version: 2.36.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -135,6 +135,9 @@ getent passwd i2pd >/dev/null || \
%changelog
+* Mon Feb 15 2021 orignal - 2.36.0
+- update to 2.36.0
+
* Mon Nov 30 2020 orignal - 2.35.0
- update to 2.35.0
diff --git a/contrib/subscriptions.txt b/contrib/subscriptions.txt
index 8f4afb03..76d73993 100644
--- a/contrib/subscriptions.txt
+++ b/contrib/subscriptions.txt
@@ -1,3 +1,4 @@
-http://inr.i2p/export/alive-hosts.txt
+http://reg.i2p/hosts.txt
+http://identiguy.i2p/hosts.txt
http://stats.i2p/cgi-bin/newhosts.txt
http://i2p-projekt.i2p/hosts.txt
diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp
index 839495a5..e33f3d6d 100644
--- a/daemon/Daemon.cpp
+++ b/daemon/Daemon.cpp
@@ -35,374 +35,409 @@
namespace i2p
{
- namespace util
+namespace util
+{
+ class Daemon_Singleton::Daemon_Singleton_Private
{
- class Daemon_Singleton::Daemon_Singleton_Private
- {
- public:
- Daemon_Singleton_Private() {};
- ~Daemon_Singleton_Private() {};
+ public:
+ Daemon_Singleton_Private() {};
+ ~Daemon_Singleton_Private() {};
- std::unique_ptr httpServer;
- std::unique_ptr m_I2PControlService;
- std::unique_ptr UPnP;
- std::unique_ptr m_NTPSync;
- };
+ std::unique_ptr httpServer;
+ std::unique_ptr m_I2PControlService;
+ std::unique_ptr UPnP;
+ std::unique_ptr m_NTPSync;
+ };
- Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
- Daemon_Singleton::~Daemon_Singleton() {
- delete &d;
- }
+ Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
+ Daemon_Singleton::~Daemon_Singleton() {
+ delete &d;
+ }
- bool Daemon_Singleton::IsService () const
- {
- bool service = false;
+ bool Daemon_Singleton::IsService () const
+ {
+ bool service = false;
#ifndef _WIN32
- i2p::config::GetOption("service", service);
+ i2p::config::GetOption("service", service);
#endif
- return service;
- }
+ return service;
+ }
- bool Daemon_Singleton::init(int argc, char* argv[]) {
- return init(argc, argv, nullptr);
- }
+ bool Daemon_Singleton::init(int argc, char* argv[]) {
+ return init(argc, argv, nullptr);
+ }
- bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream)
+ bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr logstream)
+ {
+ i2p::config::Init();
+ i2p::config::ParseCmdline(argc, argv);
+
+ std::string config; i2p::config::GetOption("conf", config);
+ std::string datadir; i2p::config::GetOption("datadir", datadir);
+ i2p::fs::DetectDataDir(datadir, IsService());
+ i2p::fs::Init();
+
+ datadir = i2p::fs::GetDataDir();
+
+ if (config == "")
{
- i2p::config::Init();
- i2p::config::ParseCmdline(argc, argv);
-
- std::string config; i2p::config::GetOption("conf", config);
- std::string datadir; i2p::config::GetOption("datadir", datadir);
- i2p::fs::DetectDataDir(datadir, IsService());
- i2p::fs::Init();
-
- datadir = i2p::fs::GetDataDir();
-
- if (config == "")
- {
- config = i2p::fs::DataDirPath("i2pd.conf");
- if (!i2p::fs::Exists (config)) {
- // use i2pd.conf only if exists
- config = ""; /* reset */
- }
+ config = i2p::fs::DataDirPath("i2pd.conf");
+ if (!i2p::fs::Exists (config)) {
+ // use i2pd.conf only if exists
+ config = ""; /* reset */
}
+ }
- i2p::config::ParseConfig(config);
- i2p::config::Finalize();
+ i2p::config::ParseConfig(config);
+ i2p::config::Finalize();
- i2p::config::GetOption("daemon", isDaemon);
+ i2p::config::GetOption("daemon", isDaemon);
- std::string logs = ""; i2p::config::GetOption("log", logs);
- std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
- std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
- bool logclftime; i2p::config::GetOption("logclftime", logclftime);
+ std::string logs = ""; i2p::config::GetOption("log", logs);
+ std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
+ std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
+ bool logclftime; i2p::config::GetOption("logclftime", logclftime);
- /* setup logging */
- if (logclftime)
- i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
+ /* setup logging */
+ if (logclftime)
+ i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
- if (isDaemon && (logs == "" || logs == "stdout"))
- logs = "file";
+ if (isDaemon && (logs == "" || logs == "stdout"))
+ logs = "file";
- i2p::log::Logger().SetLogLevel(loglevel);
- if (logstream) {
- LogPrint(eLogInfo, "Log: will send messages to std::ostream");
- i2p::log::Logger().SendTo (logstream);
- } else if (logs == "file") {
- if (logfile == "")
- logfile = i2p::fs::DataDirPath("i2pd.log");
- LogPrint(eLogInfo, "Log: will send messages to ", logfile);
- i2p::log::Logger().SendTo (logfile);
+ i2p::log::Logger().SetLogLevel(loglevel);
+ if (logstream) {
+ LogPrint(eLogInfo, "Log: will send messages to std::ostream");
+ i2p::log::Logger().SendTo (logstream);
+ } else if (logs == "file") {
+ if (logfile == "")
+ logfile = i2p::fs::DataDirPath("i2pd.log");
+ LogPrint(eLogInfo, "Log: will send messages to ", logfile);
+ i2p::log::Logger().SendTo (logfile);
#ifndef _WIN32
- } else if (logs == "syslog") {
- LogPrint(eLogInfo, "Log: will send messages to syslog");
- i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
+ } else if (logs == "syslog") {
+ LogPrint(eLogInfo, "Log: will send messages to syslog");
+ i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
#endif
- } else {
- // use stdout -- default
- }
+ } else {
+ // use stdout -- default
+ }
- LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
- LogPrint(eLogDebug, "FS: main config file: ", config);
- LogPrint(eLogDebug, "FS: data directory: ", datadir);
+ LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
+ LogPrint(eLogDebug, "FS: main config file: ", config);
+ LogPrint(eLogDebug, "FS: data directory: ", datadir);
- bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
- bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
- bool avx; i2p::config::GetOption("cpuext.avx", avx);
- bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
- i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
+ bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
+ bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
+ bool avx; i2p::config::GetOption("cpuext.avx", avx);
+ bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
+ i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
- int netID; i2p::config::GetOption("netid", netID);
- i2p::context.SetNetID (netID);
- i2p::context.Init ();
+ int netID; i2p::config::GetOption("netid", netID);
+ i2p::context.SetNetID (netID);
+ i2p::context.Init ();
- bool ipv6; i2p::config::GetOption("ipv6", ipv6);
- bool ipv4; i2p::config::GetOption("ipv4", ipv4);
+ bool ipv6; i2p::config::GetOption("ipv6", ipv6);
+ bool ipv4; i2p::config::GetOption("ipv4", ipv4);
#ifdef MESHNET
- // manual override for meshnet
- ipv4 = false;
- ipv6 = true;
+ // manual override for meshnet
+ ipv4 = false;
+ ipv6 = true;
#endif
- uint16_t port; i2p::config::GetOption("port", port);
- if (!i2p::config::IsDefault("port"))
+ bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
+ boost::asio::ip::address_v6 yggaddr;
+ if (ygg)
+ {
+ std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress);
+ if (!yggaddress.empty ())
{
- LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
- i2p::context.UpdatePort (port);
- }
- i2p::context.SetSupportsV6 (ipv6);
- i2p::context.SetSupportsV4 (ipv4);
-
- i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
- bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
- if (ntcp2)
- {
- bool published; i2p::config::GetOption("ntcp2.published", published);
- if (published)
+ yggaddr = boost::asio::ip::address_v6::from_string (yggaddress);
+ if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) ||
+ !i2p::util::net::IsLocalAddress (yggaddr))
{
- uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
- if (!ntcp2port) ntcp2port = port; // use standard port
- i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
- if (ipv6)
- {
- std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
- auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
- if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
- i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
- }
+ LogPrint(eLogWarning, "Daemon: Can't find Yggdrasil address ", yggaddress);
+ ygg = false;
}
- else
- i2p::context.PublishNTCP2Address (port, false); // unpublish
- }
-
- bool transit; i2p::config::GetOption("notransit", transit);
- i2p::context.SetAcceptsTunnels (!transit);
- uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
- SetMaxNumTransitTunnels (transitTunnels);
-
- bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
- if (isFloodfill) {
- LogPrint(eLogInfo, "Daemon: router will be floodfill");
- i2p::context.SetFloodfill (true);
- } else {
- i2p::context.SetFloodfill (false);
- }
-
- /* this section also honors 'floodfill' flag, if set above */
- std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
- if (bandwidth.length () > 0)
- {
- if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
- {
- i2p::context.SetBandwidth (bandwidth[0]);
- LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
- }
- else
- {
- auto value = std::atoi(bandwidth.c_str());
- if (value > 0)
- {
- i2p::context.SetBandwidth (value);
- LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
- }
- else
- {
- LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'");
- i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
- }
- }
- }
- else if (isFloodfill)
- {
- LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'");
- i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1);
}
else
{
- LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'");
- i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
- }
-
- int shareRatio; i2p::config::GetOption("share", shareRatio);
- i2p::context.SetShareRatio (shareRatio);
-
- std::string family; i2p::config::GetOption("family", family);
- i2p::context.SetFamily (family);
- if (family.length () > 0)
- LogPrint(eLogInfo, "Daemon: family set to ", family);
-
- bool trust; i2p::config::GetOption("trust.enabled", trust);
- if (trust)
- {
- LogPrint(eLogInfo, "Daemon: explicit trust enabled");
- std::string fam; i2p::config::GetOption("trust.family", fam);
- std::string routers; i2p::config::GetOption("trust.routers", routers);
- bool restricted = false;
- if (fam.length() > 0)
+ yggaddr = i2p::util::net::GetYggdrasilAddress ();
+ if (yggaddr.is_unspecified ())
{
- std::set fams;
- size_t pos = 0, comma;
- do
- {
- comma = fam.find (',', pos);
- fams.insert (fam.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));
- pos = comma + 1;
- }
- while (comma != std::string::npos);
- i2p::transport::transports.RestrictRoutesToFamilies(fams);
- restricted = fams.size() > 0;
+ LogPrint(eLogWarning, "Daemon: Yggdrasil is not running. Disabled");
+ ygg = false;
}
- if (routers.length() > 0) {
- std::set idents;
- size_t pos = 0, comma;
- do
- {
- comma = routers.find (',', pos);
- i2p::data::IdentHash ident;
- ident.FromBase64 (routers.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));
- idents.insert (ident);
- pos = comma + 1;
- }
- while (comma != std::string::npos);
- LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers");
- i2p::transport::transports.RestrictRoutesToRouters(idents);
- restricted = idents.size() > 0;
- }
- if(!restricted)
- LogPrint(eLogError, "Daemon: no trusted routers of families specified");
}
-
- bool hidden; i2p::config::GetOption("trust.hidden", hidden);
- if (hidden)
- {
- LogPrint(eLogInfo, "Daemon: using hidden mode");
- i2p::data::netdb.SetHidden(true);
- }
- return true;
}
- bool Daemon_Singleton::start()
+ uint16_t port; i2p::config::GetOption("port", port);
+ if (!i2p::config::IsDefault("port"))
{
- i2p::log::Logger().Start();
- LogPrint(eLogInfo, "Daemon: starting NetDB");
- i2p::data::netdb.Start();
+ LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
+ i2p::context.UpdatePort (port);
+ }
+ i2p::context.SetSupportsV6 (ipv6);
+ i2p::context.SetSupportsV4 (ipv4);
+ i2p::context.SetSupportsMesh (ygg, yggaddr);
- bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
- if (upnp) {
- d.UPnP = std::unique_ptr(new i2p::transport::UPnP);
- d.UPnP->Start ();
- }
-
- bool nettime; i2p::config::GetOption("nettime.enabled", nettime);
- if (nettime)
+ i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
+ bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
+ if (ntcp2)
+ {
+ bool published; i2p::config::GetOption("ntcp2.published", published);
+ if (published)
{
- d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync);
- d.m_NTPSync->Start ();
+ uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
+ if (!ntcp2port) ntcp2port = port; // use standard port
+ i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
+ if (ipv6)
+ {
+ std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
+ auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
+ if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
+ i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
+ }
}
+ else
+ i2p::context.PublishNTCP2Address (port, false); // unpublish
+ }
+ if (ygg)
+ {
+ if (!ntcp2)
+ i2p::context.PublishNTCP2Address (port, true);
+ i2p::context.UpdateNTCP2V6Address (yggaddr);
+ }
+
+ bool transit; i2p::config::GetOption("notransit", transit);
+ i2p::context.SetAcceptsTunnels (!transit);
+ uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
+ SetMaxNumTransitTunnels (transitTunnels);
- bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
- bool ssu; i2p::config::GetOption("ssu", ssu);
- bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
- LogPrint(eLogInfo, "Daemon: starting Transports");
- if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
- if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
+ bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
+ if (isFloodfill) {
+ LogPrint(eLogInfo, "Daemon: router will be floodfill");
+ i2p::context.SetFloodfill (true);
+ }
+ else
+ {
+ i2p::context.SetFloodfill (false);
+ }
- i2p::transport::transports.SetCheckReserved(checkInReserved);
- i2p::transport::transports.Start(ntcp2, ssu);
- if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
- LogPrint(eLogInfo, "Daemon: Transports started");
+ /* this section also honors 'floodfill' flag, if set above */
+ std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
+ if (bandwidth.length () > 0)
+ {
+ if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
+ {
+ i2p::context.SetBandwidth (bandwidth[0]);
+ LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
+ }
else
{
- LogPrint(eLogError, "Daemon: failed to start Transports");
- /** shut down netdb right away */
- i2p::transport::transports.Stop();
- i2p::data::netdb.Stop();
- return false;
- }
-
- bool http; i2p::config::GetOption("http.enabled", http);
- if (http) {
- std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
- uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
- LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
- try
+ auto value = std::atoi(bandwidth.c_str());
+ if (value > 0)
{
- d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort));
- d.httpServer->Start();
- }
- catch (std::exception& ex)
+ i2p::context.SetBandwidth (value);
+ LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
+ }
+ else
{
- LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
- ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
+ LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'");
+ i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
}
}
-
-
- LogPrint(eLogInfo, "Daemon: starting Tunnels");
- i2p::tunnel::tunnels.Start();
-
- LogPrint(eLogInfo, "Daemon: starting Client");
- i2p::client::context.Start ();
-
- // I2P Control Protocol
- bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
- if (i2pcontrol) {
- std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
- uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
- LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
- try
- {
- d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
- d.m_I2PControlService->Start ();
- }
- catch (std::exception& ex)
- {
- LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
- ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
- }
- }
- return true;
+ }
+ else if (isFloodfill)
+ {
+ LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'");
+ i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1);
+ }
+ else
+ {
+ LogPrint(eLogInfo, "Daemon: bandwidth set to 'low'");
+ i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
}
- bool Daemon_Singleton::stop()
+ int shareRatio; i2p::config::GetOption("share", shareRatio);
+ i2p::context.SetShareRatio (shareRatio);
+
+ std::string family; i2p::config::GetOption("family", family);
+ i2p::context.SetFamily (family);
+ if (family.length () > 0)
+ LogPrint(eLogInfo, "Daemon: family set to ", family);
+
+ bool trust; i2p::config::GetOption("trust.enabled", trust);
+ if (trust)
{
- LogPrint(eLogInfo, "Daemon: shutting down");
- LogPrint(eLogInfo, "Daemon: stopping Client");
- i2p::client::context.Stop();
- LogPrint(eLogInfo, "Daemon: stopping Tunnels");
- i2p::tunnel::tunnels.Stop();
-
- if (d.UPnP)
+ LogPrint(eLogInfo, "Daemon: explicit trust enabled");
+ std::string fam; i2p::config::GetOption("trust.family", fam);
+ std::string routers; i2p::config::GetOption("trust.routers", routers);
+ bool restricted = false;
+ if (fam.length() > 0)
{
- d.UPnP->Stop ();
- d.UPnP = nullptr;
+ std::set fams;
+ size_t pos = 0, comma;
+ do
+ {
+ comma = fam.find (',', pos);
+ fams.insert (fam.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));
+ pos = comma + 1;
+ }
+ while (comma != std::string::npos);
+ i2p::transport::transports.RestrictRoutesToFamilies(fams);
+ restricted = fams.size() > 0;
}
-
- if (d.m_NTPSync)
- {
- d.m_NTPSync->Stop ();
- d.m_NTPSync = nullptr;
+ if (routers.length() > 0) {
+ std::set idents;
+ size_t pos = 0, comma;
+ do
+ {
+ comma = routers.find (',', pos);
+ i2p::data::IdentHash ident;
+ ident.FromBase64 (routers.substr (pos, comma != std::string::npos ? comma - pos : std::string::npos));
+ idents.insert (ident);
+ pos = comma + 1;
+ }
+ while (comma != std::string::npos);
+ LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers");
+ i2p::transport::transports.RestrictRoutesToRouters(idents);
+ restricted = idents.size() > 0;
}
+ if(!restricted)
+ LogPrint(eLogError, "Daemon: no trusted routers of families specified");
+ }
- LogPrint(eLogInfo, "Daemon: stopping Transports");
+ bool hidden; i2p::config::GetOption("trust.hidden", hidden);
+ if (hidden)
+ {
+ LogPrint(eLogInfo, "Daemon: using hidden mode");
+ i2p::data::netdb.SetHidden(true);
+ }
+ return true;
+ }
+
+ bool Daemon_Singleton::start()
+ {
+ i2p::log::Logger().Start();
+ LogPrint(eLogInfo, "Daemon: starting NetDB");
+ i2p::data::netdb.Start();
+
+ bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
+ if (upnp) {
+ d.UPnP = std::unique_ptr(new i2p::transport::UPnP);
+ d.UPnP->Start ();
+ }
+
+ bool nettime; i2p::config::GetOption("nettime.enabled", nettime);
+ if (nettime)
+ {
+ d.m_NTPSync = std::unique_ptr(new i2p::util::NTPTimeSync);
+ d.m_NTPSync->Start ();
+ }
+
+ bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
+ bool ssu; i2p::config::GetOption("ssu", ssu);
+ bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
+ LogPrint(eLogInfo, "Daemon: starting Transports");
+ if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
+ if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
+
+ i2p::transport::transports.SetCheckReserved(checkInReserved);
+ i2p::transport::transports.Start(ntcp2 || i2p::context.SupportsMesh (), ssu);
+ if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
+ LogPrint(eLogInfo, "Daemon: Transports started");
+ else
+ {
+ LogPrint(eLogError, "Daemon: failed to start Transports");
+ /** shut down netdb right away */
i2p::transport::transports.Stop();
- LogPrint(eLogInfo, "Daemon: stopping NetDB");
i2p::data::netdb.Stop();
- if (d.httpServer) {
- LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
- d.httpServer->Stop();
- d.httpServer = nullptr;
- }
- if (d.m_I2PControlService)
- {
- LogPrint(eLogInfo, "Daemon: stopping I2PControl");
- d.m_I2PControlService->Stop ();
- d.m_I2PControlService = nullptr;
- }
- i2p::crypto::TerminateCrypto ();
- i2p::log::Logger().Stop();
-
- return true;
+ return false;
}
+
+ bool http; i2p::config::GetOption("http.enabled", http);
+ if (http) {
+ std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
+ uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
+ LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
+ try
+ {
+ d.httpServer = std::unique_ptr(new i2p::http::HTTPServer(httpAddr, httpPort));
+ d.httpServer->Start();
+ }
+ catch (std::exception& ex)
+ {
+ LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
+ ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
+ }
+ }
+
+
+ LogPrint(eLogInfo, "Daemon: starting Tunnels");
+ i2p::tunnel::tunnels.Start();
+
+ LogPrint(eLogInfo, "Daemon: starting Client");
+ i2p::client::context.Start ();
+
+ // I2P Control Protocol
+ bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
+ if (i2pcontrol) {
+ std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
+ uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
+ LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
+ try
+ {
+ d.m_I2PControlService = std::unique_ptr(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
+ d.m_I2PControlService->Start ();
+ }
+ catch (std::exception& ex)
+ {
+ LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
+ ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
+ }
+ }
+ return true;
+ }
+
+ bool Daemon_Singleton::stop()
+ {
+ LogPrint(eLogInfo, "Daemon: shutting down");
+ LogPrint(eLogInfo, "Daemon: stopping Client");
+ i2p::client::context.Stop();
+ LogPrint(eLogInfo, "Daemon: stopping Tunnels");
+ i2p::tunnel::tunnels.Stop();
+
+ if (d.UPnP)
+ {
+ d.UPnP->Stop ();
+ d.UPnP = nullptr;
+ }
+
+ if (d.m_NTPSync)
+ {
+ d.m_NTPSync->Stop ();
+ d.m_NTPSync = nullptr;
+ }
+
+ LogPrint(eLogInfo, "Daemon: stopping Transports");
+ i2p::transport::transports.Stop();
+ LogPrint(eLogInfo, "Daemon: stopping NetDB");
+ i2p::data::netdb.Stop();
+ if (d.httpServer) {
+ LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
+ d.httpServer->Stop();
+ d.httpServer = nullptr;
+ }
+ if (d.m_I2PControlService)
+ {
+ LogPrint(eLogInfo, "Daemon: stopping I2PControl");
+ d.m_I2PControlService->Stop ();
+ d.m_I2PControlService = nullptr;
+ }
+ i2p::crypto::TerminateCrypto ();
+ i2p::log::Logger().Stop();
+
+ return true;
+ }
}
}
diff --git a/debian/changelog b/debian/changelog
index 7ca75409..d83fb88c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+i2pd (2.36.0-1) unstable; urgency=high
+
+ * updated to version 2.36.0/0.9.49
+
+ -- orignal Mon, 15 Feb 2021 16:00:00 +0000
+
i2pd (2.35.0-1) unstable; urgency=high
* updated to version 2.35.0/0.9.48
diff --git a/debian/patches/02-upnp.patch b/debian/patches/02-upnp.patch
new file mode 100644
index 00000000..7b9bb317
--- /dev/null
+++ b/debian/patches/02-upnp.patch
@@ -0,0 +1,17 @@
+Description: Enable UPnP usage in package
+Author: r4sas
+
+Reviewed-By: r4sas
+Last-Update: 2021-01-16
+
+--- i2pd.orig/Makefile
++++ i2pd/Makefile
+@@ -15,7 +15,7 @@ include filelist.mk
+ USE_AESNI := yes
+ USE_STATIC := no
+ USE_MESHNET := no
+-USE_UPNP := no
++USE_UPNP := yes
+ DEBUG := yes
+
+ ifeq ($(DEBUG),yes)
diff --git a/debian/patches/series b/debian/patches/series
index 07f821c8..2f816712 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
01-fix-1210.patch
+02-upnp.patch
diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp
index d16d82d3..9da0bbe0 100644
--- a/libi2pd/Config.cpp
+++ b/libi2pd/Config.cpp
@@ -205,14 +205,18 @@ namespace config {
"https://reseed.i2pgit.org/,"
"https://i2p.novg.net/"
), "Reseed URLs, separated by comma")
+ ("reseed.yggurls", value()->default_value(
+ "http://[324:9de3:fea4:f6ac::ace]:7070/"
+ ), "Reseed URLs through the Yggdrasil, separated by comma")
;
options_description addressbook("AddressBook options");
addressbook.add_options()
("addressbook.defaulturl", value()->default_value(
- "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt"
+ "http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
), "AddressBook subscription URL for initial setup")
- ("addressbook.subscriptions", value()->default_value(""), "AddressBook subscriptions URLs, separated by comma");
+ ("addressbook.subscriptions", value()->default_value(""), "AddressBook subscriptions URLs, separated by comma")
+ ("addressbook.hostsfile", value()->default_value(""), "File to dump addresses in hosts.txt format");
options_description trust("Trust options");
trust.add_options()
@@ -272,6 +276,12 @@ namespace config {
("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines")
;
+ options_description meshnets("Meshnet transports options");
+ meshnets.add_options()
+ ("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)")
+ ("meshnets.yggaddress", value()->default_value(""), "Yggdrasil address to publish")
+ ;
+
m_OptionsDesc
.add(general)
.add(limits)
@@ -293,6 +303,7 @@ namespace config {
.add(nettime)
.add(persist)
.add(cpuext)
+ .add(meshnets)
;
}
diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp
index 3e6279ff..68850a9d 100644
--- a/libi2pd/Crypto.cpp
+++ b/libi2pd/Crypto.cpp
@@ -351,11 +351,13 @@ namespace crypto
#endif
}
- void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
+ bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
{
+ if (pub[31] & 0x80) return false; // not x25519 key
#if OPENSSL_X25519
EVP_PKEY_derive_init (m_Ctx);
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
+ if (!pkey) return false;
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
size_t len = 32;
EVP_PKEY_derive (m_Ctx, shared, &len);
@@ -363,6 +365,7 @@ namespace crypto
#else
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
#endif
+ return true;
}
void X25519Keys::GetPrivateKey (uint8_t * priv) const
diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h
index c63cc45e..a6c64c70 100644
--- a/libi2pd/Crypto.h
+++ b/libi2pd/Crypto.h
@@ -89,7 +89,7 @@ namespace crypto
const uint8_t * GetPublicKey () const { return m_PublicKey; };
void GetPrivateKey (uint8_t * priv) const;
void SetPrivateKey (const uint8_t * priv, bool calculatePublic = false);
- void Agree (const uint8_t * pub, uint8_t * shared);
+ bool Agree (const uint8_t * pub, uint8_t * shared);
bool IsElligatorIneligible () const { return m_IsElligatorIneligible; }
void SetElligatorIneligible () { m_IsElligatorIneligible = true; }
diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp
index 4518a347..ad93d386 100644
--- a/libi2pd/CryptoKey.cpp
+++ b/libi2pd/CryptoKey.cpp
@@ -173,8 +173,7 @@ namespace crypto
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding)
{
- m_StaticKeys.Agree (epub, sharedSecret);
- return true;
+ return m_StaticKeys.Agree (epub, sharedSecret);
}
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub)
diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp
index 9d61f5e0..d000a9e0 100644
--- a/libi2pd/Datagram.cpp
+++ b/libi2pd/Datagram.cpp
@@ -49,8 +49,8 @@ namespace datagram
std::shared_ptr DatagramDestination::GetSession(const i2p::data::IdentHash & ident)
{
return ObtainSession(ident);
- }
-
+ }
+
void DatagramDestination::SendDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort)
{
if (session)
@@ -67,21 +67,21 @@ namespace datagram
auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}},
fromPort, toPort, false, !session->IsRatchets ()); // datagram
session->SendMsg(msg);
- }
- }
+ }
+ }
void DatagramDestination::SendRawDatagram (std::shared_ptr session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort)
{
if (session)
session->SendMsg(CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ())); // raw
}
-
+
void DatagramDestination::FlushSendQueue (std::shared_ptr session)
{
if (session)
session->FlushSendQueue ();
- }
-
+ }
+
void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len)
{
i2p::data::IdentityEx identity;
@@ -242,7 +242,7 @@ namespace datagram
if (msg || m_SendQueue.empty ())
m_SendQueue.push_back(msg);
// flush queue right away if full
- if (!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE)
+ if (!msg || m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE)
FlushSendQueue();
}
@@ -286,16 +286,16 @@ namespace datagram
m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
if (!m_RemoteLeaseSet)
{
- if(!m_RequestingLS)
+ if(!m_RequestingLS)
{
m_RequestingLS = true;
m_LocalDestination->RequestDestination(m_RemoteIdent, std::bind(&DatagramSession::HandleLeaseSetUpdated, this, std::placeholders::_1));
}
return nullptr;
- }
- }
+ }
+ }
- if (!m_RoutingSession || !m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ())
+ if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ())
{
bool found = false;
for (auto& it: m_PendingRoutingSessions)
@@ -305,81 +305,81 @@ namespace datagram
m_PendingRoutingSessions.clear ();
found = true;
break;
- }
+ }
if (!found)
- {
+ {
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
if (!m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ())
m_PendingRoutingSessions.push_back (m_RoutingSession);
- }
- }
-
+ }
+ }
+
auto path = m_RoutingSession->GetSharedRoutingPath();
if (path && m_RoutingSession->IsRatchets () &&
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
- {
+ {
m_RoutingSession->SetSharedRoutingPath (nullptr);
path = nullptr;
}
-
- if (path)
+
+ if (path)
{
if (path->outboundTunnel && !path->outboundTunnel->IsEstablished ())
- {
+ {
// bad outbound tunnel, switch outbound tunnel
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(path->outboundTunnel);
if (!path->outboundTunnel)
m_RoutingSession->SetSharedRoutingPath (nullptr);
- }
-
- if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW))
+ }
+
+ if (path->remoteLease && path->remoteLease->ExpiresWithin(DATAGRAM_SESSION_LEASE_HANDOVER_WINDOW))
{
// bad lease, switch to next one
- if (m_RemoteLeaseSet)
+ if (m_RemoteLeaseSet)
{
auto ls = m_RemoteLeaseSet->GetNonExpiredLeasesExcluding(
- [&](const i2p::data::Lease& l) -> bool
+ [&](const i2p::data::Lease& l) -> bool
{
return l.tunnelID == path->remoteLease->tunnelID;
});
auto sz = ls.size();
- if (sz)
+ if (sz)
{
auto idx = rand() % sz;
path->remoteLease = ls[idx];
}
else
m_RoutingSession->SetSharedRoutingPath (nullptr);
- }
- else
- {
+ }
+ else
+ {
// no remote lease set?
LogPrint(eLogWarning, "DatagramSession: no cached remote lease set for ", m_RemoteIdent.ToBase32());
m_RoutingSession->SetSharedRoutingPath (nullptr);
- }
+ }
}
- }
- else
+ }
+ else
{
// no current path, make one
path = std::make_shared();
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel();
if (!path->outboundTunnel) return nullptr;
-
- if (m_RemoteLeaseSet)
+
+ if (m_RemoteLeaseSet)
{
// pick random next good lease
auto ls = m_RemoteLeaseSet->GetNonExpiredLeases();
auto sz = ls.size();
- if (sz)
+ if (sz)
{
auto idx = rand() % sz;
path->remoteLease = ls[idx];
}
else
return nullptr;
- }
- else
+ }
+ else
{
// no remote lease set currently, bail
LogPrint(eLogWarning, "DatagramSession: no remote lease set found for ", m_RemoteIdent.ToBase32());
diff --git a/libi2pd/ECIESX25519AEADRatchetSession.cpp b/libi2pd/ECIESX25519AEADRatchetSession.cpp
index d2286b15..81b83477 100644
--- a/libi2pd/ECIESX25519AEADRatchetSession.cpp
+++ b/libi2pd/ECIESX25519AEADRatchetSession.cpp
@@ -94,13 +94,23 @@ namespace garlic
m_ItermediateSymmKeys.erase (index);
}
- void RatchetTagSet::Expire ()
+ void ReceiveRatchetTagSet::Expire ()
{
if (!m_ExpirationTimestamp)
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
}
- bool RatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
+ bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const
+ {
+ return m_ExpirationTimestamp && ts > m_ExpirationTimestamp;
+ }
+
+ bool ReceiveRatchetTagSet::IsIndexExpired (int index) const
+ {
+ return index < m_TrimBehindIndex;
+ }
+
+ bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
{
auto session = GetSession ();
if (!session) return false;
@@ -108,7 +118,7 @@ namespace garlic
}
DatabaseLookupTagSet::DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key):
- RatchetTagSet (nullptr), m_Destination (destination)
+ ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
memcpy (m_Key, key, 32);
Expire ();
@@ -203,16 +213,13 @@ namespace garlic
return false;
}
- std::shared_ptr ECIESX25519AEADRatchetSession::CreateNewSessionTagset ()
+ void ECIESX25519AEADRatchetSession::InitNewSessionTagset (std::shared_ptr tagsetNsr) const
{
uint8_t tagsetKey[32];
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
// Session Tag Ratchet
- auto tagsetNsr = (m_State == eSessionStateNewSessionReceived) ? std::make_shared(shared_from_this ()):
- std::make_shared(shared_from_this ());
tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
tagsetNsr->NextSessionTagRatchet ();
- return tagsetNsr;
}
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
@@ -231,7 +238,11 @@ namespace garlic
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
- GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519(bsk, aepk)
+ if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
+ return false;
+ }
MixKey (sharedSecret);
// decrypt flags/static
@@ -251,7 +262,11 @@ namespace garlic
{
// static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32);
- GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519(bsk, apk)
+ if (!GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
+ return false;
+ }
MixKey (sharedSecret);
}
else // all zeros flags
@@ -276,7 +291,7 @@ namespace garlic
return true;
}
- void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index)
+ void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index)
{
size_t offset = 0;
while (offset < len)
@@ -344,7 +359,7 @@ namespace garlic
}
}
- void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset)
+ void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset)
{
uint8_t flag = buf[0]; buf++; // flag
if (flag & ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG)
@@ -359,7 +374,7 @@ namespace garlic
uint8_t sharedSecret[32], tagsetKey[32];
m_NextSendRatchet->key->Agree (m_NextSendRatchet->remote, sharedSecret);
i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32)
- auto newTagset = std::make_shared (shared_from_this ());
+ auto newTagset = std::make_shared ();
newTagset->SetTagSetID (1 + m_NextSendRatchet->keyID + keyID);
newTagset->DHInitialize (m_SendTagset->GetNextRootKey (), tagsetKey);
newTagset->NextSessionTagRatchet ();
@@ -401,7 +416,7 @@ namespace garlic
uint8_t sharedSecret[32], tagsetKey[32];
m_NextReceiveRatchet->key->Agree (m_NextReceiveRatchet->remote, sharedSecret);
i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32)
- auto newTagset = std::make_shared(shared_from_this ());
+ auto newTagset = std::make_shared(shared_from_this ());
newTagset->SetTagSetID (tagsetID);
newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey);
newTagset->NextSessionTagRatchet ();
@@ -448,7 +463,11 @@ namespace garlic
i2p::crypto::InitNoiseIKState (*this, m_RemoteStaticKey); // bpk
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
- m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
+ if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
+ return false;
+ }
MixKey (sharedSecret);
// encrypt flags/static key section
uint8_t nonce[12];
@@ -489,7 +508,11 @@ namespace garlic
{
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
if (GetOwner ())
- GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS);
+ {
+ auto tagsetNsr = std::make_shared(shared_from_this (), true);
+ InitNewSessionTagset (tagsetNsr);
+ GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS);
+ }
}
return true;
}
@@ -504,7 +527,11 @@ namespace garlic
MixHash (out + offset, 32); // h = SHA256(h || aepk)
offset += 32;
uint8_t sharedSecret[32];
- m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
+ if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
+ return false;
+ }
MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
@@ -522,7 +549,8 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob
- m_NSRSendTagset = CreateNewSessionTagset ();
+ m_NSRSendTagset = std::make_shared();
+ InitNewSessionTagset (m_NSRSendTagset);
uint64_t tag = m_NSRSendTagset->GetNextSessionTag ();
size_t offset = 0;
@@ -540,9 +568,17 @@ namespace garlic
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32];
- m_EphemeralKeys->Agree (m_Aepk, sharedSecret); // sharedSecret = x25519(besk, aepk)
+ if (!m_EphemeralKeys->Agree (m_Aepk, sharedSecret)) // sharedSecret = x25519(besk, aepk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
+ return false;
+ }
MixKey (sharedSecret);
- m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, apk)
+ if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
+ return false;
+ }
MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
@@ -558,10 +594,10 @@ namespace garlic
uint8_t keydata[64];
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
// k_ab = keydata[0:31], k_ba = keydata[32:63]
- auto receiveTagset = std::make_shared(shared_from_this ());
+ auto receiveTagset = std::make_shared(shared_from_this());
receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
receiveTagset->NextSessionTagRatchet ();
- m_SendTagset = std::make_shared(shared_from_this ());
+ m_SendTagset = std::make_shared();
m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
m_SendTagset->NextSessionTagRatchet ();
GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
@@ -624,7 +660,11 @@ namespace garlic
MixHash (tag, 8); // h = SHA256(h || tag)
MixHash (bepk, 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32];
- m_EphemeralKeys->Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
+ if (!m_EphemeralKeys->Agree (bepk, sharedSecret)) // sharedSecret = x25519(aesk, bepk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect Bob ephemeral key");
+ return false;
+ }
MixKey (sharedSecret);
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
MixKey (sharedSecret);
@@ -646,10 +686,10 @@ namespace garlic
{
// only first time, then we keep using existing tagsets
// k_ab = keydata[0:31], k_ba = keydata[32:63]
- m_SendTagset = std::make_shared(shared_from_this ());
+ m_SendTagset = std::make_shared();
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
m_SendTagset->NextSessionTagRatchet ();
- auto receiveTagset = std::make_shared(shared_from_this ());
+ auto receiveTagset = std::make_shared(shared_from_this ());
receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
receiveTagset->NextSessionTagRatchet ();
GenerateMoreReceiveTags (receiveTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
@@ -708,7 +748,7 @@ namespace garlic
}
bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (uint8_t * buf, size_t len,
- std::shared_ptr receiveTagset, int index)
+ std::shared_ptr receiveTagset, int index)
{
uint8_t nonce[12];
CreateNonce (index, nonce); // tag's index
@@ -747,7 +787,7 @@ namespace garlic
}
bool ECIESX25519AEADRatchetSession::HandleNextMessage (uint8_t * buf, size_t len,
- std::shared_ptr receiveTagset, int index)
+ std::shared_ptr receiveTagset, int index)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
switch (m_State)
@@ -788,7 +828,11 @@ namespace garlic
i2p::crypto::InitNoiseNState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
MixHash (buf, 32);
uint8_t sharedSecret[32];
- GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519(bsk, aepk)
+ if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
+ {
+ LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
+ return false;
+ }
MixKey (sharedSecret);
buf += 32; len -= 32;
uint8_t nonce[12];
@@ -870,10 +914,13 @@ namespace garlic
payloadLen += msg->GetPayloadLength () + 13;
if (m_Destination) payloadLen += 32;
}
- auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated ||
- (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted &&
- ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
- GetOwner ()->GetLeaseSet () : nullptr;
+ if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
+ {
+ // resubmit non-confirmed LeaseSet
+ SetLeaseSetUpdateStatus (eLeaseSetUpdated);
+ SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed
+ }
+ auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated) ? GetOwner ()->GetLeaseSet () : nullptr;
if (leaseSet)
{
payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13;
@@ -1054,7 +1101,7 @@ namespace garlic
return cloveSize + 3;
}
- void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags)
+ void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags)
{
if (GetOwner ())
{
@@ -1073,7 +1120,8 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
{
CleanupUnconfirmedLeaseSet (ts);
- return ts > m_LastActivityTimestamp + ECIESX25519_EXPIRATION_TIMEOUT;
+ return ts > m_LastActivityTimestamp + ECIESX25519_RECEIVE_EXPIRATION_TIMEOUT && // seconds
+ ts*1000 > m_LastSentTimestamp + ECIESX25519_SEND_EXPIRATION_TIMEOUT*1000; // milliseconds
}
std::shared_ptr WrapECIESX25519AEADRatchetMessage (std::shared_ptr msg, const uint8_t * key, uint64_t tag)
diff --git a/libi2pd/ECIESX25519AEADRatchetSession.h b/libi2pd/ECIESX25519AEADRatchetSession.h
index 86e3ffc0..3aaa3d62 100644
--- a/libi2pd/ECIESX25519AEADRatchetSession.h
+++ b/libi2pd/ECIESX25519AEADRatchetSession.h
@@ -26,10 +26,10 @@ namespace i2p
namespace garlic
{
const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second since session creation we can restart session after
- const int ECIESX25519_EXPIRATION_TIMEOUT = 480; // in seconds
const int ECIESX25519_INACTIVITY_TIMEOUT = 90; // number of seconds we receive nothing and should restart if we can
const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after
- const int ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT = 600; // in seconds
+ const int ECIESX25519_SEND_EXPIRATION_TIMEOUT = 480; // in seconds
+ const int ECIESX25519_RECEIVE_EXPIRATION_TIMEOUT = 600; // in seconds
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180
const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
@@ -39,13 +39,12 @@ namespace garlic
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
- class ECIESX25519AEADRatchetSession;
- class RatchetTagSet: public std::enable_shared_from_this
+ class RatchetTagSet
{
public:
- RatchetTagSet (std::shared_ptr session): m_Session (session) {};
- virtual bool IsNS () const { return false; };
+ RatchetTagSet () {};
+ virtual ~RatchetTagSet () {};
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
@@ -55,17 +54,9 @@ namespace garlic
void GetSymmKey (int index, uint8_t * key);
void DeleteSymmKey (int index);
- std::shared_ptr GetSession () { return m_Session.lock (); };
int GetTagSetID () const { return m_TagSetID; };
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
- void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
-
- void Expire ();
- bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
- virtual bool IsIndexExpired (int index) const { return m_Session.expired () || index < m_TrimBehindIndex; };
-
- virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
-
+
private:
union
@@ -79,28 +70,40 @@ namespace garlic
} m_KeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
- int m_NextIndex, m_NextSymmKeyIndex, m_TrimBehindIndex = 0;
+ int m_NextIndex, m_NextSymmKeyIndex;
std::unordered_map > m_ItermediateSymmKeys;
- std::weak_ptr m_Session;
+
int m_TagSetID = 0;
- uint64_t m_ExpirationTimestamp = 0;
};
- class NSRatchetTagSet: public RatchetTagSet
+ class ECIESX25519AEADRatchetSession;
+ class ReceiveRatchetTagSet: public RatchetTagSet,
+ public std::enable_shared_from_this
{
public:
-
- NSRatchetTagSet (std::shared_ptr session):
- RatchetTagSet (session), m_DummySession (session) {};
- bool IsNS () const { return true; };
+ ReceiveRatchetTagSet (std::shared_ptr session, bool isNS = false):
+ m_Session (session), m_IsNS (isNS) {};
+
+ bool IsNS () const { return m_IsNS; };
+ std::shared_ptr GetSession () { return m_Session; };
+ void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
+
+ void Expire ();
+ bool IsExpired (uint64_t ts) const;
+
+ virtual bool IsIndexExpired (int index) const;
+ virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
private:
-
- std::shared_ptr m_DummySession; // we need a strong pointer for NS
+
+ int m_TrimBehindIndex = 0;
+ std::shared_ptr m_Session;
+ bool m_IsNS;
+ uint64_t m_ExpirationTimestamp = 0;
};
- class DatabaseLookupTagSet: public RatchetTagSet
+ class DatabaseLookupTagSet: public ReceiveRatchetTagSet
{
public:
@@ -160,14 +163,15 @@ namespace garlic
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
~ECIESX25519AEADRatchetSession ();
- bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0);
+ bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index = 0);
bool HandleNextMessageForRouter (const uint8_t * buf, size_t len);
std::shared_ptr WrapSingleMessage (std::shared_ptr msg);
std::shared_ptr WrapOneTimeMessage (std::shared_ptr msg, bool isForRouter = false);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
-
+
+ void Terminate () { m_IsTerminated = true; }
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
{
if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest));
@@ -179,19 +183,20 @@ namespace garlic
bool IsRatchets () const { return true; };
bool IsReadyToSend () const { return m_State != eSessionStateNewSessionSent; };
+ bool IsTerminated () const { return m_IsTerminated; }
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
private:
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
- std::shared_ptr CreateNewSessionTagset ();
+ void InitNewSessionTagset (std::shared_ptr tagsetNsr) const;
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
- bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index);
- void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index);
- void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset);
+ bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr receiveTagset, int index);
+ void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset, int index);
+ void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr& receiveTagset);
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic = true);
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
@@ -203,7 +208,7 @@ namespace garlic
size_t CreateGarlicClove (std::shared_ptr msg, uint8_t * buf, size_t len);
size_t CreateLeaseSetClove (std::shared_ptr ls, uint64_t ts, uint8_t * buf, size_t len);
- void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags);
+ void GenerateMoreReceiveTags (std::shared_ptr receiveTagset, int numTags);
void NewNextSendRatchet ();
private:
@@ -213,12 +218,12 @@ namespace garlic
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
std::shared_ptr m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
- uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming
+ uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
m_LastSentTimestamp = 0; // in milliseconds
std::shared_ptr m_SendTagset, m_NSRSendTagset;
std::unique_ptr m_Destination;// TODO: might not need it
std::list > m_AckRequests; // (tagsetid, index)
- bool m_SendReverseKey = false, m_SendForwardKey = false;
+ bool m_SendReverseKey = false, m_SendForwardKey = false, m_IsTerminated = false;
std::unique_ptr m_NextReceiveRatchet, m_NextSendRatchet;
uint8_t m_PaddingSizes[32], m_NextPaddingSize;
diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp
index aff92837..42aca5be 100644
--- a/libi2pd/Garlic.cpp
+++ b/libi2pd/Garlic.cpp
@@ -445,9 +445,16 @@ namespace garlic
void GarlicDestination::CleanUp ()
{
+ for (auto it: m_Sessions)
+ it.second->SetOwner (nullptr);
m_Sessions.clear ();
m_DeliveryStatusSessions.clear ();
m_Tags.clear ();
+ for (auto it: m_ECIESx25519Sessions)
+ {
+ it.second->Terminate ();
+ it.second->SetOwner (nullptr);
+ }
m_ECIESx25519Sessions.clear ();
m_ECIESx25519Tags.clear ();
}
@@ -852,7 +859,7 @@ namespace garlic
{
if (it->second->CheckExpired (ts))
{
- it->second->SetOwner (nullptr);
+ it->second->Terminate ();
it = m_ECIESx25519Sessions.erase (it);
}
else
@@ -866,9 +873,15 @@ namespace garlic
{
it->second.tagset->DeleteSymmKey (it->second.index);
it = m_ECIESx25519Tags.erase (it);
+ numExpiredTags++;
}
else
+ {
+ auto session = it->second.tagset->GetSession ();
+ if (!session || session->IsTerminated())
+ it->second.tagset->Expire ();
++it;
+ }
}
if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
@@ -1059,7 +1072,7 @@ namespace garlic
}
}
- uint64_t GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
+ uint64_t GarlicDestination::AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset)
{
auto index = tagset->GetNextIndex ();
uint64_t tag = tagset->GetNextSessionTag ();
@@ -1076,7 +1089,7 @@ namespace garlic
{
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
{
- it->second->SetOwner (nullptr); // detach
+ it->second->Terminate (); // detach
m_ECIESx25519Sessions.erase (it);
}
else
@@ -1093,7 +1106,7 @@ namespace garlic
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
{
- it->second->SetOwner (nullptr);
+ it->second->Terminate ();
m_ECIESx25519Sessions.erase (it);
}
}
diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h
index 379477e8..4288e74b 100644
--- a/libi2pd/Garlic.h
+++ b/libi2pd/Garlic.h
@@ -115,6 +115,7 @@ namespace garlic
virtual bool MessageConfirmed (uint32_t msgID);
virtual bool IsRatchets () const { return false; };
virtual bool IsReadyToSend () const { return true; };
+ virtual bool IsTerminated () const { return !GetOwner (); };
virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only
void SetLeaseSetUpdated ()
@@ -215,12 +216,12 @@ namespace garlic
class ECIESX25519AEADRatchetSession;
typedef std::shared_ptr ECIESX25519AEADRatchetSessionPtr;
- class RatchetTagSet;
- typedef std::shared_ptr RatchetTagSetPtr;
+ class ReceiveRatchetTagSet;
+ typedef std::shared_ptr ReceiveRatchetTagSetPtr;
struct ECIESX25519AEADRatchetIndexTagset
{
int index;
- RatchetTagSetPtr tagset;
+ ReceiveRatchetTagSetPtr tagset;
};
class GarlicDestination: public i2p::data::LocalDestination
@@ -245,7 +246,7 @@ namespace garlic
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
- uint64_t AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
+ uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
void RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
@@ -285,7 +286,7 @@ namespace garlic
int m_NumRatchetInboundTags;
std::unordered_map, std::hash > > m_Tags;
std::unordered_map m_ECIESx25519Tags; // session tag -> session
- RatchetTagSetPtr m_LastTagset; // tagset last message came for
+ ReceiveRatchetTagSetPtr m_LastTagset; // tagset last message came for
// DeliveryStatus
std::mutex m_DeliveryStatusSessionsMutex;
std::unordered_map m_DeliveryStatusSessions; // msgID -> session
diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp
index 484f4c0c..b967cbb5 100644
--- a/libi2pd/HTTP.cpp
+++ b/libi2pd/HTTP.cpp
@@ -111,7 +111,14 @@ namespace http {
pos_p = pos_c + 1;
}
/* hostname[:port][/path] */
- pos_c = url.find_first_of(":/", pos_p);
+ if (url[pos_p] == '[') // ipv6
+ {
+ auto pos_b = url.find(']', pos_p);
+ if (pos_b == std::string::npos) return false;
+ pos_c = url.find_first_of(":/", pos_b);
+ }
+ else
+ pos_c = url.find_first_of(":/", pos_p);
if (pos_c == std::string::npos) {
/* only hostname, without post and path */
host = url.substr(pos_p, std::string::npos);
@@ -339,7 +346,7 @@ namespace http {
auto it = headers.find("Transfer-Encoding");
if (it == headers.end())
return false;
- if (it->second.find("chunked") == std::string::npos)
+ if (it->second.find("chunked") != std::string::npos)
return true;
return false;
}
diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp
index 5ad6df78..6897148b 100644
--- a/libi2pd/I2NPProtocol.cpp
+++ b/libi2pd/I2NPProtocol.cpp
@@ -244,7 +244,8 @@ namespace i2p
return m;
}
- std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, uint32_t replyToken)
+ std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router,
+ uint32_t replyToken, std::shared_ptr replyTunnel)
{
if (!router) // we send own RouterInfo
router = context.GetSharedRouterInfo ();
@@ -258,10 +259,20 @@ namespace i2p
uint8_t * buf = payload + DATABASE_STORE_HEADER_SIZE;
if (replyToken)
{
- memset (buf, 0, 4); // zero tunnelID means direct reply
- buf += 4;
- memcpy (buf, router->GetIdentHash (), 32);
- buf += 32;
+ if (replyTunnel)
+ {
+ htobe32buf (buf, replyTunnel->GetNextTunnelID ());
+ buf += 4; // reply tunnelID
+ memcpy (buf, replyTunnel->GetNextIdentHash (), 32);
+ buf += 32; // reply tunnel gateway
+ }
+ else
+ {
+ memset (buf, 0, 4); // zero tunnelID means direct reply
+ buf += 4;
+ memcpy (buf, context.GetIdentHash (), 32);
+ buf += 32;
+ }
}
uint8_t * sizePtr = buf;
diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h
index b8fbb303..c9b0fc04 100644
--- a/libi2pd/I2NPProtocol.h
+++ b/libi2pd/I2NPProtocol.h
@@ -276,7 +276,7 @@ namespace tunnel
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers);
- std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0);
+ std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr);
std::shared_ptr CreateDatabaseStoreMsg (const i2p::data::IdentHash& storeHash, std::shared_ptr leaseSet); // for floodfill only
std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr);
bool IsRouterInfoMsg (std::shared_ptr msg);
diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp
index 1706399d..dc485d5b 100644
--- a/libi2pd/NTCP2.cpp
+++ b/libi2pd/NTCP2.cpp
@@ -317,7 +317,8 @@ namespace transport
return true;
}
- NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter):
+ NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter,
+ std::shared_ptr addr):
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
m_Server (server), m_Socket (m_Server.GetService ()),
m_IsEstablished (false), m_IsTerminated (false),
@@ -332,7 +333,8 @@ namespace transport
if (in_RemoteRouter) // Alice
{
m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash ();
- auto addr = in_RemoteRouter->GetNTCP2Address (true); // we need a published address
+ if (!addr)
+ addr = in_RemoteRouter->GetNTCP2Address (true); // we need a published address
if (addr)
{
memcpy (m_Establisher->m_RemoteStaticKey, addr->ntcp2->staticKey, 32);
@@ -341,6 +343,8 @@ namespace transport
else
LogPrint (eLogWarning, "NTCP2: Missing NTCP2 parameters");
}
+ m_NextRouterInfoResendTime = i2p::util::GetSecondsSinceEpoch () + NTCP2_ROUTERINFO_RESEND_INTERVAL +
+ rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
}
NTCP2Session::~NTCP2Session ()
@@ -1010,7 +1014,14 @@ namespace transport
m_NumSentBytes += bytes_transferred;
i2p::transport::transports.UpdateSentBytes (bytes_transferred);
LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred);
- SendQueue ();
+ if (m_LastActivityTimestamp > m_NextRouterInfoResendTime)
+ {
+ m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
+ rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
+ SendRouterInfo ();
+ }
+ else
+ SendQueue ();
}
}
@@ -1179,7 +1190,7 @@ namespace transport
auto conn = std::make_shared(*this);
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
}
- else if (address->host.is_v6() && context.SupportsV6 ())
+ else if (address->host.is_v6() && (context.SupportsV6 () || context.SupportsMesh ()))
{
m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ()));
try
@@ -1517,7 +1528,7 @@ namespace transport
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n",
- [this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred)
+ [readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred)
{
if(ec)
{
diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h
index 5c9ecac9..a7708872 100644
--- a/libi2pd/NTCP2.h
+++ b/libi2pd/NTCP2.h
@@ -34,6 +34,8 @@ namespace transport
const int NTCP2_ESTABLISH_TIMEOUT = 10; // 10 seconds
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
+ const int NTCP2_ROUTERINFO_RESEND_INTERVAL = 25*60; // 25 minuntes in seconds
+ const int NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD = 25*60; // 25 minuntes
const int NTCP2_CLOCK_SKEW = 60; // in seconds
const int NTCP2_MAX_OUTGOING_QUEUE_SIZE = 500; // how many messages we can queue up
@@ -123,7 +125,8 @@ namespace transport
{
public:
- NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter = nullptr);
+ NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter = nullptr,
+ std::shared_ptr addr = nullptr);
~NTCP2Session ();
void Terminate ();
void TerminateByTimeout ();
@@ -211,6 +214,7 @@ namespace transport
bool m_IsSending;
std::list > m_SendQueue;
+ uint64_t m_NextRouterInfoResendTime; // seconds since epoch
};
class NTCP2Server: private i2p::util::RunnableServiceWithWork
diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp
index 20b54376..0222ccdf 100644
--- a/libi2pd/NetDb.cpp
+++ b/libi2pd/NetDb.cpp
@@ -57,7 +57,9 @@ namespace data
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
Reseed ();
-
+ else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo ()))
+ Reseed (); // we don't have a router we can connect to. Trying to reseed
+
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
m_IsRunning = true;
@@ -643,6 +645,7 @@ namespace data
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
if (floodfill)
{
+ if (direct && !floodfill->IsCompatible (i2p::context.GetRouterInfo ())) direct = false; // check if fllodfill is reachable
if (direct)
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
else
@@ -1087,7 +1090,19 @@ namespace data
LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken);
m_PublishExcluded.insert (floodfill->GetIdentHash ());
m_PublishReplyToken = replyToken;
- transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
+ if (floodfill->IsCompatible (i2p::context.GetRouterInfo ())) // able to connect?
+ // send directly
+ transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
+ else
+ {
+ // otherwise through exploratory
+ auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
+ auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
+ auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
+ if (inbound && outbound)
+ outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
+ CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
+ }
}
}
diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp
index 2812f413..2e453b00 100644
--- a/libi2pd/Reseed.cpp
+++ b/libi2pd/Reseed.cpp
@@ -82,11 +82,27 @@ namespace data
*/
int Reseeder::ReseedFromServers ()
{
- std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
+ bool ipv6; i2p::config::GetOption("ipv6", ipv6);
+ bool ipv4; i2p::config::GetOption("ipv4", ipv4);
+
std::vector httpsReseedHostList;
- boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
+ if (ipv4 || ipv6)
+ {
+ std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
+ if (!reseedURLs.empty ())
+ boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
+ }
+
+ std::vector yggReseedHostList;
+ if (!i2p::util::net::GetYggdrasilAddress ().is_unspecified ())
+ {
+ LogPrint (eLogInfo, "Reseed: yggdrasil is supported");
+ std::string yggReseedURLs; i2p::config::GetOption("reseed.yggurls", yggReseedURLs);
+ if (!yggReseedURLs.empty ())
+ boost::split(yggReseedHostList, yggReseedURLs, boost::is_any_of(","), boost::token_compress_on);
+ }
- if (reseedURLs.length () == 0)
+ if (httpsReseedHostList.empty () && yggReseedHostList.empty())
{
LogPrint (eLogWarning, "Reseed: No reseed servers specified");
return 0;
@@ -95,9 +111,12 @@ namespace data
int reseedRetries = 0;
while (reseedRetries < 10)
{
- auto ind = rand () % httpsReseedHostList.size ();
- std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
- auto num = ReseedFromSU3Url (reseedUrl);
+ auto ind = rand () % (httpsReseedHostList.size () + yggReseedHostList.size ());
+ bool isHttps = ind < httpsReseedHostList.size ();
+ std::string reseedUrl = isHttps ? httpsReseedHostList[ind] :
+ yggReseedHostList[ind - httpsReseedHostList.size ()];
+ reseedUrl += "i2pseeds.su3";
+ auto num = ReseedFromSU3Url (reseedUrl, isHttps);
if (num > 0) return num; // success
reseedRetries++;
}
@@ -110,10 +129,10 @@ namespace data
* @param url
* @return number of entries added to netDb
*/
- int Reseeder::ReseedFromSU3Url (const std::string& url)
+ int Reseeder::ReseedFromSU3Url (const std::string& url, bool isHttps)
{
LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
- std::string su3 = HttpsRequest (url);
+ std::string su3 = isHttps ? HttpsRequest (url) : YggdrasilRequest (url);
if (su3.length () > 0)
{
std::stringstream s(su3);
@@ -667,42 +686,7 @@ namespace data
if (!ecode)
{
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
- i2p::http::HTTPReq req;
- req.uri = url.to_string();
- req.AddHeader("User-Agent", "Wget/1.11.4");
- req.AddHeader("Connection", "close");
- s.write_some (boost::asio::buffer (req.to_string()));
- // read response
- std::stringstream rs;
- char recv_buf[1024]; size_t l = 0;
- do {
- l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
- if (l) rs.write (recv_buf, l);
- } while (!ecode && l);
- // process response
- std::string data = rs.str();
- i2p::http::HTTPRes res;
- int len = res.parse(data);
- if (len <= 0) {
- LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host);
- return "";
- }
- if (res.code != 200) {
- LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code);
- return "";
- }
- data.erase(0, len); /* drop http headers from response */
- LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host);
- if (res.is_chunked()) {
- std::stringstream in(data), out;
- if (!i2p::http::MergeChunkedResponse(in, out)) {
- LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host);
- return "";
- }
- LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host);
- data = out.str();
- }
- return data;
+ return ReseedRequest (s, url.to_string());
}
else
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
@@ -711,5 +695,77 @@ namespace data
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
return "";
}
+
+ template
+ std::string Reseeder::ReseedRequest (Stream& s, const std::string& uri)
+ {
+ boost::system::error_code ecode;
+ i2p::http::HTTPReq req;
+ req.uri = uri;
+ req.AddHeader("User-Agent", "Wget/1.11.4");
+ req.AddHeader("Connection", "close");
+ s.write_some (boost::asio::buffer (req.to_string()));
+ // read response
+ std::stringstream rs;
+ char recv_buf[1024]; size_t l = 0;
+ do {
+ l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
+ if (l) rs.write (recv_buf, l);
+ } while (!ecode && l);
+ // process response
+ std::string data = rs.str();
+ i2p::http::HTTPRes res;
+ int len = res.parse(data);
+ if (len <= 0) {
+ LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", uri);
+ return "";
+ }
+ if (res.code != 200) {
+ LogPrint(eLogError, "Reseed: failed to reseed from ", uri, ", http code ", res.code);
+ return "";
+ }
+ data.erase(0, len); /* drop http headers from response */
+ LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", uri);
+ if (res.is_chunked()) {
+ std::stringstream in(data), out;
+ if (!i2p::http::MergeChunkedResponse(in, out)) {
+ LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", uri);
+ return "";
+ }
+ LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", uri);
+ data = out.str();
+ }
+ return data;
+ }
+
+ std::string Reseeder::YggdrasilRequest (const std::string& address)
+ {
+ i2p::http::URL url;
+ if (!url.parse(address))
+ {
+ LogPrint(eLogError, "Reseed: failed to parse url: ", address);
+ return "";
+ }
+ url.schema = "http";
+ if (!url.port) url.port = 80;
+
+ boost::system::error_code ecode;
+ boost::asio::io_service service;
+ boost::asio::ip::tcp::socket s(service, boost::asio::ip::tcp::v6());
+
+ if (url.host.length () < 2) return ""; // assume []
+ auto host = url.host.substr (1, url.host.length () - 2);
+ LogPrint (eLogDebug, "Reseed: Connecting to yggdrasil ", url.host, ":", url.port);
+ s.connect (boost::asio::ip::tcp::endpoint (boost::asio::ip::address_v6::from_string (host), url.port), ecode);
+ if (!ecode)
+ {
+ LogPrint (eLogDebug, "Reseed: Connected to yggdrasil ", url.host, ":", url.port);
+ return ReseedRequest (s, url.to_string());
+ }
+ else
+ LogPrint (eLogError, "Reseed: Couldn't connect to yggdrasil ", url.host, ": ", ecode.message ());
+
+ return "";
+ }
}
}
diff --git a/libi2pd/Reseed.h b/libi2pd/Reseed.h
index 345b45bf..8039c07e 100644
--- a/libi2pd/Reseed.h
+++ b/libi2pd/Reseed.h
@@ -31,7 +31,6 @@ namespace data
~Reseeder();
void Bootstrap ();
int ReseedFromServers ();
- int ReseedFromSU3Url (const std::string& url);
int ProcessSU3File (const char * filename);
int ProcessZIPFile (const char * filename);
@@ -39,6 +38,7 @@ namespace data
private:
+ int ReseedFromSU3Url (const std::string& url, bool isHttps = true);
void LoadCertificate (const std::string& filename);
int ProcessSU3Stream (std::istream& s);
@@ -47,7 +47,10 @@ namespace data
bool FindZipDataDescriptor (std::istream& s);
std::string HttpsRequest (const std::string& address);
-
+ std::string YggdrasilRequest (const std::string& address);
+ template
+ std::string ReseedRequest (Stream& s, const std::string& uri);
+
private:
std::map m_SigningKeys;
diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp
index d258b341..6183f2be 100644
--- a/libi2pd/RouterContext.cpp
+++ b/libi2pd/RouterContext.cpp
@@ -28,7 +28,7 @@ namespace i2p
RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
- m_ShareRatio (100), m_Status (eRouterStatusOK),
+ m_ShareRatio (100), m_Status (eRouterStatusUnknown),
m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID)
{
}
@@ -72,10 +72,12 @@ namespace i2p
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ssu; i2p::config::GetOption("ssu", ssu);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
+ bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
bool nat; i2p::config::GetOption("nat", nat);
std::string ifname; i2p::config::GetOption("ifname", ifname);
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
+ uint8_t caps = 0;
if (ipv4)
{
std::string host = "127.0.0.1";
@@ -89,7 +91,10 @@ namespace i2p
host = i2p::util::net::GetInterfaceAddress(ifname4, false).to_string();
if (ssu)
+ {
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
+ caps |= i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // R, BC
+ }
}
if (ipv6)
{
@@ -103,11 +108,13 @@ namespace i2p
host = i2p::util::net::GetInterfaceAddress(ifname6, true).to_string();
if (ssu)
+ {
routerInfo.AddSSUAddress (host.c_str(), port, nullptr);
+ caps |= i2p::data::RouterInfo::eReachable; // R
+ }
}
-
- routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
- i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
+
+ routerInfo.SetCaps (caps); // caps + L
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys);
@@ -117,11 +124,12 @@ namespace i2p
if (ntcp2) // we don't store iv in the address if non published so we must update it from keys
{
if (!m_NTCP2Keys) NewNTCP2Keys ();
- UpdateNTCP2Address (true);
bool published; i2p::config::GetOption("ntcp2.published", published);
+ if (ipv4 || !published) UpdateNTCP2Address (true); // create not published NTCP2 address
if (published)
{
- PublishNTCP2Address (port, true);
+ if (ipv4)
+ PublishNTCP2Address (port, true);
if (ipv6)
{
// add NTCP2 ipv6 address
@@ -131,7 +139,21 @@ namespace i2p
m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, boost::asio::ip::address_v6::from_string (host), port);
}
}
+ // enable added NTCP2 addresses
+ if (ipv4) m_RouterInfo.EnableV4 ();
+ if (ipv6) m_RouterInfo.EnableV6 ();
}
+ if (ygg)
+ {
+ auto yggaddr = i2p::util::net::GetYggdrasilAddress ();
+ if (!yggaddr.is_unspecified ())
+ {
+ if (!m_NTCP2Keys) NewNTCP2Keys ();
+ m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, yggaddr, port);
+ m_RouterInfo.EnableMesh ();
+ UpdateRouterInfo ();
+ }
+ }
}
void RouterContext::UpdateRouterInfo ()
@@ -245,7 +267,8 @@ namespace i2p
bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ())
{
- if (address->host != host && address->IsCompatible (host))
+ if (address->host != host && address->IsCompatible (host) &&
+ !i2p::util::net::IsYggdrasilAddress (address->host))
{
address->host = host;
if (host.is_v6 () && address->transportStyle == i2p::data::RouterInfo::eTransportSSU)
@@ -521,15 +544,44 @@ namespace i2p
UpdateRouterInfo ();
}
+ void RouterContext::SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host)
+ {
+ if (supportsmesh)
+ {
+ m_RouterInfo.EnableMesh ();
+ uint16_t port = 0;
+ i2p::config::GetOption ("ntcp2.port", port);
+ if (!port) i2p::config::GetOption("port", port);
+ bool foundMesh = false;
+ auto& addresses = m_RouterInfo.GetAddresses ();
+ for (auto& addr: addresses)
+ {
+ if (!port) port = addr->port;
+ if (i2p::util::net::IsYggdrasilAddress (addr->host))
+ {
+ foundMesh = true;
+ break;
+ }
+ }
+ if (!foundMesh)
+ m_RouterInfo.AddNTCP2Address (m_NTCP2Keys->staticPublicKey, m_NTCP2Keys->iv, host, port);
+ }
+ else
+ m_RouterInfo.DisableMesh ();
+ UpdateRouterInfo ();
+ }
+
void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
{
+ bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
bool updated = false;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr: addresses)
{
if (addr->IsPublishedNTCP2 ())
{
- if (addr->host.is_v6 ())
+ bool isYgg1 = i2p::util::net::IsYggdrasilAddress (addr->host);
+ if (addr->host.is_v6 () && ((isYgg && isYgg1) || (!isYgg && !isYgg1)))
{
if (addr->host != host)
{
@@ -631,7 +683,8 @@ namespace i2p
// read NTCP2
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
- if (ntcp2)
+ bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
+ if (ntcp2 || ygg)
{
if (!m_NTCP2Keys) NewNTCP2Keys ();
UpdateNTCP2Address (true); // enable NTCP2
@@ -729,7 +782,11 @@ namespace i2p
m_CurrentNoiseState.reset (new i2p::crypto::NoiseSymmetricState (*m_InitialNoiseState));
m_CurrentNoiseState->MixHash (encrypted, 32); // h = SHA256(h || sepk)
uint8_t sharedSecret[32];
- m_Decryptor->Decrypt (encrypted, sharedSecret, ctx, false);
+ if (!m_Decryptor->Decrypt (encrypted, sharedSecret, ctx, false))
+ {
+ LogPrint (eLogWarning, "Router: Incorrect ephemeral public key");
+ return false;
+ }
m_CurrentNoiseState->MixKey (sharedSecret);
encrypted += 32;
uint8_t nonce[12];
diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h
index 8c13b842..12b77d65 100644
--- a/libi2pd/RouterContext.h
+++ b/libi2pd/RouterContext.h
@@ -31,7 +31,8 @@ namespace i2p
eRouterStatusOK = 0,
eRouterStatusTesting = 1,
eRouterStatusFirewalled = 2,
- eRouterStatusError = 3
+ eRouterStatusError = 3,
+ eRouterStatusUnknown = 4
};
enum RouterError
@@ -107,8 +108,10 @@ namespace i2p
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
bool SupportsV4 () const { return m_RouterInfo.IsV4 (); };
+ bool SupportsMesh () const { return m_RouterInfo.IsMesh (); };
void SetSupportsV6 (bool supportsV6);
void SetSupportsV4 (bool supportsV4);
+ void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host);
bool IsECIES () const { return GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
std::unique_ptr& GetCurrentNoiseState () { return m_CurrentNoiseState; };
diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp
index 13776b81..8da49fc6 100644
--- a/libi2pd/RouterInfo.cpp
+++ b/libi2pd/RouterInfo.cpp
@@ -16,6 +16,7 @@
#include
#endif
#include "version.h"
+#include "util.h"
#include "Crypto.h"
#include "Base.h"
#include "Timestamp.h"
@@ -198,14 +199,14 @@ namespace data
auto address = std::make_shared();
s.read ((char *)&address->cost, sizeof (address->cost));
s.read ((char *)&address->date, sizeof (address->date));
- bool isNTCP2Only = false;
+ bool isHost = false, isIntroKey = false, isStaticKey = false;
char transportStyle[6];
- auto transportStyleLen = ReadString (transportStyle, 6, s) - 1;
+ ReadString (transportStyle, 6, s);
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
- {
+ {
address->transportStyle = eTransportNTCP;
- if (transportStyleLen > 4 && transportStyle[4] == '2') isNTCP2Only= true;
- }
+ address->ntcp2.reset (new NTCP2Ext ());
+ }
else if (!strcmp (transportStyle, "SSU"))
{
address->transportStyle = eTransportSSU;
@@ -230,22 +231,7 @@ namespace data
{
boost::system::error_code ecode;
address->host = boost::asio::ip::address::from_string (value, ecode);
- if (!ecode)
- {
-#if BOOST_VERSION >= 104900
- if (!address->host.is_unspecified ()) // check if address is valid
-#else
- address->host.to_string (ecode);
- if (!ecode)
-#endif
- {
- // add supported protocol
- if (address->host.is_v4 ())
- supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
- else
- supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
- }
- }
+ if (!ecode && !address->host.is_unspecified ()) isHost = true;
}
else if (!strcmp (key, "port"))
address->port = boost::lexical_cast(value);
@@ -259,7 +245,7 @@ namespace data
else if (!strcmp (key, "key"))
{
if (address->ssu)
- Base64ToByteStream (value, strlen (value), address->ssu->key, 32);
+ isIntroKey = (Base64ToByteStream (value, strlen (value), address->ssu->key, 32) == 32);
else
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP");
}
@@ -267,14 +253,11 @@ namespace data
ExtractCaps (value);
else if (!strcmp (key, "s")) // ntcp2 static key
{
- if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
- supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32);
+ isStaticKey = true;
}
else if (!strcmp (key, "i")) // ntcp2 iv
{
- if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
- supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16);
address->ntcp2->isPublished = true; // presence if "i" means "published"
}
@@ -314,9 +297,32 @@ namespace data
}
if (!s) return;
}
- if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
- if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
- if (supportedTransports & ~(eNTCPV4 | eNTCPV6)) // exclude NTCP only
+ if (address->transportStyle == eTransportNTCP)
+ {
+ if (isStaticKey)
+ {
+ if (isHost)
+ {
+ if (address->host.is_v6 ())
+ supportedTransports |= i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6;
+ else
+ supportedTransports |= eNTCP2V4;
+ }
+ else if (!address->ntcp2->isPublished)
+ supportedTransports |= eNTCP2V4; // most likely, since we don't have host
+ }
+ }
+ else if (address->transportStyle == eTransportSSU)
+ {
+ if (isIntroKey)
+ {
+ if (isHost)
+ supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
+ else
+ if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
+ }
+ }
+ if (supportedTransports)
{
addresses->push_back(address);
m_SupportedTransports |= supportedTransports;
@@ -741,7 +747,6 @@ namespace data
addr->cost = port ? 3 : 14; // override from RouterContext::PublishNTCP2Address
addr->date = 0;
addr->ntcp2.reset (new NTCP2Ext ());
- addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
if (port) addr->ntcp2->isPublished = true;
memcpy (addr->ntcp2->staticKey, staticKey, 32);
memcpy (addr->ntcp2->iv, iv, 16);
@@ -832,26 +837,36 @@ namespace data
return m_SupportedTransports & (eNTCP2V4 | eNTCP2V6);
}
+ bool RouterInfo::IsNTCP2V6 () const
+ {
+ return m_SupportedTransports & eNTCP2V6;
+ }
+
bool RouterInfo::IsV6 () const
{
- return m_SupportedTransports & (eNTCPV6 | eSSUV6 | eNTCP2V6);
+ return m_SupportedTransports & (eSSUV6 | eNTCP2V6);
}
bool RouterInfo::IsV4 () const
{
- return m_SupportedTransports & (eNTCPV4 | eSSUV4 | eNTCP2V4);
+ return m_SupportedTransports & (eSSUV4 | eNTCP2V4);
}
+ bool RouterInfo::IsMesh () const
+ {
+ return m_SupportedTransports & eNTCP2V6Mesh;
+ }
+
void RouterInfo::EnableV6 ()
{
if (!IsV6 ())
- m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6;
+ m_SupportedTransports |= eSSUV6 | eNTCP2V6;
}
void RouterInfo::EnableV4 ()
{
if (!IsV4 ())
- m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
+ m_SupportedTransports |= eSSUV4 | eNTCP2V4;
}
@@ -859,7 +874,7 @@ namespace data
{
if (IsV6 ())
{
- m_SupportedTransports &= ~(eNTCPV6 | eSSUV6 | eNTCP2V6);
+ m_SupportedTransports &= ~(eSSUV6 | eNTCP2V6);
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
{
auto addr = *it;
@@ -875,7 +890,7 @@ namespace data
{
if (IsV4 ())
{
- m_SupportedTransports &= ~(eNTCPV4 | eSSUV4 | eNTCP2V4);
+ m_SupportedTransports &= ~(eSSUV4 | eNTCP2V4);
for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
{
auto addr = *it;
@@ -887,6 +902,27 @@ namespace data
}
}
+ void RouterInfo::EnableMesh ()
+ {
+ if (!IsMesh ())
+ m_SupportedTransports |= eNTCP2V6Mesh;
+ }
+
+ void RouterInfo::DisableMesh ()
+ {
+ if (IsMesh ())
+ {
+ m_SupportedTransports &= ~eNTCP2V6Mesh;
+ for (auto it = m_Addresses->begin (); it != m_Addresses->end ();)
+ {
+ auto addr = *it;
+ if (i2p::util::net::IsYggdrasilAddress (addr->host))
+ it = m_Addresses->erase (it);
+ else
+ ++it;
+ }
+ }
+ }
bool RouterInfo::UsesIntroducer () const
{
@@ -926,15 +962,43 @@ namespace data
return nullptr;
}
- std::shared_ptr RouterInfo::GetNTCP2Address (bool publishedOnly, bool v4only) const
+ std::shared_ptr RouterInfo::GetNTCP2Address (bool publishedOnly) const
{
return GetAddress (
- [publishedOnly, v4only](std::shared_ptr address)->bool
- {
- return address->IsNTCP2 () && (!publishedOnly || address->IsPublishedNTCP2 ()) && (!v4only || address->host.is_v4 ());
+ [publishedOnly](std::shared_ptr address)->bool
+ {
+ return address->IsNTCP2 () && (!publishedOnly || address->IsPublishedNTCP2 ());
});
}
+ std::shared_ptr RouterInfo::GetPublishedNTCP2V4Address () const
+ {
+ return GetAddress (
+ [](std::shared_ptr address)->bool
+ {
+ return address->IsPublishedNTCP2 () && address->host.is_v4 ();
+ });
+ }
+
+ std::shared_ptr RouterInfo::GetPublishedNTCP2V6Address () const
+ {
+ return GetAddress (
+ [](std::shared_ptr address)->bool
+ {
+ return address->IsPublishedNTCP2 () && address->host.is_v6 () &&
+ !i2p::util::net::IsYggdrasilAddress (address->host);
+ });
+ }
+
+ std::shared_ptr RouterInfo::GetYggdrasilAddress () const
+ {
+ return GetAddress (
+ [](std::shared_ptr address)->bool
+ {
+ return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host);
+ });
+ }
+
std::shared_ptr RouterInfo::GetProfile () const
{
if (!m_Profile)
diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h
index 733ea44a..45670ee5 100644
--- a/libi2pd/RouterInfo.h
+++ b/libi2pd/RouterInfo.h
@@ -54,12 +54,11 @@ namespace data
enum SupportedTranports
{
- eNTCPV4 = 0x01,
- eNTCPV6 = 0x02,
+ eNTCP2V4 = 0x01,
+ eNTCP2V6 = 0x02,
eSSUV4 = 0x04,
eSSUV6 = 0x08,
- eNTCP2V4 = 0x10,
- eNTCP2V6 = 0x20
+ eNTCP2V6Mesh = 0x10
};
enum Caps
@@ -104,7 +103,6 @@ namespace data
Tag<32> staticKey;
Tag<16> iv;
bool isPublished = false;
- bool isNTCP2Only = false;
};
struct Address
@@ -136,7 +134,6 @@ namespace data
bool IsNTCP2 () const { return (bool)ntcp2; };
bool IsPublishedNTCP2 () const { return IsNTCP2 () && ntcp2->isPublished; };
- bool IsNTCP2Only () const { return ntcp2 && ntcp2->isNTCP2Only; };
};
typedef std::list > Addresses;
@@ -153,9 +150,12 @@ namespace data
uint64_t GetTimestamp () const { return m_Timestamp; };
int GetVersion () const { return m_Version; };
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
- std::shared_ptr GetNTCP2Address (bool publishedOnly, bool v4only = true) const;
+ std::shared_ptr GetNTCP2Address (bool publishedOnly) const;
+ std::shared_ptr GetPublishedNTCP2V4Address () const;
+ std::shared_ptr GetPublishedNTCP2V6Address () const;
std::shared_ptr GetSSUAddress (bool v4only = true) const;
std::shared_ptr GetSSUV6Address () const;
+ std::shared_ptr GetYggdrasilAddress () const;
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, const boost::asio::ip::address& host = boost::asio::ip::address(), int port = 0);
@@ -170,13 +170,17 @@ namespace data
bool IsSSU (bool v4only = true) const;
bool IsSSUV6 () const;
bool IsNTCP2 (bool v4only = true) const;
+ bool IsNTCP2V6 () const;
bool IsV6 () const;
bool IsV4 () const;
+ bool IsMesh () const;
void EnableV6 ();
void DisableV6 ();
void EnableV4 ();
void DisableV4 ();
- bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
+ void EnableMesh ();
+ void DisableMesh ();
+ bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
bool HasValidAddresses () const { return m_SupportedTransports; };
bool UsesIntroducer () const;
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp
index 3b6280dd..79b4f35f 100644
--- a/libi2pd/SSU.cpp
+++ b/libi2pd/SSU.cpp
@@ -127,18 +127,18 @@ namespace transport
delete m_ReceiversThread;
m_ReceiversThread = nullptr;
}
- if (m_Thread)
- {
- m_Thread->join ();
- delete m_Thread;
- m_Thread = nullptr;
- }
if (m_ReceiversThreadV6)
{
m_ReceiversThreadV6->join ();
delete m_ReceiversThreadV6;
m_ReceiversThreadV6 = nullptr;
}
+ if (m_Thread)
+ {
+ m_Thread->join ();
+ delete m_Thread;
+ m_Thread = nullptr;
+ }
}
void SSUServer::Run ()
@@ -377,6 +377,7 @@ namespace transport
void SSUServer::HandleReceivedPackets (std::vector packets,
std::map > * sessions)
{
+ if (!m_IsRunning) return;
std::shared_ptr session;
for (auto& packet: packets)
{
diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h
index 213f379f..d20f1c9d 100644
--- a/libi2pd/SSU.h
+++ b/libi2pd/SSU.h
@@ -119,7 +119,7 @@ namespace transport
};
bool m_OnlyV6;
- bool m_IsRunning;
+ volatile bool m_IsRunning;
std::thread * m_Thread, * m_ReceiversThread, * m_ReceiversThreadV6;
boost::asio::io_service m_Service, m_ReceiversService, m_ReceiversServiceV6;
boost::asio::io_service::work m_Work, m_ReceiversWork, m_ReceiversWorkV6;
diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp
index f6bf7e8b..0d482303 100644
--- a/libi2pd/Streaming.cpp
+++ b/libi2pd/Streaming.cpp
@@ -764,7 +764,7 @@ namespace stream
return;
}
}
- if (!m_RoutingSession || !m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ()) // expired and detached or new session sent
+ if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ()) // expired and detached or new session sent
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
if (!m_CurrentOutboundTunnel && m_RoutingSession) // first message to send
{
@@ -817,7 +817,7 @@ namespace stream
void Stream::SendUpdatedLeaseSet ()
{
- if (m_RoutingSession)
+ if (m_RoutingSession && !m_RoutingSession->IsTerminated ())
{
if (m_RoutingSession->IsLeaseSetNonConfirmed ())
{
@@ -838,6 +838,8 @@ namespace stream
SendQuickAck ();
}
}
+ else
+ SendQuickAck ();
}
void Stream::ScheduleResend ()
diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h
index ab3c4439..fe035136 100644
--- a/libi2pd/Streaming.h
+++ b/libi2pd/Streaming.h
@@ -61,7 +61,7 @@ namespace stream
const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds
const size_t MAX_PENDING_INCOMING_BACKLOG = 128;
const int PENDING_INCOMING_TIMEOUT = 10; // in seconds
- const int MAX_RECEIVE_TIMEOUT = 30; // in seconds
+ const int MAX_RECEIVE_TIMEOUT = 20; // in seconds
struct Packet
{
diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp
index 5c2fcb6d..2eadda85 100644
--- a/libi2pd/Transports.cpp
+++ b/libi2pd/Transports.cpp
@@ -351,6 +351,7 @@ namespace transport
try
{
auto r = netdb.FindRouter (ident);
+ if (!r || !r->IsCompatible (i2p::context.GetRouterInfo ())) return;
{
std::unique_lock l(m_PeersMutex);
it = m_Peers.insert (std::pair(ident, { 0, r, {},
@@ -389,16 +390,34 @@ namespace transport
peer.router = netdb.FindRouter (ident); // try to get new one from netdb
if (peer.router) // we have RI already
{
- if (!peer.numAttempts) // NTCP2
+ if (peer.numAttempts < 2) // NTCP2, 0 - ipv6, 1- ipv4
{
- peer.numAttempts++;
if (m_NTCP2Server) // we support NTCP2
{
- // NTCP2 have priority over NTCP
- auto address = peer.router->GetNTCP2Address (true, !context.SupportsV6 ()); // published only
- if (address && !peer.router->IsUnreachable () && (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host)))
+ std::shared_ptr address;
+ if (!peer.numAttempts) // NTCP2 ipv6
{
- auto s = std::make_shared (*m_NTCP2Server, peer.router);
+ if (context.GetRouterInfo ().IsNTCP2V6 () && peer.router->IsNTCP2V6 ())
+ {
+ address = peer.router->GetPublishedNTCP2V6Address ();
+ if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ address = nullptr;
+ }
+ peer.numAttempts++;
+ }
+ if (!address && peer.numAttempts == 1) // NTCP2 ipv4
+ {
+ if (context.GetRouterInfo ().IsNTCP2 (true) && peer.router->IsNTCP2 (true) && !peer.router->IsUnreachable ())
+ {
+ address = peer.router->GetPublishedNTCP2V4Address ();
+ if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ address = nullptr;
+ }
+ peer.numAttempts++;
+ }
+ if (address)
+ {
+ auto s = std::make_shared (*m_NTCP2Server, peer.router, address);
if(m_NTCP2Server->UsingProxy())
{
@@ -415,21 +434,58 @@ namespace transport
return true;
}
}
+ else
+ peer.numAttempts = 2; // switch to SSU
}
- if (peer.numAttempts == 1)// SSU
+ if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU
{
- peer.numAttempts++;
- if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
- {
- auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
- if (!m_CheckReserved || !i2p::util::net::IsInReservedRange(address->host))
+ if (m_SSUServer)
+ {
+ std::shared_ptr address;
+ if (peer.numAttempts == 2) // SSU ipv6
+ {
+ if (context.GetRouterInfo ().IsSSUV6 () && peer.router->IsSSUV6 ())
+ {
+ address = peer.router->GetSSUV6Address ();
+ if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ address = nullptr;
+ }
+ peer.numAttempts++;
+ }
+ if (!address && peer.numAttempts == 3) // SSU ipv4
+ {
+ if (context.GetRouterInfo ().IsSSU (true) && peer.router->IsSSU (true))
+ {
+ address = peer.router->GetSSUAddress (true);
+ if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
+ address = nullptr;
+ }
+ peer.numAttempts++;
+ }
+ if (address)
{
m_SSUServer->CreateSession (peer.router, address->host, address->port);
return true;
- }
+ }
}
+ else
+ peer.numAttempts += 2; // switch to Mesh
}
- LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
+ if (peer.numAttempts == 4) // Mesh
+ {
+ peer.numAttempts++;
+ if (m_NTCP2Server && context.GetRouterInfo ().IsMesh () && peer.router->IsMesh ())
+ {
+ auto address = peer.router->GetYggdrasilAddress ();
+ if (address)
+ {
+ auto s = std::make_shared (*m_NTCP2Server, peer.router, address);
+ m_NTCP2Server->Connect (address->host, address->port, s);
+ return true;
+ }
+ }
+ }
+ LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available");
i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed
peer.Done ();
std::unique_lock l(m_PeersMutex);
diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp
index 42eeeb5d..5355a7b6 100644
--- a/libi2pd/Tunnel.cpp
+++ b/libi2pd/Tunnel.cpp
@@ -42,8 +42,8 @@ namespace tunnel
void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel)
{
auto numHops = m_Config->GetNumHops ();
- int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops;
- auto msg = NewI2NPShortMessage ();
+ int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : MAX_NUM_RECORDS;
+ auto msg = numRecords <= STANDARD_NUM_RECORDS ? NewI2NPShortMessage () : NewI2NPMessage ();
*msg->GetPayload () = numRecords;
msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1;
// shuffle records
diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h
index 37c5cddb..7e8edca7 100644
--- a/libi2pd/Tunnel.h
+++ b/libi2pd/Tunnel.h
@@ -37,7 +37,8 @@ namespace tunnel
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds
const int STANDARD_NUM_RECORDS = 4; // in VariableTunnelBuild message
-
+ const int MAX_NUM_RECORDS = 8;
+
enum TunnelState
{
eTunnelStatePending,
diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp
index 94462c93..22563e2d 100644
--- a/libi2pd/TunnelPool.cpp
+++ b/libi2pd/TunnelPool.cpp
@@ -29,6 +29,10 @@ namespace tunnel
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels),
m_IsActive (true), m_CustomPeerSelector(nullptr)
{
+ if (m_NumInboundTunnels > TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY)
+ m_NumInboundTunnels = TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY;
+ if (m_NumOutboundTunnels > TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY)
+ m_NumOutboundTunnels = TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY;
m_NextManageTime = i2p::util::GetSecondsSinceEpoch () + rand () % TUNNEL_POOL_MANAGE_INTERVAL;
}
@@ -414,7 +418,8 @@ namespace tunnel
else if (i2p::transport::transports.GetNumPeers () > 25)
{
auto r = i2p::transport::transports.GetRandomPeer ();
- if (r && !r->GetProfile ()->IsBad ())
+ if (r && !r->GetProfile ()->IsBad () &&
+ (numHops > 1 || !inbound || r->IsReachable ())) // first must be reachable
{
prevHop = r;
peers.push_back (r->GetRouterIdentity ());
@@ -430,6 +435,12 @@ namespace tunnel
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
return false;
}
+ if (inbound && (i == numHops - 1) && !hop->IsReachable ())
+ {
+ // if first is not reachable try again
+ auto hop1 = nextHop (prevHop);
+ if (hop1) hop = hop1;
+ }
prevHop = hop;
peers.push_back (hop->GetRouterIdentity ());
}
diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h
index d1024d04..4742a1f6 100644
--- a/libi2pd/TunnelPool.h
+++ b/libi2pd/TunnelPool.h
@@ -28,6 +28,8 @@ namespace i2p
namespace tunnel
{
const int TUNNEL_POOL_MANAGE_INTERVAL = 10; // in seconds
+ const int TUNNEL_POOL_MAX_INBOUND_TUNNELS_QUANTITY = 16;
+ const int TUNNEL_POOL_MAX_OUTBOUND_TUNNELS_QUANTITY = 16;
class Tunnel;
class InboundTunnel;
diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp
index 794a3f14..8c9ffae7 100644
--- a/libi2pd/util.cpp
+++ b/libi2pd/util.cpp
@@ -119,10 +119,12 @@ namespace util
}
void SetThreadName (const char *name) {
-#if defined (__APPLE__)
+#if defined(__APPLE__)
pthread_setname_np(name);
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
pthread_set_name_np(pthread_self(), name);
+#elif defined(__NetBSD__)
+ pthread_setname_np(pthread_self(), "%s", (void *)name);
#else
pthread_setname_np(pthread_self(), name);
#endif
@@ -416,7 +418,110 @@ namespace net
#endif
}
- bool IsInReservedRange (const boost::asio::ip::address& host) {
+ static bool IsYggdrasilAddress (const uint8_t addr[16])
+ {
+ return addr[0] == 0x02 || addr[0] == 0x03;
+ }
+
+ bool IsYggdrasilAddress (const boost::asio::ip::address& addr)
+ {
+ if (!addr.is_v6 ()) return false;
+ return IsYggdrasilAddress (addr.to_v6 ().to_bytes ().data ());
+ }
+
+ boost::asio::ip::address_v6 GetYggdrasilAddress ()
+ {
+#if defined(ANDROID)
+ // TODO: implement
+ return boost::asio::ip::address_v6 ();
+#elif defined(_WIN32)
+ ULONG outBufLen = 0;
+ PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
+ PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
+ PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;
+
+ if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
+ == ERROR_BUFFER_OVERFLOW)
+ {
+ FREE(pAddresses);
+ pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
+ }
+
+ DWORD dwRetVal = GetAdaptersAddresses(
+ AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
+ );
+
+ if(dwRetVal != NO_ERROR)
+ {
+ LogPrint(eLogError, "NetIface: GetYggdrasilAddress(): enclosed GetAdaptersAddresses() call has failed");
+ FREE(pAddresses);
+ return boost::asio::ip::address_v6 ();
+ }
+
+ pCurrAddresses = pAddresses;
+ while(pCurrAddresses)
+ {
+ PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;
+ pUnicast = pCurrAddresses->FirstUnicastAddress;
+
+ for(int i = 0; pUnicast != nullptr; ++i)
+ {
+ LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
+ sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr;
+ if (IsYggdrasilAddress(localInterfaceAddress->sin6_addr.u.Byte)) {
+ boost::asio::ip::address_v6::bytes_type bytes;
+ memcpy (bytes.data (), &localInterfaceAddress->sin6_addr.u.Byte, 16);
+ FREE(pAddresses);
+ return boost::asio::ip::address_v6 (bytes);
+ }
+ pUnicast = pUnicast->Next;
+ }
+ pCurrAddresses = pCurrAddresses->Next;
+ }
+ LogPrint(eLogWarning, "NetIface: interface with yggdrasil network address not found");
+ FREE(pAddresses);
+ return boost::asio::ip::address_v6 ();
+#else
+ ifaddrs * addrs = nullptr;
+ auto err = getifaddrs(&addrs);
+ if (!err)
+ {
+ ifaddrs * cur = addrs;
+ while(cur)
+ {
+ if (cur->ifa_addr && cur->ifa_addr->sa_family == AF_INET6)
+ {
+ sockaddr_in6* sa = (sockaddr_in6*)cur->ifa_addr;
+ if (IsYggdrasilAddress(sa->sin6_addr.s6_addr))
+ {
+ boost::asio::ip::address_v6::bytes_type bytes;
+ memcpy (bytes.data (), &sa->sin6_addr, 16);
+ freeifaddrs(addrs);
+ return boost::asio::ip::address_v6 (bytes);
+ }
+ }
+ cur = cur->ifa_next;
+ }
+ }
+ LogPrint(eLogWarning, "NetIface: interface with yggdrasil network address not found");
+ if(addrs) freeifaddrs(addrs);
+ return boost::asio::ip::address_v6 ();
+#endif
+ }
+
+ bool IsLocalAddress (const boost::asio::ip::address& addr)
+ {
+ auto mtu = // TODO: implement better
+#ifdef _WIN32
+ GetMTUWindows(addr, 0);
+#else
+ GetMTUUnix(addr, 0);
+#endif
+ return mtu > 0;
+ }
+
+ bool IsInReservedRange (const boost::asio::ip::address& host)
+ {
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
if(host.is_v4())
{
@@ -456,6 +561,8 @@ namespace net
if (ipv6_address >= it.first && ipv6_address <= it.second)
return true;
}
+ if (IsYggdrasilAddress (ipv6_address.data ())) // yggdrasil?
+ return true;
}
return false;
}
diff --git a/libi2pd/util.h b/libi2pd/util.h
index e6de09ed..0cab4121 100644
--- a/libi2pd/util.h
+++ b/libi2pd/util.h
@@ -188,7 +188,10 @@ namespace util
{
int GetMTU (const boost::asio::ip::address& localAddress);
const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6=false);
+ boost::asio::ip::address_v6 GetYggdrasilAddress ();
+ bool IsLocalAddress (const boost::asio::ip::address& addr);
bool IsInReservedRange (const boost::asio::ip::address& host);
+ bool IsYggdrasilAddress (const boost::asio::ip::address& addr);
}
}
}
diff --git a/libi2pd/version.h b/libi2pd/version.h
index f28d88c0..7bdd3fc5 100644
--- a/libi2pd/version.h
+++ b/libi2pd/version.h
@@ -16,7 +16,7 @@
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
#define I2PD_VERSION_MAJOR 2
-#define I2PD_VERSION_MINOR 35
+#define I2PD_VERSION_MINOR 36
#define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
@@ -30,7 +30,7 @@
#define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9
-#define I2P_VERSION_MICRO 48
+#define I2P_VERSION_MICRO 49
#define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
#define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp
index a69bd660..ba2d8276 100644
--- a/libi2pd_client/AddressBook.cpp
+++ b/libi2pd_client/AddressBook.cpp
@@ -34,14 +34,13 @@ namespace client
// TODO: this is actually proxy class
class AddressBookFilesystemStorage: public AddressBookStorage
{
- private:
- i2p::fs::HashedStorage storage;
- std::string etagsPath, indexPath, localPath;
-
public:
+
AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32")
{
i2p::config::GetOption("persist.addressbook", m_IsPersist);
+ if (m_IsPersist)
+ i2p::config::GetOption("addressbook.hostsfile", m_HostsFile);
}
std::shared_ptr GetAddress (const i2p::data::IdentHash& ident) const;
void AddAddress (std::shared_ptr address);
@@ -62,7 +61,10 @@ namespace client
private:
+ i2p::fs::HashedStorage storage;
+ std::string etagsPath, indexPath, localPath;
bool m_IsPersist;
+ std::string m_HostsFile; // file to dump hosts.txt, empty if not used
};
bool AddressBookFilesystemStorage::Init()
@@ -183,35 +185,59 @@ namespace client
int AddressBookFilesystemStorage::Save (const std::map >& addresses)
{
- if (addresses.empty()) {
+ if (addresses.empty())
+ {
LogPrint(eLogWarning, "Addressbook: not saving empty addressbook");
return 0;
}
int num = 0;
- std::ofstream f (indexPath, std::ofstream::out); // in text mode
-
- if (!f.is_open ()) {
- LogPrint (eLogWarning, "Addressbook: Can't open ", indexPath);
- return 0;
- }
-
- for (const auto& it: addresses)
{
- if (it.second->IsValid ())
- {
- f << it.first << ",";
- if (it.second->IsIdentHash ())
- f << it.second->identHash.ToBase32 ();
- else
- f << it.second->blindedPublicKey->ToB33 ();
- f << std::endl;
- num++;
+ // save index file
+ std::ofstream f (indexPath, std::ofstream::out); // in text mode
+ if (f.is_open ())
+ {
+ for (const auto& it: addresses)
+ {
+ if (it.second->IsValid ())
+ {
+ f << it.first << ",";
+ if (it.second->IsIdentHash ())
+ f << it.second->identHash.ToBase32 ();
+ else
+ f << it.second->blindedPublicKey->ToB33 ();
+ f << std::endl;
+ num++;
+ }
+ else
+ LogPrint (eLogWarning, "Addressbook: invalid address ", it.first);
+ }
+ LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved");
}
else
- LogPrint (eLogWarning, "Addressbook: invalid address ", it.first);
- }
- LogPrint (eLogInfo, "Addressbook: ", num, " addresses saved");
+ LogPrint (eLogWarning, "Addressbook: Can't open ", indexPath);
+ }
+ if (!m_HostsFile.empty ())
+ {
+ // dump full hosts.txt
+ std::ofstream f (m_HostsFile, std::ofstream::out); // in text mode
+ if (f.is_open ())
+ {
+ for (const auto& it: addresses)
+ {
+ std::shared_ptr addr;
+ if (it.second->IsIdentHash ())
+ {
+ addr = GetAddress (it.second->identHash);
+ if (addr)
+ f << it.first << "=" << addr->ToBase64 () << std::endl;
+ }
+ }
+ }
+ else
+ LogPrint (eLogWarning, "Addressbook: Can't open ", m_HostsFile);
+ }
+
return num;
}
@@ -494,7 +520,7 @@ namespace client
while (!f.eof ())
{
getline(f, s);
- if (!s.length()) continue; // skip empty line
+ if (s.empty () || s[0] == '#') continue; // skip empty line or comment
m_Subscriptions.push_back (std::make_shared (*this, s));
}
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
@@ -507,9 +533,10 @@ namespace client
std::vector subsList;
boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
- for (size_t i = 0; i < subsList.size (); i++)
+ for (const auto& s: subsList)
{
- m_Subscriptions.push_back (std::make_shared (*this, subsList[i]));
+ if (s.empty () || s[0] == '#') continue; // skip empty line or comment
+ m_Subscriptions.push_back (std::make_shared (*this, s));
}
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
}
diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp
index 860e8cfd..cac472f9 100644
--- a/libi2pd_client/ClientContext.cpp
+++ b/libi2pd_client/ClientContext.cpp
@@ -404,9 +404,10 @@ namespace client
{
std::map params
{
- { I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, "2" },
- { I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, "2" },
- { I2CP_PARAM_LEASESET_TYPE, "3" }
+ { I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, "3" },
+ { I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, "3" },
+ { I2CP_PARAM_LEASESET_TYPE, "3" },
+ { I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, "0,4" }
};
m_SharedLocalDestination = CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, ¶ms); // non-public, EDDSA
diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp
index 64080752..5deaa7b5 100644
--- a/libi2pd_client/HTTPProxy.cpp
+++ b/libi2pd_client/HTTPProxy.cpp
@@ -32,16 +32,19 @@
namespace i2p {
namespace proxy {
std::map jumpservices = {
- { "inr.i2p", "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/search/?q=" },
- { "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" },
+ { "reg.i2p", "http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/jump/" },
+ { "identiguy.i2p", "http://3mzmrus2oron5fxptw7hw2puho3bnqmw2hqy7nw64dsrrjwdilva.b32.i2p/cgi-bin/query?hostname=" },
+ { "stats.i2p", "http://7tbay5p4kzeekxvyvbf6v7eauazemsnnl2aoyqhg5jzpr5eke7tq.b32.i2p/cgi-bin/jump.cgi?a=" },
};
static const char *pageHead =
"\r\n"
+ " \r\n"
" I2Pd HTTP proxy\r\n"
" \r\n"
"\r\n"
;
diff --git a/qt/.gitignore b/qt/.gitignore
deleted file mode 100644
index a0155cb2..00000000
--- a/qt/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build*/
diff --git a/qt/i2pd_qt/.gitignore b/qt/i2pd_qt/.gitignore
deleted file mode 100644
index 1f9d6012..00000000
--- a/qt/i2pd_qt/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-i2pd_qt.pro.user*
-moc_*
-ui_*
-qrc_*
-i2pd_qt
-Makefile*
-*.stash
-object_script.*
-i2pd_qt_plugin_import.cpp
-i2pd_qt.pro.autosave*
-build*
-nohup.out
-
diff --git a/qt/i2pd_qt/AboutDialog.cpp b/qt/i2pd_qt/AboutDialog.cpp
deleted file mode 100644
index ac92694a..00000000
--- a/qt/i2pd_qt/AboutDialog.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "AboutDialog.h"
-#include "ui_AboutDialog.h"
-#include
-#include "version.h"
-#include "BuildDateTimeQt.h"
-
-AboutDialog::AboutDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::AboutDialog)
-{
- ui->setupUi(this);
- ui->i2pdVersionLabel->setText(I2PD_VERSION);
- ui->i2pVersionLabel->setText(I2P_VERSION);
- ui->buildDateTimeLabel->setText(BUILD_DATE_TIME_QT);
- ui->vcsCommitInfoLabel->setText(VCS_COMMIT_INFO);
-}
-
-AboutDialog::~AboutDialog()
-{
- delete ui;
-}
diff --git a/qt/i2pd_qt/AboutDialog.h b/qt/i2pd_qt/AboutDialog.h
deleted file mode 100644
index d462de28..00000000
--- a/qt/i2pd_qt/AboutDialog.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef ABOUTDIALOG_H
-#define ABOUTDIALOG_H
-
-#include
-
-namespace Ui {
-class AboutDialog;
-}
-
-class AboutDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit AboutDialog(QWidget *parent = 0);
- ~AboutDialog();
-
-private:
- Ui::AboutDialog *ui;
-};
-
-#endif // ABOUTDIALOG_H
diff --git a/qt/i2pd_qt/AboutDialog.ui b/qt/i2pd_qt/AboutDialog.ui
deleted file mode 100644
index 6e662706..00000000
--- a/qt/i2pd_qt/AboutDialog.ui
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
- AboutDialog
-
-
- Qt::WindowModal
-
-
-
- 0
- 0
- 400
- 199
-
-
-
- About i2pd_qt
-
-
-
- :/icons/mask:/icons/mask
-
-
-
-
- 10
- 160
- 381
- 32
-
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Ok
-
-
-
-
-
- 10
- 10
- 381
- 17
-
-
-
- <html><head/><body><p><span style=" font-weight:600;">About i2pd_qt</span></p></body></html>
-
-
-
-
-
- 10
- 40
- 131
- 17
-
-
-
- i2pd Version:
-
-
-
-
-
- 10
- 70
- 131
- 17
-
-
-
- Build Date/Time:
-
-
-
-
-
- 150
- 40
- 241
- 20
-
-
-
- I2PD_VERSION_LABEL
-
-
-
-
-
- 10
- 130
- 131
- 17
-
-
-
- I2P Version:
-
-
-
-
-
- 150
- 130
- 241
- 17
-
-
-
- I2P_VERSION_LABEL
-
-
-
-
-
- 150
- 70
- 241
- 20
-
-
-
- BUILD_DATE_TIME_LABEL
-
-
-
-
-
- 10
- 100
- 131
- 17
-
-
-
- Version Control:
-
-
-
-
-
- 150
- 100
- 241
- 17
-
-
-
- VCS_COMMIT_INFO_LABEL
-
-
-
-
-
-
-
-
- buttonBox
- accepted()
- AboutDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
-
- buttonBox
- rejected()
- AboutDialog
- reject()
-
-
- 316
- 260
-
-
- 286
- 274
-
-
-
-
-
diff --git a/qt/i2pd_qt/BuildDateTimeQt.h b/qt/i2pd_qt/BuildDateTimeQt.h
deleted file mode 100644
index 139e2083..00000000
--- a/qt/i2pd_qt/BuildDateTimeQt.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef BUILDDATETIMEQT_H
-#define BUILDDATETIMEQT_H
-
-#include
-const QString BUILD_DATE_TIME_QT = QStringLiteral(__DATE__ " " __TIME__);
-
-#endif // BUILDDATETIMEQT_H
diff --git a/qt/i2pd_qt/ClientTunnelPane.cpp b/qt/i2pd_qt/ClientTunnelPane.cpp
deleted file mode 100644
index fbfa74cb..00000000
--- a/qt/i2pd_qt/ClientTunnelPane.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-#include "ClientTunnelPane.h"
-#include "ClientContext.h"
-#include "SignatureTypeComboboxFactory.h"
-#include "QVBoxLayout"
-
-ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow):
- TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_, mainWindow) {}
-
-void ClientTunnelPane::setGroupBoxTitle(const QString & title) {
- clientTunnelNameGroupBox->setTitle(title);
-}
-
-void ClientTunnelPane::deleteClientTunnelForm() {
- TunnelPane::deleteTunnelForm();
- delete clientTunnelNameGroupBox;
- clientTunnelNameGroupBox=nullptr;
-
- //gridLayoutWidget_2->deleteLater();
- //gridLayoutWidget_2=nullptr;
-}
-
-int ClientTunnelPane::appendClientTunnelForm(
- ClientTunnelConfig* tunnelConfig, QWidget *tunnelsFormGridLayoutWidget, int tunnelsRow, int height) {
-
- ClientTunnelPane& ui = *this;
-
- clientTunnelNameGroupBox = new QGroupBox(tunnelsFormGridLayoutWidget);
- clientTunnelNameGroupBox->setObjectName(QStringLiteral("clientTunnelNameGroupBox"));
-
- //tunnel
- gridLayoutWidget_2 = new QWidget(clientTunnelNameGroupBox);
-
- QComboBox *tunnelTypeComboBox = new QComboBox(gridLayoutWidget_2);
- tunnelTypeComboBox->setObjectName(QStringLiteral("tunnelTypeComboBox"));
- tunnelTypeComboBox->addItem("Client", i2p::client::I2P_TUNNELS_SECTION_TYPE_CLIENT);
- tunnelTypeComboBox->addItem("Socks", i2p::client::I2P_TUNNELS_SECTION_TYPE_SOCKS);
- tunnelTypeComboBox->addItem("Websocks", i2p::client::I2P_TUNNELS_SECTION_TYPE_WEBSOCKS);
- tunnelTypeComboBox->addItem("HTTP Proxy", i2p::client::I2P_TUNNELS_SECTION_TYPE_HTTPPROXY);
- tunnelTypeComboBox->addItem("UDP Client", i2p::client::I2P_TUNNELS_SECTION_TYPE_UDPCLIENT);
-
- int h=(7+4)*60;
- gridLayoutWidget_2->setGeometry(QRect(0, 0, 561, h));
- clientTunnelNameGroupBox->setGeometry(QRect(0, 0, 561, h));
-
- {
- const QString& type = tunnelConfig->getType();
- int index=0;
- if(type==i2p::client::I2P_TUNNELS_SECTION_TYPE_CLIENT)tunnelTypeComboBox->setCurrentIndex(index);
- ++index;
- if(type==i2p::client::I2P_TUNNELS_SECTION_TYPE_SOCKS)tunnelTypeComboBox->setCurrentIndex(index);
- ++index;
- if(type==i2p::client::I2P_TUNNELS_SECTION_TYPE_WEBSOCKS)tunnelTypeComboBox->setCurrentIndex(index);
- ++index;
- if(type==i2p::client::I2P_TUNNELS_SECTION_TYPE_HTTPPROXY)tunnelTypeComboBox->setCurrentIndex(index);
- ++index;
- if(type==i2p::client::I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)tunnelTypeComboBox->setCurrentIndex(index);
- ++index;
- }
-
- setupTunnelPane(tunnelConfig,
- clientTunnelNameGroupBox,
- gridLayoutWidget_2, tunnelTypeComboBox,
- tunnelsFormGridLayoutWidget, tunnelsRow, height, h);
- //this->tunnelGroupBox->setGeometry(QRect(0, tunnelsFormGridLayoutWidget->height()+10, 561, (7+5)*40+10));
-
- /*
- std::string destination;
- */
-
- //host
- ui.horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.destinationLabel = new QLabel(gridLayoutWidget_2);
- destinationLabel->setObjectName(QStringLiteral("destinationLabel"));
- horizontalLayout_2->addWidget(destinationLabel);
- ui.destinationLineEdit = new QLineEdit(gridLayoutWidget_2);
- destinationLineEdit->setObjectName(QStringLiteral("destinationLineEdit"));
- destinationLineEdit->setText(tunnelConfig->getdest().c_str());
- QObject::connect(destinationLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(destinationLineEdit);
- ui.destinationHorizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(destinationHorizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
-
- /*
- * int port;
- */
- int gridIndex = 2;
- {
- int port = tunnelConfig->getport();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.portLabel = new QLabel(gridLayoutWidget_2);
- portLabel->setObjectName(QStringLiteral("portLabel"));
- horizontalLayout_2->addWidget(portLabel);
- ui.portLineEdit = new QLineEdit(gridLayoutWidget_2);
- portLineEdit->setObjectName(QStringLiteral("portLineEdit"));
- portLineEdit->setText(QString::number(port));
- portLineEdit->setMaximumWidth(80);
- QObject::connect(portLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(portLineEdit);
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
- /*
- * std::string keys;
-*/
- {
- std::string keys = tunnelConfig->getkeys();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.keysLabel = new QLabel(gridLayoutWidget_2);
- keysLabel->setObjectName(QStringLiteral("keysLabel"));
- horizontalLayout_2->addWidget(keysLabel);
- ui.keysLineEdit = new QLineEdit(gridLayoutWidget_2);
- keysLineEdit->setObjectName(QStringLiteral("keysLineEdit"));
- keysLineEdit->setText(keys.c_str());
- QObject::connect(keysLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(keysLineEdit);
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
- /*
- * std::string address;
- */
- {
- std::string address = tunnelConfig->getaddress();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.addressLabel = new QLabel(gridLayoutWidget_2);
- addressLabel->setObjectName(QStringLiteral("addressLabel"));
- horizontalLayout_2->addWidget(addressLabel);
- ui.addressLineEdit = new QLineEdit(gridLayoutWidget_2);
- addressLineEdit->setObjectName(QStringLiteral("addressLineEdit"));
- addressLineEdit->setText(address.c_str());
- QObject::connect(addressLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(addressLineEdit);
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
-
- /*
- int destinationPort;
- i2p::data::SigningKeyType sigType;
-*/
- {
- int destinationPort = tunnelConfig->getdestinationPort();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.destinationPortLabel = new QLabel(gridLayoutWidget_2);
- destinationPortLabel->setObjectName(QStringLiteral("destinationPortLabel"));
- horizontalLayout_2->addWidget(destinationPortLabel);
- ui.destinationPortLineEdit = new QLineEdit(gridLayoutWidget_2);
- destinationPortLineEdit->setObjectName(QStringLiteral("destinationPortLineEdit"));
- destinationPortLineEdit->setText(QString::number(destinationPort));
- destinationPortLineEdit->setMaximumWidth(80);
- QObject::connect(destinationPortLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(destinationPortLineEdit);
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
- {
- int cryptoType = tunnelConfig->getcryptoType();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- ui.cryptoTypeLabel = new QLabel(gridLayoutWidget_2);
- cryptoTypeLabel->setObjectName(QStringLiteral("cryptoTypeLabel"));
- horizontalLayout_2->addWidget(cryptoTypeLabel);
- ui.cryptoTypeLineEdit = new QLineEdit(gridLayoutWidget_2);
- cryptoTypeLineEdit->setObjectName(QStringLiteral("cryptoTypeLineEdit"));
- cryptoTypeLineEdit->setText(QString::number(cryptoType));
- cryptoTypeLineEdit->setMaximumWidth(80);
- QObject::connect(cryptoTypeLineEdit, SIGNAL(textChanged(const QString &)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(cryptoTypeLineEdit);
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
- {
- i2p::data::SigningKeyType sigType = tunnelConfig->getsigType();
- QHBoxLayout *horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
- ui.sigTypeLabel = new QLabel(gridLayoutWidget_2);
- sigTypeLabel->setObjectName(QStringLiteral("sigTypeLabel"));
- horizontalLayout_2->addWidget(sigTypeLabel);
- ui.sigTypeComboBox = SignatureTypeComboBoxFactory::createSignatureTypeComboBox(gridLayoutWidget_2, sigType);
- sigTypeComboBox->setObjectName(QStringLiteral("sigTypeComboBox"));
- QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)),
- this, SLOT(updated()));
- horizontalLayout_2->addWidget(sigTypeComboBox);
- QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2);
- horizontalLayout_2->addWidget(lockButton2);
- widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2));
- QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
- horizontalLayout_2->addItem(horizontalSpacer);
- tunnelGridLayout->addLayout(horizontalLayout_2);
- }
- {
- I2CPParameters& i2cpParameters = tunnelConfig->getI2cpParameters();
- appendControlsForI2CPParameters(i2cpParameters, gridIndex);
- }
-
- retranslateClientTunnelForm(ui);
-
- tunnelGridLayout->invalidate();
-
- return h;
-}
-
-ServerTunnelPane* ClientTunnelPane::asServerTunnelPane(){return nullptr;}
-ClientTunnelPane* ClientTunnelPane::asClientTunnelPane(){return this;}
diff --git a/qt/i2pd_qt/ClientTunnelPane.h b/qt/i2pd_qt/ClientTunnelPane.h
deleted file mode 100644
index f6bf4376..00000000
--- a/qt/i2pd_qt/ClientTunnelPane.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef CLIENTTUNNELPANE_H
-#define CLIENTTUNNELPANE_H
-
-#include "QGridLayout"
-#include "QVBoxLayout"
-
-#include "TunnelPane.h"
-
-class ClientTunnelConfig;
-
-class ServerTunnelPane;
-class TunnelPane;
-
-class ClientTunnelPane : public TunnelPane {
- Q_OBJECT
-public:
- ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow);
- virtual ~ClientTunnelPane(){}
- virtual ServerTunnelPane* asServerTunnelPane();
- virtual ClientTunnelPane* asClientTunnelPane();
- int appendClientTunnelForm(ClientTunnelConfig* tunnelConfig, QWidget *tunnelsFormGridLayoutWidget,
- int tunnelsRow, int height);
- void deleteClientTunnelForm();
-private:
- QGroupBox *clientTunnelNameGroupBox;
-
- //tunnel
- QWidget *gridLayoutWidget_2;
-
- //destination
- QHBoxLayout *horizontalLayout_2;
- QLabel *destinationLabel;
- QLineEdit *destinationLineEdit;
- QSpacerItem *destinationHorizontalSpacer;
-
- //port
- QLabel * portLabel;
- QLineEdit * portLineEdit;
-
- //keys
- QLabel * keysLabel;
- QLineEdit * keysLineEdit;
-
- //address
- QLabel * addressLabel;
- QLineEdit * addressLineEdit;
-
- //destinationPort
- QLabel * destinationPortLabel;
- QLineEdit * destinationPortLineEdit;
-
- //sigType
- QLabel * sigTypeLabel;
- QComboBox * sigTypeComboBox;
-
- //cryptoType
- QLabel * cryptoTypeLabel;
- QLineEdit * cryptoTypeLineEdit;
-
-protected slots:
- virtual void setGroupBoxTitle(const QString & title);
-
-private:
- void retranslateClientTunnelForm(ClientTunnelPane& /*ui*/) {
- typeLabel->setText(QApplication::translate("cltTunForm", "Client tunnel type:", 0));
- destinationLabel->setText(QApplication::translate("cltTunForm", "Destination:", 0));
- portLabel->setText(QApplication::translate("cltTunForm", "Port:", 0));
- cryptoTypeLabel->setText(QApplication::translate("cltTunForm", "Crypto type:", 0));
- keysLabel->setText(QApplication::translate("cltTunForm", "Keys:", 0));
- destinationPortLabel->setText(QApplication::translate("cltTunForm", "Destination port:", 0));
- addressLabel->setText(QApplication::translate("cltTunForm", "Address:", 0));
- sigTypeLabel->setText(QApplication::translate("cltTunForm", "Signature type:", 0));
- }
-protected:
- virtual bool applyDataFromUIToTunnelConfig() {
- QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
- bool ok=TunnelPane::applyDataFromUIToTunnelConfig();
- if(!ok)return false;
- ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig();
- assert(ctc!=nullptr);
-
- if(!isValidSingleLine(destinationLineEdit))return false;
- if(!isValidSingleLine(portLineEdit))return false;
- if(!isValidSingleLine(cryptoTypeLineEdit))return false;
- if(!isValidSingleLine(keysLineEdit))return false;
- if(!isValidSingleLine(addressLineEdit))return false;
- if(!isValidSingleLine(destinationPortLineEdit))return false;
-
- //destination
- ctc->setdest(destinationLineEdit->text().toStdString());
-
- auto portStr=portLineEdit->text();
- int portInt=portStr.toInt(&ok);
-
- if(!ok){
- highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit);
- return false;
- }
- ctc->setport(portInt);
-
- auto cryptoTypeStr=cryptoTypeLineEdit->text();
- int cryptoTypeInt=cryptoTypeStr.toInt(&ok);
- if(!ok){
- highlightWrongInput(QApplication::tr("Bad crypto type, must be int.")+" "+cannotSaveSettings,cryptoTypeLineEdit);
- return false;
- }
- ctc->setcryptoType(cryptoTypeInt);
-
- ctc->setkeys(keysLineEdit->text().toStdString());
-
- ctc->setaddress(addressLineEdit->text().toStdString());
-
- auto dportStr=destinationPortLineEdit->text();
- int dportInt=dportStr.toInt(&ok);
- if(!ok){
- highlightWrongInput(QApplication::tr("Bad destinationPort, must be int.")+" "+cannotSaveSettings,destinationPortLineEdit);
- return false;
- }
- ctc->setdestinationPort(dportInt);
-
- ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox));
- return true;
- }
-};
-
-#endif // CLIENTTUNNELPANE_H
diff --git a/qt/i2pd_qt/DaemonQT.cpp b/qt/i2pd_qt/DaemonQT.cpp
deleted file mode 100644
index 1e45c583..00000000
--- a/qt/i2pd_qt/DaemonQT.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-#include
-
-#include "DaemonQT.h"
-#include "Daemon.h"
-#include "mainwindow.h"
-
-#include "Log.h"
-
-#include
-#include
-#include
-#include
-
-//#define DEBUG_WITH_DEFAULT_LOGGING (1)
-
-namespace i2p
-{
-namespace qt
-{
- Worker::Worker (DaemonQTImpl& daemon):
- m_Daemon (daemon)
- {
- }
-
- void Worker::startDaemon()
- {
- qDebug("Performing daemon start...");
- //try{
- m_Daemon.start();
- qDebug("Daemon started.");
- emit resultReady(false, "");
- /*}catch(std::exception ex){
- emit resultReady(true, ex.what());
- }catch(...){
- emit resultReady(true, QObject::tr("Error: unknown exception"));
- }*/
- }
- void Worker::restartDaemon()
- {
- qDebug("Performing daemon restart...");
- //try{
- m_Daemon.restart();
- qDebug("Daemon restarted.");
- emit resultReady(false, "");
- /*}catch(std::exception ex){
- emit resultReady(true, ex.what());
- }catch(...){
- emit resultReady(true, QObject::tr("Error: unknown exception"));
- }*/
- }
- void Worker::stopDaemon() {
- qDebug("Performing daemon stop...");
- //try{
- m_Daemon.stop();
- qDebug("Daemon stopped.");
- emit resultReady(false, "");
- /*}catch(std::exception ex){
- emit resultReady(true, ex.what());
- }catch(...){
- emit resultReady(true, QObject::tr("Error: unknown exception"));
- }*/
- }
-
- Controller::Controller(DaemonQTImpl& daemon):
- m_Daemon (daemon)
- {
- Worker *worker = new Worker (m_Daemon);
- worker->moveToThread(&workerThread);
- connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
- connect(this, &Controller::startDaemon, worker, &Worker::startDaemon);
- connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon);
- connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon);
- connect(worker, &Worker::resultReady, this, &Controller::handleResults);
- workerThread.start();
- }
- Controller::~Controller()
- {
- qDebug("Closing and waiting for daemon worker thread...");
- workerThread.quit();
- workerThread.wait();
- qDebug("Waiting for daemon worker thread finished.");
- if(m_Daemon.isRunning())
- {
- qDebug("Stopping the daemon...");
- m_Daemon.stop();
- qDebug("Stopped the daemon.");
- }
- }
-
- DaemonQTImpl::DaemonQTImpl ():
- mutex(nullptr), m_IsRunning(nullptr), m_RunningChangedCallback(nullptr)
- {
- }
-
- DaemonQTImpl::~DaemonQTImpl ()
- {
- delete mutex;
- }
-
- bool DaemonQTImpl::init(int argc, char* argv[], std::shared_ptr logstream)
- {
- mutex=new QMutex(QMutex::Recursive);
- setRunningCallback(0);
- m_IsRunning=false;
- return Daemon.init(argc,argv,logstream);
- }
-
- void DaemonQTImpl::start()
- {
- QMutexLocker locker(mutex);
- setRunning(true);
- Daemon.start();
- }
-
- void DaemonQTImpl::stop()
- {
- QMutexLocker locker(mutex);
- Daemon.stop();
- setRunning(false);
- }
-
- void DaemonQTImpl::restart()
- {
- QMutexLocker locker(mutex);
- stop();
- start();
- }
-
- void DaemonQTImpl::setRunningCallback(runningChangedCallback cb)
- {
- m_RunningChangedCallback = cb;
- }
-
- bool DaemonQTImpl::isRunning()
- {
- return m_IsRunning;
- }
-
- void DaemonQTImpl::setRunning(bool newValue)
- {
- bool oldValue = m_IsRunning;
- if(oldValue!=newValue)
- {
- m_IsRunning = newValue;
- if(m_RunningChangedCallback)
- m_RunningChangedCallback();
- }
- }
-
- int RunQT (int argc, char* argv[])
- {
- QApplication app(argc, argv);
- int result;
-
- {
- std::shared_ptr logstreamptr=
-#ifdef DEBUG_WITH_DEFAULT_LOGGING
- nullptr
-#else
- std::make_shared()
-#endif
- ;
- //TODO move daemon init deinit to a bg thread
- DaemonQTImpl daemon;
- if(logstreamptr) (*logstreamptr) << "Initialising the daemon..." << std::endl;
- bool daemonInitSuccess = daemon.init(argc, argv, logstreamptr);
- if(!daemonInitSuccess)
- {
- QMessageBox::critical(0, "Error", "Daemon init failed");
- return 1;
- }
- LogPrint(eLogDebug, "Initialised, creating the main window...");
- MainWindow w(logstreamptr);
- LogPrint(eLogDebug, "Before main window.show()...");
- w.show ();
-
- {
- i2p::qt::Controller daemonQtController(daemon);
- w.setI2PController(&daemonQtController);
- LogPrint(eLogDebug, "Starting the daemon...");
- emit daemonQtController.startDaemon();
- //daemon.start ();
- LogPrint(eLogDebug, "Starting GUI event loop...");
- result = app.exec();
- //daemon.stop ();
- }
- }
-
- //QMessageBox::information(&w, "Debug", "demon stopped");
- LogPrint(eLogDebug, "Exiting the application");
- return result;
- }
-}
-}
-
diff --git a/qt/i2pd_qt/DaemonQT.h b/qt/i2pd_qt/DaemonQT.h
deleted file mode 100644
index aa329f56..00000000
--- a/qt/i2pd_qt/DaemonQT.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef DAEMONQT_H
-#define DAEMONQT_H
-
-#include
-#include
-#include
-#include
-#include
-
-namespace i2p
-{
-namespace qt
-{
- class DaemonQTImpl
- {
- public:
-
- DaemonQTImpl ();
- ~DaemonQTImpl ();
-
- typedef void (*runningChangedCallback)();
-
- /**
- * @brief init
- * @param argc
- * @param argv
- * @return success
- */
- bool init(int argc, char* argv[], std::shared_ptr logstream);
- void start();
- void stop();
- void restart();
- void setRunningCallback(runningChangedCallback cb);
- bool isRunning();
- private:
- void setRunning(bool running);
- void showError(std::string errorMsg);
- private:
- QMutex* mutex;
- bool m_IsRunning;
- runningChangedCallback m_RunningChangedCallback;
- };
-
- class Worker : public QObject
- {
- Q_OBJECT
- public:
-
- Worker (DaemonQTImpl& daemon);
-
- private:
-
- DaemonQTImpl& m_Daemon;
-
- public slots:
- void startDaemon();
- void restartDaemon();
- void stopDaemon();
-
- signals:
- void resultReady(bool failed, QString failureMessage);
- };
-
- class Controller : public QObject
- {
- Q_OBJECT
- QThread workerThread;
- public:
- Controller(DaemonQTImpl& daemon);
- ~Controller();
- private:
- DaemonQTImpl& m_Daemon;
-
- public slots:
- void handleResults(bool failed, QString failureMessage){
- if(failed){
- QMessageBox::critical(0, QObject::tr("Error"), failureMessage);
- }
- }
- signals:
- void startDaemon();
- void stopDaemon();
- void restartDaemon();
- };
-}
-}
-
-#endif // DAEMONQT_H
diff --git a/qt/i2pd_qt/DelayedSaveManager.cpp b/qt/i2pd_qt/DelayedSaveManager.cpp
deleted file mode 100644
index 8e17d111..00000000
--- a/qt/i2pd_qt/DelayedSaveManager.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "DelayedSaveManager.h"
-
-DelayedSaveManager::DelayedSaveManager(){}
diff --git a/qt/i2pd_qt/DelayedSaveManager.h b/qt/i2pd_qt/DelayedSaveManager.h
deleted file mode 100644
index 23821439..00000000
--- a/qt/i2pd_qt/DelayedSaveManager.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef DELAYEDSAVEMANAGER_H
-#define DELAYEDSAVEMANAGER_H
-
-#include "Saver.h"
-#include "I2pdQtTypes.h"
-
-class DelayedSaveManager
-{
-public:
- DelayedSaveManager();
-
- virtual void setSaver(Saver* saver)=0;
-
- typedef unsigned int DATA_SERIAL_TYPE;
-
- virtual void delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus)=0;
-
- //returns false iff save failed
- virtual bool appExiting()=0;
-
- virtual FocusEnum getFocusOn()=0;
- virtual std::string& getTunnelNameToFocus()=0;
- virtual QWidget* getWidgetToFocus()=0;
-};
-
-#endif // DELAYEDSAVEMANAGER_H
diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp
deleted file mode 100644
index bad6fdb5..00000000
--- a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-#include "DelayedSaveManagerImpl.h"
-
-#include
-
-DelayedSaveManagerImpl::DelayedSaveManagerImpl() :
- widgetToFocus(nullptr),
- saver(nullptr),
- lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL),
- lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP),
- exiting(false),
- thread(new DelayedSaveThread(this))
-{
-}
-
-void DelayedSaveManagerImpl::setSaver(Saver* saver) {
- this->saver = saver;
-}
-
-void DelayedSaveManagerImpl::start() {
- thread->start();
-}
-
-bool DelayedSaveManagerImpl::isSaverValid() {
- return saver != nullptr;
-}
-
-void DelayedSaveManagerImpl::delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus) {
- if(lastDataSerialSeen==dataSerial)return;
- this->reloadAfterSave = reloadAfterSave;
- this->focusOn = focusOn;
- this->tunnelNameToFocus = tunnelNameToFocus;
- this->widgetToFocus = widgetToFocus;
- lastDataSerialSeen=dataSerial;
- assert(isSaverValid());
- TIMESTAMP_TYPE now = getTime();
- TIMESTAMP_TYPE wakeTime = lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS;
- if(now < wakeTime) {
- //defer save until lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS
- thread->deferSaveUntil(wakeTime);
- return;
- }
- lastSaveStartedTimestamp = now;
- thread->startSavingNow();
-}
-
-bool DelayedSaveManagerImpl::appExiting() {
- exiting=true;
- thread->wakeThreadAndJoinThread();
- assert(isSaverValid());
- saver->save(false, FocusEnum::noFocus);
- return true;
-}
-
-DelayedSaveThread::DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl_):
- delayedSaveManagerImpl(delayedSaveManagerImpl_),
- mutex(new QMutex()),
- waitCondition(new QWaitCondition()),
- saveNow(false),
- defer(false)
-{
- mutex->lock();
-}
-
-DelayedSaveThread::~DelayedSaveThread(){
- mutex->unlock();
- delete mutex;
- delete waitCondition;
-}
-
-void DelayedSaveThread::run() {
- forever {
- if(delayedSaveManagerImpl->isExiting())return;
- waitCondition->wait(mutex, WAIT_TIME_MILLIS);
- if(delayedSaveManagerImpl->isExiting())return;
- Saver* saver = delayedSaveManagerImpl->getSaver();
- assert(saver!=nullptr);
- if(saveNow) {
- saveNow = false;
- const FocusEnum focusOn = delayedSaveManagerImpl->getFocusOn();
- const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
- QWidget* widgetToFocus = delayedSaveManagerImpl->getWidgetToFocus();
- saver->save(delayedSaveManagerImpl->isReloadAfterSave(), focusOn, tunnelNameToFocus, widgetToFocus);
- continue;
- }
- if(defer) {
- defer=false;
-#define max(a,b) (((a)>(b))?(a):(b))
- forever {
- TIMESTAMP_TYPE now = DelayedSaveManagerImpl::getTime();
- TIMESTAMP_TYPE millisToWait = max(wakeTime-now, 0);
- if(millisToWait>0) {
- waitCondition->wait(mutex, millisToWait);
- if(delayedSaveManagerImpl->isExiting())return;
- continue;
- }
- const FocusEnum focusOn = delayedSaveManagerImpl->getFocusOn();
- const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
- QWidget* widgetToFocus = delayedSaveManagerImpl->getWidgetToFocus();
- saver->save(delayedSaveManagerImpl->isReloadAfterSave(), focusOn, tunnelNameToFocus, widgetToFocus);
- break; //break inner loop
- }
- }
- }
-}
-
-void DelayedSaveThread::wakeThreadAndJoinThread() {
- waitCondition->wakeAll();
- quit();
- wait();//join //"similar to the POSIX pthread_join()"
-}
-
-DelayedSaveManagerImpl::TIMESTAMP_TYPE DelayedSaveManagerImpl::getTime() {
- return QDateTime::currentMSecsSinceEpoch();
-}
-
-void DelayedSaveThread::deferSaveUntil(TIMESTAMP_TYPE wakeTime_) {
- wakeTime = wakeTime_;
- defer = true;
- waitCondition->wakeAll();
-}
-
-void DelayedSaveThread::startSavingNow() {
- //mutex->lock();
- saveNow=true;
- waitCondition->wakeAll();
- //mutex->unlock();
-}
-
-DelayedSaveManagerImpl::~DelayedSaveManagerImpl() {
- thread->wakeThreadAndJoinThread();
- delete thread;
-}
-
-bool DelayedSaveManagerImpl::isExiting() {
- return exiting;
-}
-Saver* DelayedSaveManagerImpl::getSaver() {
- return saver;
-}
-
diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.h b/qt/i2pd_qt/DelayedSaveManagerImpl.h
deleted file mode 100644
index c9a77c31..00000000
--- a/qt/i2pd_qt/DelayedSaveManagerImpl.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef DELAYEDSAVEMANAGERIMPL_H
-#define DELAYEDSAVEMANAGERIMPL_H
-
-#include
-#include
-#include
-#include
-#include
-
-#include "I2pdQtTypes.h"
-#include "DelayedSaveManager.h"
-#include "Saver.h"
-
-class DelayedSaveManagerImpl;
-class Saver;
-
-class DelayedSaveThread : public QThread {
- Q_OBJECT
-
-public:
- static constexpr unsigned long WAIT_TIME_MILLIS = 1000L;
-
- typedef qint64 TIMESTAMP_TYPE;
- static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=0;
-
- DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl);
- virtual ~DelayedSaveThread();
-
- void run() override;
-
- void deferSaveUntil(TIMESTAMP_TYPE wakeTime);
- void startSavingNow();
-
- void wakeThreadAndJoinThread();
-
-private:
- DelayedSaveManagerImpl* delayedSaveManagerImpl;
- QMutex* mutex;
- QWaitCondition* waitCondition;
- volatile bool saveNow;
- volatile bool defer;
- volatile TIMESTAMP_TYPE wakeTime;
-};
-
-class DelayedSaveManagerImpl : public DelayedSaveManager {
- FocusEnum focusOn;
- std::string tunnelNameToFocus;
- QWidget* widgetToFocus;
- bool reloadAfterSave;
-public:
- DelayedSaveManagerImpl();
- virtual ~DelayedSaveManagerImpl();
- virtual void setSaver(Saver* saver);
- virtual void start();
- virtual void delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus);
- virtual bool appExiting();
-
- typedef DelayedSaveThread::TIMESTAMP_TYPE TIMESTAMP_TYPE;
-
- static constexpr DATA_SERIAL_TYPE INITIAL_DATA_SERIAL=0;
- bool isExiting();
- Saver* getSaver();
- static TIMESTAMP_TYPE getTime();
-
- bool isReloadAfterSave() { return reloadAfterSave; }
- FocusEnum getFocusOn() { return focusOn; }
- std::string& getTunnelNameToFocus() { return tunnelNameToFocus; }
- QWidget* getWidgetToFocus() { return widgetToFocus; }
-
-private:
- Saver* saver;
- bool isSaverValid();
-
- DATA_SERIAL_TYPE lastDataSerialSeen;
-
- static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=DelayedSaveThread::A_VERY_OBSOLETE_TIMESTAMP;
- TIMESTAMP_TYPE lastSaveStartedTimestamp;
-
- bool exiting;
- DelayedSaveThread* thread;
- void wakeThreadAndJoinThread();
-};
-
-#endif // DELAYEDSAVEMANAGERIMPL_H
diff --git a/qt/i2pd_qt/I2pdQtTypes.h b/qt/i2pd_qt/I2pdQtTypes.h
deleted file mode 100644
index c7b1917a..00000000
--- a/qt/i2pd_qt/I2pdQtTypes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef I2PDQTTYPES_H
-#define I2PDQTTYPES_H
-
-enum WrongInputPageEnum { generalSettingsPage, tunnelsSettingsPage };
-enum FocusEnum { noFocus, focusOnTunnelName, focusOnWidget };
-
-#endif // I2PDQTTYPES_H
diff --git a/qt/i2pd_qt/I2pdQtUtil.cpp b/qt/i2pd_qt/I2pdQtUtil.cpp
deleted file mode 100644
index 35a7adff..00000000
--- a/qt/i2pd_qt/I2pdQtUtil.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "I2pdQtUtil.h"
-
-bool isValidSingleLine(QLineEdit* widget, WrongInputPageEnum inputPage, MainWindow* mainWindow) {
- bool correct = !widget->text().contains(QRegularExpression("[\r\n]"), nullptr);
- if(!correct) {
- mainWindow->highlightWrongInput(
- QApplication::tr("Single line input expected, but it's multiline"),
- inputPage,
- widget);
- }
- return correct;
-}
diff --git a/qt/i2pd_qt/I2pdQtUtil.h b/qt/i2pd_qt/I2pdQtUtil.h
deleted file mode 100644
index 90c3e521..00000000
--- a/qt/i2pd_qt/I2pdQtUtil.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef I2pdQtUtil_H
-#define I2pdQtUtil_H
-
-class QLineEdit;
-#include "mainwindow.h"
-
-bool isValidSingleLine(QLineEdit* widget, WrongInputPageEnum inputPage, MainWindow* mainWindow);
-
-#endif // I2pdQtUtil_H
diff --git a/qt/i2pd_qt/MainWindowItems.cpp b/qt/i2pd_qt/MainWindowItems.cpp
deleted file mode 100644
index c1e1ab0a..00000000
--- a/qt/i2pd_qt/MainWindowItems.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "MainWindowItems.h"
-
diff --git a/qt/i2pd_qt/MainWindowItems.h b/qt/i2pd_qt/MainWindowItems.h
deleted file mode 100644
index a4be5fe0..00000000
--- a/qt/i2pd_qt/MainWindowItems.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef MAINWINDOWITEMS_H
-#define MAINWINDOWITEMS_H
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "mainwindow.h"
-
-class MainWindow;
-
-#endif // MAINWINDOWITEMS_H
diff --git a/qt/i2pd_qt/README.md b/qt/i2pd_qt/README.md
deleted file mode 100644
index 94186ecf..00000000
--- a/qt/i2pd_qt/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Build Requirements
-
- * Qt 5 is necessary (because Qt4 lacks QtWidgets/ folder)
diff --git a/qt/i2pd_qt/Saver.cpp b/qt/i2pd_qt/Saver.cpp
deleted file mode 100644
index 4841acb0..00000000
--- a/qt/i2pd_qt/Saver.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "Saver.h"
-
-Saver::Saver()
-{
-
-}
diff --git a/qt/i2pd_qt/Saver.h b/qt/i2pd_qt/Saver.h
deleted file mode 100644
index bf971fb6..00000000
--- a/qt/i2pd_qt/Saver.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef SAVER_H
-#define SAVER_H
-
-#include
-#include
-#include
-class QWidget;
-
-#include "I2pdQtTypes.h"
-
-class Saver : public QObject
-{
- Q_OBJECT
-
-public:
- Saver();
- //FocusEnum::focusNone iff failures //??? wtf
- virtual bool save(bool reloadAfterSave, const FocusEnum focusOn, const std::string& tunnelNameToFocus="", QWidget* widgetToFocus=nullptr)=0;
-
-signals:
- void reloadTunnelsConfigAndUISignal(const QString);
-
-};
-
-#endif // SAVER_H
diff --git a/qt/i2pd_qt/SaverImpl.cpp b/qt/i2pd_qt/SaverImpl.cpp
deleted file mode 100644
index fee2526b..00000000
--- a/qt/i2pd_qt/SaverImpl.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-#include "SaverImpl.h"
-
-#include
-#include
-#include
-
-#include "QList"
-#include "QString"
-
-#include "mainwindow.h"
-
-SaverImpl::SaverImpl(MainWindow *mainWindowPtr_, QList * configItems_, std::map* tunnelConfigs_) :
- configItems(configItems_), tunnelConfigs(tunnelConfigs_), confpath(), tunconfpath(), mainWindowPtr(mainWindowPtr_)
-{}
-
-SaverImpl::~SaverImpl() {}
-
-bool SaverImpl::save(bool reloadAfterSave, const FocusEnum focusOn, const std::string& tunnelNameToFocus, QWidget* widgetToFocus) {
- //save main config
- {
- std::stringstream out;
- for(QList::iterator it = configItems->begin(); it!= configItems->end(); ++it) {
- MainWindowItem* item = *it;
- item->saveToStringStream(out);
- }
-
- using namespace std;
-
-
- QString backup=confpath+"~";
- if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
- if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors
- ofstream outfile;
- outfile.open(confpath.toStdString());//TODO handle errors
- outfile << out.str().c_str();
- outfile.close();
- }
-
- //save tunnels config
- {
- std::stringstream out;
-
- for (std::map::iterator it=tunnelConfigs->begin(); it!=tunnelConfigs->end(); ++it) {
- //const std::string& name = it->first;
- TunnelConfig* tunconf = it->second;
- tunconf->saveHeaderToStringStream(out);
- tunconf->saveToStringStream(out);
- tunconf->saveI2CPParametersToStringStream(out);
- }
-
- using namespace std;
-
- QString backup=tunconfpath+"~";
- if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
- if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors
- ofstream outfile;
- outfile.open(tunconfpath.toStdString());//TODO handle errors
- outfile << out.str().c_str();
- outfile.close();
- }
-
- if(reloadAfterSave) {
- //reload saved configs
-#if 0
- i2p::client::context.ReloadConfig();
-#endif
-
- if(reloadAfterSave) emit reloadTunnelsConfigAndUISignal(focusOn==FocusEnum::focusOnTunnelName?QString::fromStdString(tunnelNameToFocus):"");
- }
-
- return true;
-}
-
-void SaverImpl::setConfPath(QString& confpath_) { confpath = confpath_; }
-
-void SaverImpl::setTunnelsConfPath(QString& tunconfpath_) { tunconfpath = tunconfpath_; }
-
-/*void SaverImpl::setTunnelFocus(bool focusOnTunnel, std::string tunnelNameToFocus) {
- this->focusOnTunnel=focusOnTunnel;
- this->tunnelNameToFocus=tunnelNameToFocus;
-}*/
diff --git a/qt/i2pd_qt/SaverImpl.h b/qt/i2pd_qt/SaverImpl.h
deleted file mode 100644
index d20f1bbf..00000000
--- a/qt/i2pd_qt/SaverImpl.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef SAVERIMPL_H
-#define SAVERIMPL_H
-
-#include