mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-05 04:23:48 +01:00
commit
b992fbab52
186 changed files with 6237 additions and 4312 deletions
50
ChangeLog
50
ChangeLog
|
@ -1,6 +1,56 @@
|
||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [2.32.0] - 2020-05-25
|
||||||
|
### Added
|
||||||
|
- Multiple encryption types for local destinations
|
||||||
|
- Next key and tagset for ECIES-X25519-AEAD-Ratchet
|
||||||
|
- NTCP2 through SOCKS proxy
|
||||||
|
- Throw error message if any port to bind is occupied
|
||||||
|
- gzip parameter for UDP tunnels
|
||||||
|
- Show ECIES-X25519-AEAD-Ratchet sessions and tags on the web console
|
||||||
|
- Simplified implementation of gzip for no compression mode
|
||||||
|
- Allow ECIES-X25519-AEAD-Ratchet session restart after 2 minutes
|
||||||
|
- Added logrotate config for rpm package
|
||||||
|
### Changed
|
||||||
|
- Select peers for client tunnels among routers >= 0.9.36
|
||||||
|
- Check ECIES flag for encrypted lookup reply
|
||||||
|
- Streaming MTU size 1812 for ECIES-X25519-AEAD-Ratchet
|
||||||
|
- Don't calculate checksum for Data message send through ECIES-X25519-AEAD-Ratchet
|
||||||
|
- Catch network connectivity status for Windows
|
||||||
|
- Stop as soon as no more transit tunnels during graceful shutdown for Android
|
||||||
|
- RouterInfo gzip compression level depends on size
|
||||||
|
- Send response to received datagram from ECIES-X25519-AEAD-Ratchet session
|
||||||
|
- Update webconsole functional
|
||||||
|
- Increased max transit tunnels limit
|
||||||
|
- Reseeds list
|
||||||
|
- Dropped windows support in cmake
|
||||||
|
### Fixed
|
||||||
|
- Correct timestamp check for LeaseSet2
|
||||||
|
- Encrypted leaseset without authentication
|
||||||
|
- Change SOCKS proxy connection response for clients without socks5h support (#1336)
|
||||||
|
|
||||||
|
## [2.31.0] - 2020-04-10
|
||||||
|
### Added
|
||||||
|
- NTCP2 through HTTP proxy
|
||||||
|
- Publish LeaseSet2 for I2CP destinations
|
||||||
|
- Show status page on main activity for android
|
||||||
|
- Handle ECIESFlag in DatabaseLookup at floodfill
|
||||||
|
- C++17 features for eligible compilers
|
||||||
|
### Changed
|
||||||
|
- Droped Websockets and Lua support
|
||||||
|
- Send DeliveryStatusMsg for LeaseSet for ECIES-X25519-AEAD-Ratchet
|
||||||
|
- Keep sending new session reply until established for ECIES-X25519-AEAD-Ratchet
|
||||||
|
- Updated SSU log messages
|
||||||
|
- Reopen SSU socket on exception
|
||||||
|
- Security hardening headers in web console
|
||||||
|
- Various web console changes
|
||||||
|
- Various QT changes
|
||||||
|
### Fixed
|
||||||
|
- NTCP2 socket descriptors leak
|
||||||
|
- Race condition with router's identity in transport sessions
|
||||||
|
- Not terminated streams remain forever
|
||||||
|
|
||||||
## [2.30.0] - 2020-02-25
|
## [2.30.0] - 2020-02-25
|
||||||
### Added
|
### Added
|
||||||
- Single threaded SAM
|
- Single threaded SAM
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -41,7 +41,7 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||||
include Makefile.bsd
|
include Makefile.bsd
|
||||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
|
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
|
||||||
include Makefile.mingw
|
include Makefile.mingw
|
||||||
else # not supported
|
else # not supported
|
||||||
$(error Not supported platform)
|
$(error Not supported platform)
|
||||||
|
|
|
@ -20,7 +20,7 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # gcc 4.7 - 4.9
|
||||||
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
|
||||||
NEEDED_CXXFLAGS += -std=c++11
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
LDLIBS = -latomic
|
LDLIBS = -latomic
|
||||||
else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc >= 7
|
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
|
||||||
NEEDED_CXXFLAGS += -std=c++17
|
NEEDED_CXXFLAGS += -std=c++17
|
||||||
LDLIBS = -latomic
|
LDLIBS = -latomic
|
||||||
else # not supported
|
else # not supported
|
||||||
|
|
|
@ -2,10 +2,19 @@ USE_WIN32_APP=yes
|
||||||
CXX = g++
|
CXX = g++
|
||||||
WINDRES = windres
|
WINDRES = windres
|
||||||
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||||
NEEDED_CXXFLAGS = -std=c++11
|
|
||||||
INCFLAGS = -Idaemon -I.
|
INCFLAGS = -Idaemon -I.
|
||||||
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++
|
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc -static-libstdc++
|
||||||
|
|
||||||
|
# detect proper flag for c++11 support by compilers
|
||||||
|
CXXVER := $(shell $(CXX) -dumpversion)
|
||||||
|
ifeq ($(shell expr match ${CXXVER} "[4]\.[7-9]\|4\.1[0-9]\|[5-6]"),4) # gcc 4.7 - 6
|
||||||
|
NEEDED_CXXFLAGS += -std=c++11
|
||||||
|
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
|
||||||
|
NEEDED_CXXFLAGS += -std=c++17
|
||||||
|
else # not supported
|
||||||
|
$(error Compiler too old)
|
||||||
|
endif
|
||||||
|
|
||||||
# Boost libraries suffix
|
# Boost libraries suffix
|
||||||
BOOST_SUFFIX = -mt
|
BOOST_SUFFIX = -mt
|
||||||
|
|
||||||
|
@ -27,6 +36,8 @@ LDLIBS += \
|
||||||
-lws2_32 \
|
-lws2_32 \
|
||||||
-lgdi32 \
|
-lgdi32 \
|
||||||
-liphlpapi \
|
-liphlpapi \
|
||||||
|
-lole32 \
|
||||||
|
-luuid \
|
||||||
-lstdc++ \
|
-lstdc++ \
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
[![Snapcraft release](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd)
|
[![Snapcraft release](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd)
|
||||||
[![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE)
|
[![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE)
|
||||||
[![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions)
|
[![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)
|
||||||
|
|
||||||
i2pd
|
i2pd
|
||||||
====
|
====
|
||||||
|
@ -68,7 +69,7 @@ Build instructions:
|
||||||
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
|
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
|
||||||
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
* 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)
|
* 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://dockerbuildbadges.quelltext.eu/status.svg?organization=meeh&repository=i2pd)](https://hub.docker.com/r/meeh/i2pd/builds/)
|
* 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 - [![Snap Status](https://build.snapcraft.io/badge/PurpleI2P/i2pd-snap.svg)](https://build.snapcraft.io/user/PurpleI2P/i2pd-snap)
|
||||||
* FreeBSD
|
* FreeBSD
|
||||||
* Android
|
* Android
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <thread>
|
#include <thread>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
@ -8,6 +16,7 @@
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Win32/Win32Service.h"
|
#include "Win32/Win32Service.h"
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
|
#include <windows.h>
|
||||||
#include "Win32/Win32App.h"
|
#include "Win32/Win32App.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -23,6 +32,11 @@ namespace util
|
||||||
setlocale(LC_ALL, "Russian");
|
setlocale(LC_ALL, "Russian");
|
||||||
setlocale(LC_TIME, "C");
|
setlocale(LC_TIME, "C");
|
||||||
|
|
||||||
|
i2p::log::SetThrowFunction ([](const std::string& s)
|
||||||
|
{
|
||||||
|
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
|
||||||
|
});
|
||||||
|
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
@ -11,7 +20,7 @@
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
#include "Win32App.h"
|
#include "Win32App.h"
|
||||||
#include <stdio.h>
|
#include "Win32NetState.h"
|
||||||
|
|
||||||
#define ID_ABOUT 2000
|
#define ID_ABOUT 2000
|
||||||
#define ID_EXIT 2001
|
#define ID_EXIT 2001
|
||||||
|
@ -338,11 +347,6 @@ namespace win32
|
||||||
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
|
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case FRAME_UPDATE_TIMER:
|
|
||||||
{
|
|
||||||
InvalidateRect(hWnd, NULL, TRUE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
|
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
|
||||||
{
|
{
|
||||||
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
|
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
|
||||||
|
@ -351,6 +355,11 @@ namespace win32
|
||||||
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
|
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case FRAME_UPDATE_TIMER:
|
||||||
|
{
|
||||||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -411,6 +420,7 @@ namespace win32
|
||||||
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
|
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
SubscribeToEvents();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +440,7 @@ namespace win32
|
||||||
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
||||||
if (hWnd)
|
if (hWnd)
|
||||||
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
|
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
|
||||||
|
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
|
||||||
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
|
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +459,5 @@ namespace win32
|
||||||
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
|
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
|
||||||
return hWnd;
|
return hWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 WIN32APP_H__
|
#ifndef WIN32APP_H__
|
||||||
#define WIN32APP_H__
|
#define WIN32APP_H__
|
||||||
|
|
||||||
|
|
86
Win32/Win32NetState.cpp
Normal file
86
Win32/Win32NetState.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if WINVER != 0x0501 // supported since Vista
|
||||||
|
#include "Win32NetState.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
IUnknown *pUnknown = nullptr;
|
||||||
|
INetworkListManager *pNetworkListManager = nullptr;
|
||||||
|
IConnectionPointContainer *pCPContainer = nullptr;
|
||||||
|
IConnectionPoint *pConnectPoint = nullptr;
|
||||||
|
DWORD Cookie = 0;
|
||||||
|
|
||||||
|
void SubscribeToEvents()
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "NetState: Trying to subscribe to NetworkListManagerEvents");
|
||||||
|
CoInitialize(NULL);
|
||||||
|
|
||||||
|
HRESULT Result = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void **)&pUnknown);
|
||||||
|
if (SUCCEEDED(Result))
|
||||||
|
{
|
||||||
|
Result = pUnknown->QueryInterface(IID_INetworkListManager, (void **)&pNetworkListManager);
|
||||||
|
if (SUCCEEDED(Result))
|
||||||
|
{
|
||||||
|
VARIANT_BOOL IsConnect = VARIANT_FALSE;
|
||||||
|
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
|
||||||
|
if (SUCCEEDED(Result)) {
|
||||||
|
i2p::transport::transports.SetOnline (true);
|
||||||
|
LogPrint(eLogInfo, "NetState: current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer);
|
||||||
|
if (SUCCEEDED(Result))
|
||||||
|
{
|
||||||
|
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint);
|
||||||
|
if(SUCCEEDED(Result))
|
||||||
|
{
|
||||||
|
CNetworkListManagerEvent *NetEvent = new CNetworkListManagerEvent;
|
||||||
|
Result = pConnectPoint->Advise((IUnknown *)NetEvent, &Cookie);
|
||||||
|
if (SUCCEEDED(Result))
|
||||||
|
LogPrint(eLogInfo, "NetState: Successfully subscribed to NetworkListManagerEvent messages");
|
||||||
|
else
|
||||||
|
LogPrint(eLogError, "NetState: Unable to subscribe to NetworkListManagerEvent messages");
|
||||||
|
} else
|
||||||
|
LogPrint(eLogError, "NetState: Unable to find interface connection point");
|
||||||
|
} else
|
||||||
|
LogPrint(eLogError, "NetState: Unable to query NetworkListManager interface");
|
||||||
|
} else
|
||||||
|
LogPrint(eLogError, "NetState: Unable to query global interface");
|
||||||
|
} else
|
||||||
|
LogPrint(eLogError, "NetState: Unable to create INetworkListManager interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnSubscribeFromEvents()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (pConnectPoint) {
|
||||||
|
pConnectPoint->Unadvise(Cookie);
|
||||||
|
pConnectPoint->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pCPContainer)
|
||||||
|
pCPContainer->Release();
|
||||||
|
|
||||||
|
if (pNetworkListManager)
|
||||||
|
pNetworkListManager->Release();
|
||||||
|
|
||||||
|
if (pUnknown)
|
||||||
|
pUnknown->Release();
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NetState: received exception: ", ex.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WINVER
|
93
Win32/Win32NetState.h
Normal file
93
Win32/Win32NetState.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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 WIN_32_NETSTATE_H__
|
||||||
|
#define WIN_32_NETSTATE_H__
|
||||||
|
|
||||||
|
#if WINVER != 0x0501 // supported since Vista
|
||||||
|
#include <netlistmgr.h>
|
||||||
|
#include <ocidl.h>
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Transports.h"
|
||||||
|
|
||||||
|
class CNetworkListManagerEvent : public INetworkListManagerEvents
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CNetworkListManagerEvent() : m_ref(1) { }
|
||||||
|
~CNetworkListManagerEvent() { }
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
|
||||||
|
{
|
||||||
|
HRESULT Result = S_OK;
|
||||||
|
if (IsEqualIID(riid, IID_IUnknown)) {
|
||||||
|
*ppvObject = (IUnknown *)this;
|
||||||
|
} else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) {
|
||||||
|
*ppvObject = (INetworkListManagerEvents *)this;
|
||||||
|
} else {
|
||||||
|
Result = E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef()
|
||||||
|
{
|
||||||
|
return (ULONG)InterlockedIncrement(&m_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release()
|
||||||
|
{
|
||||||
|
LONG Result = InterlockedDecrement(&m_ref);
|
||||||
|
if (Result == 0)
|
||||||
|
delete this;
|
||||||
|
return (ULONG)Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
|
||||||
|
{
|
||||||
|
if (newConnectivity == NLM_CONNECTIVITY_DISCONNECTED) {
|
||||||
|
i2p::transport::transports.SetOnline (false);
|
||||||
|
LogPrint(eLogInfo, "NetState: disconnected from network");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((int)newConnectivity & (int)NLM_CONNECTIVITY_IPV4_INTERNET) != 0) {
|
||||||
|
i2p::transport::transports.SetOnline (true);
|
||||||
|
LogPrint(eLogInfo, "NetState: connected to internet with IPv4 capability");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((int)newConnectivity & (int)NLM_CONNECTIVITY_IPV6_INTERNET) != 0) {
|
||||||
|
i2p::transport::transports.SetOnline (true);
|
||||||
|
LogPrint(eLogInfo, "NetState: connected to internet with IPv6 capability");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(((int)newConnectivity & (int)NLM_CONNECTIVITY_IPV4_INTERNET) == 0) &&
|
||||||
|
(((int)newConnectivity & (int)NLM_CONNECTIVITY_IPV6_INTERNET) == 0)
|
||||||
|
) {
|
||||||
|
i2p::transport::transports.SetOnline (false);
|
||||||
|
LogPrint(eLogInfo, "NetState: connected without internet access");
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
LONG m_ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
void SubscribeToEvents();
|
||||||
|
void UnSubscribeFromEvents();
|
||||||
|
|
||||||
|
#else // WINVER == 0x0501
|
||||||
|
|
||||||
|
void SubscribeToEvents() { }
|
||||||
|
void UnSubscribeFromEvents() { }
|
||||||
|
|
||||||
|
#endif // WINVER
|
||||||
|
#endif
|
|
@ -1,10 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define _CRT_SECURE_NO_WARNINGS // to use freopen
|
#define _CRT_SECURE_NO_WARNINGS // to use freopen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Win32Service.h"
|
#include "Win32Service.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <strsafe.h>
|
//#include <strsafe.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 WIN_32_SERVICE_H__
|
#ifndef WIN_32_SERVICE_H__
|
||||||
#define WIN_32_SERVICE_H__
|
#define WIN_32_SERVICE_H__
|
||||||
|
|
||||||
|
@ -26,7 +34,7 @@
|
||||||
|
|
||||||
class I2PService
|
class I2PService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PService(PSTR pszServiceName,
|
I2PService(PSTR pszServiceName,
|
||||||
BOOL fCanStop = TRUE,
|
BOOL fCanStop = TRUE,
|
||||||
|
@ -39,7 +47,7 @@ public:
|
||||||
static BOOL Run(I2PService &service);
|
static BOOL Run(I2PService &service);
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
||||||
virtual void OnStop();
|
virtual void OnStop();
|
||||||
|
@ -50,7 +58,7 @@ protected:
|
||||||
DWORD dwWin32ExitCode = NO_ERROR,
|
DWORD dwWin32ExitCode = NO_ERROR,
|
||||||
DWORD dwWaitHint = 0);
|
DWORD dwWaitHint = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
||||||
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
||||||
|
@ -77,7 +85,7 @@ void InstallService(
|
||||||
PCSTR pszDependencies,
|
PCSTR pszDependencies,
|
||||||
PCSTR pszAccount,
|
PCSTR pszAccount,
|
||||||
PCSTR pszPassword
|
PCSTR pszPassword
|
||||||
);
|
);
|
||||||
|
|
||||||
void UninstallService(PCSTR pszServiceName);
|
void UninstallService(PCSTR pszServiceName);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#define I2Pd_AppName "i2pd"
|
#define I2Pd_AppName "i2pd"
|
||||||
#define I2Pd_ver "2.30.0"
|
#define I2Pd_ver "2.32.0"
|
||||||
#define I2Pd_Publisher "PurpleI2P"
|
#define I2Pd_Publisher "PurpleI2P"
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
|
2
android/.gitignore
vendored
2
android/.gitignore
vendored
|
@ -4,6 +4,7 @@ bin
|
||||||
libs
|
libs
|
||||||
log*
|
log*
|
||||||
obj
|
obj
|
||||||
|
.cxx
|
||||||
.gradle
|
.gradle
|
||||||
.idea
|
.idea
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
@ -14,3 +15,4 @@ android.iml
|
||||||
build
|
build
|
||||||
*.iml
|
*.iml
|
||||||
*.local
|
*.local
|
||||||
|
*.jks
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
>
|
>
|
||||||
|
|
||||||
<receiver android:name=".NetworkStateChangeReceiver">
|
<receiver android:name=".NetworkStateChangeReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||||
|
@ -30,10 +31,10 @@
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".I2PDActivity"
|
android:name=".I2PDActivity"
|
||||||
android:label="@string/app_name" />
|
android:label="@string/app_name" />
|
||||||
|
|
|
@ -42,6 +42,8 @@ inbound.quantity = 5
|
||||||
outbound.length = 1
|
outbound.length = 1
|
||||||
outbound.quantity = 5
|
outbound.quantity = 5
|
||||||
signaturetype=7
|
signaturetype=7
|
||||||
|
i2cp.leaseSetType=3
|
||||||
|
i2cp.leaseSetEncType=0,4
|
||||||
keys = proxy-keys.dat
|
keys = proxy-keys.dat
|
||||||
# addresshelper = true
|
# addresshelper = true
|
||||||
# outproxy = http://false.i2p
|
# outproxy = http://false.i2p
|
||||||
|
|
|
@ -30,8 +30,8 @@ android {
|
||||||
applicationId "org.purplei2p.i2pd"
|
applicationId "org.purplei2p.i2pd"
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
versionCode 2300
|
versionCode 2320
|
||||||
versionName "2.30.0"
|
versionName "2.32.0"
|
||||||
setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
|
setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters 'armeabi-v7a'
|
abiFilters 'armeabi-v7a'
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <iostream>
|
#include <iostream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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
|
#ifndef DAEMON_ANDROID_H
|
||||||
#define DAEMON_ANDROID_H
|
#define DAEMON_ANDROID_H
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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 <jni.h>
|
#include <jni.h>
|
||||||
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
#include "org_purplei2p_i2pd_I2PD_JNI.h"
|
||||||
#include "DaemonAndroid.h"
|
#include "DaemonAndroid.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
#include "ClientContext.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
|
#include "Tunnel.h"
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
|
||||||
(JNIEnv *env, jclass clazz) {
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
@ -61,6 +71,11 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
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
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv *env, jclass clazz, jboolean isConnected) {
|
(JNIEnv *env, jclass clazz, jboolean isConnected) {
|
||||||
bool isConnectedBool = (bool) isConnected;
|
bool isConnectedBool = (bool) isConnected;
|
||||||
|
@ -92,3 +107,8 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
|
||||||
// Set DataDir
|
// Set DataDir
|
||||||
i2p::android::SetDataDir(dataDir);
|
i2p::android::SetDataDir(dataDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
|
||||||
|
(JNIEnv *env, jclass clazz) {
|
||||||
|
return i2p::tunnel::tunnels.CountTransitTunnels();
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 */
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
/* Header for class org_purplei2p_i2pd_I2PD_JNI */
|
/* Header for class org_purplei2p_i2pd_I2PD_JNI */
|
||||||
|
@ -27,12 +35,18 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
|
||||||
(JNIEnv *env, jclass clazz, jstring jdataDir);
|
(JNIEnv *env, jclass clazz, jstring jdataDir);
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,13 +15,12 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
||||||
android:visibility="gone"
|
android:visibility="gone" />
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_request_write_ext_storage_perms"
|
android:id="@+id/button_request_write_ext_storage_perms"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Retry requesting the SD card write permissions"
|
android:text="@string/retryPermRequest"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -15,13 +15,11 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
android:layout_marginBottom="@dimen/horizontal_page_margin"
|
||||||
android:text="SD card write access is required to write the keys and other files to the I2PD folder on SD card."
|
android:text="@string/permRequired" />
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_ok"
|
android:id="@+id/button_ok"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="OK"
|
android:text="@string/ok" />
|
||||||
/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -5,9 +5,8 @@
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
tools:context=".I2PDActivity">
|
tools:context=".I2PDActivity">
|
||||||
|
|
||||||
<WebView
|
<WebView
|
||||||
android:id="@+id/webview1"
|
android:id="@+id/webview1"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"/>
|
android:layout_height="fill_parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -3,23 +3,29 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".I2PDActivity">
|
tools:context=".I2PDActivity">
|
||||||
<group android:id="@+id/group_i2pd_control" >
|
|
||||||
|
<group android:id="@+id/group_various">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_stop"
|
android:id="@+id/action_battery_otimizations"
|
||||||
android:orderInCategory="99"
|
android:title="@string/menu_item_battery_optimizations_str" />
|
||||||
android:title="@string/action_stop" />
|
</group>
|
||||||
|
|
||||||
|
<group android:id="@+id/group_i2pd_control">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_start_webview"
|
||||||
|
android:orderInCategory="96"
|
||||||
|
android:title="@string/action_start_webview" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_reload_tunnels_config"
|
||||||
|
android:orderInCategory="97"
|
||||||
|
android:title="@string/action_reload_tunnels_config" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_graceful_stop"
|
android:id="@+id/action_graceful_stop"
|
||||||
android:orderInCategory="98"
|
android:orderInCategory="98"
|
||||||
android:title="@string/action_graceful_stop" />
|
android:title="@string/action_graceful_stop" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_start_webview"
|
android:id="@+id/action_stop"
|
||||||
android:orderInCategory="97"
|
android:orderInCategory="99"
|
||||||
android:title="@string/action_start_webview" />
|
android:title="@string/action_stop" />
|
||||||
</group>
|
|
||||||
<group android:id="@+id/group_various" >
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_battery_otimizations"
|
|
||||||
android:title="@string/menu_item_battery_optimizations_str" />
|
|
||||||
</group>
|
</group>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -1,28 +1,40 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
|
|
||||||
<string name="action_stop">Остановить</string>
|
<string name="action_stop">Остановить</string>
|
||||||
<string name="action_graceful_stop">Корректная остановка</string>
|
<string name="action_graceful_stop">Корректная остановка</string>
|
||||||
<string name="action_cancel_graceful_stop">Отменить корректную остановку</string>
|
<string name="action_cancel_graceful_stop">Отменить корректную остановку</string>
|
||||||
|
<string name="action_reload_tunnels_config">Перезагрузить туннели</string>
|
||||||
|
<string name="action_start_webview">Открыть Веб Консоль</string>
|
||||||
|
|
||||||
<string name="graceful_stop_is_already_in_progress">Корректная остановка уже запущена</string>
|
<string name="graceful_stop_is_already_in_progress">Корректная остановка уже запущена</string>
|
||||||
<string name="graceful_stop_is_in_progress">Корректная остановка запущена</string>
|
<string name="graceful_stop_is_in_progress">Корректная остановка запущена</string>
|
||||||
|
<string name="gracefulShutdownInProgress">Корректная остановка запущена</string>
|
||||||
|
|
||||||
<string name="already_stopped">Уже остановлено</string>
|
<string name="already_stopped">Уже остановлено</string>
|
||||||
<string name="uninitialized">Приложение инициализируется</string>
|
<string name="uninitialized">Приложение инициализируется</string>
|
||||||
<string name="starting">Приложение запускается</string>
|
<string name="starting">Приложение запускается</string>
|
||||||
<string name="jniLibraryLoaded">Загружены JNI библиотеки</string>
|
<string name="jniLibraryLoaded">Загружены JNI библиотеки</string>
|
||||||
<string name="startedOkay">Приложение запущено</string>
|
<string name="startedOkay">Приложение запущено</string>
|
||||||
<string name="startFailed">Запуск не удался</string>
|
<string name="startFailed">Запуск не удался</string>
|
||||||
<string name="gracefulShutdownInProgress">Корректная остановка запущена</string>
|
|
||||||
<string name="stopped">Приложение было остановлено</string>
|
<string name="stopped">Приложение было остановлено</string>
|
||||||
<string name="remaining">осталось</string>
|
<string name="remaining">осталось</string>
|
||||||
|
|
||||||
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
|
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
|
||||||
<string name="permDenied">Права для записи на SD карту отклонены, вам необходимо предоставить их для продолжения</string>
|
<string name="permDenied">Права для записи на SD карту отклонены, вам необходимо предоставить их для продолжения</string>
|
||||||
|
<string name="permRequired">Права на запись на SD карту необходимы для записи ключей и других файлов в папку I2PD на внутренней памяти.</string>
|
||||||
|
<string name="retryPermRequest">Повторить запрос прав на запись на SD карту</string>
|
||||||
|
|
||||||
<string name="menu_item_battery_optimizations_str">Оптимизации аккумулятора</string>
|
<string name="menu_item_battery_optimizations_str">Оптимизации аккумулятора</string>
|
||||||
<string name="battery_optimizations_enabled">Оптимизации аккумулятора включены</string>
|
<string name="battery_optimizations_enabled">Оптимизации аккумулятора включены</string>
|
||||||
<string name="device_does_not_support_disabling_battery_optimizations">Ваша версия Андроид не поддерживает отключение оптимизаций аккумулятора</string>
|
|
||||||
<string name="battery_optimizations_enabled_explained">Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\nРекомендуется отключить эти оптимизации.</string>
|
<string name="battery_optimizations_enabled_explained">Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\nРекомендуется отключить эти оптимизации.</string>
|
||||||
<string name="battery_optimizations_enabled_dialog" >Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\n\nВам сейчас будет предложено разрешить отключение этих оптимизаций.</string>
|
<string name="battery_optimizations_enabled_dialog">Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\n\nВам сейчас будет предложено разрешить отключение этих оптимизаций.</string>
|
||||||
<string name="continue_str">Продолжить</string>
|
<string name="continue_str">Продолжить</string>
|
||||||
|
<string name="device_does_not_support_disabling_battery_optimizations">Ваша версия Андроид не поддерживает отключение оптимизаций аккумулятора</string>
|
||||||
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Ваша версия Андроид не поддерживает показ диалога об оптимизациях аккумулятора для приложений.</string>
|
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Ваша версия Андроид не поддерживает показ диалога об оптимизациях аккумулятора для приложений.</string>
|
||||||
|
|
||||||
<string name="shutdown_canceled">Плановая остановка отменена</string>
|
<string name="shutdown_canceled">Плановая остановка отменена</string>
|
||||||
|
|
||||||
|
<string name="tunnels_reloading">Перезагрузка конфигурации туннелей...</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,29 +1,41 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
|
|
||||||
<string name="action_stop">Stop</string>
|
<string name="action_stop">Stop</string>
|
||||||
<string name="action_graceful_stop">Graceful Stop</string>
|
<string name="action_graceful_stop">Graceful Stop</string>
|
||||||
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
|
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
|
||||||
|
<string name="action_reload_tunnels_config">Reload tunnels</string>
|
||||||
|
<string name="action_start_webview">Open Web Console</string>
|
||||||
|
|
||||||
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
||||||
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
||||||
|
<string name="gracefulShutdownInProgress">Graceful shutdown in progress</string>
|
||||||
|
|
||||||
<string name="already_stopped">Already stopped</string>
|
<string name="already_stopped">Already stopped</string>
|
||||||
<string name="uninitialized">Application initializing</string>
|
<string name="uninitialized">Application initializing</string>
|
||||||
<string name="starting">Application starting</string>
|
<string name="starting">Application starting</string>
|
||||||
<string name="jniLibraryLoaded">Loaded JNI libraries</string>
|
<string name="jniLibraryLoaded">Loaded JNI libraries</string>
|
||||||
<string name="startedOkay">Application Started</string>
|
<string name="startedOkay">Application Started</string>
|
||||||
<string name="startFailed">Start failed</string>
|
<string name="startFailed">Start failed</string>
|
||||||
<string name="gracefulShutdownInProgress">Graceful shutdown in progress</string>
|
|
||||||
<string name="stopped">Application stopped</string>
|
<string name="stopped">Application stopped</string>
|
||||||
<string name="remaining">remaining</string>
|
<string name="remaining">remaining</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
|
||||||
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
||||||
<string name="permDenied">SD card write permission denied, you need to allow this to continue</string>
|
<string name="permDenied">SD card write permission denied, you need to allow this to continue</string>
|
||||||
|
<string name="permRequired">SD card write access is required to write the keys and other files to the I2PD folder on SD card.</string>
|
||||||
|
<string name="retryPermRequest">Retry requesting the SD card write permissions</string>
|
||||||
|
|
||||||
|
<string name="menu_item_battery_optimizations_str">Battery Optimizations</string>
|
||||||
<string name="battery_optimizations_enabled">Battery optimizations enabled</string>
|
<string name="battery_optimizations_enabled">Battery optimizations enabled</string>
|
||||||
<string name="battery_optimizations_enabled_explained">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.</string>
|
<string name="battery_optimizations_enabled_explained">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.</string>
|
||||||
<string name="battery_optimizations_enabled_dialog" >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.</string>
|
<string name="battery_optimizations_enabled_dialog">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.</string>
|
||||||
<string name="continue_str">Continue</string>
|
<string name="continue_str">Continue</string>
|
||||||
<string name="device_does_not_support_disabling_battery_optimizations">Your Android version does not support opting out of battery optimizations</string>
|
<string name="device_does_not_support_disabling_battery_optimizations">Your Android version does not support opting out of battery optimizations</string>
|
||||||
<string name="menu_item_battery_optimizations_str">Battery Optimizations</string>
|
|
||||||
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Your Android OS version does not support showing the dialog for battery optimizations for applications.</string>
|
<string name="os_version_does_not_support_battery_optimizations_show_os_dialog_api">Your Android OS version does not support showing the dialog for battery optimizations for applications.</string>
|
||||||
|
|
||||||
<string name="shutdown_canceled">Planned shutdown canceled</string>
|
<string name="shutdown_canceled">Planned shutdown canceled</string>
|
||||||
<string name="action_start_webview">Start webview</string>
|
|
||||||
|
<string name="tunnels_reloading">Reloading tunnels config...</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -10,36 +10,65 @@ import org.purplei2p.i2pd.R;
|
||||||
public class DaemonSingleton {
|
public class DaemonSingleton {
|
||||||
private static final String TAG = "i2pd";
|
private static final String TAG = "i2pd";
|
||||||
private static final DaemonSingleton instance = new DaemonSingleton();
|
private static final DaemonSingleton instance = new DaemonSingleton();
|
||||||
public interface StateUpdateListener { void daemonStateUpdate(); }
|
|
||||||
|
public interface StateUpdateListener {
|
||||||
|
void daemonStateUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
||||||
|
|
||||||
public static DaemonSingleton getInstance() { return instance; }
|
public static DaemonSingleton getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
|
public synchronized void addStateChangeListener(StateUpdateListener listener) {
|
||||||
public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
|
stateUpdateListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeStateChangeListener(StateUpdateListener listener) {
|
||||||
|
stateUpdateListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void setState(State newState) {
|
private synchronized void setState(State newState) {
|
||||||
if(newState==null)throw new NullPointerException();
|
if (newState == null)
|
||||||
|
throw new NullPointerException();
|
||||||
|
|
||||||
State oldState = state;
|
State oldState = state;
|
||||||
if(oldState==null)throw new NullPointerException();
|
|
||||||
if(oldState.equals(newState))return;
|
if (oldState == null)
|
||||||
state=newState;
|
throw new NullPointerException();
|
||||||
|
|
||||||
|
if (oldState.equals(newState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
state = newState;
|
||||||
fireStateUpdate1();
|
fireStateUpdate1();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stopAcceptingTunnels() {
|
public synchronized void stopAcceptingTunnels() {
|
||||||
if(isStartedOkay()){
|
if (isStartedOkay()) {
|
||||||
setState(State.gracefulShutdownInProgress);
|
setState(State.gracefulShutdownInProgress);
|
||||||
I2PD_JNI.stopAcceptingTunnels();
|
I2PD_JNI.stopAcceptingTunnels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void startAcceptingTunnels() {
|
public synchronized void startAcceptingTunnels() {
|
||||||
if(isStartedOkay()){
|
if (isStartedOkay()) {
|
||||||
setState(State.startedOkay);
|
setState(State.startedOkay);
|
||||||
I2PD_JNI.startAcceptingTunnels();
|
I2PD_JNI.startAcceptingTunnels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void reloadTunnelsConfigs() {
|
||||||
|
if (isStartedOkay()) {
|
||||||
|
I2PD_JNI.reloadTunnelsConfigs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int GetTransitTunnelsCount() {
|
||||||
|
return I2PD_JNI.GetTransitTunnelsCount();
|
||||||
|
}
|
||||||
|
|
||||||
private volatile boolean startedOkay;
|
private volatile boolean startedOkay;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
|
@ -64,11 +93,13 @@ public class DaemonSingleton {
|
||||||
|
|
||||||
private volatile State state = State.uninitialized;
|
private volatile State state = State.uninitialized;
|
||||||
|
|
||||||
public State getState() { return state; }
|
public State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
setState(State.starting);
|
setState(State.starting);
|
||||||
new Thread(new Runnable(){
|
new Thread(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -76,7 +107,7 @@ public class DaemonSingleton {
|
||||||
I2PD_JNI.loadLibraries();
|
I2PD_JNI.loadLibraries();
|
||||||
setState(State.jniLibraryLoaded);
|
setState(State.jniLibraryLoaded);
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
lastThrowable=tr;
|
lastThrowable = tr;
|
||||||
setState(State.startFailed);
|
setState(State.startFailed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,25 +115,27 @@ public class DaemonSingleton {
|
||||||
synchronized (DaemonSingleton.this) {
|
synchronized (DaemonSingleton.this) {
|
||||||
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
|
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
|
||||||
daemonStartResult = I2PD_JNI.startDaemon();
|
daemonStartResult = I2PD_JNI.startDaemon();
|
||||||
if("ok".equals(daemonStartResult)){
|
if ("ok".equals(daemonStartResult)) {
|
||||||
setState(State.startedOkay);
|
setState(State.startedOkay);
|
||||||
setStartedOkay(true);
|
setStartedOkay(true);
|
||||||
}else setState(State.startFailed);
|
} else
|
||||||
|
setState(State.startFailed);
|
||||||
}
|
}
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
lastThrowable=tr;
|
lastThrowable = tr;
|
||||||
setState(State.startFailed);
|
setState(State.startFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}, "i2pdDaemonStart").start();
|
}, "i2pdDaemonStart").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Throwable lastThrowable;
|
private Throwable lastThrowable;
|
||||||
private String daemonStartResult="N/A";
|
private String daemonStartResult = "N/A";
|
||||||
|
|
||||||
private void fireStateUpdate1() {
|
private void fireStateUpdate1() {
|
||||||
Log.i(TAG, "daemon state change: "+state);
|
Log.i(TAG, "daemon state change: " + state);
|
||||||
for(StateUpdateListener listener : stateUpdateListeners) {
|
for (StateUpdateListener listener : stateUpdateListeners) {
|
||||||
try {
|
try {
|
||||||
listener.daemonStateUpdate();
|
listener.daemonStateUpdate();
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
|
@ -134,8 +167,13 @@ public class DaemonSingleton {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stopDaemon() {
|
public synchronized void stopDaemon() {
|
||||||
if(isStartedOkay()){
|
if (isStartedOkay()) {
|
||||||
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);}
|
try {
|
||||||
|
I2PD_JNI.stopDaemon();
|
||||||
|
} catch(Throwable tr) {
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
|
}
|
||||||
|
|
||||||
setStartedOkay(false);
|
setStartedOkay(false);
|
||||||
setState(State.stopped);
|
setState(State.stopped);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,17 +68,16 @@ public class I2PDActivity extends Activity {
|
||||||
|
|
||||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||||
|
|
||||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() {
|
||||||
new DaemonSingleton.StateUpdateListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void daemonStateUpdate()
|
public void daemonStateUpdate() {
|
||||||
{
|
|
||||||
processAssets();
|
processAssets();
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
try {
|
try {
|
||||||
if(textView==null) return;
|
if (textView == null)
|
||||||
|
return;
|
||||||
Throwable tr = daemon.getLastThrowable();
|
Throwable tr = daemon.getLastThrowable();
|
||||||
if(tr!=null) {
|
if (tr!=null) {
|
||||||
textView.setText(throwableToString(tr));
|
textView.setText(throwableToString(tr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -93,17 +92,17 @@ public class I2PDActivity extends Activity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private static volatile long graceStartedMillis;
|
private static volatile long graceStartedMillis;
|
||||||
private static final Object graceStartedMillis_LOCK=new Object();
|
private static final Object graceStartedMillis_LOCK = new Object();
|
||||||
private Menu optionsMenu;
|
private Menu optionsMenu;
|
||||||
|
|
||||||
private static String formatGraceTimeRemaining() {
|
private static String formatGraceTimeRemaining() {
|
||||||
long remainingSeconds;
|
long remainingSeconds;
|
||||||
synchronized (graceStartedMillis_LOCK){
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D);
|
remainingSeconds = Math.round(Math.max(0, graceStartedMillis + GRACEFUL_DELAY_MILLIS - System.currentTimeMillis()) / 1000.0D);
|
||||||
}
|
}
|
||||||
long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D);
|
long remainingMinutes = (long)Math.floor(remainingSeconds / 60.0D);
|
||||||
long remSec=remainingSeconds-remainingMinutes*60;
|
long remSec = remainingSeconds - remainingMinutes * 60;
|
||||||
return remainingMinutes+":"+(remSec/10)+remSec%10;
|
return remainingMinutes + ":" + (remSec / 10) + remSec % 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,10 +116,8 @@ public class I2PDActivity extends Activity {
|
||||||
daemonStateUpdatedListener.daemonStateUpdate();
|
daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
|
|
||||||
// request permissions
|
// request permissions
|
||||||
if (Build.VERSION.SDK_INT >= 23)
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
{
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
|
||||||
{
|
|
||||||
ActivityCompat.requestPermissions(this,
|
ActivityCompat.requestPermissions(this,
|
||||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||||
|
@ -131,7 +128,7 @@ public class I2PDActivity extends Activity {
|
||||||
doBindService();
|
doBindService();
|
||||||
|
|
||||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||||
if(gracefulQuitTimer!=null){
|
if (gracefulQuitTimer != null) {
|
||||||
long gracefulStopAtMillis;
|
long gracefulStopAtMillis;
|
||||||
synchronized (graceStartedMillis_LOCK) {
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||||
|
@ -148,9 +145,9 @@ public class I2PDActivity extends Activity {
|
||||||
textView = null;
|
textView = null;
|
||||||
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
daemon.removeStateChangeListener(daemonStateUpdatedListener);
|
||||||
//cancelGracefulStop0();
|
//cancelGracefulStop0();
|
||||||
try{
|
try {
|
||||||
doUnbindService();
|
doUnbindService();
|
||||||
}catch(Throwable tr){
|
} catch(Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +168,7 @@ public class I2PDActivity extends Activity {
|
||||||
|
|
||||||
private void cancelGracefulStop0() {
|
private void cancelGracefulStop0() {
|
||||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||||
if(gracefulQuitTimer!=null) {
|
if (gracefulQuitTimer != null) {
|
||||||
gracefulQuitTimer.cancel();
|
gracefulQuitTimer.cancel();
|
||||||
setGracefulQuitTimer(null);
|
setGracefulQuitTimer(null);
|
||||||
}
|
}
|
||||||
|
@ -216,7 +213,8 @@ public class I2PDActivity extends Activity {
|
||||||
|
|
||||||
private void doBindService() {
|
private void doBindService() {
|
||||||
synchronized (I2PDActivity.class) {
|
synchronized (I2PDActivity.class) {
|
||||||
if (mIsBound) return;
|
if (mIsBound)
|
||||||
|
return;
|
||||||
// Establish a connection with the service. We use an explicit
|
// Establish a connection with the service. We use an explicit
|
||||||
// class name because we want a specific service implementation that
|
// class name because we want a specific service implementation that
|
||||||
// we know will be running in our own process (and thus won't be
|
// we know will be running in our own process (and thus won't be
|
||||||
|
@ -256,10 +254,11 @@ public class I2PDActivity extends Activity {
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
|
|
||||||
switch(id){
|
switch(id) {
|
||||||
case R.id.action_stop:
|
case R.id.action_stop:
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.action_graceful_stop:
|
case R.id.action_graceful_stop:
|
||||||
synchronized (graceStartedMillis_LOCK) {
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
if (getGracefulQuitTimer() != null)
|
if (getGracefulQuitTimer() != null)
|
||||||
|
@ -268,9 +267,15 @@ public class I2PDActivity extends Activity {
|
||||||
i2pdGracefulStop();
|
i2pdGracefulStop();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.action_battery_otimizations:
|
case R.id.action_battery_otimizations:
|
||||||
onActionBatteryOptimizations();
|
onActionBatteryOptimizations();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case R.id.action_reload_tunnels_config:
|
||||||
|
onReloadTunnelsConfig();
|
||||||
|
return true;
|
||||||
|
|
||||||
case R.id.action_start_webview:
|
case R.id.action_start_webview:
|
||||||
setContentView(R.layout.webview);
|
setContentView(R.layout.webview);
|
||||||
this.webView = (WebView) findViewById(R.id.webview1);
|
this.webView = (WebView) findViewById(R.id.webview1);
|
||||||
|
@ -291,12 +296,18 @@ public class I2PDActivity extends Activity {
|
||||||
try {
|
try {
|
||||||
startActivity(new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
|
startActivity(new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
Log.e(TAG,"BATT_OPTIM_DIALOG_ActvtNotFound", 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();
|
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() {
|
private void i2pdStop() {
|
||||||
cancelGracefulStop0();
|
cancelGracefulStop0();
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
@ -307,84 +318,83 @@ public class I2PDActivity extends Activity {
|
||||||
Log.e(TAG, "", 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.
|
quit(); //TODO make menu items for starting i2pd. On my Android, I need to reboot the OS to restart i2pd.
|
||||||
},"stop").start();
|
}, "stop").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static volatile Timer gracefulQuitTimer;
|
private static volatile Timer gracefulQuitTimer;
|
||||||
|
|
||||||
private void i2pdGracefulStop() {
|
private void i2pdGracefulStop() {
|
||||||
if(daemon.getState()==DaemonSingleton.State.stopped){
|
if (daemon.getState() == DaemonSingleton.State.stopped) {
|
||||||
Toast.makeText(this, R.string.already_stopped,
|
Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show();
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(getGracefulQuitTimer()!=null){
|
if (getGracefulQuitTimer() != null) {
|
||||||
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress,
|
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress, Toast.LENGTH_SHORT).show();
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
|
Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show();
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "grac stopping");
|
Log.d(TAG, "graceful stopping");
|
||||||
if(daemon.isStartedOkay()) {
|
if (daemon.isStartedOkay()) {
|
||||||
daemon.stopAcceptingTunnels();
|
daemon.stopAcceptingTunnels();
|
||||||
long gracefulStopAtMillis;
|
long gracefulStopAtMillis;
|
||||||
synchronized (graceStartedMillis_LOCK) {
|
synchronized (graceStartedMillis_LOCK) {
|
||||||
graceStartedMillis = System.currentTimeMillis();
|
graceStartedMillis = System.currentTimeMillis();
|
||||||
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
|
||||||
}
|
}
|
||||||
rescheduleGraceStop(null,gracefulStopAtMillis);
|
rescheduleGraceStop(null, gracefulStopAtMillis);
|
||||||
} else {
|
} else
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
}
|
|
||||||
} catch(Throwable tr) {
|
} catch(Throwable tr) {
|
||||||
Log.e(TAG,"",tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
},"gracInit").start();
|
}, "gracInit").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelGracefulStop()
|
private void cancelGracefulStop()
|
||||||
{
|
{
|
||||||
cancelGracefulStop0();
|
cancelGracefulStop0();
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try
|
try {
|
||||||
{
|
Log.d(TAG, "canceling graceful stop");
|
||||||
Log.d(TAG, "canceling grac stop");
|
if (daemon.isStartedOkay()) {
|
||||||
if(daemon.isStartedOkay()) {
|
|
||||||
daemon.startAcceptingTunnels();
|
daemon.startAcceptingTunnels();
|
||||||
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
|
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
|
} catch(Throwable tr) {
|
||||||
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
catch(Throwable tr)
|
}, "gracCancel").start();
|
||||||
{
|
|
||||||
Log.e(TAG,"",tr);
|
|
||||||
}
|
|
||||||
},"gracCancel").start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
if (gracefulQuitTimerOld != null)
|
||||||
|
gracefulQuitTimerOld.cancel();
|
||||||
|
|
||||||
|
if(daemon.GetTransitTunnelsCount() <= 0) { // no tunnels left
|
||||||
|
Log.d(TAG, "no transit tunnels left, stopping");
|
||||||
|
i2pdStop();
|
||||||
|
}
|
||||||
|
|
||||||
final Timer gracefulQuitTimer = new Timer(true);
|
final Timer gracefulQuitTimer = new Timer(true);
|
||||||
setGracefulQuitTimer(gracefulQuitTimer);
|
setGracefulQuitTimer(gracefulQuitTimer);
|
||||||
gracefulQuitTimer.schedule(new TimerTask(){
|
gracefulQuitTimer.schedule(new TimerTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
|
}, Math.max(0, gracefulStopAtMillis - System.currentTimeMillis()));
|
||||||
final TimerTask tickerTask = new TimerTask() {
|
final TimerTask tickerTask = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
daemonStateUpdatedListener.daemonStateUpdate();
|
daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
|
gracefulQuitTimer.scheduleAtFixedRate(tickerTask, 0/*start delay*/, 1000/*millis period*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Timer getGracefulQuitTimer() {
|
private static Timer getGracefulQuitTimer() {
|
||||||
|
@ -454,9 +464,9 @@ public class I2PDActivity extends Activity {
|
||||||
*/
|
*/
|
||||||
private void copyFileAsset(String path) {
|
private void copyFileAsset(String path) {
|
||||||
File file = new File(i2pdpath, path);
|
File file = new File(i2pdpath, path);
|
||||||
if(!file.exists()) {
|
if (!file.exists()) {
|
||||||
try {
|
try {
|
||||||
try (InputStream in = getAssets().open(path) ) {
|
try (InputStream in = getAssets().open(path)) {
|
||||||
try (OutputStream out = new FileOutputStream(file)) {
|
try (OutputStream out = new FileOutputStream(file)) {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int read = in.read(buffer);
|
int read = in.read(buffer);
|
||||||
|
@ -475,18 +485,20 @@ public class I2PDActivity extends Activity {
|
||||||
private void deleteRecursive(File fileOrDirectory) {
|
private void deleteRecursive(File fileOrDirectory) {
|
||||||
if (fileOrDirectory.isDirectory()) {
|
if (fileOrDirectory.isDirectory()) {
|
||||||
File[] files = fileOrDirectory.listFiles();
|
File[] files = fileOrDirectory.listFiles();
|
||||||
if(files!=null) {
|
if (files != null) {
|
||||||
for (File child : files) {
|
for (File child : files) {
|
||||||
deleteRecursive(child);
|
deleteRecursive(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean deleteResult = fileOrDirectory.delete();
|
boolean deleteResult = fileOrDirectory.delete();
|
||||||
if(!deleteResult)Log.e(TAG, "fileOrDirectory.delete() returned "+deleteResult+", absolute path='"+fileOrDirectory.getAbsolutePath()+"'");
|
if (!deleteResult)
|
||||||
|
Log.e(TAG, "fileOrDirectory.delete() returned " + deleteResult + ", absolute path='" + fileOrDirectory.getAbsolutePath() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processAssets() {
|
private void processAssets() {
|
||||||
if (!assetsCopied) try {
|
if (!assetsCopied) {
|
||||||
|
try {
|
||||||
assetsCopied = true; // prevent from running on every state update
|
assetsCopied = true; // prevent from running on every state update
|
||||||
|
|
||||||
File holderFile = new File(i2pdpath, "assets.ready");
|
File holderFile = new File(i2pdpath, "assets.ready");
|
||||||
|
@ -507,14 +519,14 @@ public class I2PDActivity extends Activity {
|
||||||
text.append(line);
|
text.append(line);
|
||||||
}
|
}
|
||||||
}finally {
|
}finally {
|
||||||
try{
|
try {
|
||||||
br.close();
|
br.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "", e);
|
Log.e(TAG, "", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try{
|
try {
|
||||||
fileReader.close();
|
fileReader.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "", e);
|
Log.e(TAG, "", e);
|
||||||
|
@ -526,9 +538,11 @@ public class I2PDActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if version differs from current app version or null, try to delete certificates folder
|
// if version differs from current app version or null, try to delete certificates folder
|
||||||
if (!text.toString().contains(versionName)) try {
|
if (!text.toString().contains(versionName))
|
||||||
|
try {
|
||||||
boolean deleteResult = holderFile.delete();
|
boolean deleteResult = holderFile.delete();
|
||||||
if(!deleteResult)Log.e(TAG, "holderFile.delete() returned "+deleteResult+", absolute path='"+holderFile.getAbsolutePath()+"'");
|
if (!deleteResult)
|
||||||
|
Log.e(TAG, "holderFile.delete() returned " + deleteResult + ", absolute path='" + holderFile.getAbsolutePath() + "'");
|
||||||
File certPath = new File(i2pdpath, "certificates");
|
File certPath = new File(i2pdpath, "certificates");
|
||||||
deleteRecursive(certPath);
|
deleteRecursive(certPath);
|
||||||
}
|
}
|
||||||
|
@ -549,9 +563,9 @@ public class I2PDActivity extends Activity {
|
||||||
try {
|
try {
|
||||||
writer.append(versionName);
|
writer.append(versionName);
|
||||||
} finally {
|
} finally {
|
||||||
try{
|
try {
|
||||||
writer.close();
|
writer.close();
|
||||||
}catch (IOException e){
|
} catch (IOException e) {
|
||||||
Log.e(TAG,"on writer close", e);
|
Log.e(TAG,"on writer close", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,11 +575,12 @@ public class I2PDActivity extends Activity {
|
||||||
Log.e(TAG,"on assets copying", tr);
|
Log.e(TAG,"on assets copying", tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("BatteryLife")
|
@SuppressLint("BatteryLife")
|
||||||
private void openBatteryOptimizationDialogIfNeeded() {
|
private void openBatteryOptimizationDialogIfNeeded() {
|
||||||
boolean questionEnabled = getPreferences().getBoolean(getBatteryOptimizationPreferenceKey(), true);
|
boolean questionEnabled = getPreferences().getBoolean(getBatteryOptimizationPreferenceKey(), true);
|
||||||
Log.i(TAG,"BATT_OPTIM_questionEnabled=="+questionEnabled);
|
Log.i(TAG, "BATT_OPTIM_questionEnabled==" + questionEnabled);
|
||||||
if (!isKnownIgnoringBatteryOptimizations()
|
if (!isKnownIgnoringBatteryOptimizations()
|
||||||
&& android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
|
&& android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
|
||||||
&& questionEnabled) {
|
&& questionEnabled) {
|
||||||
|
@ -576,7 +591,7 @@ public class I2PDActivity extends Activity {
|
||||||
try {
|
try {
|
||||||
startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse(PACKAGE_URI_SCHEME + getPackageName())));
|
startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse(PACKAGE_URI_SCHEME + getPackageName())));
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
Log.e(TAG,"BATT_OPTIM_ActvtNotFound", e);
|
Log.e(TAG, "BATT_OPTIM_ActvtNotFound", e);
|
||||||
Toast.makeText(this, R.string.device_does_not_support_disabling_battery_optimizations, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.device_does_not_support_disabling_battery_optimizations, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -602,7 +617,7 @@ public class I2PDActivity extends Activity {
|
||||||
Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
|
Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
|
||||||
return ignoring;
|
return ignoring;
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "BATT_OPTIM: old sdk version=="+Build.VERSION.SDK_INT);
|
Log.i(TAG, "BATT_OPTIM: old sdk version==" + Build.VERSION.SDK_INT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,12 +641,12 @@ public class I2PDActivity extends Activity {
|
||||||
//moveTaskToBack(true);
|
//moveTaskToBack(true);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
try{
|
try {
|
||||||
daemon.stopDaemon();
|
daemon.stopDaemon();
|
||||||
}catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
Log.e(TAG, "", tr);
|
Log.e(TAG, "", tr);
|
||||||
}
|
}
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|
|
@ -16,10 +16,14 @@ public class I2PD_JNI {
|
||||||
|
|
||||||
public static native void startAcceptingTunnels();
|
public static native void startAcceptingTunnels();
|
||||||
|
|
||||||
|
public static native void reloadTunnelsConfigs();
|
||||||
|
|
||||||
public static native void onNetworkStateChanged(boolean isConnected);
|
public static native void onNetworkStateChanged(boolean isConnected);
|
||||||
|
|
||||||
public static native void setDataDir(String jdataDir);
|
public static native void setDataDir(String jdataDir);
|
||||||
|
|
||||||
|
public static native int GetTransitTunnelsCount();
|
||||||
|
|
||||||
public static void loadLibraries() {
|
public static void loadLibraries() {
|
||||||
//System.loadLibrary("c++_shared");
|
//System.loadLibrary("c++_shared");
|
||||||
System.loadLibrary("i2pd");
|
System.loadLibrary("i2pd");
|
||||||
|
|
35
appveyor.yml
35
appveyor.yml
|
@ -1,4 +1,4 @@
|
||||||
version: 2.30.0.{build}
|
version: 2.32.0.{build}
|
||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
branches:
|
branches:
|
||||||
|
@ -14,34 +14,25 @@ environment:
|
||||||
CHERE_INVOKING: enabled_from_arguments
|
CHERE_INVOKING: enabled_from_arguments
|
||||||
matrix:
|
matrix:
|
||||||
- MSYSTEM: MINGW64
|
- MSYSTEM: MINGW64
|
||||||
|
MSYS_PACKAGES: mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc
|
||||||
|
MSYS_BITNESS: 64
|
||||||
- MSYSTEM: MINGW32
|
- MSYSTEM: MINGW32
|
||||||
|
MSYS_PACKAGES: mingw-w64-i686-boost mingw-w64-i686-miniupnpc
|
||||||
|
MSYS_BITNESS: 32
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
|
||||||
|
# TODO: revert that change when appveyor's images will be updated
|
||||||
|
- c:\msys64\usr\bin\bash -l "build/appveyor-msys2-upgrade.bash"
|
||||||
|
# update runtime
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
||||||
|
# update packages and install required
|
||||||
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
|
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}"
|
||||||
|
|
||||||
- if "%MSYSTEM%" == "MINGW64" (
|
|
||||||
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc"
|
|
||||||
) else (
|
|
||||||
c:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-boost mingw-w64-i686-miniupnpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
- if "%MSYSTEM%" == "MINGW64" (
|
|
||||||
set "bitness=64"
|
|
||||||
) else (
|
|
||||||
set "bitness=32"
|
|
||||||
)
|
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: >-
|
- echo MSYSTEM = %MSYSTEM%, bitness = %MSYS_BITNESS%
|
||||||
cd \projects\i2pd
|
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes -j3"
|
||||||
|
- 7z a -tzip -mx9 -mmt i2pd-mingw-win%MSYS_BITNESS%.zip i2pd.exe
|
||||||
echo MSYSTEM = %MSYSTEM%, bitness = %bitness%
|
|
||||||
|
|
||||||
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes -j2"
|
|
||||||
- 7z a -tzip -mx9 -mmt i2pd-mingw-win%bitness%.zip i2pd.exe
|
|
||||||
|
|
||||||
test: off
|
test: off
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
cmake_minimum_required ( VERSION 2.8.12 )
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
# this addresses CMP0059 with CMake > 3.3 for PCH flags
|
# this addresses CMP0059 with CMake > 3.3 for PCH flags
|
||||||
cmake_policy( VERSION 2.8.12 )
|
cmake_policy(VERSION 2.8.12)
|
||||||
project ( "i2pd" )
|
project("i2pd")
|
||||||
|
|
||||||
# for debugging
|
# for debugging
|
||||||
#set(CMAKE_VERBOSE_MAKEFILE on)
|
#set(CMAKE_VERBOSE_MAKEFILE on)
|
||||||
|
|
||||||
|
# Win32 build with cmake is not supported
|
||||||
|
if(WIN32 OR MSVC OR MSYS OR MINGW)
|
||||||
|
message(SEND_ERROR "cmake build for windows is not supported. Please use MSYS2 with makefiles in project root.")
|
||||||
|
endif()
|
||||||
|
|
||||||
# configurale options
|
# configurale options
|
||||||
option(WITH_AESNI "Use AES-NI instructions set" OFF)
|
option(WITH_AESNI "Use AES-NI instructions set" OFF)
|
||||||
option(WITH_AVX "Use AVX instructions" OFF)
|
option(WITH_AVX "Use AVX instructions" OFF)
|
||||||
|
@ -15,14 +20,13 @@ option(WITH_BINARY "Build binary" ON)
|
||||||
option(WITH_STATIC "Static build" OFF)
|
option(WITH_STATIC "Static build" OFF)
|
||||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||||
option(WITH_PCH "Use precompiled header" OFF)
|
option(WITH_PCH "Use precompiled header" OFF)
|
||||||
option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
|
|
||||||
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
||||||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
||||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
||||||
set ( CMAKE_SOURCE_DIR ".." )
|
set(CMAKE_SOURCE_DIR "..")
|
||||||
|
|
||||||
# architecture
|
# architecture
|
||||||
include(TargetArch)
|
include(TargetArch)
|
||||||
|
@ -30,67 +34,65 @@ target_architecture(ARCHITECTURE)
|
||||||
|
|
||||||
set(LIBI2PD_SRC_DIR ../libi2pd)
|
set(LIBI2PD_SRC_DIR ../libi2pd)
|
||||||
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
|
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
|
||||||
|
set(DAEMON_SRC_DIR ../daemon)
|
||||||
|
|
||||||
include_directories(${LIBI2PD_SRC_DIR})
|
include_directories(${LIBI2PD_SRC_DIR})
|
||||||
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
|
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
|
||||||
|
include_directories(${DAEMON_SRC_DIR})
|
||||||
|
|
||||||
set (LIBI2PD_SRC
|
set(LIBI2PD_SRC
|
||||||
|
"${LIBI2PD_SRC_DIR}/api.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Base.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Blinding.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
|
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/ChaCha20.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Config.cpp"
|
"${LIBI2PD_SRC_DIR}/Config.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/CPU.cpp"
|
"${LIBI2PD_SRC_DIR}/CPU.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
|
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
|
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Datagram.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Destination.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Ed25519.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Elligator.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Family.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/FS.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
|
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Gost.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Gzip.cpp"
|
"${LIBI2PD_SRC_DIR}/Gzip.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/HTTP.cpp"
|
"${LIBI2PD_SRC_DIR}/HTTP.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/I2NPProtocol.cpp"
|
"${LIBI2PD_SRC_DIR}/I2NPProtocol.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Identity.cpp"
|
"${LIBI2PD_SRC_DIR}/Identity.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/LeaseSet.cpp"
|
"${LIBI2PD_SRC_DIR}/LeaseSet.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/FS.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Log.cpp"
|
"${LIBI2PD_SRC_DIR}/Log.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
|
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/RouterContext.cpp"
|
"${LIBI2PD_SRC_DIR}/RouterContext.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/RouterInfo.cpp"
|
"${LIBI2PD_SRC_DIR}/RouterInfo.cpp"
|
||||||
|
"${LIBI2PD_SRC_DIR}/Signature.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/SSU.cpp"
|
"${LIBI2PD_SRC_DIR}/SSU.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/SSUData.cpp"
|
"${LIBI2PD_SRC_DIR}/SSUData.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/SSUSession.cpp"
|
"${LIBI2PD_SRC_DIR}/SSUSession.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Streaming.cpp"
|
"${LIBI2PD_SRC_DIR}/Streaming.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Destination.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/TransitTunnel.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Tunnel.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/TunnelGateway.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Transports.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/TunnelEndpoint.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/TunnelPool.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Base.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/util.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Datagram.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Family.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Signature.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/Timestamp.cpp"
|
"${LIBI2PD_SRC_DIR}/Timestamp.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/api.cpp"
|
"${LIBI2PD_SRC_DIR}/TransitTunnel.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Gost.cpp"
|
"${LIBI2PD_SRC_DIR}/Transports.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/ChaCha20.cpp"
|
"${LIBI2PD_SRC_DIR}/Tunnel.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
|
"${LIBI2PD_SRC_DIR}/TunnelEndpoint.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Ed25519.cpp"
|
"${LIBI2PD_SRC_DIR}/TunnelGateway.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
|
"${LIBI2PD_SRC_DIR}/TunnelPool.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Blinding.cpp"
|
"${LIBI2PD_SRC_DIR}/util.cpp"
|
||||||
"${LIBI2PD_SRC_DIR}/Elligator.cpp"
|
|
||||||
"${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32 OR MSYS)
|
|
||||||
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_library(libi2pd ${LIBI2PD_SRC})
|
add_library(libi2pd ${LIBI2PD_SRC})
|
||||||
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
||||||
|
|
||||||
if (WITH_LIBRARY)
|
if(WITH_LIBRARY)
|
||||||
install(TARGETS libi2pd
|
install(TARGETS libi2pd
|
||||||
EXPORT libi2pd
|
EXPORT libi2pd
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
|
@ -101,7 +103,7 @@ if (WITH_LIBRARY)
|
||||||
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set (CLIENT_SRC
|
set(CLIENT_SRC
|
||||||
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
||||||
"${LIBI2PD_CLIENT_SRC_DIR}/BOB.cpp"
|
"${LIBI2PD_CLIENT_SRC_DIR}/BOB.cpp"
|
||||||
"${LIBI2PD_CLIENT_SRC_DIR}/ClientContext.cpp"
|
"${LIBI2PD_CLIENT_SRC_DIR}/ClientContext.cpp"
|
||||||
|
@ -117,7 +119,7 @@ set (CLIENT_SRC
|
||||||
add_library(libi2pdclient ${CLIENT_SRC})
|
add_library(libi2pdclient ${CLIENT_SRC})
|
||||||
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
|
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
|
||||||
|
|
||||||
if (WITH_LIBRARY)
|
if(WITH_LIBRARY)
|
||||||
install(TARGETS libi2pdclient
|
install(TARGETS libi2pdclient
|
||||||
EXPORT libi2pdclient
|
EXPORT libi2pdclient
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
|
@ -125,9 +127,7 @@ if (WITH_LIBRARY)
|
||||||
COMPONENT Libraries)
|
COMPONENT Libraries)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(DAEMON_SRC_DIR ../daemon)
|
set(DAEMON_SRC
|
||||||
|
|
||||||
set (DAEMON_SRC
|
|
||||||
"${DAEMON_SRC_DIR}/Daemon.cpp"
|
"${DAEMON_SRC_DIR}/Daemon.cpp"
|
||||||
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
|
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
|
||||||
"${DAEMON_SRC_DIR}/I2PControl.cpp"
|
"${DAEMON_SRC_DIR}/I2PControl.cpp"
|
||||||
|
@ -135,37 +135,20 @@ set (DAEMON_SRC
|
||||||
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_MESHNET)
|
if(WITH_MESHNET)
|
||||||
add_definitions(-DMESHNET)
|
add_definitions(-DMESHNET)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (WITH_UPNP)
|
if(WITH_UPNP)
|
||||||
add_definitions(-DUSE_UPNP)
|
add_definitions(-DUSE_UPNP)
|
||||||
if (NOT MSVC AND NOT MSYS)
|
endif()
|
||||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# compiler flags customization (by vendor)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
|
||||||
if (MSVC)
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
|
||||||
add_definitions( -DWIN32_LEAN_AND_MEAN -DNOMINMAX )
|
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
|
||||||
# TODO Check & report to Boost dev, there should be no need for these two
|
# Multiple definitions of __stack_chk_fail(libssp & libc)
|
||||||
add_definitions( -DBOOST_THREAD_NO_LIB -DBOOST_CHRONO_NO_LIB )
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections")
|
||||||
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL" )
|
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
|
||||||
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /INCREMENTAL:NO /LTCG" )
|
|
||||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} /GL" )
|
|
||||||
set( CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO /LTCG" )
|
|
||||||
else()
|
|
||||||
if (MSYS OR MINGW)
|
|
||||||
add_definitions( -DWIN32_LEAN_AND_MEAN )
|
|
||||||
endif ()
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter" )
|
|
||||||
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic" )
|
|
||||||
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
|
|
||||||
# Multiple definitions of __stack_chk_fail (libssp & libc)
|
|
||||||
set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections" )
|
|
||||||
set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections" ) # -flto is added from above
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# check for c++17 & c++11 support
|
# check for c++17 & c++11 support
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
@ -179,72 +162,53 @@ else()
|
||||||
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
|
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
|
||||||
if (WITH_HARDENING)
|
if(WITH_HARDENING)
|
||||||
add_definitions( "-D_FORTIFY_SOURCE=2" )
|
add_definitions("-D_FORTIFY_SOURCE=2")
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security")
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector --param ssp-buffer-size=4" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector --param ssp-buffer-size=4")
|
||||||
endif ()
|
endif()
|
||||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
# more tweaks
|
# more tweaks
|
||||||
if (LINUX)
|
if(LINUX)
|
||||||
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++" ) # required for <atomic>
|
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++") # required for <atomic>
|
||||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++
|
list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++
|
||||||
endif()
|
endif()
|
||||||
if (NOT (MSVC OR MSYS OR APPLE))
|
if(NOT APPLE)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions")
|
||||||
endif()
|
endif()
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (WITH_HARDENING AND MSVC)
|
# compiler flags customization(by system)
|
||||||
# Most security options like dynamic base, buffer & stack checks are ON by default
|
if(UNIX)
|
||||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /guard:cf" )
|
list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
||||||
endif ()
|
if(NOT(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE))
|
||||||
|
|
||||||
# compiler flags customization (by system)
|
|
||||||
if (UNIX)
|
|
||||||
list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
|
|
||||||
if (NOT (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE))
|
|
||||||
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
|
||||||
add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" )
|
add_definitions("-D_GLIBCXX_USE_NANOSLEEP=1")
|
||||||
endif ()
|
|
||||||
elseif (WIN32 OR MSYS)
|
|
||||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp")
|
|
||||||
if (WITH_GUI)
|
|
||||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Win32App.cpp")
|
|
||||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp"
|
|
||||||
PROPERTIES COMPILE_DEFINITIONS WIN32_APP)
|
|
||||||
endif ()
|
|
||||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Win32Service.cpp")
|
|
||||||
list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Resource.rc")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (WITH_AESNI)
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes" )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_AVX)
|
|
||||||
set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx" )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_ADDRSANITIZER)
|
|
||||||
if (NOT MSVC)
|
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer" )
|
|
||||||
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address" )
|
|
||||||
else ()
|
|
||||||
message( SEND_ERROR "MSVC does not support address sanitizer option")
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_THREADSANITIZER)
|
if(WITH_AESNI)
|
||||||
if (WITH_ADDRSANITIZER)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
||||||
message( FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer")
|
add_definitions(-DAESNI)
|
||||||
elseif (NOT MSVC)
|
endif()
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread" )
|
|
||||||
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread" )
|
if(WITH_AVX)
|
||||||
else ()
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
|
||||||
message( SEND_ERROR "MSVC does not support address sanitizer option")
|
endif()
|
||||||
|
|
||||||
|
if(WITH_ADDRSANITIZER)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WITH_THREADSANITIZER)
|
||||||
|
if(WITH_ADDRSANITIZER)
|
||||||
|
message(FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -253,63 +217,38 @@ endif()
|
||||||
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
|
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
|
||||||
# use imported Threads::Threads instead
|
# use imported Threads::Threads instead
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
if (IOS)
|
if(IOS)
|
||||||
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||||
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
||||||
set(CMAKE_USE_PTHREADS_INIT 1)
|
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
else()
|
else()
|
||||||
find_package ( Threads REQUIRED )
|
find_package(Threads REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
|
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_STATIC)
|
if(WITH_STATIC)
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
if (WIN32 AND NOT MSYS AND NOT MINGW)
|
|
||||||
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace
|
|
||||||
foreach(flag_var
|
|
||||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
|
||||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
|
||||||
if(${flag_var} MATCHES "/MD")
|
|
||||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
|
||||||
endif(${flag_var} MATCHES "/MD")
|
|
||||||
endforeach(flag_var)
|
|
||||||
else ()
|
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
|
|
||||||
endif ()
|
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
if (${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
# set( CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive" )
|
# set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
|
||||||
set( CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,-u,pthread_create,-u,pthread_once,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_join,-u,pthread_equal,-u,pthread_detach,-u,pthread_cond_wait,-u,pthread_cond_signal,-u,pthread_cond_destroy,-u,pthread_cond_broadcast,-u,pthread_cancel" )
|
set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,-u,pthread_create,-u,pthread_once,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_join,-u,pthread_equal,-u,pthread_detach,-u,pthread_cond_wait,-u,pthread_cond_signal,-u,pthread_cond_destroy,-u,pthread_cond_broadcast,-u,pthread_cancel")
|
||||||
endif ()
|
endif()
|
||||||
else()
|
else()
|
||||||
if (NOT WIN32 AND NOT MSYS)
|
|
||||||
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
|
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
|
||||||
# No need in -fPIC overhead for binary if not interested in library
|
# No need in -fPIC overhead for binary if not interested in library
|
||||||
# HINT: revert c266cff CMakeLists.txt: compilation speed up
|
# HINT: revert c266cff CMakeLists.txt: compilation speed up
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||||
endif ()
|
|
||||||
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
|
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (WITH_PCH)
|
if(WITH_PCH)
|
||||||
include_directories(BEFORE ${CMAKE_BINARY_DIR})
|
include_directories(BEFORE ${CMAKE_BINARY_DIR})
|
||||||
add_library(stdafx STATIC "${LIBI2PD_SRC_DIR}/stdafx.cpp")
|
add_library(stdafx STATIC "${LIBI2PD_SRC_DIR}/stdafx.cpp")
|
||||||
if(MSVC)
|
|
||||||
target_compile_options(stdafx PRIVATE /Ycstdafx.h /Zm155)
|
|
||||||
add_custom_command(TARGET stdafx POST_BUILD
|
|
||||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb libi2pd.dir\\$<CONFIG>\\
|
|
||||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb i2pdclient.dir\\$<CONFIG>\\
|
|
||||||
COMMAND xcopy /y stdafx.dir\\$<CONFIG>\\*.pdb i2pd.dir\\$<CONFIG>\\
|
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
||||||
)
|
|
||||||
target_compile_options(libi2pd PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
|
||||||
target_compile_options(libi2pdclient PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
|
||||||
else()
|
|
||||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
||||||
get_directory_property(DEFS DEFINITIONS)
|
get_directory_property(DEFS DEFINITIONS)
|
||||||
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
|
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
|
||||||
|
@ -318,76 +257,47 @@ if (WITH_PCH)
|
||||||
)
|
)
|
||||||
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
|
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
|
||||||
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
|
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
|
||||||
endif()
|
|
||||||
target_link_libraries(libi2pd stdafx)
|
target_link_libraries(libi2pd stdafx)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libi2pdclient libi2pd)
|
target_link_libraries(libi2pdclient libi2pd)
|
||||||
|
|
||||||
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
|
||||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||||
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package ( OpenSSL REQUIRED )
|
find_package(OpenSSL REQUIRED)
|
||||||
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
||||||
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_UPNP)
|
if(WITH_UPNP)
|
||||||
find_package ( MiniUPnPc REQUIRED )
|
find_package(MiniUPnPc REQUIRED)
|
||||||
include_directories( SYSTEM ${MINIUPNPC_INCLUDE_DIR} )
|
if(NOT MINIUPNPC_FOUND)
|
||||||
|
message(SEND_ERROR "Could not find MiniUPnPc. Please download and install it first!")
|
||||||
|
else()
|
||||||
|
include_directories(SYSTEM ${MINIUPNPC_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package ( ZLIB )
|
find_package(ZLIB)
|
||||||
if (NOT ZLIB_FOUND )
|
if(ZLIB_FOUND)
|
||||||
# We are probably on Windows
|
|
||||||
find_program( PATCH patch C:/Program Files/Git/usr/bin C:/msys64/usr/bin C:/msys32/usr/bin C:/Strawberry/c/bin )
|
|
||||||
include( ExternalProject )
|
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
set( ZLIB_EXTRA -DAMD64=ON )
|
|
||||||
else()
|
|
||||||
set( ZLIB_EXTRA -DASM686=ON "-DCMAKE_ASM_MASM_FLAGS=/W0 /safeseh" )
|
|
||||||
endif()
|
|
||||||
ExternalProject_Add(zlib-project
|
|
||||||
URL https://zlib.net/zlib-1.2.11.tar.gz
|
|
||||||
URL_HASH SHA256=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
|
||||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/zlib
|
|
||||||
PATCH_COMMAND "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-static.patch
|
|
||||||
&& "${PATCH}" -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/cmake-zlib-amd64.patch
|
|
||||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
|
||||||
-DWITH_STATIC=${WITH_STATIC} ${ZLIB_EXTRA}
|
|
||||||
)
|
|
||||||
if (WITH_PCH)
|
|
||||||
add_dependencies( stdafx zlib-project )
|
|
||||||
else ()
|
|
||||||
add_dependencies( libi2pd zlib-project )
|
|
||||||
endif ()
|
|
||||||
# ExternalProject_Get_Property(zlib-project install_dir)
|
|
||||||
set ( ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/zlib/include" CACHE FILEPATH "zlib include dir" FORCE)
|
|
||||||
if (NOT WITH_STATIC)
|
|
||||||
set ( ZLIB_LIBRARY debug zlibd optimized zlib CACHE STRING "zlib libraries" FORCE)
|
|
||||||
endif ()
|
|
||||||
link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib)
|
|
||||||
else()
|
|
||||||
link_directories(${ZLIB_ROOT}/lib)
|
link_directories(${ZLIB_ROOT}/lib)
|
||||||
endif ()
|
endif()
|
||||||
if (WITH_STATIC AND (MSVC OR MSYS))
|
|
||||||
set ( ZLIB_LIBRARY debug zlibstaticd optimized zlibstatic CACHE STRING "zlib libraries" FORCE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# load includes
|
# load includes
|
||||||
include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
|
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
# warn if for meshnet
|
# warn if for meshnet
|
||||||
if (WITH_MESHNET)
|
if(WITH_MESHNET)
|
||||||
message(STATUS "Building for testnet")
|
message(STATUS "Building for testnet")
|
||||||
message(WARNING "This build will NOT work on mainline i2p")
|
message(WARNING "This build will NOT work on mainline i2p")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CheckAtomic)
|
if(NOT MSYS)
|
||||||
|
include(CheckAtomic)
|
||||||
|
endif()
|
||||||
|
|
||||||
# show summary
|
# show summary
|
||||||
message(STATUS "---------------------------------------")
|
message(STATUS "---------------------------------------")
|
||||||
|
@ -414,32 +324,24 @@ message(STATUS "---------------------------------------")
|
||||||
#Handle paths nicely
|
#Handle paths nicely
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
if (WITH_BINARY)
|
if(WITH_BINARY)
|
||||||
add_executable ( "${PROJECT_NAME}" ${DAEMON_SRC} )
|
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
|
||||||
if (WIN32 AND WITH_GUI)
|
|
||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES WIN32_EXECUTABLE TRUE )
|
if(WITH_STATIC)
|
||||||
endif()
|
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
|
||||||
if(NOT MSVC)
|
|
||||||
if (WITH_STATIC)
|
|
||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static" )
|
|
||||||
endif ()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_PCH)
|
if(WITH_PCH)
|
||||||
if (MSVC)
|
|
||||||
target_compile_options("${PROJECT_NAME}" PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
|
||||||
else()
|
|
||||||
target_compile_options("${PROJECT_NAME}" PRIVATE -include libi2pd/stdafx.h)
|
target_compile_options("${PROJECT_NAME}" PRIVATE -include libi2pd/stdafx.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT MSYS AND NOT MINGW)
|
if(WITH_UPNP)
|
||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" )
|
set(UPNP_LIB ${MINIUPNPC_LIBRARY})
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (WITH_UPNP)
|
|
||||||
target_link_libraries("${PROJECT_NAME}" "${MINIUPNPC_LIBRARY}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
||||||
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
||||||
|
@ -447,128 +349,15 @@ if (WITH_BINARY)
|
||||||
list(REMOVE_AT Boost_LIBRARIES -1)
|
list(REMOVE_AT Boost_LIBRARIES -1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSYS OR MINGW)
|
|
||||||
set (MINGW_EXTRA -lws2_32 -lmswsock -liphlpapi )
|
if(WITH_STATIC)
|
||||||
endif ()
|
|
||||||
if (WITH_STATIC)
|
|
||||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
|
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
|
||||||
target_link_libraries( "${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
||||||
|
|
||||||
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
||||||
set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||||
set (DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin")
|
set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin")
|
||||||
if (MSVC)
|
|
||||||
install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}> DESTINATION ${CMAKE_INSTALL_BINDIR} CONFIGURATIONS DEBUG RELWITHDEBINFO COMPONENT Symbols)
|
|
||||||
# TODO Somehow this picks lots of unrelevant stuff with MSYS. OS X testing needed.
|
|
||||||
INSTALL(CODE "
|
|
||||||
include(BundleUtilities)
|
|
||||||
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
|
|
||||||
" COMPONENT Runtime)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
install(FILES ../LICENSE
|
|
||||||
DESTINATION .
|
|
||||||
COMPONENT Runtime
|
|
||||||
)
|
|
||||||
# Take a copy on Appveyor
|
|
||||||
install(FILES "C:/projects/openssl-$ENV{OPENSSL}/LICENSE"
|
|
||||||
DESTINATION .
|
|
||||||
COMPONENT Runtime
|
|
||||||
RENAME LICENSE_OPENSSL
|
|
||||||
OPTIONAL # for local builds only!
|
|
||||||
)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE I2PD_SOURCES "../libi2pd/*.cpp" "../libi2pd_client/*.cpp" "../daemon/*.cpp" "../build" "../Win32" "../Makefile*")
|
|
||||||
install(FILES ${I2PD_SOURCES} DESTINATION src/ COMPONENT Source)
|
|
||||||
# install(DIRECTORY ../ DESTINATION src/
|
|
||||||
# # OPTIONAL
|
|
||||||
# COMPONENT Source FILES_MATCHING
|
|
||||||
# PATTERN .git EXCLUDE
|
|
||||||
# PATTERN "*.cpp"
|
|
||||||
# )
|
|
||||||
|
|
||||||
file(GLOB I2PD_HEADERS "../libi2pd/*.h" "../libi2pd_client/*.h" "../daemon/*.h")
|
|
||||||
install(FILES ${I2PD_HEADERS} DESTINATION src/ COMPONENT Headers)
|
|
||||||
# install(DIRECTORY ../ DESTINATION src/
|
|
||||||
# # OPTIONAL
|
|
||||||
# COMPONENT Headers FILES_MATCHING
|
|
||||||
# PATTERN .git EXCLUDE
|
|
||||||
# PATTERN "*.h"
|
|
||||||
# )
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Purple I2P, a C++ I2P daemon")
|
|
||||||
set(CPACK_PACKAGE_VENDOR "Purple I2P")
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../README.md")
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE")
|
|
||||||
file(READ ../libi2pd/version.h version_h)
|
|
||||||
string(REGEX REPLACE ".*I2PD_VERSION_MAJOR ([0-9]+).*" "\\1" CPACK_PACKAGE_VERSION_MAJOR "${version_h}")
|
|
||||||
string(REGEX REPLACE ".*I2PD_VERSION_MINOR ([0-9]+).*" "\\1" CPACK_PACKAGE_VERSION_MINOR "${version_h}")
|
|
||||||
string(REGEX REPLACE ".*I2PD_VERSION_MICRO ([0-9]+).*" "\\1" CPACK_PACKAGE_VERSION_MICRO "${version_h}")
|
|
||||||
string(REGEX REPLACE ".*I2PD_VERSION_PATCH ([0-9]+).*" "\\1" CPACK_PACKAGE_VERSION_PATCH "${version_h}")
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Purple I2P")# ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
|
|
||||||
include(CPackComponent)
|
|
||||||
cpack_add_component(Runtime
|
|
||||||
DESCRIPTION "Main files"
|
|
||||||
REQUIRED INSTALL_TYPES minimal)
|
|
||||||
cpack_add_component(Symbols
|
|
||||||
DISPLAY_NAME "Debug symbols"
|
|
||||||
DESCRIPTION "Debug symbols for use with WinDbg or Visual Studio"
|
|
||||||
INSTALL_TYPES recommended full
|
|
||||||
)
|
|
||||||
cpack_add_component(Libraries
|
|
||||||
DESCRIPTION "Binary libraries for development"
|
|
||||||
INSTALL_TYPES full dev3rd
|
|
||||||
)
|
|
||||||
cpack_add_component(Source
|
|
||||||
DISPLAY_NAME "Source code"
|
|
||||||
DESCRIPTION "I2pd source code"
|
|
||||||
INSTALL_TYPES full
|
|
||||||
)
|
|
||||||
cpack_add_component(Headers
|
|
||||||
DISPLAY_NAME "Header files"
|
|
||||||
DESCRIPTION "I2pd header files for development"
|
|
||||||
INSTALL_TYPES full dev3rd
|
|
||||||
)
|
|
||||||
install(FILES ${MINIUPNPC_INCLUDE_DIR}/miniupnpc/miniupnpc.dll
|
|
||||||
DESTINATION bin
|
|
||||||
COMPONENT MiniUPnPc
|
|
||||||
OPTIONAL
|
|
||||||
)
|
|
||||||
install(FILES ${MINIUPNPC_INCLUDE_DIR}/miniupnpc/LICENSE
|
|
||||||
DESTINATION .
|
|
||||||
COMPONENT MiniUPnPc
|
|
||||||
RENAME LICENSE_MINIUPNPC
|
|
||||||
OPTIONAL
|
|
||||||
)
|
|
||||||
cpack_add_component(MiniUPnPc
|
|
||||||
INSTALL_TYPES full recommended
|
|
||||||
# DOWNLOADED
|
|
||||||
# ARCHIVE_FILE miniupnpc-win32.zip
|
|
||||||
)
|
|
||||||
cpack_add_install_type(recommended DISPLAY_NAME Recommended)
|
|
||||||
cpack_add_install_type(dev3rd DISPLAY_NAME "Third party development")
|
|
||||||
cpack_add_install_type(full DISPLAY_NAME Full)
|
|
||||||
cpack_add_install_type(minimal DISPLAY_NAME Minimal)
|
|
||||||
if((WIN32 OR MSYS) AND NOT UNIX)
|
|
||||||
# There is a bug in NSI that does not handle full unix paths properly. Make
|
|
||||||
# sure there is at least one set of four (4) backlasshes.
|
|
||||||
set(CPACK_NSIS_DEFINES "RequestExecutionLevel user")
|
|
||||||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/../Win32\\\\mask.bmp")
|
|
||||||
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin/i2pd.exe")
|
|
||||||
SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
|
|
||||||
set(CPACK_NSIS_HELP_LINK "https:\\\\\\\\github.com\\\\PurpleI2P\\\\i2pd\\\\issues")
|
|
||||||
set(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\github.com\\\\PurpleI2P\\\\i2pd")
|
|
||||||
set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Install i2pd as windows service.lnk' '$INSTDIR\\\\bin\\\\i2pd.exe' '--service=install'
|
|
||||||
CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Remove i2pd windows service.lnk' '$INSTDIR\\\\bin\\\\i2pd.exe' '--service=remove'")
|
|
||||||
set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\\\$START_MENU\\\\Install i2pd as windows service.lnk'
|
|
||||||
Delete '$SMPROGRAMS\\\\$START_MENU\\\\Remove i2pd windows service.lnk'")
|
|
||||||
else()
|
|
||||||
set(CPACK_STRIP_FILES "bin/i2pd")
|
|
||||||
set(CPACK_SOURCE_STRIP_FILES "")
|
|
||||||
endif()
|
endif()
|
||||||
set(CPACK_PACKAGE_EXECUTABLES "i2pd" "C++ I2P daemon")
|
|
||||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
|
||||||
include(CPack)
|
|
||||||
|
|
10
build/appveyor-msys2-upgrade.bash
Normal file
10
build/appveyor-msys2-upgrade.bash
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
set -e -x
|
||||||
|
|
||||||
|
base_url='http://repo.msys2.org/msys/x86_64/'
|
||||||
|
packages="libzstd-1.4.4-2-x86_64.pkg.tar.xz pacman-5.2.1-6-x86_64.pkg.tar.xz zstd-1.4.4-2-x86_64.pkg.tar.xz"
|
||||||
|
for p in $packages
|
||||||
|
do
|
||||||
|
curl "${base_url}$p" -o "$p"
|
||||||
|
done
|
||||||
|
pacman -U --noconfirm $packages
|
||||||
|
rm -f $packages
|
|
@ -1,10 +0,0 @@
|
||||||
--- CMakeLists.txt.orig 2015-12-07 14:19:36.447689600 -0600
|
|
||||||
+++ CMakeLists.txt 2015-12-07 14:18:23.004419900 -0600
|
|
||||||
@@ -165,6 +165,7 @@
|
|
||||||
ENABLE_LANGUAGE(ASM_MASM)
|
|
||||||
set(ZLIB_ASMS
|
|
||||||
contrib/masmx64/gvmat64.asm
|
|
||||||
+ contrib/masmx64/inffas8664.c
|
|
||||||
contrib/masmx64/inffasx64.asm
|
|
||||||
)
|
|
||||||
endif()
|
|
|
@ -1,28 +0,0 @@
|
||||||
--- CMakeLists.txt.orig 2013-04-28 17:57:10.000000000 -0500
|
|
||||||
+++ CMakeLists.txt 2015-12-03 12:53:52.371087900 -0600
|
|
||||||
@@ -7,6 +7,7 @@
|
|
||||||
|
|
||||||
option(ASM686 "Enable building i686 assembly implementation")
|
|
||||||
option(AMD64 "Enable building amd64 assembly implementation")
|
|
||||||
+option(WITH_STATIC "Static runtime on Windows" OFF)
|
|
||||||
|
|
||||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
|
||||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
|
||||||
@@ -66,6 +67,17 @@
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
+if(WITH_STATIC AND (MSVC OR MSYS))
|
|
||||||
+ # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace
|
|
||||||
+ foreach(flag_var
|
|
||||||
+ CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
|
||||||
+ CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
|
|
||||||
+ if(${flag_var} MATCHES "/MD")
|
|
||||||
+ string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
|
||||||
+ endif(${flag_var} MATCHES "/MD")
|
|
||||||
+ endforeach(flag_var)
|
|
||||||
+endif()
|
|
||||||
+
|
|
||||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
|
||||||
# If we're doing an out of source build and the user has a zconf.h
|
|
||||||
# in their source tree...
|
|
|
@ -19,6 +19,7 @@
|
||||||
/etc/nsswitch.conf r,
|
/etc/nsswitch.conf r,
|
||||||
/etc/resolv.conf r,
|
/etc/resolv.conf r,
|
||||||
/run/resolvconf/resolv.conf r,
|
/run/resolvconf/resolv.conf r,
|
||||||
|
/run/systemd/resolve/resolv.conf r,
|
||||||
/run/systemd/resolve/stub-resolv.conf r,
|
/run/systemd/resolve/stub-resolv.conf r,
|
||||||
|
|
||||||
# path specific (feel free to modify if you have another paths)
|
# path specific (feel free to modify if you have another paths)
|
||||||
|
|
34
contrib/certificates/reseed/hankhill19580_at_gmail.com.crt
Normal file
34
contrib/certificates/reseed/hankhill19580_at_gmail.com.crt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIF3TCCA8WgAwIBAgIRAKye34BRrKyQN6kMVPHddykwDQYJKoZIhvcNAQELBQAw
|
||||||
|
dzELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
|
||||||
|
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxIDAeBgNVBAMM
|
||||||
|
F2hhbmtoaWxsMTk1ODBAZ21haWwuY29tMB4XDTIwMDUwNzA1MDkxMFoXDTMwMDUw
|
||||||
|
NzA1MDkxMFowdzELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJY
|
||||||
|
WDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAx
|
||||||
|
IDAeBgNVBAMMF2hhbmtoaWxsMTk1ODBAZ21haWwuY29tMIICIjANBgkqhkiG9w0B
|
||||||
|
AQEFAAOCAg8AMIICCgKCAgEA5Vt7c0SeUdVkcXXEYe3M9LmCTUyiCv/PHF2Puys6
|
||||||
|
8luLH8lO0U/pQ4j703kFKK7s4rV65jVpGNncjHWbfSCNevvs6VcbAFoo7oJX7Yjt
|
||||||
|
5+Z4oU1g7JG86feTwU6pzfFjAs0RO2lNq2L8AyLYKWOnPsVrmuGYl2c6N5WDzTxA
|
||||||
|
Et66IudfGsppTv7oZkgX6VNUMioV8tCjBTLaPCkSfyYKBX7r6ByHY86PflhFgYES
|
||||||
|
zIB92Ma75YFtCB0ktCM+o6d7wmnt10Iy4I6craZ+z7szCDRF73jhf3Vk7vGzb2cN
|
||||||
|
aCfr2riwlRJBaKrLJP5m0dGf5RdhviMgxc6JAgkN7Ius5lkxO/p3OSy5co0DrMJ7
|
||||||
|
lvwdZ2hu0dnO75unTt6ImR4RQ90Sqj7MUdorKR/8FcYEo+twBV8cV3s9kjuO5jxV
|
||||||
|
g976Q+GD3zDoixiege3W5UT4ff/Anm4mJpE5PKbNuO+KUjk6WA4B1PeudkEcxkO4
|
||||||
|
tQYy0aBzfjeyENee9otd4TgN1epY4wlHIORCa3HUFmFZd9VZMQcxwv7c47wl2kc9
|
||||||
|
Cv1L6Nae78wRzRu2CHD8zWhq+tv5q7Md2eRd3mFPI09ljsOgG2TQv6300WvHvI5M
|
||||||
|
enNdjYjLqOTRCzUJ2Jst4BZsvDxjWYkHsSZc1UORzm2LQmh2bJvbhC3m81qANGw6
|
||||||
|
ZhcCAwEAAaNkMGIwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMC
|
||||||
|
BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCAGA1UdDgQZBBdoYW5raGlsbDE5
|
||||||
|
NTgwQGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAVtMF7lrgkDLTNXlavI7h
|
||||||
|
HJqFxFHjmxPk3iu2Qrgwk302Gowqg5NjVVamT20cXeuJaUa6maTTHzDyyCai3+3e
|
||||||
|
roaosGxZQRpRf5/RBz2yhdEPLZBV9IqxGgIxvCWNqNIYB1SNk00rwC4q5heW1me0
|
||||||
|
EsOK4Mw5IbS2jUjbi9E5th781QDj91elwltghxwtDvpE2vzAJwmxwwBhjySGsKfq
|
||||||
|
w8SBZOxN+Ih5/IIpDnYGNoN1LSkJnBVGSkjY6OpstuJRIPYWl5zX5tJtYdaxiD+8
|
||||||
|
qNbFHBIZ5WrktMopJ3QJJxHdERyK6BFYYSzX/a1gO7woOFCkx8qMCsVzfcE/z1pp
|
||||||
|
JxJvshT32hnrKZ6MbZMd9JpTFclQ62RV5tNs3FPP3sbDsFtKBUtj87SW7XsimHbZ
|
||||||
|
OrWlPacSnQDbOoV5TfDDCqWi4PW2EqzDsDcg+Lc8EnBRIquWcAox2+4zmcQI29wO
|
||||||
|
C1TUpMT5o/wGyL/i9pf6GuTbH0D+aYukULropgSrK57EALbuvqnN3vh5l2QlX/rM
|
||||||
|
+7lCKsGCNLiJFXb0m6l/B9CC1947XVEbpMEAC/80Shwxl/UB+mKFpJxcNLFtPXzv
|
||||||
|
FYv2ixarBPbJx/FclOO8G91QC4ZhAKbsVZn5HPMSgtZe+xWM1r0/UJVChsMTafpd
|
||||||
|
CCOJyu3XtyzFf+tAeixOnuQ=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -1,2 +1,2 @@
|
||||||
d /var/run/i2pd 0755 i2pd i2pd - -
|
d /run/i2pd 0755 i2pd i2pd - -
|
||||||
d /var/log/i2pd 0755 i2pd i2pd - -
|
d /var/log/i2pd 0755 i2pd i2pd - -
|
||||||
|
|
|
@ -36,9 +36,9 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib
|
||||||
&& cd /usr/local/bin \
|
&& cd /usr/local/bin \
|
||||||
&& strip i2pd \
|
&& strip i2pd \
|
||||||
&& rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \
|
&& rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \
|
||||||
boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \
|
boost-python3 python3 gdbm boost-unit_test_framework boost-python2 linux-headers boost-prg_exec_monitor \
|
||||||
boost-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \
|
boost-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre2 \
|
||||||
libtool g++ gcc pkgconfig
|
libtool g++ gcc
|
||||||
|
|
||||||
# 2. Adding required libraries to run i2pd to ensure it will run.
|
# 2. Adding required libraries to run i2pd to ensure it will run.
|
||||||
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++
|
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
## Tunnels config files path
|
## Tunnels config files path
|
||||||
## Use that path to store separated tunnels in different config files.
|
## Use that path to store separated tunnels in different config files.
|
||||||
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
|
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
|
||||||
# tunnelsdir = /var/lib/i2pd/tunnels.conf.d
|
# tunnelsdir = /var/lib/i2pd/tunnels.d
|
||||||
|
|
||||||
## Where to write pidfile (don't write by default)
|
## Where to write pidfile (default: i2pd.pid, not used in Windows)
|
||||||
# pidfile = /var/run/i2pd.pid
|
# pidfile = /run/i2pd.pid
|
||||||
|
|
||||||
## Logging configuration section
|
## Logging configuration section
|
||||||
## By default logs go to stdout with level 'info' and higher
|
## By default logs go to stdout with level 'info' and higher
|
||||||
|
@ -27,10 +27,10 @@
|
||||||
## * syslog - use syslog, see man 3 syslog
|
## * syslog - use syslog, see man 3 syslog
|
||||||
# log = file
|
# log = file
|
||||||
## Path to logfile (default - autodetect)
|
## Path to logfile (default - autodetect)
|
||||||
# logfile = /var/log/i2pd.log
|
# logfile = /var/log/i2pd/i2pd.log
|
||||||
## Log messages above this level (debug, *info, warn, error, none)
|
## Log messages above this level (debug, info, *warn, error, none)
|
||||||
## If you set it to none, logging will be disabled
|
## If you set it to none, logging will be disabled
|
||||||
# loglevel = info
|
# loglevel = warn
|
||||||
## Write full CLF-formatted date and time to log (default: write only time)
|
## Write full CLF-formatted date and time to log (default: write only time)
|
||||||
# logclftime = true
|
# logclftime = true
|
||||||
|
|
||||||
|
|
9
contrib/i2pd.logrotate
Normal file
9
contrib/i2pd.logrotate
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
"/var/log/i2pd/*.log" {
|
||||||
|
copytruncate
|
||||||
|
daily
|
||||||
|
rotate 5
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
}
|
|
@ -11,9 +11,9 @@ RuntimeDirectoryMode=0700
|
||||||
LogsDirectory=i2pd
|
LogsDirectory=i2pd
|
||||||
LogsDirectoryMode=0700
|
LogsDirectoryMode=0700
|
||||||
Type=forking
|
Type=forking
|
||||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/sh -c "kill -HUP $MAINPID"
|
||||||
PIDFile=/var/run/i2pd/i2pd.pid
|
PIDFile=/run/i2pd/i2pd.pid
|
||||||
### Uncomment, if auto restart needed
|
### Uncomment, if auto restart needed
|
||||||
#Restart=on-failure
|
#Restart=on-failure
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ KillSignal=SIGQUIT
|
||||||
LimitNOFILE=4096
|
LimitNOFILE=4096
|
||||||
# To enable write of coredump uncomment this
|
# To enable write of coredump uncomment this
|
||||||
#LimitCORE=infinity
|
#LimitCORE=infinity
|
||||||
PrivateDevices=yes
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||||
|
|
||||||
Name: i2pd-git
|
Name: i2pd-git
|
||||||
Version: 2.30.0
|
Version: 2.32.0
|
||||||
Release: git%{git_hash}%{?dist}
|
Release: git%{git_hash}%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd
|
Conflicts: i2pd
|
||||||
|
@ -24,6 +24,7 @@ BuildRequires: openssl-devel
|
||||||
BuildRequires: miniupnpc-devel
|
BuildRequires: miniupnpc-devel
|
||||||
BuildRequires: systemd-units
|
BuildRequires: systemd-units
|
||||||
|
|
||||||
|
Requires: logrotate
|
||||||
Requires: systemd
|
Requires: systemd
|
||||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||||
|
|
||||||
|
@ -73,16 +74,17 @@ pushd build
|
||||||
|
|
||||||
chrpath -d i2pd
|
chrpath -d i2pd
|
||||||
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||||
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||||
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
|
||||||
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
|
||||||
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.d/README %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d/README
|
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
|
||||||
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name}
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
||||||
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||||
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,16 +110,30 @@ getent passwd i2pd >/dev/null || \
|
||||||
%files
|
%files
|
||||||
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
|
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
|
||||||
%{_sbindir}/i2pd
|
%{_sbindir}/i2pd
|
||||||
%config(noreplace) %{_sysconfdir}/i2pd/*
|
%config(noreplace) %{_sysconfdir}/i2pd/*.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*.conf
|
||||||
|
%config %{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
|
%doc %{_sysconfdir}/i2pd/tunnels.conf.d/README
|
||||||
|
%{_sysconfdir}/logrotate.d/i2pd
|
||||||
%{_unitdir}/i2pd.service
|
%{_unitdir}/i2pd.service
|
||||||
%{_mandir}/man1/i2pd.1*
|
%{_mandir}/man1/i2pd.1*
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||||
%{_datadir}/%{name}/certificates
|
%{_datadir}/i2pd/certificates
|
||||||
%{_sharedstatedir}/i2pd/certificates
|
%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon May 25 2020 r4sas <r4sas@i2pmail.org> - 2.32.0
|
||||||
|
- update to 2.32.0
|
||||||
|
- updated systemd service file (#1394)
|
||||||
|
|
||||||
|
* Thu May 7 2020 Anatolii Vorona <vorona.tolik@gmail.com> - 2.31.0-3
|
||||||
|
- added RPM logrotate config
|
||||||
|
|
||||||
|
* Fri Apr 10 2020 orignal <i2porignal@yandex.ru> - 2.31.0
|
||||||
|
- update to 2.31.0
|
||||||
|
|
||||||
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
|
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
|
||||||
- update to 2.30.0
|
- update to 2.30.0
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../i2pd.service
|
|
|
@ -1,6 +1,6 @@
|
||||||
Name: i2pd
|
Name: i2pd
|
||||||
Version: 2.30.0
|
Version: 2.32.0
|
||||||
Release: 1%{?dist}
|
Release: 2%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd-git
|
Conflicts: i2pd-git
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ BuildRequires: openssl-devel
|
||||||
BuildRequires: miniupnpc-devel
|
BuildRequires: miniupnpc-devel
|
||||||
BuildRequires: systemd-units
|
BuildRequires: systemd-units
|
||||||
|
|
||||||
|
Requires: logrotate
|
||||||
Requires: systemd
|
Requires: systemd
|
||||||
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||||
|
|
||||||
|
@ -70,18 +71,19 @@ pushd build
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
chrpath -d i2pd
|
chrpath -d i2pd
|
||||||
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||||
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
|
||||||
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
|
||||||
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
|
||||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||||
ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
|
||||||
|
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
|
@ -104,18 +106,32 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%doc LICENSE README.md
|
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
|
||||||
%{_sbindir}/i2pd
|
%{_sbindir}/i2pd
|
||||||
%{_datadir}/i2pd/certificates
|
%config(noreplace) %{_sysconfdir}/i2pd/*.conf
|
||||||
%config(noreplace) %{_sysconfdir}/i2pd/*
|
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*.conf
|
||||||
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
|
%config %{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
/%{_unitdir}/i2pd.service
|
%doc %{_sysconfdir}/i2pd/tunnels.conf.d/README
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
%{_sysconfdir}/logrotate.d/i2pd
|
||||||
|
%{_unitdir}/i2pd.service
|
||||||
|
%{_mandir}/man1/i2pd.1*
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||||
|
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||||
|
%{_datadir}/i2pd/certificates
|
||||||
%{_sharedstatedir}/i2pd/certificates
|
%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon May 25 2020 r4sas <r4sas@i2pmail.org> - 2.32.0
|
||||||
|
- update to 2.32.0
|
||||||
|
- updated systemd service file (#1394)
|
||||||
|
|
||||||
|
* Thu May 7 2020 Anatolii Vorona <vorona.tolik@gmail.com> - 2.31.0-3
|
||||||
|
- added RPM logrotate config
|
||||||
|
|
||||||
|
* Fri Apr 10 2020 orignal <i2porignal@yandex.ru> - 2.31.0
|
||||||
|
- update to 2.31.0
|
||||||
|
|
||||||
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
|
* Tue Feb 25 2020 orignal <i2porignal@yandex.ru> - 2.30.0
|
||||||
- update to 2.30.0
|
- update to 2.30.0
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <thread>
|
#include <thread>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -71,20 +79,15 @@ namespace i2p
|
||||||
i2p::fs::Init();
|
i2p::fs::Init();
|
||||||
|
|
||||||
datadir = i2p::fs::GetDataDir();
|
datadir = i2p::fs::GetDataDir();
|
||||||
// TODO: drop old name detection in v2.8.0
|
|
||||||
if (config == "")
|
if (config == "")
|
||||||
{
|
{
|
||||||
config = i2p::fs::DataDirPath("i2p.conf");
|
|
||||||
if (i2p::fs::Exists (config)) {
|
|
||||||
LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config);
|
|
||||||
} else {
|
|
||||||
config = i2p::fs::DataDirPath("i2pd.conf");
|
config = i2p::fs::DataDirPath("i2pd.conf");
|
||||||
if (!i2p::fs::Exists (config)) {
|
if (!i2p::fs::Exists (config)) {
|
||||||
// use i2pd.conf only if exists
|
// use i2pd.conf only if exists
|
||||||
config = ""; /* reset */
|
config = ""; /* reset */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
i2p::config::ParseConfig(config);
|
i2p::config::ParseConfig(config);
|
||||||
i2p::config::Finalize();
|
i2p::config::Finalize();
|
||||||
|
@ -177,10 +180,13 @@ namespace i2p
|
||||||
SetMaxNumTransitTunnels (transitTunnels);
|
SetMaxNumTransitTunnels (transitTunnels);
|
||||||
|
|
||||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||||
if (isFloodfill) {
|
if (isFloodfill)
|
||||||
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||||
i2p::context.SetFloodfill (true);
|
i2p::context.SetFloodfill (true);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
i2p::context.SetFloodfill (false);
|
i2p::context.SetFloodfill (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +254,8 @@ namespace i2p
|
||||||
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
||||||
restricted = fams.size() > 0;
|
restricted = fams.size() > 0;
|
||||||
}
|
}
|
||||||
if (routers.length() > 0) {
|
if (routers.length() > 0)
|
||||||
|
{
|
||||||
std::set<i2p::data::IdentHash> idents;
|
std::set<i2p::data::IdentHash> idents;
|
||||||
size_t pos = 0, comma;
|
size_t pos = 0, comma;
|
||||||
do
|
do
|
||||||
|
@ -265,7 +272,7 @@ namespace i2p
|
||||||
restricted = idents.size() > 0;
|
restricted = idents.size() > 0;
|
||||||
}
|
}
|
||||||
if(!restricted)
|
if(!restricted)
|
||||||
LogPrint(eLogError, "Daemon: no trusted routers of families specififed");
|
LogPrint(eLogError, "Daemon: no trusted routers of families specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
|
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
|
||||||
|
@ -284,7 +291,8 @@ namespace i2p
|
||||||
i2p::data::netdb.Start();
|
i2p::data::netdb.Start();
|
||||||
|
|
||||||
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
||||||
if (upnp) {
|
if (upnp)
|
||||||
|
{
|
||||||
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
||||||
d.UPnP->Start ();
|
d.UPnP->Start ();
|
||||||
}
|
}
|
||||||
|
@ -315,14 +323,22 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http; i2p::config::GetOption("http.enabled", http);
|
bool http; i2p::config::GetOption("http.enabled", http);
|
||||||
if (http) {
|
if (http)
|
||||||
|
{
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
|
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
||||||
|
try
|
||||||
|
{
|
||||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||||
d.httpServer->Start();
|
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");
|
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||||
i2p::tunnel::tunnels.Start();
|
i2p::tunnel::tunnels.Start();
|
||||||
|
@ -336,9 +352,17 @@ namespace i2p
|
||||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||||
|
try
|
||||||
|
{
|
||||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||||
d.m_I2PControlService->Start ();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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_H__
|
#ifndef DAEMON_H__
|
||||||
#define DAEMON_H__
|
#define DAEMON_H__
|
||||||
|
|
||||||
|
@ -13,6 +21,7 @@ namespace util
|
||||||
class Daemon_Singleton
|
class Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||||
virtual bool init(int argc, char* argv[]);
|
virtual bool init(int argc, char* argv[]);
|
||||||
virtual bool start();
|
virtual bool start();
|
||||||
|
@ -23,6 +32,7 @@ namespace util
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Daemon_Singleton();
|
Daemon_Singleton();
|
||||||
virtual ~Daemon_Singleton();
|
virtual ~Daemon_Singleton();
|
||||||
|
|
||||||
|
@ -39,6 +49,7 @@ namespace util
|
||||||
class DaemonQT: public i2p::util::Daemon_Singleton
|
class DaemonQT: public i2p::util::Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonQT& Instance()
|
static DaemonQT& Instance()
|
||||||
{
|
{
|
||||||
static DaemonQT instance;
|
static DaemonQT instance;
|
||||||
|
@ -51,6 +62,7 @@ namespace util
|
||||||
class DaemonWin32 : public Daemon_Singleton
|
class DaemonWin32 : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonWin32& Instance()
|
static DaemonWin32& Instance()
|
||||||
{
|
{
|
||||||
static DaemonWin32 instance;
|
static DaemonWin32 instance;
|
||||||
|
@ -72,6 +84,7 @@ namespace util
|
||||||
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonAndroid& Instance()
|
static DaemonAndroid& Instance()
|
||||||
{
|
{
|
||||||
static DaemonAndroid instance;
|
static DaemonAndroid instance;
|
||||||
|
@ -83,6 +96,7 @@ namespace util
|
||||||
class DaemonLinux : public Daemon_Singleton
|
class DaemonLinux : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonLinux& Instance()
|
static DaemonLinux& Instance()
|
||||||
{
|
{
|
||||||
static DaemonLinux instance;
|
static DaemonLinux instance;
|
||||||
|
@ -94,10 +108,12 @@ namespace util
|
||||||
void run ();
|
void run ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string pidfile;
|
std::string pidfile;
|
||||||
int pidFH;
|
int pidFH;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int gracefulShutdownInterval; // in seconds
|
int gracefulShutdownInterval; // in seconds
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -22,6 +30,7 @@
|
||||||
#include "HTTPServer.h"
|
#include "HTTPServer.h"
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "ECIESX25519AEADRatchetSession.h"
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
#include "Win32/Win32App.h"
|
#include "Win32/Win32App.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,7 +63,7 @@ namespace http {
|
||||||
" body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n"
|
" body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n"
|
||||||
" a, .slide label { text-decoration: none; color: #894C84; }\r\n"
|
" a, .slide label { text-decoration: none; color: #894C84; }\r\n"
|
||||||
" a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n"
|
" a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n"
|
||||||
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial; width: 1.5em;}\r\n"
|
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none; color: initial; padding: 0 5px; }\r\n"
|
||||||
" .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n"
|
" .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n"
|
||||||
" .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n"
|
" .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n"
|
||||||
" .left { float: left; position: absolute; }\r\n"
|
" .left { float: left; position: absolute; }\r\n"
|
||||||
|
@ -93,6 +102,7 @@ namespace http {
|
||||||
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
|
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
|
||||||
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
|
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
|
||||||
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
|
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
|
||||||
|
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
|
||||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||||
|
|
||||||
|
@ -397,18 +407,36 @@ namespace http {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
|
|
||||||
|
s << "<b>Tags</b><br>\r\nIncoming: <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
|
||||||
if (!dest->GetSessions ().empty ()) {
|
if (!dest->GetSessions ().empty ()) {
|
||||||
std::stringstream tmp_s; uint32_t out_tags = 0;
|
std::stringstream tmp_s; uint32_t out_tags = 0;
|
||||||
for (const auto& it: dest->GetSessions ()) {
|
for (const auto& it: dest->GetSessions ()) {
|
||||||
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
|
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
|
||||||
out_tags = out_tags + it.second->GetNumOutgoingTags ();
|
out_tags += it.second->GetNumOutgoingTags ();
|
||||||
}
|
}
|
||||||
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n"
|
s << "<div class='slide'><label for='slide-tags'>Outgoing: <i>" << out_tags << "</i></label>\r\n<input type='checkbox' id='slide-tags'/>\r\n"
|
||||||
<< "<div class='content'>\r\n<table><tbody><thead><th>Destination</th><th>Amount</th></thead>\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
<< "<div class='content'>\r\n<table><tbody><thead><th>Destination</th><th>Amount</th></thead>\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||||
} else
|
} else
|
||||||
s << "Outgoing: <i>0</i><br>\r\n";
|
s << "Outgoing: <i>0</i><br>\r\n";
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
|
|
||||||
|
auto numECIESx25519Tags = dest->GetNumIncomingECIESx25519Tags ();
|
||||||
|
if (numECIESx25519Tags > 0) {
|
||||||
|
s << "<b>ECIESx25519</b><br>\r\nIncoming Tags: <i>" << numECIESx25519Tags << "</i><br>\r\n";
|
||||||
|
if (!dest->GetECIESx25519Sessions ().empty ())
|
||||||
|
{
|
||||||
|
std::stringstream tmp_s; uint32_t ecies_sessions = 0;
|
||||||
|
for (const auto& it: dest->GetECIESx25519Sessions ()) {
|
||||||
|
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "</td><td>" << it.second->GetState () << "</td></tr>\r\n";
|
||||||
|
ecies_sessions++;
|
||||||
|
}
|
||||||
|
s << "<div class='slide'><label for='slide-ecies-sessions'>Tags sessions: <i>" << ecies_sessions << "</i></label>\r\n<input type='checkbox' id='slide-ecies-sessions'/>\r\n"
|
||||||
|
<< "<div class='content'>\r\n<table><tbody><thead><th>Destination</th><th>Status</th></thead>\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
|
||||||
|
} else
|
||||||
|
s << "Tags sessions: <i>0</i><br>\r\n";
|
||||||
|
s << "<br>\r\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token)
|
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token)
|
||||||
|
@ -580,14 +608,25 @@ namespace http {
|
||||||
else
|
else
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
|
||||||
#endif
|
#endif
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n<br>\r\n";
|
||||||
|
|
||||||
s << "<br>\r\n<b>Logging level</b><br>\r\n";
|
s << "<small><b>Note:</b> any action done here are not persistent and not changes your config files.</small>\r\n<br>\r\n";
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
|
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
|
s << "<b>Logging level</b><br>\r\n";
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
|
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
|
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
|
||||||
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
|
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
|
||||||
|
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
|
||||||
|
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
|
||||||
|
|
||||||
|
uint16_t maxTunnels = GetMaxNumTransitTunnels ();
|
||||||
|
s << "<b>Transit tunnels limit</b><br>\r\n";
|
||||||
|
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
|
||||||
|
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
|
||||||
|
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
|
||||||
|
s << " <input type=\"number\" min=\"0\" max=\"65535\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
|
||||||
|
s << " <button type=\"submit\">Change</button>\r\n";
|
||||||
|
s << "</form>\r\n<br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTransitTunnels (std::stringstream& s)
|
void ShowTransitTunnels (std::stringstream& s)
|
||||||
|
@ -1125,6 +1164,19 @@ namespace http {
|
||||||
res.add_header("Refresh", redirect.c_str());
|
res.add_header("Refresh", redirect.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (cmd == HTTP_COMMAND_LIMITTRANSIT)
|
||||||
|
{
|
||||||
|
uint32_t limit = std::stoul(params["limit"], nullptr);
|
||||||
|
if (limit > 0 && limit <= 65535)
|
||||||
|
SetMaxNumTransitTunnels (limit);
|
||||||
|
else {
|
||||||
|
s << "<b>ERROR</b>: Transit tunnels count must not exceed 65535<br><br>\r\n";
|
||||||
|
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a><br>\r\n";
|
||||||
|
s << "<p>You will be redirected back in 5 seconds</b>";
|
||||||
|
res.add_header("Refresh", redirect.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res.code = 400;
|
res.code = 400;
|
||||||
|
@ -1182,8 +1234,9 @@ namespace http {
|
||||||
i2p::config::SetOption("http.pass", pass);
|
i2p::config::SetOption("http.pass", pass);
|
||||||
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
|
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = std::unique_ptr<std::thread>(new std::thread (std::bind (&HTTPServer::Run, this)));
|
m_Thread.reset (new std::thread (std::bind (&HTTPServer::Run, this)));
|
||||||
m_Acceptor.listen ();
|
m_Acceptor.listen ();
|
||||||
Accept ();
|
Accept ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 HTTP_SERVER_H__
|
#ifndef HTTP_SERVER_H__
|
||||||
#define HTTP_SERVER_H__
|
#define HTTP_SERVER_H__
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
@ -80,8 +88,7 @@ namespace client
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||||
&I2PControlService::TunnelsSuccessRateHandler;
|
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 I2P_CONTROL_H__
|
#ifndef I2P_CONTROL_H__
|
||||||
#define I2P_CONTROL_H__
|
#define I2P_CONTROL_H__
|
||||||
|
|
||||||
|
@ -27,6 +35,7 @@ namespace client
|
||||||
class I2PControlService
|
class I2PControlService
|
||||||
{
|
{
|
||||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PControlService (const std::string& address, int port);
|
I2PControlService (const std::string& address, int port);
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef USE_UPNP
|
#ifdef USE_UPNP
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -110,7 +118,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||||
m_upnpUrlsInitialized=err!=0;
|
m_upnpUrlsInitialized = err != 0;
|
||||||
if (err == UPNP_IGD_VALID_CONNECTED)
|
if (err == UPNP_IGD_VALID_CONNECTED)
|
||||||
{
|
{
|
||||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 __UPNP_H__
|
#ifndef __UPNP_H__
|
||||||
#define __UPNP_H__
|
#define __UPNP_H__
|
||||||
|
|
||||||
|
@ -60,7 +68,7 @@ namespace transport
|
||||||
std::mutex m_StartedMutex;
|
std::mutex m_StartedMutex;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::deadline_timer m_Timer;
|
boost::asio::deadline_timer m_Timer;
|
||||||
bool m_upnpUrlsInitialized=false;
|
bool m_upnpUrlsInitialized = false;
|
||||||
struct UPNPUrls m_upnpUrls;
|
struct UPNPUrls m_upnpUrls;
|
||||||
struct IGDdatas m_upnpData;
|
struct IGDdatas m_upnpData;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -175,7 +183,6 @@ namespace i2p
|
||||||
bool DaemonLinux::stop()
|
bool DaemonLinux::stop()
|
||||||
{
|
{
|
||||||
i2p::fs::Remove(pidfile);
|
i2p::fs::Remove(pidfile);
|
||||||
|
|
||||||
return Daemon_Singleton::stop();
|
return Daemon_Singleton::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,5 +204,4 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
||||||
#if defined(QT_GUI_LIB)
|
#if defined(QT_GUI_LIB)
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace qt
|
namespace qt
|
||||||
|
@ -10,11 +17,11 @@ namespace qt
|
||||||
int RunQT (int argc, char* argv[]);
|
int RunQT (int argc, char* argv[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
return i2p::qt::RunQT (argc, argv);
|
return i2p::qt::RunQT (argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
|
|
15
debian/changelog
vendored
15
debian/changelog
vendored
|
@ -1,3 +1,18 @@
|
||||||
|
i2pd (2.32.0-1) unstable; urgency=high
|
||||||
|
|
||||||
|
* updated to version 2.32.0/0.9.46
|
||||||
|
* updated systemd service file (see #1394)
|
||||||
|
* updated apparmor profile (see 9318388007cff0495b4b360d0480f4fc1219a9dc)
|
||||||
|
* updated logrotate config and moved it to contrib
|
||||||
|
|
||||||
|
-- r4sas <r4sas@i2pmail.org> Mon, 25 May 2020 12:45:00 +0000
|
||||||
|
|
||||||
|
i2pd (2.31.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.31.0
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Fri, 10 Apr 2020 16:00:00 +0000
|
||||||
|
|
||||||
i2pd (2.30.0-1) unstable; urgency=medium
|
i2pd (2.30.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* updated to version 2.30.0/0.9.45
|
* updated to version 2.30.0/0.9.45
|
||||||
|
|
6
debian/copyright
vendored
6
debian/copyright
vendored
|
@ -3,7 +3,7 @@ Upstream-Name: i2pd
|
||||||
Source: https://github.com/PurpleI2P
|
Source: https://github.com/PurpleI2P
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: 2013-2017 PurpleI2P
|
Copyright: 2013-2020 PurpleI2P
|
||||||
License: BSD-3-clause
|
License: BSD-3-clause
|
||||||
|
|
||||||
Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl
|
Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl
|
||||||
|
@ -16,8 +16,8 @@ License: BSD-2-Clause
|
||||||
Files: debian/*
|
Files: debian/*
|
||||||
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
|
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
|
||||||
2014-2016 hagen <hagen@i2pmail.org>
|
2014-2016 hagen <hagen@i2pmail.org>
|
||||||
2016-2017 R4SAS <r4sas@i2pmail.org>
|
2016-2020 R4SAS <r4sas@i2pmail.org>
|
||||||
2017-2018 Yangfl <mmyangfl@gmail.com>
|
2017-2020 Yangfl <mmyangfl@gmail.com>
|
||||||
License: GPL-2+
|
License: GPL-2+
|
||||||
|
|
||||||
License: BSD-3-clause
|
License: BSD-3-clause
|
||||||
|
|
9
debian/i2pd.logrotate
vendored
9
debian/i2pd.logrotate
vendored
|
@ -1,9 +0,0 @@
|
||||||
/var/log/i2pd/i2pd.log {
|
|
||||||
rotate 6
|
|
||||||
daily
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
compress
|
|
||||||
delaycompress
|
|
||||||
copytruncate
|
|
||||||
}
|
|
1
debian/i2pd.logrotate
vendored
Symbolic link
1
debian/i2pd.logrotate
vendored
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../contrib/i2pd.logrotate
|
14
debian/patches/01-tune-build-opts.patch
vendored
14
debian/patches/01-tune-build-opts.patch
vendored
|
@ -1,17 +1,15 @@
|
||||||
diff --git a/Makefile b/Makefile
|
Index: i2pd/Makefile
|
||||||
index bdadfe0..2f71eec 100644
|
===================================================================
|
||||||
--- a/Makefile
|
--- i2pd.orig/Makefile
|
||||||
+++ b/Makefile
|
+++ i2pd/Makefile
|
||||||
@@ -9,10 +9,10 @@ DEPS := obj/make.dep
|
@@ -13,8 +13,8 @@ DAEMON_SRC_DIR := daemon
|
||||||
|
|
||||||
include filelist.mk
|
include filelist.mk
|
||||||
|
|
||||||
-USE_AESNI := yes
|
-USE_AESNI := yes
|
||||||
+USE_AESNI := no
|
|
||||||
-USE_AVX := yes
|
-USE_AVX := yes
|
||||||
|
+USE_AESNI := no
|
||||||
+USE_AVX := no
|
+USE_AVX := no
|
||||||
USE_STATIC := no
|
USE_STATIC := no
|
||||||
USE_MESHNET := no
|
USE_MESHNET := no
|
||||||
USE_UPNP := no
|
USE_UPNP := no
|
||||||
DEBUG := yes
|
|
||||||
|
|
||||||
|
|
12
debian/patches/02-fix-1210.patch
vendored
12
debian/patches/02-fix-1210.patch
vendored
|
@ -4,10 +4,12 @@ Author: r4sas <r4sas@i2pmail.org>
|
||||||
|
|
||||||
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
|
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
|
||||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||||
Last-Update: 2018-08-25
|
Last-Update: 2020-05-25
|
||||||
|
|
||||||
--- a/contrib/i2pd.service
|
Index: i2pd/contrib/i2pd.service
|
||||||
+++ b/contrib/i2pd.service
|
===================================================================
|
||||||
|
--- i2pd.orig/contrib/i2pd.service
|
||||||
|
+++ i2pd/contrib/i2pd.service
|
||||||
@@ -6,10 +6,10 @@ After=network.target
|
@@ -6,10 +6,10 @@ After=network.target
|
||||||
[Service]
|
[Service]
|
||||||
User=i2pd
|
User=i2pd
|
||||||
|
@ -21,5 +23,5 @@ Last-Update: 2018-08-25
|
||||||
+#LogsDirectory=i2pd
|
+#LogsDirectory=i2pd
|
||||||
+#LogsDirectoryMode=0700
|
+#LogsDirectoryMode=0700
|
||||||
Type=forking
|
Type=forking
|
||||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/sh -c "kill -HUP $MAINPID"
|
||||||
|
|
2
debian/postrm
vendored
2
debian/postrm
vendored
|
@ -6,7 +6,7 @@ if [ "$1" = "purge" ]; then
|
||||||
rm -rf /etc/i2pd
|
rm -rf /etc/i2pd
|
||||||
rm -rf /var/lib/i2pd
|
rm -rf /var/lib/i2pd
|
||||||
rm -rf /var/log/i2pd
|
rm -rf /var/log/i2pd
|
||||||
rm -rf /var/run/i2pd
|
rm -rf /run/i2pd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#DEBHELPER#
|
#DEBHELPER#
|
||||||
|
|
104
libi2pd/Base.cpp
104
libi2pd/Base.cpp
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -7,7 +15,8 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
static const char T32[32] = {
|
static const char T32[32] =
|
||||||
|
{
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
||||||
|
@ -29,7 +38,8 @@ namespace data
|
||||||
* Direct Substitution Table
|
* Direct Substitution Table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char T64[64] = {
|
static const char T64[64] =
|
||||||
|
{
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||||
|
@ -67,14 +77,12 @@ namespace data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t /* Number of bytes in the encoded buffer */
|
size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */
|
||||||
ByteStreamToBase64 (
|
|
||||||
const uint8_t * InBuffer, /* Input buffer, binary data */
|
const uint8_t * InBuffer, /* Input buffer, binary data */
|
||||||
size_t InCount, /* Number of bytes in the input buffer */
|
size_t InCount, /* Number of bytes in the input buffer */
|
||||||
char * OutBuffer, /* output buffer */
|
char * OutBuffer, /* output buffer */
|
||||||
size_t len /* length of output buffer */
|
size_t len /* length of output buffer */
|
||||||
)
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned char * ps;
|
unsigned char * ps;
|
||||||
unsigned char * pd;
|
unsigned char * pd;
|
||||||
|
@ -86,33 +94,37 @@ namespace data
|
||||||
size_t outCount;
|
size_t outCount;
|
||||||
|
|
||||||
ps = (unsigned char *)InBuffer;
|
ps = (unsigned char *)InBuffer;
|
||||||
n = InCount/3;
|
n = InCount / 3;
|
||||||
m = InCount%3;
|
m = InCount % 3;
|
||||||
if (!m)
|
if (!m)
|
||||||
outCount = 4*n;
|
outCount = 4 * n;
|
||||||
else
|
else
|
||||||
outCount = 4*(n+1);
|
outCount = 4 * (n + 1);
|
||||||
|
|
||||||
if (outCount > len) return 0;
|
if (outCount > len) return 0;
|
||||||
|
|
||||||
pd = (unsigned char *)OutBuffer;
|
pd = (unsigned char *)OutBuffer;
|
||||||
for ( i = 0; i<n; i++ ){
|
for ( i = 0; i < n; i++ )
|
||||||
|
{
|
||||||
acc_1 = *ps++;
|
acc_1 = *ps++;
|
||||||
acc_2 = (acc_1<<4)&0x30;
|
acc_2 = (acc_1 << 4) & 0x30;
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
*pd++ = T64[acc_1];
|
*pd++ = T64[acc_1];
|
||||||
acc_1 = *ps++;
|
acc_1 = *ps++;
|
||||||
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
||||||
*pd++ = T64[acc_2];
|
*pd++ = T64[acc_2];
|
||||||
acc_1 &= 0x0f;
|
acc_1 &= 0x0f;
|
||||||
acc_1 <<=2;
|
acc_1 <<= 2;
|
||||||
acc_2 = *ps++;
|
acc_2 = *ps++;
|
||||||
acc_1 |= acc_2>>6; /* base64 digit #3 */
|
acc_1 |= acc_2 >> 6; /* base64 digit #3 */
|
||||||
*pd++ = T64[acc_1];
|
*pd++ = T64[acc_1];
|
||||||
acc_2 &= 0x3f; /* base64 digit #4 */
|
acc_2 &= 0x3f; /* base64 digit #4 */
|
||||||
*pd++ = T64[acc_2];
|
*pd++ = T64[acc_2];
|
||||||
}
|
}
|
||||||
if ( m == 1 ){
|
if ( m == 1 )
|
||||||
|
{
|
||||||
acc_1 = *ps++;
|
acc_1 = *ps++;
|
||||||
acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */
|
acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
*pd++ = T64[acc_1];
|
*pd++ = T64[acc_1];
|
||||||
*pd++ = T64[acc_2];
|
*pd++ = T64[acc_2];
|
||||||
|
@ -120,16 +132,17 @@ namespace data
|
||||||
*pd++ = P64;
|
*pd++ = P64;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( m == 2 ){
|
else if ( m == 2 )
|
||||||
|
{
|
||||||
acc_1 = *ps++;
|
acc_1 = *ps++;
|
||||||
acc_2 = (acc_1<<4)&0x3f;
|
acc_2 = (acc_1 << 4) & 0x3f;
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
*pd++ = T64[acc_1];
|
*pd++ = T64[acc_1];
|
||||||
acc_1 = *ps++;
|
acc_1 = *ps++;
|
||||||
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
||||||
*pd++ = T64[acc_2];
|
*pd++ = T64[acc_2];
|
||||||
acc_1 &= 0x0f;
|
acc_1 &= 0x0f;
|
||||||
acc_1 <<=2; /* base64 digit #3 */
|
acc_1 <<= 2; /* base64 digit #3 */
|
||||||
*pd++ = T64[acc_1];
|
*pd++ = T64[acc_1];
|
||||||
*pd++ = P64;
|
*pd++ = P64;
|
||||||
}
|
}
|
||||||
|
@ -147,8 +160,7 @@ namespace data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t /* Number of output bytes */
|
size_t Base64ToByteStream ( /* Number of output bytes */
|
||||||
Base64ToByteStream (
|
|
||||||
const char * InBuffer, /* BASE64 encoded buffer */
|
const char * InBuffer, /* BASE64 encoded buffer */
|
||||||
size_t InCount, /* Number of input bytes */
|
size_t InCount, /* Number of input bytes */
|
||||||
uint8_t * OutBuffer, /* output buffer length */
|
uint8_t * OutBuffer, /* output buffer length */
|
||||||
|
@ -164,36 +176,46 @@ namespace data
|
||||||
int m;
|
int m;
|
||||||
size_t outCount;
|
size_t outCount;
|
||||||
|
|
||||||
if (isFirstTime) iT64Build();
|
if (isFirstTime)
|
||||||
n = InCount/4;
|
iT64Build();
|
||||||
m = InCount%4;
|
|
||||||
|
n = InCount / 4;
|
||||||
|
m = InCount % 4;
|
||||||
|
|
||||||
if (InCount && !m)
|
if (InCount && !m)
|
||||||
outCount = 3*n;
|
outCount = 3 * n;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
outCount = 0;
|
outCount = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps = (unsigned char *)(InBuffer + InCount - 1);
|
ps = (unsigned char *)(InBuffer + InCount - 1);
|
||||||
while ( *ps-- == P64 ) outCount--;
|
while ( *ps-- == P64 )
|
||||||
|
outCount--;
|
||||||
ps = (unsigned char *)InBuffer;
|
ps = (unsigned char *)InBuffer;
|
||||||
|
|
||||||
if (outCount > len) return -1;
|
if (outCount > len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
pd = OutBuffer;
|
pd = OutBuffer;
|
||||||
auto endOfOutBuffer = OutBuffer + outCount;
|
auto endOfOutBuffer = OutBuffer + outCount;
|
||||||
for ( i = 0; i < n; i++ ){
|
for ( i = 0; i < n; i++ )
|
||||||
|
{
|
||||||
acc_1 = iT64[*ps++];
|
acc_1 = iT64[*ps++];
|
||||||
acc_2 = iT64[*ps++];
|
acc_2 = iT64[*ps++];
|
||||||
acc_1 <<= 2;
|
acc_1 <<= 2;
|
||||||
acc_1 |= acc_2>>4;
|
acc_1 |= acc_2 >> 4;
|
||||||
*pd++ = acc_1;
|
*pd++ = acc_1;
|
||||||
if (pd >= endOfOutBuffer) break;
|
if (pd >= endOfOutBuffer)
|
||||||
|
break;
|
||||||
|
|
||||||
acc_2 <<= 4;
|
acc_2 <<= 4;
|
||||||
acc_1 = iT64[*ps++];
|
acc_1 = iT64[*ps++];
|
||||||
acc_2 |= acc_1 >> 2;
|
acc_2 |= acc_1 >> 2;
|
||||||
*pd++ = acc_2;
|
*pd++ = acc_2;
|
||||||
if (pd >= endOfOutBuffer) break;
|
if (pd >= endOfOutBuffer)
|
||||||
|
break;
|
||||||
|
|
||||||
acc_2 = iT64[*ps++];
|
acc_2 = iT64[*ps++];
|
||||||
acc_2 |= acc_1 << 6;
|
acc_2 |= acc_1 << 6;
|
||||||
|
@ -206,20 +228,25 @@ namespace data
|
||||||
size_t Base64EncodingBufferSize (const size_t input_size)
|
size_t Base64EncodingBufferSize (const size_t input_size)
|
||||||
{
|
{
|
||||||
auto d = div (input_size, 3);
|
auto d = div (input_size, 3);
|
||||||
if (d.rem) d.quot++;
|
if (d.rem)
|
||||||
return 4*d.quot;
|
d.quot++;
|
||||||
|
|
||||||
|
return 4 * d.quot;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToBase64Standard (const std::string& in)
|
std::string ToBase64Standard (const std::string& in)
|
||||||
{
|
{
|
||||||
auto len = Base64EncodingBufferSize (in.length ());
|
auto len = Base64EncodingBufferSize (in.length ());
|
||||||
char * str = new char[len+1];
|
char * str = new char[len + 1];
|
||||||
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
|
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
|
||||||
str[l] = 0;
|
str[l] = 0;
|
||||||
// replace '-' by '+' and '~' by '/'
|
// replace '-' by '+' and '~' by '/'
|
||||||
for (size_t i = 0; i < l; i++)
|
for (size_t i = 0; i < l; i++)
|
||||||
if (str[i] == '-') str[i] = '+';
|
if (str[i] == '-')
|
||||||
else if (str[i] == '~') str[i] = '/';
|
str[i] = '+';
|
||||||
|
else if (str[i] == '~')
|
||||||
|
str[i] = '/';
|
||||||
|
|
||||||
std::string s(str);
|
std::string s(str);
|
||||||
delete[] str;
|
delete[] str;
|
||||||
return s;
|
return s;
|
||||||
|
@ -238,8 +265,8 @@ namespace data
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
isFirstTime = 0;
|
isFirstTime = 0;
|
||||||
for ( i=0; i<256; i++ ) iT64[i] = -1;
|
for ( i = 0; i < 256; i++ ) iT64[i] = -1;
|
||||||
for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
|
for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i;
|
||||||
iT64[(int)P64] = 0;
|
iT64[(int)P64] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,4 +329,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 BASE_H__
|
#ifndef BASE_H__
|
||||||
#define BASE_H__
|
#define BASE_H__
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <zlib.h> // for crc32
|
#include <zlib.h> // for crc32
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include <openssl/hmac.h>
|
#include <openssl/hmac.h>
|
||||||
|
@ -314,4 +322,3 @@ namespace data
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 BLINDING_H__
|
#ifndef BLINDING_H__
|
||||||
#define BLINDING_H__
|
#define BLINDING_H__
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 "BloomFilter.h"
|
#include "BloomFilter.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 BLOOM_FILTER_H_
|
#ifndef BLOOM_FILTER_H_
|
||||||
#define BLOOM_FILTER_H_
|
#define BLOOM_FILTER_H_
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 "CPU.h"
|
#include "CPU.h"
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 LIBI2PD_CPU_H
|
#ifndef LIBI2PD_CPU_H
|
||||||
#define LIBI2PD_CPU_H
|
#define LIBI2PD_CPU_H
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2018, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -78,7 +78,6 @@ void block (Chacha20State &input, int rounds)
|
||||||
}
|
}
|
||||||
x += input;
|
x += input;
|
||||||
input.block << x;
|
input.block << x;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
@ -130,9 +129,9 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chacha
|
} // namespace chacha
|
||||||
|
} // namespace crypto
|
||||||
|
} // namespace i2p
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2018, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -64,9 +64,9 @@ namespace chacha
|
||||||
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
||||||
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
|
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
|
||||||
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
|
||||||
}
|
} // namespace chacha
|
||||||
}
|
} // namespace crypto
|
||||||
}
|
} // namespace i2p
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2017, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,7 @@ namespace config {
|
||||||
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
|
||||||
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
|
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
|
||||||
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
|
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
|
||||||
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error, none)")
|
("loglevel", value<std::string>()->default_value("warn"), "Set the minimal level of log messages (debug, info, warn, error, none)")
|
||||||
("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)")
|
("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)")
|
||||||
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
|
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
|
||||||
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
|
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
|
||||||
|
@ -97,7 +97,8 @@ namespace config {
|
||||||
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
||||||
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
||||||
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
||||||
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
||||||
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
||||||
|
@ -106,6 +107,8 @@ namespace config {
|
||||||
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
|
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
|
||||||
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
|
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
|
||||||
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
|
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
|
||||||
|
("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("1"), "Local destination's LeaseSet type")
|
||||||
|
("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0"), "Local destination's LeaseSet encryption type")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description socksproxy("SOCKS Proxy options");
|
options_description socksproxy("SOCKS Proxy options");
|
||||||
|
@ -114,7 +117,8 @@ namespace config {
|
||||||
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
||||||
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
||||||
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->
|
||||||
|
default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||||
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
||||||
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
||||||
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
||||||
|
@ -124,6 +128,8 @@ namespace config {
|
||||||
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
|
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
|
||||||
("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
|
("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
|
||||||
("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
|
("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
|
||||||
|
("socksproxy.i2cp.leaseSetType", value<std::string>()->default_value("1"), "Local destination's LeaseSet type")
|
||||||
|
("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0"), "Local destination's LeaseSet encryption type")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description sam("SAM bridge options");
|
options_description sam("SAM bridge options");
|
||||||
|
@ -190,15 +196,12 @@ namespace config {
|
||||||
("reseed.urls", value<std::string>()->default_value(
|
("reseed.urls", value<std::string>()->default_value(
|
||||||
"https://reseed.i2p-projekt.de/,"
|
"https://reseed.i2p-projekt.de/,"
|
||||||
"https://i2p.mooo.com/netDb/,"
|
"https://i2p.mooo.com/netDb/,"
|
||||||
"https://netdb.i2p2.no/,"
|
|
||||||
"https://reseed.i2p2.no/,"
|
"https://reseed.i2p2.no/,"
|
||||||
"https://reseed2.i2p2.no/,"
|
|
||||||
// "https://us.reseed.i2p2.no:444/," // mamoth's shit
|
|
||||||
// "https://uk.reseed.i2p2.no:444/," // mamoth's shit
|
|
||||||
"https://reseed-fr.i2pd.xyz/,"
|
"https://reseed-fr.i2pd.xyz/,"
|
||||||
"https://reseed.memcpy.io/,"
|
"https://reseed.memcpy.io/,"
|
||||||
"https://reseed.onion.im/,"
|
"https://reseed.onion.im/,"
|
||||||
"https://i2pseed.creativecowpat.net:8443/,"
|
"https://i2pseed.creativecowpat.net:8443/,"
|
||||||
|
"https://reseed.i2pgit.org/,"
|
||||||
"https://i2p.novg.net/"
|
"https://i2p.novg.net/"
|
||||||
), "Reseed URLs, separated by comma")
|
), "Reseed URLs, separated by comma")
|
||||||
;
|
;
|
||||||
|
@ -218,6 +221,14 @@ namespace config {
|
||||||
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
|
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
// Save deprecated websocket options for compatibility
|
||||||
|
options_description websocket("Websocket Options");
|
||||||
|
websocket.add_options()
|
||||||
|
("websockets.enabled", value<bool>()->default_value(false), "Deprecated option")
|
||||||
|
("websockets.address", value<std::string>()->default_value(""), "Deprecated option")
|
||||||
|
("websockets.port", value<uint16_t>()->default_value(0), "Deprecated option")
|
||||||
|
;
|
||||||
|
|
||||||
options_description exploratory("Exploratory Options");
|
options_description exploratory("Exploratory Options");
|
||||||
exploratory.add_options()
|
exploratory.add_options()
|
||||||
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
|
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
|
||||||
|
@ -268,6 +279,7 @@ namespace config {
|
||||||
.add(reseed)
|
.add(reseed)
|
||||||
.add(addressbook)
|
.add(addressbook)
|
||||||
.add(trust)
|
.add(trust)
|
||||||
|
.add(websocket) // deprecated
|
||||||
.add(exploratory)
|
.add(exploratory)
|
||||||
.add(ntcp2)
|
.add(ntcp2)
|
||||||
.add(nettime)
|
.add(nettime)
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
|
@ -63,7 +71,8 @@ namespace config {
|
||||||
*/
|
*/
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
/* @brief Accessor to parameters by name
|
/**
|
||||||
|
* @brief Accessor to parameters by name
|
||||||
* @param name Name of the requested parameter
|
* @param name Name of the requested parameter
|
||||||
* @param value Variable where to store option
|
* @param value Variable where to store option
|
||||||
* @return this function returns false if parameter not found
|
* @return this function returns false if parameter not found
|
||||||
|
@ -71,7 +80,8 @@ namespace config {
|
||||||
* Example: uint16_t port; GetOption("sam.port", port);
|
* Example: uint16_t port; GetOption("sam.port", port);
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool GetOption(const char *name, T& value) {
|
bool GetOption(const char *name, T& value)
|
||||||
|
{
|
||||||
if (!m_Options.count(name))
|
if (!m_Options.count(name))
|
||||||
return false;
|
return false;
|
||||||
value = m_Options[name].as<T>();
|
value = m_Options[name].as<T>();
|
||||||
|
@ -96,7 +106,8 @@ namespace config {
|
||||||
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool SetOption(const char *name, const T& value) {
|
bool SetOption(const char *name, const T& value)
|
||||||
|
{
|
||||||
if (!m_Options.count(name))
|
if (!m_Options.count(name))
|
||||||
return false;
|
return false;
|
||||||
m_Options.at(name).value() = value;
|
m_Options.at(name).value() = value;
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -884,7 +892,6 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
#ifdef __AES__
|
#ifdef __AES__
|
||||||
|
@ -1364,4 +1371,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 CRYPTO_H__
|
#ifndef CRYPTO_H__
|
||||||
#define CRYPTO_H__
|
#define CRYPTO_H__
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Gost.h"
|
#include "Gost.h"
|
||||||
|
@ -178,4 +186,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 CRYPTO_KEY_H__
|
#ifndef CRYPTO_KEY_H__
|
||||||
#define CRYPTO_KEY_H__
|
#define CRYPTO_KEY_H__
|
||||||
|
|
||||||
|
@ -153,4 +161,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 CRYPTO_WORKER_H_
|
#ifndef CRYPTO_WORKER_H_
|
||||||
#define CRYPTO_WORKER_H_
|
#define CRYPTO_WORKER_H_
|
||||||
|
|
||||||
|
@ -77,5 +85,4 @@ namespace worker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "TunnelBase.h"
|
#include "TunnelBase.h"
|
||||||
|
@ -11,9 +18,13 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace datagram
|
namespace datagram
|
||||||
{
|
{
|
||||||
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner):
|
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
|
||||||
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr)
|
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
|
||||||
{
|
{
|
||||||
|
auto identityLen = m_Owner->GetIdentity ()->GetFullLen ();
|
||||||
|
m_From.resize (identityLen);
|
||||||
|
m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen);
|
||||||
|
m_Signature.resize (m_Owner->GetIdentity ()->GetSignatureLen ());
|
||||||
}
|
}
|
||||||
|
|
||||||
DatagramDestination::~DatagramDestination ()
|
DatagramDestination::~DatagramDestination ()
|
||||||
|
@ -23,35 +34,25 @@ namespace datagram
|
||||||
|
|
||||||
void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
|
void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
|
||||||
{
|
{
|
||||||
auto owner = m_Owner;
|
if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
|
||||||
std::vector<uint8_t> v(MAX_DATAGRAM_SIZE);
|
|
||||||
uint8_t * buf = v.data();
|
|
||||||
auto localIdentity = m_Owner->GetIdentity ();
|
|
||||||
auto identityLen = localIdentity->ToBuffer (buf, MAX_DATAGRAM_SIZE);
|
|
||||||
uint8_t * signature = buf + identityLen;
|
|
||||||
auto signatureLen = localIdentity->GetSignatureLen ();
|
|
||||||
uint8_t * buf1 = signature + signatureLen;
|
|
||||||
size_t headerLen = identityLen + signatureLen;
|
|
||||||
|
|
||||||
memcpy (buf1, payload, len);
|
|
||||||
if (localIdentity->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
|
|
||||||
{
|
{
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
SHA256(buf1, len, hash);
|
SHA256(payload, len, hash);
|
||||||
owner->Sign (hash, 32, signature);
|
m_Owner->Sign (hash, 32, m_Signature.data ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
owner->Sign (buf1, len, signature);
|
m_Owner->Sign (payload, len, m_Signature.data ());
|
||||||
|
|
||||||
auto msg = CreateDataMessage (buf, len + headerLen, fromPort, toPort);
|
|
||||||
auto session = ObtainSession(identity);
|
auto session = ObtainSession(identity);
|
||||||
|
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);
|
session->SendMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
|
void DatagramDestination::SendRawDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort)
|
||||||
{
|
{
|
||||||
auto msg = CreateDataMessage (payload, len, fromPort, toPort, true); // raw
|
|
||||||
auto session = ObtainSession(identity);
|
auto session = ObtainSession(identity);
|
||||||
|
auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw
|
||||||
session->SendMsg(msg);
|
session->SendMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,13 +122,15 @@ namespace datagram
|
||||||
LogPrint (eLogWarning, "Datagram: decompression failed");
|
LogPrint (eLogWarning, "Datagram: decompression failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
|
||||||
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw)
|
const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
||||||
|
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
|
||||||
{
|
{
|
||||||
auto msg = NewI2NPMessage ();
|
auto msg = NewI2NPMessage ();
|
||||||
uint8_t * buf = msg->GetPayload ();
|
uint8_t * buf = msg->GetPayload ();
|
||||||
buf += 4; // reserve for length
|
buf += 4; // reserve for length
|
||||||
size_t size = m_Deflator.Deflate (payload, len, buf, msg->maxLen - msg->len);
|
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
|
||||||
|
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
htobe32buf (msg->GetPayload (), size); // length
|
htobe32buf (msg->GetPayload (), size); // length
|
||||||
|
@ -135,7 +138,7 @@ namespace datagram
|
||||||
htobe16buf (buf + 6, toPort); // destination port
|
htobe16buf (buf + 6, toPort); // destination port
|
||||||
buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol
|
buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol
|
||||||
msg->len += size + 4;
|
msg->len += size + 4;
|
||||||
msg->FillI2NPMessageHeader (eI2NPData);
|
msg->FillI2NPMessageHeader (eI2NPData, 0, checksum);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
msg = nullptr;
|
msg = nullptr;
|
||||||
|
@ -247,11 +250,14 @@ namespace datagram
|
||||||
auto path = GetSharedRoutingPath();
|
auto path = GetSharedRoutingPath();
|
||||||
if(path)
|
if(path)
|
||||||
path->updateTime = i2p::util::GetSecondsSinceEpoch ();
|
path->updateTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
if (IsRatchets ())
|
||||||
|
SendMsg (nullptr); // send empty message in case if we have some data to send
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetSharedRoutingPath ()
|
std::shared_ptr<i2p::garlic::GarlicRoutingPath> DatagramSession::GetSharedRoutingPath ()
|
||||||
{
|
{
|
||||||
if(!m_RoutingSession) {
|
if (!m_RoutingSession || !m_RoutingSession->GetOwner ())
|
||||||
|
{
|
||||||
if(!m_RemoteLeaseSet) {
|
if(!m_RemoteLeaseSet) {
|
||||||
m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
|
m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
|
||||||
}
|
}
|
||||||
|
@ -352,6 +358,7 @@ namespace datagram
|
||||||
|
|
||||||
void DatagramSession::HandleSend(std::shared_ptr<I2NPMessage> msg)
|
void DatagramSession::HandleSend(std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
|
if (msg || m_SendQueue.empty ())
|
||||||
m_SendQueue.push_back(msg);
|
m_SendQueue.push_back(msg);
|
||||||
// flush queue right away if full
|
// flush queue right away if full
|
||||||
if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue();
|
if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue();
|
||||||
|
@ -359,7 +366,6 @@ namespace datagram
|
||||||
|
|
||||||
void DatagramSession::FlushSendQueue ()
|
void DatagramSession::FlushSendQueue ()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<i2p::tunnel::TunnelMessageBlock> send;
|
std::vector<i2p::tunnel::TunnelMessageBlock> send;
|
||||||
auto routingPath = GetSharedRoutingPath();
|
auto routingPath = GetSharedRoutingPath();
|
||||||
// if we don't have a routing path we will drop all queued messages
|
// if we don't have a routing path we will drop all queued messages
|
||||||
|
@ -368,6 +374,7 @@ namespace datagram
|
||||||
for (const auto & msg : m_SendQueue)
|
for (const auto & msg : m_SendQueue)
|
||||||
{
|
{
|
||||||
auto m = m_RoutingSession->WrapSingleMessage(msg);
|
auto m = m_RoutingSession->WrapSingleMessage(msg);
|
||||||
|
if (m)
|
||||||
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
|
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
|
||||||
}
|
}
|
||||||
routingPath->outboundTunnel->SendTunnelDataMsg(send);
|
routingPath->outboundTunnel->SendTunnelDataMsg(send);
|
||||||
|
@ -385,4 +392,3 @@ namespace datagram
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 DATAGRAM_H__
|
#ifndef DATAGRAM_H__
|
||||||
#define DATAGRAM_H__
|
#define DATAGRAM_H__
|
||||||
|
|
||||||
|
@ -5,6 +13,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
|
@ -36,7 +45,9 @@ namespace datagram
|
||||||
|
|
||||||
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
|
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
|
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
|
@ -51,6 +62,8 @@ namespace datagram
|
||||||
/** get the last time in milliseconds for when we used this datagram session */
|
/** get the last time in milliseconds for when we used this datagram session */
|
||||||
uint64_t LastActivity() const { return m_LastUse; }
|
uint64_t LastActivity() const { return m_LastUse; }
|
||||||
|
|
||||||
|
bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
|
||||||
|
|
||||||
struct Info
|
struct Info
|
||||||
{
|
{
|
||||||
std::shared_ptr<const i2p::data::IdentHash> IBGW;
|
std::shared_ptr<const i2p::data::IdentHash> IBGW;
|
||||||
|
@ -81,6 +94,7 @@ namespace datagram
|
||||||
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
|
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
|
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
|
||||||
i2p::data::IdentHash m_RemoteIdent;
|
i2p::data::IdentHash m_RemoteIdent;
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
||||||
|
@ -101,11 +115,9 @@ namespace datagram
|
||||||
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
|
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
|
||||||
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
|
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
|
||||||
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
|
|
||||||
~DatagramDestination ();
|
~DatagramDestination ();
|
||||||
|
|
||||||
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
||||||
|
@ -130,7 +142,8 @@ namespace datagram
|
||||||
|
|
||||||
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
|
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw = false);
|
std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
||||||
|
uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true);
|
||||||
|
|
||||||
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
|
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
|
||||||
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||||
|
@ -143,6 +156,7 @@ namespace datagram
|
||||||
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
|
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
|
||||||
Receiver m_Receiver; // default
|
Receiver m_Receiver; // default
|
||||||
RawReceiver m_RawReceiver; // default
|
RawReceiver m_RawReceiver; // default
|
||||||
|
bool m_Gzip; // gzip compression of data messages
|
||||||
std::mutex m_SessionsMutex;
|
std::mutex m_SessionsMutex;
|
||||||
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
|
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
|
||||||
std::mutex m_ReceiversMutex;
|
std::mutex m_ReceiversMutex;
|
||||||
|
@ -150,6 +164,7 @@ namespace datagram
|
||||||
|
|
||||||
i2p::data::GzipInflator m_Inflator;
|
i2p::data::GzipInflator m_Inflator;
|
||||||
i2p::data::GzipDeflator m_Deflator;
|
i2p::data::GzipDeflator m_Deflator;
|
||||||
|
std::vector<uint8_t> m_From, m_Signature;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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 <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
|
@ -157,7 +168,6 @@ namespace client
|
||||||
|
|
||||||
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
||||||
if (itr != params.end())
|
if (itr != params.end())
|
||||||
{
|
{
|
||||||
|
@ -412,7 +422,8 @@ namespace client
|
||||||
auto it2 = m_LeaseSetRequests.find (key);
|
auto it2 = m_LeaseSetRequests.find (key);
|
||||||
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
|
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
|
||||||
{
|
{
|
||||||
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr, GetPreferredCryptoType ());
|
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
|
||||||
|
it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
|
||||||
if (ls2->IsValid ())
|
if (ls2->IsValid ())
|
||||||
{
|
{
|
||||||
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
|
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
|
||||||
|
@ -824,8 +835,8 @@ namespace client
|
||||||
|
|
||||||
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
|
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
|
||||||
{
|
{
|
||||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
|
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET;
|
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,23 +850,53 @@ namespace client
|
||||||
if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
|
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
|
||||||
|
|
||||||
m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType ();
|
|
||||||
// extract encryption type params for LS2
|
// extract encryption type params for LS2
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 && params)
|
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
||||||
|
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
||||||
|
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
||||||
{
|
{
|
||||||
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
m_EncryptionKeyType = std::stoi(it->second);
|
{
|
||||||
|
// comma-separated values
|
||||||
|
std::vector<std::string> values;
|
||||||
|
boost::split(values, it->second, boost::is_any_of(","));
|
||||||
|
for (auto& it1: values)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
encryptionKeyTypes.insert (std::stoi(it1));
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "Destination: Unexpected crypto type ", it1, ". ", ex.what ());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if no param or valid crypto type use from identity
|
||||||
|
bool isSingleKey = false;
|
||||||
|
if (encryptionKeyTypes.empty ())
|
||||||
|
{
|
||||||
|
isSingleKey = true;
|
||||||
|
encryptionKeyTypes.insert (GetIdentity ()->GetCryptoKeyType ());
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (m_EncryptionPrivateKey, 0, 256);
|
for (auto& it: encryptionKeyTypes)
|
||||||
memset (m_EncryptionPublicKey, 0, 256);
|
{
|
||||||
|
auto encryptionKey = new EncryptionKey (it);
|
||||||
if (isPublic)
|
if (isPublic)
|
||||||
PersistTemporaryKeys ();
|
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
||||||
else
|
else
|
||||||
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
encryptionKey->GenerateKeys ();
|
||||||
|
encryptionKey->CreateDecryptor ();
|
||||||
|
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
||||||
|
m_ECIESx25519EncryptionKey.reset (encryptionKey);
|
||||||
|
else
|
||||||
|
m_StandardEncryptionKey.reset (encryptionKey);
|
||||||
|
}
|
||||||
|
|
||||||
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_EncryptionKeyType, m_EncryptionPrivateKey);
|
|
||||||
if (isPublic)
|
if (isPublic)
|
||||||
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
||||||
|
|
||||||
|
@ -1071,10 +1112,10 @@ namespace client
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
|
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
|
||||||
{
|
{
|
||||||
if (m_DatagramDestination == nullptr)
|
if (m_DatagramDestination == nullptr)
|
||||||
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ());
|
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
|
||||||
return m_DatagramDestination;
|
return m_DatagramDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,27 +1133,29 @@ namespace client
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::PersistTemporaryKeys ()
|
void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey)
|
||||||
{
|
{
|
||||||
|
if (!keys) return;
|
||||||
std::string ident = GetIdentHash().ToBase32();
|
std::string ident = GetIdentHash().ToBase32();
|
||||||
std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat"));
|
std::string path = i2p::fs::DataDirPath("destinations",
|
||||||
|
isSingleKey ? (ident + ".dat") : (ident + "." + std::to_string (keys->keyType) + ".dat"));
|
||||||
std::ifstream f(path, std::ifstream::binary);
|
std::ifstream f(path, std::ifstream::binary);
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
f.read ((char *)m_EncryptionPublicKey, 256);
|
f.read ((char *)keys->pub, 256);
|
||||||
f.read ((char *)m_EncryptionPrivateKey, 256);
|
f.read ((char *)keys->priv, 256);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
|
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
|
||||||
memset (m_EncryptionPrivateKey, 0, 256);
|
memset (keys->priv, 0, 256);
|
||||||
memset (m_EncryptionPublicKey, 0, 256);
|
memset (keys->pub, 0, 256);
|
||||||
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
keys->GenerateKeys ();
|
||||||
// TODO:: persist crypto key type
|
// TODO:: persist crypto key type
|
||||||
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
||||||
if (f1) {
|
if (f1) {
|
||||||
f1.write ((char *)m_EncryptionPublicKey, 256);
|
f1.write ((char *)keys->pub, 256);
|
||||||
f1.write ((char *)m_EncryptionPrivateKey, 256);
|
f1.write ((char *)keys->priv, 256);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
||||||
|
@ -1123,18 +1166,27 @@ namespace client
|
||||||
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
|
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
{
|
{
|
||||||
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_EncryptionPublicKey, tunnels);
|
if (m_StandardEncryptionKey)
|
||||||
|
{
|
||||||
|
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_StandardEncryptionKey->pub, tunnels);
|
||||||
// sign
|
// sign
|
||||||
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// standard LS2 (type 3) first
|
// standard LS2 (type 3) first
|
||||||
uint16_t keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256;
|
i2p::data::LocalLeaseSet2::KeySections keySections;
|
||||||
|
if (m_ECIESx25519EncryptionKey)
|
||||||
|
keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} );
|
||||||
|
if (m_StandardEncryptionKey)
|
||||||
|
keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} );
|
||||||
|
|
||||||
bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
||||||
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
||||||
m_Keys, i2p::data::LocalLeaseSet2::KeySections { {m_EncryptionKeyType, keyLen, m_EncryptionPublicKey} },
|
m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted);
|
||||||
tunnels, IsPublic (), isPublishedEncrypted);
|
|
||||||
if (isPublishedEncrypted) // encrypt if type 5
|
if (isPublishedEncrypted) // encrypt if type 5
|
||||||
ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
|
ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
|
||||||
leaseSet = ls2;
|
leaseSet = ls2;
|
||||||
|
@ -1149,13 +1201,28 @@ namespace client
|
||||||
|
|
||||||
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
|
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
|
||||||
{
|
{
|
||||||
if (m_Decryptor)
|
if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
||||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
if (m_ECIESx25519EncryptionKey && m_ECIESx25519EncryptionKey->decryptor)
|
||||||
|
return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true);
|
||||||
|
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor)
|
||||||
|
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destinations: decryptor is not set");
|
LogPrint (eLogError, "Destinations: decryptor is not set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
|
||||||
|
{
|
||||||
|
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
|
||||||
|
{
|
||||||
|
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
||||||
|
return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr;
|
||||||
|
return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
|
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
|
||||||
{
|
{
|
||||||
for (auto it: *params)
|
for (auto it: *params)
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
|
/*
|
||||||
|
* 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 DESTINATION_H__
|
#ifndef DESTINATION_H__
|
||||||
#define DESTINATION_H__
|
#define DESTINATION_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -93,7 +102,6 @@ namespace client
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
|
@ -192,6 +200,17 @@ namespace client
|
||||||
|
|
||||||
class ClientDestination: public LeaseSetDestination
|
class ClientDestination: public LeaseSetDestination
|
||||||
{
|
{
|
||||||
|
struct EncryptionKey
|
||||||
|
{
|
||||||
|
uint8_t pub[256], priv[256];
|
||||||
|
i2p::data::CryptoKeyType keyType;
|
||||||
|
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> decryptor;
|
||||||
|
|
||||||
|
EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); };
|
||||||
|
void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); };
|
||||||
|
void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); };
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||||
|
@ -224,13 +243,13 @@ namespace client
|
||||||
|
|
||||||
// datagram
|
// datagram
|
||||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||||
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
|
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
|
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
|
||||||
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
|
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -244,15 +263,14 @@ namespace client
|
||||||
std::shared_ptr<ClientDestination> GetSharedFromThis () {
|
std::shared_ptr<ClientDestination> GetSharedFromThis () {
|
||||||
return std::static_pointer_cast<ClientDestination>(shared_from_this ());
|
return std::static_pointer_cast<ClientDestination>(shared_from_this ());
|
||||||
}
|
}
|
||||||
void PersistTemporaryKeys ();
|
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
|
||||||
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
std::unique_ptr<EncryptionKey> m_StandardEncryptionKey;
|
||||||
i2p::data::CryptoKeyType m_EncryptionKeyType;
|
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
|
|
||||||
|
|
||||||
int m_StreamingAckDelay;
|
int m_StreamingAckDelay;
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
@ -20,7 +28,7 @@ namespace garlic
|
||||||
// DH_INITIALIZE(rootKey, k)
|
// DH_INITIALIZE(rootKey, k)
|
||||||
uint8_t keydata[64];
|
uint8_t keydata[64];
|
||||||
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
|
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
|
||||||
// nextRootKey = keydata[0:31]
|
memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
|
||||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
|
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
|
||||||
// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
|
// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
|
||||||
memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
|
memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
|
||||||
|
@ -38,36 +46,55 @@ namespace garlic
|
||||||
{
|
{
|
||||||
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
|
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
|
||||||
m_NextIndex++;
|
m_NextIndex++;
|
||||||
if (m_NextIndex >= 65535) m_NextIndex = 0; // TODO: dirty hack, should create new tagset
|
if (m_NextIndex >= 65535)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return m_KeyData.GetTag ();
|
return m_KeyData.GetTag ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
|
void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
|
||||||
{
|
{
|
||||||
if (m_NextSymmKeyIndex > 0 && index >= m_NextSymmKeyIndex)
|
if (index >= m_NextSymmKeyIndex)
|
||||||
{
|
{
|
||||||
auto num = index + 1 - m_NextSymmKeyIndex;
|
auto num = index + 1 - m_NextSymmKeyIndex;
|
||||||
|
if (!m_NextSymmKeyIndex)
|
||||||
|
{
|
||||||
|
i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64)
|
||||||
|
m_NextSymmKeyIndex = 1;
|
||||||
|
num--;
|
||||||
|
}
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK);
|
i2p::crypto::HKDF (m_CurrentSymmKeyCK, nullptr, 0, "SymmetricRatchet", m_CurrentSymmKeyCK);
|
||||||
|
if (i < num - 1)
|
||||||
|
m_ItermediateSymmKeys.emplace (m_NextSymmKeyIndex + i, m_CurrentSymmKeyCK + 32);
|
||||||
|
}
|
||||||
m_NextSymmKeyIndex += num;
|
m_NextSymmKeyIndex += num;
|
||||||
memcpy (key, m_CurrentSymmKeyCK + 32, 32);
|
memcpy (key, m_CurrentSymmKeyCK + 32, 32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CalculateSymmKeyCK (index, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RatchetTagSet::CalculateSymmKeyCK (int index, uint8_t * key)
|
|
||||||
{
|
{
|
||||||
// TODO: store intermediate keys
|
auto it = m_ItermediateSymmKeys.find (index);
|
||||||
uint8_t currentSymmKeyCK[64];
|
if (it != m_ItermediateSymmKeys.end ())
|
||||||
i2p::crypto::HKDF (m_SymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_0 = HKDF(symmKey_ck, SYMMKEY_CONSTANT, "SymmetricRatchet", 64)
|
{
|
||||||
for (int i = 0; i < index; i++)
|
memcpy (key, it->second, 32);
|
||||||
i2p::crypto::HKDF (currentSymmKeyCK, nullptr, 0, "SymmetricRatchet", currentSymmKeyCK); // keydata_n = HKDF(symmKey_chainKey_(n-1), SYMMKEY_CONSTANT, "SymmetricRatchet", 64)
|
m_ItermediateSymmKeys.erase (it);
|
||||||
memcpy (key, currentSymmKeyCK + 32, 32);
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Garlic: Missing symmetric key for index ", index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner):
|
void RatchetTagSet::Expire ()
|
||||||
GarlicRoutingSession (owner, true)
|
{
|
||||||
|
if (!m_ExpirationTimestamp)
|
||||||
|
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
|
||||||
|
GarlicRoutingSession (owner, attachLeaseSet)
|
||||||
{
|
{
|
||||||
ResetKeys ();
|
ResetKeys ();
|
||||||
}
|
}
|
||||||
|
@ -78,11 +105,18 @@ namespace garlic
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::ResetKeys ()
|
void ECIESX25519AEADRatchetSession::ResetKeys ()
|
||||||
{
|
{
|
||||||
// TODO : use precalculated hashes
|
static const uint8_t protocolNameHash[32] =
|
||||||
static const char protocolName[41] = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"; // 40 bytes
|
{
|
||||||
SHA256 ((const uint8_t *)protocolName, 40, m_H);
|
0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
|
||||||
memcpy (m_CK, m_H, 32);
|
0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
|
||||||
SHA256 (m_H, 32, m_H);
|
}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
|
||||||
|
static const uint8_t hh[32] =
|
||||||
|
{
|
||||||
|
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
|
||||||
|
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
|
||||||
|
}; // SHA256 (protocolNameHash)
|
||||||
|
memcpy (m_CK, protocolNameHash, 32);
|
||||||
|
memcpy (m_H, hh, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
|
void ECIESX25519AEADRatchetSession::MixHash (const uint8_t * buf, size_t len)
|
||||||
|
@ -111,15 +145,15 @@ namespace garlic
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ECIESX25519AEADRatchetSession::CreateNewSessionTag () const
|
std::shared_ptr<RatchetTagSet> ECIESX25519AEADRatchetSession::CreateNewSessionTagset ()
|
||||||
{
|
{
|
||||||
uint8_t tagsetKey[32];
|
uint8_t tagsetKey[32];
|
||||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
|
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
|
||||||
// Session Tag Ratchet
|
// Session Tag Ratchet
|
||||||
RatchetTagSet tagsetNsr;
|
auto tagsetNsr = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
tagsetNsr.DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
|
tagsetNsr->DHInitialize (m_CK, tagsetKey); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
|
||||||
tagsetNsr.NextSessionTagRatchet ();
|
tagsetNsr->NextSessionTagRatchet ();
|
||||||
return tagsetNsr.GetNextSessionTag ();
|
return tagsetNsr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
|
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
|
||||||
|
@ -127,7 +161,7 @@ namespace garlic
|
||||||
if (!GetOwner ()) return false;
|
if (!GetOwner ()) return false;
|
||||||
// we are Bob
|
// we are Bob
|
||||||
// KDF1
|
// KDF1
|
||||||
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32); // h = SHA256(h || bpk)
|
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk)
|
||||||
|
|
||||||
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
||||||
{
|
{
|
||||||
|
@ -138,7 +172,7 @@ namespace garlic
|
||||||
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
|
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
|
||||||
|
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, aepk)
|
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
|
|
||||||
// decrypt flags/static
|
// decrypt flags/static
|
||||||
|
@ -152,19 +186,20 @@ namespace garlic
|
||||||
MixHash (buf, 48); // h = SHA256(h || ciphertext)
|
MixHash (buf, 48); // h = SHA256(h || ciphertext)
|
||||||
buf += 48; len -= 48; // 32 data + 16 poly
|
buf += 48; len -= 48; // 32 data + 16 poly
|
||||||
|
|
||||||
// decrypt payload
|
|
||||||
std::vector<uint8_t> payload (len - 16);
|
|
||||||
// KDF2 for payload
|
// KDF2 for payload
|
||||||
bool isStatic = !i2p::data::Tag<32> (fs).IsZero ();
|
bool isStatic = !i2p::data::Tag<32> (fs).IsZero ();
|
||||||
if (isStatic)
|
if (isStatic)
|
||||||
{
|
{
|
||||||
// static key, fs is apk
|
// static key, fs is apk
|
||||||
memcpy (m_RemoteStaticKey, fs, 32);
|
memcpy (m_RemoteStaticKey, fs, 32);
|
||||||
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, apk)
|
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
}
|
}
|
||||||
else // all zeros flags
|
else // all zeros flags
|
||||||
CreateNonce (1, nonce);
|
CreateNonce (1, nonce);
|
||||||
|
|
||||||
|
// decrypt payload
|
||||||
|
std::vector<uint8_t> payload (len - 16); // we must save original ciphertext
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
|
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
|
||||||
|
@ -174,12 +209,12 @@ namespace garlic
|
||||||
m_State = eSessionStateNewSessionReceived;
|
m_State = eSessionStateNewSessionReceived;
|
||||||
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
||||||
|
|
||||||
HandlePayload (payload.data (), len - 16);
|
HandlePayload (payload.data (), len - 16, nullptr, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, int index)
|
void ECIESX25519AEADRatchetSession::HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index)
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
while (offset < len)
|
while (offset < len)
|
||||||
|
@ -197,8 +232,37 @@ namespace garlic
|
||||||
switch (blk)
|
switch (blk)
|
||||||
{
|
{
|
||||||
case eECIESx25519BlkGalicClove:
|
case eECIESx25519BlkGalicClove:
|
||||||
|
if (GetOwner ())
|
||||||
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
|
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
|
||||||
break;
|
break;
|
||||||
|
case eECIESx25519BlkNextKey:
|
||||||
|
LogPrint (eLogDebug, "Garlic: next key");
|
||||||
|
HandleNextKey (buf + offset, size, receiveTagset);
|
||||||
|
break;
|
||||||
|
case eECIESx25519BlkAck:
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Garlic: ack");
|
||||||
|
int numAcks = size >> 2; // /4
|
||||||
|
auto offset1 = offset;
|
||||||
|
for (auto i = 0; i < numAcks; i++)
|
||||||
|
{
|
||||||
|
offset1 += 2; // tagsetid
|
||||||
|
MessageConfirmed (bufbe16toh (buf + offset1)); offset1 += 2; // N
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eECIESx25519BlkAckRequest:
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Garlic: ack request");
|
||||||
|
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eECIESx25519BlkTermination:
|
||||||
|
LogPrint (eLogDebug, "Garlic: termination");
|
||||||
|
if (GetOwner ())
|
||||||
|
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||||
|
if (receiveTagset) receiveTagset->Expire ();
|
||||||
|
break;
|
||||||
case eECIESx25519BlkDateTime:
|
case eECIESx25519BlkDateTime:
|
||||||
LogPrint (eLogDebug, "Garlic: datetime");
|
LogPrint (eLogDebug, "Garlic: datetime");
|
||||||
break;
|
break;
|
||||||
|
@ -208,12 +272,6 @@ namespace garlic
|
||||||
case eECIESx25519BlkPadding:
|
case eECIESx25519BlkPadding:
|
||||||
LogPrint (eLogDebug, "Garlic: padding");
|
LogPrint (eLogDebug, "Garlic: padding");
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkAckRequest:
|
|
||||||
{
|
|
||||||
LogPrint (eLogDebug, "Garlic: ack request");
|
|
||||||
m_AckRequests.push_back ({0, index}); // TODO: use actual tagsetid
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
|
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +279,94 @@ namespace garlic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset)
|
||||||
|
{
|
||||||
|
uint8_t flag = buf[0]; buf++; // flag
|
||||||
|
if (flag & ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG)
|
||||||
|
{
|
||||||
|
if (!m_SendForwardKey || !m_NextSendRatchet) return;
|
||||||
|
uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
|
||||||
|
if (((!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID) && keyID == m_NextSendRatchet->keyID) ||
|
||||||
|
(m_NextSendRatchet->newKey && keyID == m_NextSendRatchet->keyID -1))
|
||||||
|
{
|
||||||
|
if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG)
|
||||||
|
memcpy (m_NextSendRatchet->remote, buf, 32);
|
||||||
|
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<RatchetTagSet> (shared_from_this ());
|
||||||
|
newTagset->SetTagSetID (1 + m_NextSendRatchet->keyID + keyID);
|
||||||
|
newTagset->DHInitialize (m_SendTagset->GetNextRootKey (), tagsetKey);
|
||||||
|
newTagset->NextSessionTagRatchet ();
|
||||||
|
m_SendTagset = newTagset;
|
||||||
|
m_SendForwardKey = false;
|
||||||
|
LogPrint (eLogDebug, "Garlic: next send tagset ", newTagset->GetTagSetID (), " created");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
|
||||||
|
bool newKey = flag & ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG;
|
||||||
|
m_SendReverseKey = true;
|
||||||
|
if (!m_NextReceiveRatchet)
|
||||||
|
m_NextReceiveRatchet.reset (new DHRatchet ());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (keyID == m_NextReceiveRatchet->keyID && newKey == m_NextReceiveRatchet->newKey)
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Garlic: Duplicate ", newKey ? "new" : "old", " key ", keyID, " received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_NextReceiveRatchet->keyID = keyID;
|
||||||
|
}
|
||||||
|
int tagsetID = 2*keyID;
|
||||||
|
if (newKey)
|
||||||
|
{
|
||||||
|
m_NextReceiveRatchet->key.GenerateKeys ();
|
||||||
|
m_NextReceiveRatchet->newKey = true;
|
||||||
|
tagsetID++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_NextReceiveRatchet->newKey = false;
|
||||||
|
if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG)
|
||||||
|
memcpy (m_NextReceiveRatchet->remote, buf, 32);
|
||||||
|
|
||||||
|
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<RatchetTagSet>(shared_from_this ());
|
||||||
|
newTagset->SetTagSetID (tagsetID);
|
||||||
|
newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey);
|
||||||
|
newTagset->NextSessionTagRatchet ();
|
||||||
|
GenerateMoreReceiveTags (newTagset, ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
||||||
|
receiveTagset->Expire ();
|
||||||
|
LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ECIESX25519AEADRatchetSession::NewNextSendRatchet ()
|
||||||
|
{
|
||||||
|
if (m_NextSendRatchet)
|
||||||
|
{
|
||||||
|
if (!m_NextSendRatchet->newKey || !m_NextSendRatchet->keyID)
|
||||||
|
{
|
||||||
|
m_NextSendRatchet->keyID++;
|
||||||
|
m_NextSendRatchet->newKey = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_NextSendRatchet->newKey = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_NextSendRatchet.reset (new DHRatchet ());
|
||||||
|
if (m_NextSendRatchet->newKey)
|
||||||
|
m_NextSendRatchet->key.GenerateKeys ();
|
||||||
|
|
||||||
|
m_SendForwardKey = true;
|
||||||
|
LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
|
||||||
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
ResetKeys ();
|
ResetKeys ();
|
||||||
|
@ -242,7 +388,7 @@ namespace garlic
|
||||||
// encrypt static key section
|
// encrypt static key section
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
|
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
|
||||||
return false;
|
return false;
|
||||||
|
@ -250,7 +396,7 @@ namespace garlic
|
||||||
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
|
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
|
||||||
offset += 48;
|
offset += 48;
|
||||||
// KDF2
|
// KDF2
|
||||||
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bpk)
|
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
// encrypt payload
|
// encrypt payload
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
|
||||||
|
@ -262,7 +408,7 @@ namespace garlic
|
||||||
|
|
||||||
m_State = eSessionStateNewSessionSent;
|
m_State = eSessionStateNewSessionSent;
|
||||||
if (GetOwner ())
|
if (GetOwner ())
|
||||||
GetOwner ()->AddECIESx25519SessionTag (0, CreateNewSessionTag (), shared_from_this ());
|
GenerateMoreReceiveTags (CreateNewSessionTagset (), ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +416,8 @@ namespace garlic
|
||||||
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
// we are Bob
|
// we are Bob
|
||||||
uint64_t tag = CreateNewSessionTag ();
|
m_NSRTagset = CreateNewSessionTagset ();
|
||||||
|
uint64_t tag = m_NSRTagset->GetNextSessionTag ();
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
memcpy (out + offset, &tag, 8);
|
memcpy (out + offset, &tag, 8);
|
||||||
|
@ -280,6 +427,8 @@ namespace garlic
|
||||||
LogPrint (eLogError, "Garlic: Can't encode elligator");
|
LogPrint (eLogError, "Garlic: Can't encode elligator");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
|
||||||
|
memcpy (m_NSRH, m_H, 32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
// KDF for Reply Key Section
|
// KDF for Reply Key Section
|
||||||
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
|
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
|
||||||
|
@ -291,24 +440,25 @@ namespace garlic
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
// calulate hash for zero length
|
// calculate hash for zero length
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (sharedSecret /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
|
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
|
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
||||||
offset += 16;
|
offset += 16;
|
||||||
memcpy (m_NSRHeader, out, 56); // for possible next NSR
|
|
||||||
// KDF for payload
|
// KDF for payload
|
||||||
uint8_t keydata[64];
|
uint8_t keydata[64];
|
||||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||||
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
||||||
m_ReceiveTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
m_ReceiveTagset.NextSessionTagRatchet ();
|
receiveTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
||||||
m_SendTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
receiveTagset->NextSessionTagRatchet ();
|
||||||
m_SendTagset.NextSessionTagRatchet ();
|
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
|
m_SendTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
||||||
|
m_SendTagset->NextSessionTagRatchet ();
|
||||||
|
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
|
||||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
||||||
// encrypt payload
|
// encrypt payload
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
|
||||||
|
@ -317,6 +467,7 @@ namespace garlic
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_State = eSessionStateNewSessionReplySent;
|
m_State = eSessionStateNewSessionReplySent;
|
||||||
|
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -324,9 +475,21 @@ namespace garlic
|
||||||
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
// we are Bob and sent NSR already
|
// we are Bob and sent NSR already
|
||||||
memcpy (out, m_NSRHeader, 56);
|
uint64_t tag = m_NSRTagset->GetNextSessionTag (); // next tag
|
||||||
|
memcpy (out, &tag, 8);
|
||||||
|
memcpy (out + 8, m_NSREncodedKey, 32);
|
||||||
|
// recalculate h with new tag
|
||||||
|
memcpy (m_H, m_NSRH, 32);
|
||||||
|
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
|
||||||
|
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MixHash (out + 40, 16); // h = SHA256(h || ciphertext)
|
||||||
// encrypt payload
|
// encrypt payload
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt
|
||||||
{
|
{
|
||||||
|
@ -336,7 +499,7 @@ namespace garlic
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len)
|
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
// we are Alice
|
// we are Alice
|
||||||
LogPrint (eLogDebug, "Garlic: reply received");
|
LogPrint (eLogDebug, "Garlic: reply received");
|
||||||
|
@ -350,17 +513,22 @@ namespace garlic
|
||||||
}
|
}
|
||||||
buf += 32; len -= 32;
|
buf += 32; len -= 32;
|
||||||
// KDF for Reply Key Section
|
// KDF for Reply Key Section
|
||||||
|
uint8_t h[32]; memcpy (h, m_H, 32); // save m_H
|
||||||
MixHash (tag, 8); // h = SHA256(h || tag)
|
MixHash (tag, 8); // h = SHA256(h || tag)
|
||||||
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
|
if (m_State == eSessionStateNewSessionSent)
|
||||||
|
{
|
||||||
|
// only fist time, we assume ephemeral keys the same
|
||||||
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
|
||||||
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bepk)
|
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk)
|
||||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||||
|
}
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
// calulate hash for zero length
|
// calculate hash for zero length
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anyting */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
|
LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
|
||||||
return false;
|
return false;
|
||||||
|
@ -370,24 +538,37 @@ namespace garlic
|
||||||
// KDF for payload
|
// KDF for payload
|
||||||
uint8_t keydata[64];
|
uint8_t keydata[64];
|
||||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||||
|
if (m_State == eSessionStateNewSessionSent)
|
||||||
|
{
|
||||||
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
||||||
m_SendTagset.DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
m_SendTagset.NextSessionTagRatchet ();
|
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
||||||
m_ReceiveTagset.DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
m_SendTagset->NextSessionTagRatchet ();
|
||||||
m_ReceiveTagset.NextSessionTagRatchet ();
|
auto receiveTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
|
receiveTagset->DHInitialize (m_CK, keydata + 32); // tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
||||||
|
receiveTagset->NextSessionTagRatchet ();
|
||||||
|
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_MIN_NUM_GENERATED_TAGS);
|
||||||
|
}
|
||||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
||||||
// decrypt payload
|
// decrypt payload
|
||||||
std::vector<uint8_t> payload (len - 16);
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, payload.data (), len - 16, false)) // decrypt
|
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
|
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_State == eSessionStateNewSessionSent)
|
||||||
|
{
|
||||||
m_State = eSessionStateEstablished;
|
m_State = eSessionStateEstablished;
|
||||||
|
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
||||||
HandlePayload (payload.data (), len - 16);
|
}
|
||||||
|
memcpy (m_H, h, 32); // restore m_H
|
||||||
|
HandlePayload (buf, len - 16, nullptr, 0);
|
||||||
|
|
||||||
|
// we have received reply to NS with LeaseSet in it
|
||||||
|
SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
|
||||||
|
SetLeaseSetUpdateMsgID (0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -395,56 +576,70 @@ namespace garlic
|
||||||
bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
auto index = m_SendTagset.GetNextIndex ();
|
auto index = m_SendTagset->GetNextIndex ();
|
||||||
CreateNonce (index, nonce); // tag's index
|
CreateNonce (index, nonce); // tag's index
|
||||||
uint64_t tag = m_SendTagset.GetNextSessionTag ();
|
uint64_t tag = m_SendTagset->GetNextSessionTag ();
|
||||||
memcpy (out, &tag, 8);
|
memcpy (out, &tag, 8);
|
||||||
// ad = The session tag, 8 bytes
|
// ad = The session tag, 8 bytes
|
||||||
// ciphertext = ENCRYPT(k, n, payload, ad)
|
// ciphertext = ENCRYPT(k, n, payload, ad)
|
||||||
uint8_t key[32];
|
uint8_t key[32];
|
||||||
m_SendTagset.GetSymmKey (index, key);
|
m_SendTagset->GetSymmKey (index, key);
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, out, 8, key, nonce, out + 8, outLen - 8, true)) // encrypt
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (index >= ECIESX25519_TAGSET_MAX_NUM_TAGS && !m_SendForwardKey)
|
||||||
|
NewNextSendRatchet ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index)
|
bool ECIESX25519AEADRatchetSession::HandleExistingSessionMessage (uint8_t * buf, size_t len,
|
||||||
|
std::shared_ptr<RatchetTagSet> receiveTagset, int index)
|
||||||
{
|
{
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (index, nonce); // tag's index
|
CreateNonce (index, nonce); // tag's index
|
||||||
len -= 8; // tag
|
len -= 8; // tag
|
||||||
std::vector<uint8_t> payload (len - 16);
|
uint8_t * payload = buf + 8;
|
||||||
uint8_t key[32];
|
uint8_t key[32];
|
||||||
m_ReceiveTagset.GetSymmKey (index, key);
|
receiveTagset->GetSymmKey (index, key);
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + 8, len - 16, buf, 8, key, nonce, payload.data (), len - 16, false)) // decrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 16, buf, 8, key, nonce, payload, len - 16, false)) // decrypt
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
|
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
HandlePayload (payload.data (), len - 16, index);
|
HandlePayload (payload, len - 16, receiveTagset, index);
|
||||||
if (m_ReceiveTagset.GetNextIndex () - index <= GetOwner ()->GetNumTags ()*2/3)
|
int moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4
|
||||||
GenerateMoreReceiveTags (GetOwner ()->GetNumTags ());
|
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
|
||||||
|
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||||
|
if (moreTags > 0 && GetOwner ())
|
||||||
|
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len, int index)
|
bool ECIESX25519AEADRatchetSession::HandleNextMessage (uint8_t * buf, size_t len,
|
||||||
|
std::shared_ptr<RatchetTagSet> receiveTagset, int index)
|
||||||
{
|
{
|
||||||
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
switch (m_State)
|
switch (m_State)
|
||||||
{
|
{
|
||||||
case eSessionStateNewSessionReplySent:
|
case eSessionStateNewSessionReplySent:
|
||||||
m_State = eSessionStateEstablished;
|
m_State = eSessionStateEstablished;
|
||||||
|
m_NSRTagset = nullptr;
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
case eSessionStateEstablished:
|
case eSessionStateEstablished:
|
||||||
return HandleExistingSessionMessage (buf, len, index);
|
if (HandleExistingSessionMessage (buf, len, receiveTagset, index)) return true;
|
||||||
|
// check NSR just in case
|
||||||
|
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
|
||||||
|
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
|
||||||
|
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
||||||
|
return HandleNewOutgoingSessionReply (buf, len);
|
||||||
case eSessionStateNew:
|
case eSessionStateNew:
|
||||||
return HandleNewIncomingSession (buf, len);
|
return HandleNewIncomingSession (buf, len);
|
||||||
case eSessionStateNewSessionSent:
|
case eSessionStateNewSessionSent:
|
||||||
|
receiveTagset->Expire (); // NSR tagset
|
||||||
return HandleNewOutgoingSessionReply (buf, len);
|
return HandleNewOutgoingSessionReply (buf, len);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -454,11 +649,12 @@ namespace garlic
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
auto m = NewI2NPMessage ();
|
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
|
||||||
|
size_t len = payload.size ();
|
||||||
|
if (!len) return nullptr;
|
||||||
|
auto m = NewI2NPMessage (len + 100); // 96 + 4
|
||||||
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
||||||
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
|
||||||
auto payload = CreatePayload (msg);
|
|
||||||
size_t len = payload.size ();
|
|
||||||
|
|
||||||
switch (m_State)
|
switch (m_State)
|
||||||
{
|
{
|
||||||
|
@ -492,43 +688,79 @@ namespace garlic
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg)
|
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first)
|
||||||
{
|
{
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
size_t payloadLen = 7; // datatime
|
size_t payloadLen = 0;
|
||||||
|
if (first) payloadLen += 7;// datatime
|
||||||
if (msg && m_Destination)
|
if (msg && m_Destination)
|
||||||
payloadLen += msg->GetPayloadLength () + 13 + 32;
|
payloadLen += msg->GetPayloadLength () + 13 + 32;
|
||||||
auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated) ? CreateDatabaseStoreMsg (GetOwner ()->GetLeaseSet ()) : nullptr;
|
auto leaseSet = (GetLeaseSetUpdateStatus () == eLeaseSetUpdated ||
|
||||||
std::shared_ptr<I2NPMessage> deliveryStatus;
|
(GetLeaseSetUpdateStatus () == eLeaseSetSubmitted &&
|
||||||
|
ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)) ?
|
||||||
|
GetOwner ()->GetLeaseSet () : nullptr;
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
payloadLen += leaseSet->GetPayloadLength () + 13;
|
payloadLen += leaseSet->GetBufferLen () + DATABASE_STORE_HEADER_SIZE + 13;
|
||||||
deliveryStatus = CreateEncryptedDeliveryStatusMsg (leaseSet->GetMsgID ());
|
if (!first)
|
||||||
payloadLen += deliveryStatus->GetPayloadLength () + 49;
|
{
|
||||||
if (GetLeaseSetUpdateMsgID ()) GetOwner ()->RemoveDeliveryStatusSession (GetLeaseSetUpdateMsgID ()); // remove previous
|
// ack request
|
||||||
SetLeaseSetUpdateStatus (eLeaseSetSubmitted);
|
SetLeaseSetUpdateStatus (eLeaseSetSubmitted);
|
||||||
SetLeaseSetUpdateMsgID (leaseSet->GetMsgID ());
|
SetLeaseSetUpdateMsgID (m_SendTagset->GetNextIndex ());
|
||||||
SetLeaseSetSubmissionTime (ts);
|
SetLeaseSetSubmissionTime (ts);
|
||||||
GetOwner ()->DeliveryStatusSent (shared_from_this (), leaseSet->GetMsgID ());
|
payloadLen += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m_AckRequests.size () > 0)
|
if (m_AckRequests.size () > 0)
|
||||||
payloadLen += m_AckRequests.size ()*4 + 3;
|
payloadLen += m_AckRequests.size ()*4 + 3;
|
||||||
uint8_t paddingSize;
|
if (m_SendReverseKey)
|
||||||
|
{
|
||||||
|
payloadLen += 6;
|
||||||
|
if (m_NextReceiveRatchet->newKey) payloadLen += 32;
|
||||||
|
}
|
||||||
|
if (m_SendForwardKey)
|
||||||
|
{
|
||||||
|
payloadLen += 6;
|
||||||
|
if (m_NextSendRatchet->newKey) payloadLen += 32;
|
||||||
|
}
|
||||||
|
uint8_t paddingSize = 0;
|
||||||
|
if (payloadLen)
|
||||||
|
{
|
||||||
|
int delta = (int)ECIESX25519_OPTIMAL_PAYLOAD_SIZE - (int)payloadLen;
|
||||||
|
if (delta < 0 || delta > 3) // don't create padding if we are close to optimal size
|
||||||
|
{
|
||||||
RAND_bytes (&paddingSize, 1);
|
RAND_bytes (&paddingSize, 1);
|
||||||
paddingSize &= 0x0F; paddingSize++; // 1 - 16
|
paddingSize &= 0x0F; // 0 - 15
|
||||||
|
if (delta > 3)
|
||||||
|
{
|
||||||
|
delta -= 3;
|
||||||
|
if (paddingSize >= delta) paddingSize %= delta;
|
||||||
|
}
|
||||||
|
paddingSize++;
|
||||||
payloadLen += paddingSize + 3;
|
payloadLen += paddingSize + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::vector<uint8_t> v(payloadLen);
|
std::vector<uint8_t> v(payloadLen);
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// DateTime
|
// DateTime
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
v[offset] = eECIESx25519BlkDateTime; offset++;
|
v[offset] = eECIESx25519BlkDateTime; offset++;
|
||||||
htobe16buf (v.data () + offset, 4); offset += 2;
|
htobe16buf (v.data () + offset, 4); offset += 2;
|
||||||
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
|
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
|
||||||
|
}
|
||||||
// LeaseSet
|
// LeaseSet
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
offset += CreateGarlicClove (leaseSet, v.data () + offset, payloadLen - offset);
|
{
|
||||||
// DeliveryStatus
|
offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset);
|
||||||
if (deliveryStatus)
|
if (!first)
|
||||||
offset += CreateDeliveryStatusClove (deliveryStatus, v.data () + offset, payloadLen - offset);
|
{
|
||||||
|
// ack request
|
||||||
|
v[offset] = eECIESx25519BlkAckRequest; offset++;
|
||||||
|
htobe16buf (v.data () + offset, 1); offset += 2;
|
||||||
|
v[offset] = 0; offset++; // flags
|
||||||
|
}
|
||||||
|
}
|
||||||
// msg
|
// msg
|
||||||
if (msg && m_Destination)
|
if (msg && m_Destination)
|
||||||
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
|
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset, true);
|
||||||
|
@ -536,7 +768,7 @@ namespace garlic
|
||||||
if (m_AckRequests.size () > 0)
|
if (m_AckRequests.size () > 0)
|
||||||
{
|
{
|
||||||
v[offset] = eECIESx25519BlkAck; offset++;
|
v[offset] = eECIESx25519BlkAck; offset++;
|
||||||
htobe16buf (v.data () + offset, m_AckRequests.size ()*4); offset += 2;
|
htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2;
|
||||||
for (auto& it: m_AckRequests)
|
for (auto& it: m_AckRequests)
|
||||||
{
|
{
|
||||||
htobe16buf (v.data () + offset, it.first); offset += 2;
|
htobe16buf (v.data () + offset, it.first); offset += 2;
|
||||||
|
@ -544,10 +776,48 @@ namespace garlic
|
||||||
}
|
}
|
||||||
m_AckRequests.clear ();
|
m_AckRequests.clear ();
|
||||||
}
|
}
|
||||||
|
// next keys
|
||||||
|
if (m_SendReverseKey)
|
||||||
|
{
|
||||||
|
v[offset] = eECIESx25519BlkNextKey; offset++;
|
||||||
|
htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2;
|
||||||
|
v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG;
|
||||||
|
int keyID = m_NextReceiveRatchet->keyID - 1;
|
||||||
|
if (m_NextReceiveRatchet->newKey)
|
||||||
|
{
|
||||||
|
v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG;
|
||||||
|
keyID++;
|
||||||
|
}
|
||||||
|
offset++; // flag
|
||||||
|
htobe16buf (v.data () + offset, keyID); offset += 2; // keyid
|
||||||
|
if (m_NextReceiveRatchet->newKey)
|
||||||
|
{
|
||||||
|
memcpy (v.data () + offset, m_NextReceiveRatchet->key.GetPublicKey (), 32);
|
||||||
|
offset += 32; // public key
|
||||||
|
}
|
||||||
|
m_SendReverseKey = false;
|
||||||
|
}
|
||||||
|
if (m_SendForwardKey)
|
||||||
|
{
|
||||||
|
v[offset] = eECIESx25519BlkNextKey; offset++;
|
||||||
|
htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2;
|
||||||
|
v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG;
|
||||||
|
if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only
|
||||||
|
offset++; // flag
|
||||||
|
htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid
|
||||||
|
if (m_NextSendRatchet->newKey)
|
||||||
|
{
|
||||||
|
memcpy (v.data () + offset, m_NextSendRatchet->key.GetPublicKey (), 32);
|
||||||
|
offset += 32; // public key
|
||||||
|
}
|
||||||
|
}
|
||||||
// padding
|
// padding
|
||||||
|
if (paddingSize)
|
||||||
|
{
|
||||||
v[offset] = eECIESx25519BlkPadding; offset++;
|
v[offset] = eECIESx25519BlkPadding; offset++;
|
||||||
htobe16buf (v.data () + offset, paddingSize); offset += 2;
|
htobe16buf (v.data () + offset, paddingSize); offset += 2;
|
||||||
memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
|
memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
|
||||||
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,52 +840,41 @@ namespace garlic
|
||||||
buf++; // flag and delivery instructions
|
buf++; // flag and delivery instructions
|
||||||
*buf = msg->GetTypeID (); // I2NP msg type
|
*buf = msg->GetTypeID (); // I2NP msg type
|
||||||
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
|
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
|
||||||
htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds
|
htobe32buf (buf + 5, msg->GetExpiration () / 1000); // expiration in seconds
|
||||||
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
||||||
return cloveSize + 3;
|
return cloveSize + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ECIESX25519AEADRatchetSession::CreateDeliveryStatusClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len)
|
size_t ECIESX25519AEADRatchetSession::CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 37 /* delivery instruction */;
|
if (!ls || ls->GetStoreType () != i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Garlic: Incorrect LeasetSet type to send");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t cloveSize = 1 + 9 + DATABASE_STORE_HEADER_SIZE + ls->GetBufferLen (); // to local
|
||||||
if ((int)len < cloveSize + 3) return 0;
|
if ((int)len < cloveSize + 3) return 0;
|
||||||
buf[0] = eECIESx25519BlkGalicClove; // clove type
|
buf[0] = eECIESx25519BlkGalicClove; // clove type
|
||||||
htobe16buf (buf + 1, cloveSize); // size
|
htobe16buf (buf + 1, cloveSize); // size
|
||||||
buf += 3;
|
buf += 3;
|
||||||
if (GetOwner ())
|
*buf = 0; buf++; // flag and delivery instructions
|
||||||
{
|
*buf = eI2NPDatabaseStore; buf++; // I2NP msg type
|
||||||
auto inboundTunnel = GetOwner ()->GetTunnelPool ()->GetNextInboundTunnel ();
|
RAND_bytes (buf, 4); buf += 4; // msgID
|
||||||
if (inboundTunnel)
|
htobe32buf (buf, (ts + I2NP_MESSAGE_EXPIRATION_TIMEOUT)/1000); buf += 4; // expiration
|
||||||
{
|
// payload
|
||||||
// delivery instructions
|
memcpy (buf + DATABASE_STORE_KEY_OFFSET, ls->GetStoreHash (), 32);
|
||||||
*buf = eGarlicDeliveryTypeTunnel << 5; buf++; // delivery instructions flag tunnel
|
buf[DATABASE_STORE_TYPE_OFFSET] = i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2;
|
||||||
// hash and tunnelID sequence is reversed for Garlic
|
memset (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0, 4); // replyToken = 0
|
||||||
memcpy (buf, inboundTunnel->GetNextIdentHash (), 32); buf += 32;// To Hash
|
buf += DATABASE_STORE_HEADER_SIZE;
|
||||||
htobe32buf (buf, inboundTunnel->GetNextTunnelID ()); buf += 4;// tunnelID
|
memcpy (buf, ls->GetBuffer (), ls->GetBufferLen ());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*buf = msg->GetTypeID (); // I2NP msg type
|
|
||||||
htobe32buf (buf + 1, msg->GetMsgID ()); // msgID
|
|
||||||
htobe32buf (buf + 5, msg->GetExpiration ()/1000); // expiration in seconds
|
|
||||||
memcpy (buf + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
return cloveSize + 3;
|
return cloveSize + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (int numTags)
|
void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numTags; i++)
|
for (int i = 0; i < numTags; i++)
|
||||||
{
|
GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
|
||||||
auto index = m_ReceiveTagset.GetNextIndex ();
|
|
||||||
uint64_t tag = m_ReceiveTagset.GetNextSessionTag ();
|
|
||||||
GetOwner ()->AddECIESx25519SessionTag (index, tag, shared_from_this ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
|
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
|
||||||
|
@ -642,7 +901,7 @@ namespace garlic
|
||||||
*payload = 0; payload++; // flag and delivery instructions
|
*payload = 0; payload++; // flag and delivery instructions
|
||||||
*payload = msg->GetTypeID (); // I2NP msg type
|
*payload = msg->GetTypeID (); // I2NP msg type
|
||||||
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
|
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
|
||||||
htobe32buf (payload + 5, msg->GetExpiration ()/1000); // expiration in seconds
|
htobe32buf (payload + 5, msg->GetExpiration () / 1000); // expiration in seconds
|
||||||
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
|
||||||
|
|
||||||
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
|
||||||
|
@ -660,5 +919,3 @@ namespace garlic
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 ECIES_X25519_AEAD_RATCHET_SESSION_H__
|
#ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__
|
||||||
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__
|
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__
|
||||||
|
|
||||||
|
@ -7,27 +15,49 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
|
#include "Tag.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace garlic
|
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 second we receive nothing and should restart if we can
|
||||||
|
const int ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT = 600; // in seconds
|
||||||
|
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180
|
||||||
|
const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 4096; // number of tags we request new tagset after
|
||||||
|
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
|
||||||
|
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
|
||||||
|
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
|
||||||
|
|
||||||
|
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
|
class RatchetTagSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
|
||||||
|
|
||||||
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
||||||
void NextSessionTagRatchet ();
|
void NextSessionTagRatchet ();
|
||||||
uint64_t GetNextSessionTag ();
|
uint64_t GetNextSessionTag ();
|
||||||
|
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
||||||
int GetNextIndex () const { return m_NextIndex; };
|
int GetNextIndex () const { return m_NextIndex; };
|
||||||
void GetSymmKey (int index, uint8_t * key);
|
void GetSymmKey (int index, uint8_t * key);
|
||||||
|
|
||||||
private:
|
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
||||||
|
int GetTagSetID () const { return m_TagSetID; };
|
||||||
|
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
|
||||||
|
|
||||||
void CalculateSymmKeyCK (int index, uint8_t * key);
|
void Expire ();
|
||||||
|
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -41,8 +71,12 @@ namespace garlic
|
||||||
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
|
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
|
||||||
|
|
||||||
} m_KeyData;
|
} m_KeyData;
|
||||||
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64];
|
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
||||||
int m_NextIndex, m_NextSymmKeyIndex;
|
int m_NextIndex, m_NextSymmKeyIndex;
|
||||||
|
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
||||||
|
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
||||||
|
int m_TagSetID = 0;
|
||||||
|
uint64_t m_ExpirationTimestamp = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ECIESx25519BlockType
|
enum ECIESx25519BlockType
|
||||||
|
@ -51,34 +85,42 @@ namespace garlic
|
||||||
eECIESx25519BlkSessionID = 1,
|
eECIESx25519BlkSessionID = 1,
|
||||||
eECIESx25519BlkTermination = 4,
|
eECIESx25519BlkTermination = 4,
|
||||||
eECIESx25519BlkOptions = 5,
|
eECIESx25519BlkOptions = 5,
|
||||||
eECIESx25519BlkNextSessionKey = 7,
|
eECIESx25519BlkNextKey = 7,
|
||||||
eECIESx25519BlkAck = 8,
|
eECIESx25519BlkAck = 8,
|
||||||
eECIESx25519BlkAckRequest = 9,
|
eECIESx25519BlkAckRequest = 9,
|
||||||
eECIESx25519BlkGalicClove = 11,
|
eECIESx25519BlkGalicClove = 11,
|
||||||
eECIESx25519BlkPadding = 254
|
eECIESx25519BlkPadding = 254
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
|
||||||
const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second of inactivity we should restart after
|
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
|
||||||
const int ECIESX25519_EXPIRATION_TIMEOUT = 600; // in seconds
|
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
|
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
|
||||||
{
|
{
|
||||||
enum SessionState
|
enum SessionState
|
||||||
{
|
{
|
||||||
eSessionStateNew =0,
|
eSessionStateNew = 0,
|
||||||
eSessionStateNewSessionReceived,
|
eSessionStateNewSessionReceived,
|
||||||
eSessionStateNewSessionSent,
|
eSessionStateNewSessionSent,
|
||||||
eSessionStateNewSessionReplySent,
|
eSessionStateNewSessionReplySent,
|
||||||
eSessionStateEstablished
|
eSessionStateEstablished
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DHRatchet
|
||||||
|
{
|
||||||
|
int keyID = 0;
|
||||||
|
i2p::crypto::X25519Keys key;
|
||||||
|
uint8_t remote[32]; // last remote public key
|
||||||
|
bool newKey = true;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ECIESX25519AEADRatchetSession (GarlicDestination * owner);
|
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
|
||||||
~ECIESX25519AEADRatchetSession ();
|
~ECIESX25519AEADRatchetSession ();
|
||||||
|
|
||||||
bool HandleNextMessage (const uint8_t * buf, size_t len, int index = 0);
|
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
|
||||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
||||||
|
@ -90,7 +132,10 @@ namespace garlic
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckExpired (uint64_t ts); // true is expired
|
bool CheckExpired (uint64_t ts); // true is expired
|
||||||
bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; }
|
bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; }
|
||||||
|
bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); }
|
||||||
|
|
||||||
|
bool IsRatchets () const { return true; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -98,35 +143,48 @@ namespace garlic
|
||||||
void MixHash (const uint8_t * buf, size_t len);
|
void MixHash (const uint8_t * buf, size_t len);
|
||||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||||
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
||||||
uint64_t CreateNewSessionTag () const;
|
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
|
||||||
|
|
||||||
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
||||||
bool HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len);
|
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
|
||||||
bool HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index);
|
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
|
||||||
void HandlePayload (const uint8_t * buf, size_t len, int index = 0);
|
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
|
||||||
|
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset);
|
||||||
|
|
||||||
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
|
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
||||||
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
|
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
|
||||||
size_t CreateDeliveryStatusClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
|
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
||||||
|
|
||||||
void GenerateMoreReceiveTags (int numTags);
|
void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
|
||||||
|
void NewNextSendRatchet ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
||||||
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
|
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
|
||||||
uint8_t m_NSRHeader[56], m_NSRKey[32]; // new session reply, for incoming only
|
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
|
||||||
i2p::crypto::X25519Keys m_EphemeralKeys;
|
i2p::crypto::X25519Keys m_EphemeralKeys;
|
||||||
SessionState m_State = eSessionStateNew;
|
SessionState m_State = eSessionStateNew;
|
||||||
uint64_t m_LastActivityTimestamp = 0; // incoming
|
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0; // incoming
|
||||||
RatchetTagSet m_SendTagset, m_ReceiveTagset;
|
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
|
||||||
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
||||||
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
|
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
|
||||||
|
bool m_SendReverseKey = false, m_SendForwardKey = false;
|
||||||
|
std::unique_ptr<DHRatchet> m_NextReceiveRatchet, m_NextSendRatchet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// for HTTP only
|
||||||
|
int GetState () const { return (int)m_State; }
|
||||||
|
i2p::data::IdentHash GetDestination () const
|
||||||
|
{
|
||||||
|
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
@ -597,4 +605,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 ED25519_H__
|
#ifndef ED25519_H__
|
||||||
#define ED25519_H__
|
#define ED25519_H__
|
||||||
|
|
||||||
|
@ -128,6 +136,4 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Elligator.h"
|
#include "Elligator.h"
|
||||||
|
@ -204,4 +212,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 ELLIGATOR_H__
|
#ifndef ELLIGATOR_H__
|
||||||
#define ELLIGATOR_H__
|
#define ELLIGATOR_H__
|
||||||
|
|
||||||
|
@ -35,5 +43,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2016, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -35,8 +35,10 @@ namespace fs {
|
||||||
* std::vector<std::string> files;
|
* std::vector<std::string> files;
|
||||||
* h.Traverse(files); <- finds all files in storage and saves in given vector
|
* h.Traverse(files); <- finds all files in storage and saves in given vector
|
||||||
*/
|
*/
|
||||||
class HashedStorage {
|
class HashedStorage
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::string root; /**< path to storage with it's name included */
|
std::string root; /**< path to storage with it's name included */
|
||||||
std::string name; /**< name of the storage */
|
std::string name; /**< name of the storage */
|
||||||
std::string prefix1; /**< hashed directory prefix */
|
std::string prefix1; /**< hashed directory prefix */
|
||||||
|
@ -44,6 +46,7 @@ namespace fs {
|
||||||
std::string suffix; /**< suffix of file in storage (extension) */
|
std::string suffix; /**< suffix of file in storage (extension) */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::function<void(const std::string &)> FilenameVisitor;
|
typedef std::function<void(const std::string &)> FilenameVisitor;
|
||||||
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
|
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
|
||||||
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
|
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
@ -113,9 +121,9 @@ namespace data
|
||||||
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||||
const char * signature, const char * key)
|
const char * signature, const char * key)
|
||||||
{
|
{
|
||||||
uint8_t buf[50], signatureBuf[64];
|
uint8_t buf[100], signatureBuf[64];
|
||||||
size_t len = family.length (), signatureLen = strlen (signature);
|
size_t len = family.length (), signatureLen = strlen (signature);
|
||||||
if (len + 32 > 50)
|
if (len + 32 > 100)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Family: ", family, " is too long");
|
LogPrint (eLogError, "Family: ", family, " is too long");
|
||||||
return false;
|
return false;
|
||||||
|
@ -179,4 +187,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 FAMILY_H__
|
#ifndef FAMILY_H__
|
||||||
#define FAMILY_H__
|
#define FAMILY_H__
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -466,8 +474,9 @@ namespace garlic
|
||||||
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto mod = length & 0x0f; // %16
|
||||||
buf += 4; // length
|
buf += 4; // length
|
||||||
auto it = m_Tags.find (SessionTag(buf));
|
auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
|
||||||
// AES tag might be used even if encryption type is not ElGamal/AES
|
// AES tag might be used even if encryption type is not ElGamal/AES
|
||||||
if (it != m_Tags.end ())
|
if (it != m_Tags.end ())
|
||||||
{
|
{
|
||||||
|
@ -487,15 +496,30 @@ namespace garlic
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// tag not found. Handle depending on encryption type
|
bool found = false;
|
||||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
|
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
{
|
{
|
||||||
HandleECIESx25519 (buf, length);
|
// try ECIESx25519 tag
|
||||||
return;
|
uint64_t tag;
|
||||||
|
memcpy (&tag, buf, 8);
|
||||||
|
auto it1 = m_ECIESx25519Tags.find (tag);
|
||||||
|
if (it1 != m_ECIESx25519Tags.end ())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
auto session = it1->second.tagset->GetSession ();
|
||||||
|
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
||||||
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
|
m_ECIESx25519Tags.erase (it1);
|
||||||
}
|
}
|
||||||
// otherwise assume ElGamal/AES
|
}
|
||||||
|
|
||||||
|
if (!found) // assume new session
|
||||||
|
{
|
||||||
|
// AES tag not found. Handle depending on encryption type
|
||||||
|
// try ElGamal/AES first if leading block is 514
|
||||||
ElGamalBlock elGamal;
|
ElGamalBlock elGamal;
|
||||||
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
|
if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
|
||||||
|
Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
|
||||||
{
|
{
|
||||||
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
||||||
uint8_t iv[32]; // IV is first 16 bytes
|
uint8_t iv[32]; // IV is first 16 bytes
|
||||||
|
@ -504,10 +528,18 @@ namespace garlic
|
||||||
decryption->Decrypt(buf + 514, length - 514, buf + 514);
|
decryption->Decrypt(buf + 514, length - 514, buf + 514);
|
||||||
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
||||||
}
|
}
|
||||||
|
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
|
{
|
||||||
|
// otherwise ECIESx25519
|
||||||
|
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
||||||
|
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
||||||
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||||
|
@ -679,18 +711,25 @@ namespace garlic
|
||||||
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
|
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
|
||||||
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
|
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
|
||||||
{
|
{
|
||||||
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET &&
|
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
|
||||||
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
|
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
{
|
{
|
||||||
ECIESX25519AEADRatchetSessionPtr session;
|
ECIESX25519AEADRatchetSessionPtr session;
|
||||||
uint8_t staticKey[32];
|
uint8_t staticKey[32];
|
||||||
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
|
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
|
||||||
auto it = m_ECIESx25519Sessions.find (staticKey);
|
auto it = m_ECIESx25519Sessions.find (staticKey);
|
||||||
if (it != m_ECIESx25519Sessions.end ())
|
if (it != m_ECIESx25519Sessions.end ())
|
||||||
|
{
|
||||||
session = it->second;
|
session = it->second;
|
||||||
|
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Garlic: session restarted");
|
||||||
|
session = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!session)
|
if (!session)
|
||||||
{
|
{
|
||||||
session = std::make_shared<ECIESX25519AEADRatchetSession> (this);
|
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
|
||||||
session->SetRemoteStaticKey (staticKey);
|
session->SetRemoteStaticKey (staticKey);
|
||||||
}
|
}
|
||||||
session->SetDestination (destination->GetIdentHash ()); // TODO: remove
|
session->SetDestination (destination->GetIdentHash ()); // TODO: remove
|
||||||
|
@ -764,7 +803,7 @@ namespace garlic
|
||||||
// ECIESx25519
|
// ECIESx25519
|
||||||
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
for (auto it = m_ECIESx25519Tags.begin (); it != m_ECIESx25519Tags.end ();)
|
||||||
{
|
{
|
||||||
if (ts > it->second.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
it = m_ECIESx25519Tags.erase (it);
|
it = m_ECIESx25519Tags.erase (it);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
|
@ -906,26 +945,6 @@ namespace garlic
|
||||||
i2p::fs::Remove (it);
|
i2p::fs::Remove (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len)
|
|
||||||
{
|
|
||||||
uint64_t tag;
|
|
||||||
memcpy (&tag, buf, 8);
|
|
||||||
ECIESX25519AEADRatchetSessionPtr session;
|
|
||||||
int index = 0;
|
|
||||||
auto it = m_ECIESx25519Tags.find (tag);
|
|
||||||
if (it != m_ECIESx25519Tags.end ())
|
|
||||||
{
|
|
||||||
session = it->second.session;
|
|
||||||
index = it->second.index;
|
|
||||||
m_ECIESx25519Tags.erase (tag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
session = std::make_shared<ECIESX25519AEADRatchetSession> (this); // incoming
|
|
||||||
|
|
||||||
if (!session->HandleNextMessage (buf, len, index))
|
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
const uint8_t * buf1 = buf;
|
const uint8_t * buf1 = buf;
|
||||||
|
@ -985,9 +1004,11 @@ namespace garlic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session)
|
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
|
||||||
{
|
{
|
||||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexSession{index, session, i2p::util::GetSecondsSinceEpoch ()});
|
auto index = tagset->GetNextIndex ();
|
||||||
|
uint64_t tag = tagset->GetNextSessionTag ();
|
||||||
|
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
||||||
|
@ -997,7 +1018,10 @@ namespace garlic
|
||||||
if (it != m_ECIESx25519Sessions.end ())
|
if (it != m_ECIESx25519Sessions.end ())
|
||||||
{
|
{
|
||||||
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
|
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
|
||||||
|
{
|
||||||
|
it->second->SetOwner (nullptr); // detach
|
||||||
m_ECIESx25519Sessions.erase (it);
|
m_ECIESx25519Sessions.erase (it);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
||||||
|
@ -1007,5 +1031,14 @@ namespace garlic
|
||||||
m_ECIESx25519Sessions.emplace (staticKeyTag, session);
|
m_ECIESx25519Sessions.emplace (staticKeyTag, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GarlicDestination::RemoveECIESx25519Session (const uint8_t * staticKey)
|
||||||
|
{
|
||||||
|
auto it = m_ECIESx25519Sessions.find (staticKey);
|
||||||
|
if (it != m_ECIESx25519Sessions.end ())
|
||||||
|
{
|
||||||
|
it->second->SetOwner (nullptr);
|
||||||
|
m_ECIESx25519Sessions.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 GARLIC_H__
|
#ifndef GARLIC_H__
|
||||||
#define GARLIC_H__
|
#define GARLIC_H__
|
||||||
|
|
||||||
|
@ -105,6 +113,7 @@ namespace garlic
|
||||||
virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
|
virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
|
||||||
virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
|
virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
|
||||||
virtual bool MessageConfirmed (uint32_t msgID);
|
virtual bool MessageConfirmed (uint32_t msgID);
|
||||||
|
virtual bool IsRatchets () const { return false; };
|
||||||
|
|
||||||
void SetLeaseSetUpdated ()
|
void SetLeaseSetUpdated ()
|
||||||
{
|
{
|
||||||
|
@ -142,6 +151,7 @@ namespace garlic
|
||||||
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
virtual size_t GetNumOutgoingTags () const { return 0; };
|
virtual size_t GetNumOutgoingTags () const { return 0; };
|
||||||
};
|
};
|
||||||
|
@ -195,6 +205,7 @@ namespace garlic
|
||||||
i2p::crypto::CBCEncryption m_Encryption;
|
i2p::crypto::CBCEncryption m_Encryption;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
||||||
};
|
};
|
||||||
|
@ -202,10 +213,12 @@ namespace garlic
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession;
|
class ECIESX25519AEADRatchetSession;
|
||||||
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
|
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
|
||||||
struct ECIESX25519AEADRatchetIndexSession
|
class RatchetTagSet;
|
||||||
|
typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
|
||||||
|
struct ECIESX25519AEADRatchetIndexTagset
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
ECIESX25519AEADRatchetSessionPtr session;
|
RatchetTagSetPtr tagset;
|
||||||
uint64_t creationTime; // seconds since epoch
|
uint64_t creationTime; // seconds since epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -228,8 +241,9 @@ namespace garlic
|
||||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||||
void AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session);
|
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||||
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
||||||
|
void RemoveECIESx25519Session (const uint8_t * staticKey);
|
||||||
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
@ -255,9 +269,6 @@ namespace garlic
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
|
|
||||||
// ECIES-X25519-AEAD-Ratchet
|
|
||||||
void HandleECIESx25519 (const uint8_t * buf, size_t len);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
BN_CTX * m_Ctx; // incoming
|
BN_CTX * m_Ctx; // incoming
|
||||||
|
@ -268,7 +279,7 @@ namespace garlic
|
||||||
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
|
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
|
||||||
// incoming
|
// incoming
|
||||||
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
||||||
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexSession> m_ECIESx25519Tags; // session tag -> session
|
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
|
||||||
// DeliveryStatus
|
// DeliveryStatus
|
||||||
std::mutex m_DeliveryStatusSessionsMutex;
|
std::mutex m_DeliveryStatusSessionsMutex;
|
||||||
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
||||||
|
@ -277,7 +288,9 @@ namespace garlic
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
size_t GetNumIncomingTags () const { return m_Tags.size (); }
|
size_t GetNumIncomingTags () const { return m_Tags.size (); }
|
||||||
|
size_t GetNumIncomingECIESx25519Tags () const { return m_ECIESx25519Tags.size (); }
|
||||||
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
||||||
|
const decltype(m_ECIESx25519Sessions)& GetECIESx25519Sessions () const { return m_ECIESx25519Sessions; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void CleanUpTagsFiles ();
|
void CleanUpTagsFiles ();
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
#include <string.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 GOST_H__
|
#ifndef GOST_H__
|
||||||
#define GOST_H__
|
#define GOST_H__
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2017, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
#include <string.h> /* memset */
|
#include <string.h> /* memset */
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "I2PEndian.h"
|
||||||
#include "Gzip.h"
|
#include "Gzip.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -30,6 +31,21 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
if (inLen < 23) return 0;
|
||||||
|
if (in[10] == 0x01) // non compressed
|
||||||
|
{
|
||||||
|
size_t len = bufle16toh (in + 11);
|
||||||
|
if (len + 23 < inLen)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Gzip: Incorrect length");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (len > outLen) len = outLen;
|
||||||
|
memcpy (out, in + 15, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (m_IsDirty) inflateReset (&m_Inflator);
|
if (m_IsDirty) inflateReset (&m_Inflator);
|
||||||
m_IsDirty = true;
|
m_IsDirty = true;
|
||||||
|
@ -44,6 +60,7 @@ namespace data
|
||||||
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
|
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
|
||||||
{
|
{
|
||||||
|
@ -106,10 +123,79 @@ namespace data
|
||||||
m_Deflator.avail_out = outLen;
|
m_Deflator.avail_out = outLen;
|
||||||
int err;
|
int err;
|
||||||
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END)
|
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END)
|
||||||
|
{
|
||||||
|
out[9] = 0xff; // OS is always unknown
|
||||||
return outLen - m_Deflator.avail_out;
|
return outLen - m_Deflator.avail_out;
|
||||||
|
}
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GzipDeflator::Deflate (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
if (m_IsDirty) deflateReset (&m_Deflator);
|
||||||
|
m_IsDirty = true;
|
||||||
|
size_t offset = 0;
|
||||||
|
int err;
|
||||||
|
for (const auto& it: bufs)
|
||||||
|
{
|
||||||
|
m_Deflator.next_in = const_cast<uint8_t *>(it.first);
|
||||||
|
m_Deflator.avail_in = it.second;
|
||||||
|
m_Deflator.next_out = out + offset;
|
||||||
|
m_Deflator.avail_out = outLen - offset;
|
||||||
|
auto flush = (it == bufs.back ()) ? Z_FINISH : Z_NO_FLUSH;
|
||||||
|
err = deflate (&m_Deflator, flush);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (flush && err == Z_STREAM_END)
|
||||||
|
{
|
||||||
|
out[9] = 0xff; // OS is always unknown
|
||||||
|
return outLen - m_Deflator.avail_out;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset = outLen - m_Deflator.avail_out;
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
||||||
|
if (outLen < (size_t)inLen + 23) return 0;
|
||||||
|
memcpy (out, gzipHeader, 11);
|
||||||
|
htole16buf (out + 11, inLen);
|
||||||
|
htole16buf (out + 13, 0xffff - inLen);
|
||||||
|
memcpy (out + 15, in, inLen);
|
||||||
|
htole32buf (out + inLen + 15, crc32 (0, in, inLen));
|
||||||
|
htole32buf (out + inLen + 19, inLen);
|
||||||
|
return inLen + 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
||||||
|
memcpy (out, gzipHeader, 11);
|
||||||
|
uint32_t crc = 0;
|
||||||
|
size_t len = 0, len1;
|
||||||
|
for (const auto& it: bufs)
|
||||||
|
{
|
||||||
|
len1 = len;
|
||||||
|
len += it.second;
|
||||||
|
if (outLen < len + 23) return 0;
|
||||||
|
memcpy (out + 15 + len1, it.first, it.second);
|
||||||
|
crc = crc32 (crc, it.first, it.second);
|
||||||
|
}
|
||||||
|
if (len > 0xffff) return 0;
|
||||||
|
htole32buf (out + len + 15, crc);
|
||||||
|
htole32buf (out + len + 19, len);
|
||||||
|
htole16buf (out + 11, len);
|
||||||
|
htole16buf (out + 13, 0xffff - len);
|
||||||
|
return len + 23;
|
||||||
|
}
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
|
@ -1,10 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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 GZIP_H__
|
#ifndef GZIP_H__
|
||||||
#define GZIP_H__
|
#define GZIP_H__
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p
|
||||||
namespace data {
|
{
|
||||||
|
namespace data
|
||||||
|
{
|
||||||
class GzipInflator
|
class GzipInflator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -32,12 +43,16 @@ namespace data {
|
||||||
|
|
||||||
void SetCompressionLevel (int level);
|
void SetCompressionLevel (int level);
|
||||||
size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
||||||
|
size_t Deflate (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
z_stream m_Deflator;
|
z_stream m_Deflator;
|
||||||
bool m_IsDirty;
|
bool m_IsDirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K
|
||||||
|
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2019, The PurpleI2P Project
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue