Merge pull request #1525 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2020-05-30 13:33:45 -04:00 committed by GitHub
commit b992fbab52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
186 changed files with 6237 additions and 4312 deletions

View File

@ -1,6 +1,56 @@
# for this file format description,
# 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
### Added
- Single threaded SAM

View File

@ -41,7 +41,7 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.bsd
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
else # not supported
$(error Not supported platform)

View File

@ -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
NEEDED_CXXFLAGS += -std=c++11
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
LDLIBS = -latomic
else # not supported

View File

@ -2,10 +2,19 @@ USE_WIN32_APP=yes
CXX = g++
WINDRES = windres
CXXFLAGS := ${CXX_DEBUG} -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
NEEDED_CXXFLAGS = -std=c++11
INCFLAGS = -Idaemon -I.
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_SUFFIX = -mt
@ -27,6 +36,8 @@ LDLIBS += \
-lws2_32 \
-lgdi32 \
-liphlpapi \
-lole32 \
-luuid \
-lstdc++ \
-lpthread

View File

@ -2,6 +2,7 @@
[![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)
[![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
====
@ -68,7 +69,7 @@ Build instructions:
* 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)
* 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)
* FreeBSD
* Android

View File

@ -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 <clocale>
#include "Config.h"
@ -8,6 +16,7 @@
#ifdef _WIN32
#include "Win32/Win32Service.h"
#ifdef WIN32_APP
#include <windows.h>
#include "Win32/Win32App.h"
#endif
@ -23,6 +32,11 @@ namespace util
setlocale(LC_ALL, "Russian");
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))
return false;

View File

@ -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 <windows.h>
#include <shellapi.h>
@ -11,7 +20,7 @@
#include "resource.h"
#include "Daemon.h"
#include "Win32App.h"
#include <stdio.h>
#include "Win32NetState.h"
#define ID_ABOUT 2000
#define ID_EXIT 2001
@ -338,11 +347,6 @@ namespace win32
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
return 0;
}
case FRAME_UPDATE_TIMER:
{
InvalidateRect(hWnd, NULL, TRUE);
return 0;
}
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
{
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
@ -351,6 +355,11 @@ namespace win32
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
return 0;
}
case FRAME_UPDATE_TIMER:
{
InvalidateRect(hWnd, NULL, TRUE);
return 0;
}
}
break;
}
@ -411,6 +420,7 @@ namespace win32
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
}
SubscribeToEvents();
return true;
}
@ -430,6 +440,7 @@ namespace win32
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
}
@ -448,6 +459,5 @@ namespace win32
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
return hWnd;
}
}
}

View File

@ -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__
#define WIN32APP_H__

86
Win32/Win32NetState.cpp Normal file
View 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
View 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

View File

@ -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
#define _CRT_SECURE_NO_WARNINGS // to use freopen
#endif
#include "Win32Service.h"
#include <assert.h>
#include <strsafe.h>
//#include <strsafe.h>
#include <windows.h>
#include "Daemon.h"

View File

@ -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__
#define WIN_32_SERVICE_H__
@ -26,48 +34,48 @@
class I2PService
{
public:
public:
I2PService(PSTR pszServiceName,
BOOL fCanStop = TRUE,
BOOL fCanShutdown = TRUE,
BOOL fCanPauseContinue = FALSE);
I2PService(PSTR pszServiceName,
BOOL fCanStop = TRUE,
BOOL fCanShutdown = TRUE,
BOOL fCanPauseContinue = FALSE);
virtual ~I2PService(void);
virtual ~I2PService(void);
static BOOL isService();
static BOOL Run(I2PService &service);
void Stop();
static BOOL isService();
static BOOL Run(I2PService &service);
void Stop();
protected:
protected:
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop();
virtual void OnPause();
virtual void OnContinue();
virtual void OnShutdown();
void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode = NO_ERROR,
DWORD dwWaitHint = 0);
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop();
virtual void OnPause();
virtual void OnContinue();
virtual void OnShutdown();
void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode = NO_ERROR,
DWORD dwWaitHint = 0);
private:
private:
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
void WorkerThread();
void Start(DWORD dwArgc, PSTR *pszArgv);
void Pause();
void Continue();
void Shutdown();
static I2PService* s_service;
PSTR m_name;
SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_statusHandle;
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
void WorkerThread();
void Start(DWORD dwArgc, PSTR *pszArgv);
void Pause();
void Continue();
void Shutdown();
static I2PService* s_service;
PSTR m_name;
SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_statusHandle;
BOOL m_fStopping;
HANDLE m_hStoppedEvent;
BOOL m_fStopping;
HANDLE m_hStoppedEvent;
std::thread* _worker;
std::thread* _worker;
};
void InstallService(
@ -77,7 +85,7 @@ void InstallService(
PCSTR pszDependencies,
PCSTR pszAccount,
PCSTR pszPassword
);
);
void UninstallService(PCSTR pszServiceName);

View File

@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.30.0"
#define I2Pd_ver "2.32.0"
#define I2Pd_Publisher "PurpleI2P"
[Setup]

View File

@ -1,11 +1,11 @@
//{{NO_DEPENDENCIES}}
#define MAINICON 101
#define MAINICON 101
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

2
android/.gitignore vendored
View File

@ -4,6 +4,7 @@ bin
libs
log*
obj
.cxx
.gradle
.idea
.externalNativeBuild
@ -14,3 +15,4 @@ android.iml
build
*.iml
*.local
*.jks

View File

@ -17,8 +17,9 @@
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light.DarkActionBar"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
android:usesCleartextTraffic="true"
>
<receiver android:name=".NetworkStateChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
@ -30,10 +31,10 @@
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".I2PDActivity"
android:label="@string/app_name" />

View File

@ -42,6 +42,8 @@ inbound.quantity = 5
outbound.length = 1
outbound.quantity = 5
signaturetype=7
i2cp.leaseSetType=3
i2cp.leaseSetEncType=0,4
keys = proxy-keys.dat
# addresshelper = true
# outproxy = http://false.i2p

View File

@ -30,8 +30,8 @@ android {
applicationId "org.purplei2p.i2pd"
targetSdkVersion 29
minSdkVersion 14
versionCode 2300
versionName "2.30.0"
versionCode 2320
versionName "2.32.0"
setProperty("archivesBaseName", archivesBaseName + "-" + versionName)
ndk {
abiFilters 'armeabi-v7a'

View File

@ -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 <chrono>
#include <thread>

View File

@ -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
#define DAEMON_ANDROID_H

View File

@ -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 "org_purplei2p_i2pd_I2PD_JNI.h"
#include "DaemonAndroid.h"
#include "RouterContext.h"
#include "ClientContext.h"
#include "Transports.h"
#include "Tunnel.h"
JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith
(JNIEnv *env, jclass clazz) {
@ -61,6 +71,11 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
i2p::context.SetAcceptsTunnels (true);
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
(JNIEnv *env, jclass clazz) {
i2p::client::context.ReloadConfig();
}
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv *env, jclass clazz, jboolean isConnected) {
bool isConnectedBool = (bool) isConnected;
@ -92,3 +107,8 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
// Set DataDir
i2p::android::SetDataDir(dataDir);
}
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
(JNIEnv *env, jclass clazz) {
return i2p::tunnel::tunnels.CountTransitTunnels();
}

View File

@ -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 */
#include <jni.h>
/* 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
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_reloadTunnelsConfigs
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
(JNIEnv * env, jclass clazz, jboolean isConnected);
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_setDataDir
(JNIEnv *env, jclass clazz, jstring jdataDir);
JNIEXPORT jint JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_GetTransitTunnelsCount
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif

View File

@ -15,13 +15,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/horizontal_page_margin"
android:visibility="gone"
/>
android:visibility="gone" />
<Button
android:id="@+id/button_request_write_ext_storage_perms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Retry requesting the SD card write permissions"
android:visibility="gone"/>
android:text="@string/retryPermRequest"
android:visibility="gone" />
</LinearLayout>

View File

@ -15,13 +15,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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
android:id="@+id/button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
/>
android:text="@string/ok" />
</LinearLayout>

View File

@ -5,9 +5,8 @@
android:layout_height="fill_parent"
tools:context=".I2PDActivity">
<WebView
android:id="@+id/webview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<WebView
android:id="@+id/webview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>

View File

@ -3,23 +3,29 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".I2PDActivity">
<group android:id="@+id/group_i2pd_control" >
<group android:id="@+id/group_various">
<item
android:id="@+id/action_stop"
android:orderInCategory="99"
android:title="@string/action_stop" />
android:id="@+id/action_battery_otimizations"
android:title="@string/menu_item_battery_optimizations_str" />
</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
android:id="@+id/action_graceful_stop"
android:orderInCategory="98"
android:title="@string/action_graceful_stop" />
<item
android:id="@+id/action_start_webview"
android:orderInCategory="97"
android:title="@string/action_start_webview" />
</group>
<group android:id="@+id/group_various" >
<item
android:id="@+id/action_battery_otimizations"
android:title="@string/menu_item_battery_optimizations_str" />
android:id="@+id/action_stop"
android:orderInCategory="99"
android:title="@string/action_stop" />
</group>
</menu>

View File

@ -1,28 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">i2pd</string>
<string name="action_stop">Остановить</string>
<string name="action_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_in_progress">Корректная остановка запущена</string>
<string name="gracefulShutdownInProgress">Корректная остановка запущена</string>
<string name="already_stopped">Уже остановлено</string>
<string name="uninitialized">Приложение инициализируется</string>
<string name="starting">Приложение запускается</string>
<string name="jniLibraryLoaded">Загружены JNI библиотеки</string>
<string name="startedOkay">Приложение запущено</string>
<string name="startFailed">Запуск не удался</string>
<string name="gracefulShutdownInProgress">Корректная остановка запущена</string>
<string name="stopped">Приложение было остановлено</string>
<string name="remaining">осталось</string>
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</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="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_dialog" >Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\n\nВам сейчас будет предложено разрешить отключение этих оптимизаций.</string>
<string name="battery_optimizations_enabled_dialog">Ваша операционная система осуществляет оптимизации расхода аккумулятора, которые могут приводить к выгрузке I2PD из памяти и прекращению его работы с целью сэкономить заряд аккумулятора.\n\nВам сейчас будет предложено разрешить отключение этих оптимизаций.</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="shutdown_canceled">Плановая остановка отменена</string>
<string name="tunnels_reloading">Перезагрузка конфигурации туннелей...</string>
</resources>

View File

@ -1,29 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="app_name">i2pd</string>
<string name="action_stop">Stop</string>
<string name="action_graceful_stop">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_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="uninitialized">Application initializing</string>
<string name="starting">Application starting</string>
<string name="jniLibraryLoaded">Loaded JNI libraries</string>
<string name="startedOkay">Application Started</string>
<string name="startFailed">Start failed</string>
<string name="gracefulShutdownInProgress">Graceful shutdown in progress</string>
<string name="stopped">Application stopped</string>
<string name="remaining">remaining</string>
<string name="ok">OK</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="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_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="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="shutdown_canceled">Planned shutdown canceled</string>
<string name="action_start_webview">Start webview</string>
<string name="tunnels_reloading">Reloading tunnels config...</string>
</resources>

View File

@ -10,36 +10,65 @@ import org.purplei2p.i2pd.R;
public class DaemonSingleton {
private static final String TAG = "i2pd";
private static final DaemonSingleton instance = new DaemonSingleton();
public interface StateUpdateListener { void daemonStateUpdate(); }
public interface StateUpdateListener {
void daemonStateUpdate();
}
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 removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
public synchronized void addStateChangeListener(StateUpdateListener listener) {
stateUpdateListeners.add(listener);
}
public synchronized void removeStateChangeListener(StateUpdateListener listener) {
stateUpdateListeners.remove(listener);
}
private synchronized void setState(State newState) {
if(newState==null)throw new NullPointerException();
if (newState == null)
throw new NullPointerException();
State oldState = state;
if(oldState==null)throw new NullPointerException();
if(oldState.equals(newState))return;
state=newState;
if (oldState == null)
throw new NullPointerException();
if (oldState.equals(newState))
return;
state = newState;
fireStateUpdate1();
}
public synchronized void stopAcceptingTunnels() {
if(isStartedOkay()){
if (isStartedOkay()) {
setState(State.gracefulShutdownInProgress);
I2PD_JNI.stopAcceptingTunnels();
}
}
public synchronized void startAcceptingTunnels() {
if(isStartedOkay()){
if (isStartedOkay()) {
setState(State.startedOkay);
I2PD_JNI.startAcceptingTunnels();
}
}
public synchronized void reloadTunnelsConfigs() {
if (isStartedOkay()) {
I2PD_JNI.reloadTunnelsConfigs();
}
}
public synchronized int GetTransitTunnelsCount() {
return I2PD_JNI.GetTransitTunnelsCount();
}
private volatile boolean startedOkay;
public enum State {
@ -64,11 +93,13 @@ public class DaemonSingleton {
private volatile State state = State.uninitialized;
public State getState() { return state; }
public State getState() {
return state;
}
{
setState(State.starting);
new Thread(new Runnable(){
new Thread(new Runnable() {
@Override
public void run() {
@ -76,7 +107,7 @@ public class DaemonSingleton {
I2PD_JNI.loadLibraries();
setState(State.jniLibraryLoaded);
} catch (Throwable tr) {
lastThrowable=tr;
lastThrowable = tr;
setState(State.startFailed);
return;
}
@ -84,25 +115,27 @@ public class DaemonSingleton {
synchronized (DaemonSingleton.this) {
I2PD_JNI.setDataDir(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd");
daemonStartResult = I2PD_JNI.startDaemon();
if("ok".equals(daemonStartResult)){
if ("ok".equals(daemonStartResult)) {
setState(State.startedOkay);
setStartedOkay(true);
}else setState(State.startFailed);
} else
setState(State.startFailed);
}
} catch (Throwable tr) {
lastThrowable=tr;
lastThrowable = tr;
setState(State.startFailed);
}
}
}, "i2pdDaemonStart").start();
}
private Throwable lastThrowable;
private String daemonStartResult="N/A";
private String daemonStartResult = "N/A";
private void fireStateUpdate1() {
Log.i(TAG, "daemon state change: "+state);
for(StateUpdateListener listener : stateUpdateListeners) {
Log.i(TAG, "daemon state change: " + state);
for (StateUpdateListener listener : stateUpdateListeners) {
try {
listener.daemonStateUpdate();
} catch (Throwable tr) {
@ -134,8 +167,13 @@ public class DaemonSingleton {
}
public synchronized void stopDaemon() {
if(isStartedOkay()){
try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);}
if (isStartedOkay()) {
try {
I2PD_JNI.stopDaemon();
} catch(Throwable tr) {
Log.e(TAG, "", tr);
}
setStartedOkay(false);
setState(State.stopped);
}

View File

@ -68,42 +68,41 @@ public class I2PDActivity extends Activity {
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
new DaemonSingleton.StateUpdateListener() {
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() {
@Override
public void daemonStateUpdate()
{
public void daemonStateUpdate() {
processAssets();
runOnUiThread(() -> {
try {
if(textView==null) return;
Throwable tr = daemon.getLastThrowable();
if(tr!=null) {
textView.setText(throwableToString(tr));
return;
}
DaemonSingleton.State state = daemon.getState();
String startResultStr = DaemonSingleton.State.startFailed.equals(state) ? String.format(": %s", daemon.getDaemonStartResult()) : "";
String graceStr = DaemonSingleton.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
});
try {
if (textView == null)
return;
Throwable tr = daemon.getLastThrowable();
if (tr!=null) {
textView.setText(throwableToString(tr));
return;
}
DaemonSingleton.State state = daemon.getState();
String startResultStr = DaemonSingleton.State.startFailed.equals(state) ? String.format(": %s", daemon.getDaemonStartResult()) : "";
String graceStr = DaemonSingleton.State.gracefulShutdownInProgress.equals(state) ? String.format(": %s %s", formatGraceTimeRemaining(), getText(R.string.remaining)) : "";
textView.setText(String.format("%s%s%s", getText(state.getStatusStringResourceId()), startResultStr, graceStr));
} catch (Throwable tr) {
Log.e(TAG,"error ignored",tr);
}
});
}
};
private static volatile long graceStartedMillis;
private static final Object graceStartedMillis_LOCK=new Object();
private static final Object graceStartedMillis_LOCK = new Object();
private Menu optionsMenu;
private static String formatGraceTimeRemaining() {
long remainingSeconds;
synchronized (graceStartedMillis_LOCK){
remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D);
synchronized (graceStartedMillis_LOCK) {
remainingSeconds = Math.round(Math.max(0, graceStartedMillis + GRACEFUL_DELAY_MILLIS - System.currentTimeMillis()) / 1000.0D);
}
long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D);
long remSec=remainingSeconds-remainingMinutes*60;
return remainingMinutes+":"+(remSec/10)+remSec%10;
long remainingMinutes = (long)Math.floor(remainingSeconds / 60.0D);
long remSec = remainingSeconds - remainingMinutes * 60;
return remainingMinutes + ":" + (remSec / 10) + remSec % 10;
}
@Override
@ -117,10 +116,8 @@ public class I2PDActivity extends Activity {
daemonStateUpdatedListener.daemonStateUpdate();
// request permissions
if (Build.VERSION.SDK_INT >= 23)
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
{
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
@ -131,7 +128,7 @@ public class I2PDActivity extends Activity {
doBindService();
final Timer gracefulQuitTimer = getGracefulQuitTimer();
if(gracefulQuitTimer!=null){
if (gracefulQuitTimer != null) {
long gracefulStopAtMillis;
synchronized (graceStartedMillis_LOCK) {
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
@ -148,9 +145,9 @@ public class I2PDActivity extends Activity {
textView = null;
daemon.removeStateChangeListener(daemonStateUpdatedListener);
//cancelGracefulStop0();
try{
try {
doUnbindService();
}catch(Throwable tr){
} catch(Throwable tr) {
Log.e(TAG, "", tr);
}
}
@ -158,20 +155,20 @@ public class I2PDActivity extends Activity {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Log.e(TAG, "WR_EXT_STORAGE perm granted");
else {
Log.e(TAG, "WR_EXT_STORAGE perm declined, stopping i2pd");
i2pdStop();
//TODO must work w/o this perm, ask orignal
}
}
if (requestCode == MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Log.e(TAG, "WR_EXT_STORAGE perm granted");
else {
Log.e(TAG, "WR_EXT_STORAGE perm declined, stopping i2pd");
i2pdStop();
//TODO must work w/o this perm, ask orignal
}
}
}
private void cancelGracefulStop0() {
Timer gracefulQuitTimer = getGracefulQuitTimer();
if(gracefulQuitTimer!=null) {
if (gracefulQuitTimer != null) {
gracefulQuitTimer.cancel();
setGracefulQuitTimer(null);
}
@ -216,7 +213,8 @@ public class I2PDActivity extends Activity {
private void doBindService() {
synchronized (I2PDActivity.class) {
if (mIsBound) return;
if (mIsBound)
return;
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
@ -256,10 +254,11 @@ public class I2PDActivity extends Activity {
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch(id){
switch(id) {
case R.id.action_stop:
i2pdStop();
return true;
i2pdStop();
return true;
case R.id.action_graceful_stop:
synchronized (graceStartedMillis_LOCK) {
if (getGracefulQuitTimer() != null)
@ -268,9 +267,15 @@ public class I2PDActivity extends Activity {
i2pdGracefulStop();
}
return true;
case R.id.action_battery_otimizations:
onActionBatteryOptimizations();
return true;
case R.id.action_reload_tunnels_config:
onReloadTunnelsConfig();
return true;
case R.id.action_start_webview:
setContentView(R.layout.webview);
this.webView = (WebView) findViewById(R.id.webview1);
@ -291,100 +296,105 @@ public class I2PDActivity extends Activity {
try {
startActivity(new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
} 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();
}
}
}
private void onReloadTunnelsConfig() {
Log.d(TAG, "reloading tunnels");
daemon.reloadTunnelsConfigs();
Toast.makeText(this, R.string.tunnels_reloading, Toast.LENGTH_SHORT).show();
}
private void i2pdStop() {
cancelGracefulStop0();
new Thread(() -> {
Log.d(TAG, "stopping");
try {
daemon.stopDaemon();
} catch (Throwable tr) {
Log.e(TAG, "", tr);
}
quit(); //TODO make menu items for starting i2pd. On my Android, I need to reboot the OS to restart i2pd.
},"stop").start();
Log.d(TAG, "stopping");
try {
daemon.stopDaemon();
} catch (Throwable tr) {
Log.e(TAG, "", tr);
}
quit(); //TODO make menu items for starting i2pd. On my Android, I need to reboot the OS to restart i2pd.
}, "stop").start();
}
private static volatile Timer gracefulQuitTimer;
private void i2pdGracefulStop() {
if(daemon.getState()==DaemonSingleton.State.stopped){
Toast.makeText(this, R.string.already_stopped,
Toast.LENGTH_SHORT).show();
if (daemon.getState() == DaemonSingleton.State.stopped) {
Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show();
return;
}
if(getGracefulQuitTimer()!=null){
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress,
Toast.LENGTH_SHORT).show();
if (getGracefulQuitTimer() != null) {
Toast.makeText(this, R.string.graceful_stop_is_already_in_progress, Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
Toast.LENGTH_SHORT).show();
Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show();
new Thread(() -> {
try {
Log.d(TAG, "grac stopping");
if(daemon.isStartedOkay()) {
daemon.stopAcceptingTunnels();
long gracefulStopAtMillis;
synchronized (graceStartedMillis_LOCK) {
graceStartedMillis = System.currentTimeMillis();
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
}
rescheduleGraceStop(null,gracefulStopAtMillis);
} else {
i2pdStop();
}
} catch(Throwable tr) {
Log.e(TAG,"",tr);
}
},"gracInit").start();
try {
Log.d(TAG, "graceful stopping");
if (daemon.isStartedOkay()) {
daemon.stopAcceptingTunnels();
long gracefulStopAtMillis;
synchronized (graceStartedMillis_LOCK) {
graceStartedMillis = System.currentTimeMillis();
gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS;
}
rescheduleGraceStop(null, gracefulStopAtMillis);
} else
i2pdStop();
} catch(Throwable tr) {
Log.e(TAG, "", tr);
}
}, "gracInit").start();
}
private void cancelGracefulStop()
{
cancelGracefulStop0();
new Thread(() -> {
try
{
Log.d(TAG, "canceling grac stop");
if(daemon.isStartedOkay()) {
try {
Log.d(TAG, "canceling graceful stop");
if (daemon.isStartedOkay()) {
daemon.startAcceptingTunnels();
runOnUiThread(() -> Toast.makeText(this, R.string.shutdown_canceled, Toast.LENGTH_SHORT).show());
}
else
i2pdStop();
}
catch(Throwable tr)
{
Log.e(TAG,"",tr);
}
},"gracCancel").start();
} else
i2pdStop();
} catch(Throwable tr) {
Log.e(TAG, "", tr);
}
}, "gracCancel").start();
}
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);
setGracefulQuitTimer(gracefulQuitTimer);
gracefulQuitTimer.schedule(new TimerTask(){
gracefulQuitTimer.schedule(new TimerTask() {
@Override
public void run() {
i2pdStop();
}
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
}, Math.max(0, gracefulStopAtMillis - System.currentTimeMillis()));
final TimerTask tickerTask = new TimerTask() {
@Override
public void run() {
daemonStateUpdatedListener.daemonStateUpdate();
}
};
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
gracefulQuitTimer.scheduleAtFixedRate(tickerTask, 0/*start delay*/, 1000/*millis period*/);
}
private static Timer getGracefulQuitTimer() {
@ -454,9 +464,9 @@ public class I2PDActivity extends Activity {
*/
private void copyFileAsset(String path) {
File file = new File(i2pdpath, path);
if(!file.exists()) {
if (!file.exists()) {
try {
try (InputStream in = getAssets().open(path) ) {
try (InputStream in = getAssets().open(path)) {
try (OutputStream out = new FileOutputStream(file)) {
byte[] buffer = new byte[1024];
int read = in.read(buffer);
@ -475,97 +485,102 @@ public class I2PDActivity extends Activity {
private void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory()) {
File[] files = fileOrDirectory.listFiles();
if(files!=null) {
if (files != null) {
for (File child : files) {
deleteRecursive(child);
}
}
}
boolean deleteResult = fileOrDirectory.delete();
if(!deleteResult)Log.e(TAG, "fileOrDirectory.delete() returned "+deleteResult+", absolute path='"+fileOrDirectory.getAbsolutePath()+"'");
if (!deleteResult)
Log.e(TAG, "fileOrDirectory.delete() returned " + deleteResult + ", absolute path='" + fileOrDirectory.getAbsolutePath() + "'");
}
private void processAssets() {
if (!assetsCopied) try {
assetsCopied = true; // prevent from running on every state update
File holderFile = new File(i2pdpath, "assets.ready");
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
StringBuilder text = new StringBuilder();
if (holderFile.exists()) {
try { // if holder file exists, read assets version string
FileReader fileReader = new FileReader(holderFile);
try {
BufferedReader br = new BufferedReader(fileReader);
try {
String line;
while ((line = br.readLine()) != null) {
text.append(line);
}
}finally {
try{
br.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} finally {
try{
fileReader.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
// if version differs from current app version or null, try to delete certificates folder
if (!text.toString().contains(versionName)) try {
boolean deleteResult = holderFile.delete();
if(!deleteResult)Log.e(TAG, "holderFile.delete() returned "+deleteResult+", absolute path='"+holderFile.getAbsolutePath()+"'");
File certPath = new File(i2pdpath, "certificates");
deleteRecursive(certPath);
}
catch (Throwable tr) {
Log.e(TAG, "", tr);
}
// copy assets. If processed file exists, it won't be overwritten
copyAsset("addressbook");
copyAsset("certificates");
copyAsset("tunnels.d");
copyAsset("i2pd.conf");
copyAsset("subscriptions.txt");
copyAsset("tunnels.conf");
// update holder file about successful copying
FileWriter writer = new FileWriter(holderFile);
if (!assetsCopied) {
try {
writer.append(versionName);
} finally {
try{
writer.close();
}catch (IOException e){
Log.e(TAG,"on writer close", e);
}
}
}
catch (Throwable tr)
{
Log.e(TAG,"on assets copying", tr);
assetsCopied = true; // prevent from running on every state update
File holderFile = new File(i2pdpath, "assets.ready");
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
StringBuilder text = new StringBuilder();
if (holderFile.exists()) {
try { // if holder file exists, read assets version string
FileReader fileReader = new FileReader(holderFile);
try {
BufferedReader br = new BufferedReader(fileReader);
try {
String line;
while ((line = br.readLine()) != null) {
text.append(line);
}
}finally {
try {
br.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} finally {
try {
fileReader.close();
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
} catch (IOException e) {
Log.e(TAG, "", e);
}
}
// if version differs from current app version or null, try to delete certificates folder
if (!text.toString().contains(versionName))
try {
boolean deleteResult = holderFile.delete();
if (!deleteResult)
Log.e(TAG, "holderFile.delete() returned " + deleteResult + ", absolute path='" + holderFile.getAbsolutePath() + "'");
File certPath = new File(i2pdpath, "certificates");
deleteRecursive(certPath);
}
catch (Throwable tr) {
Log.e(TAG, "", tr);
}
// copy assets. If processed file exists, it won't be overwritten
copyAsset("addressbook");
copyAsset("certificates");
copyAsset("tunnels.d");
copyAsset("i2pd.conf");
copyAsset("subscriptions.txt");
copyAsset("tunnels.conf");
// update holder file about successful copying
FileWriter writer = new FileWriter(holderFile);
try {
writer.append(versionName);
} finally {
try {
writer.close();
} catch (IOException e) {
Log.e(TAG,"on writer close", e);
}
}
}
catch (Throwable tr)
{
Log.e(TAG,"on assets copying", tr);
}
}
}
@SuppressLint("BatteryLife")
private void openBatteryOptimizationDialogIfNeeded() {
boolean questionEnabled = getPreferences().getBoolean(getBatteryOptimizationPreferenceKey(), true);
Log.i(TAG,"BATT_OPTIM_questionEnabled=="+questionEnabled);
Log.i(TAG, "BATT_OPTIM_questionEnabled==" + questionEnabled);
if (!isKnownIgnoringBatteryOptimizations()
&& android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M
&& questionEnabled) {
@ -576,7 +591,7 @@ public class I2PDActivity extends Activity {
try {
startActivity(new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse(PACKAGE_URI_SCHEME + getPackageName())));
} catch (ActivityNotFoundException e) {
Log.e(TAG,"BATT_OPTIM_ActvtNotFound", e);
Log.e(TAG, "BATT_OPTIM_ActvtNotFound", e);
Toast.makeText(this, R.string.device_does_not_support_disabling_battery_optimizations, Toast.LENGTH_SHORT).show();
}
});
@ -595,14 +610,14 @@ public class I2PDActivity extends Activity {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (pm == null) {
Log.i(TAG, "BATT_OPTIM: POWER_SERVICE==null");
return false;
}
boolean ignoring = pm.isIgnoringBatteryOptimizations(getPackageName());
Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
return ignoring;
Log.i(TAG, "BATT_OPTIM: POWER_SERVICE==null");
return false;
}
boolean ignoring = pm.isIgnoringBatteryOptimizations(getPackageName());
Log.i(TAG, "BATT_OPTIM: ignoring==" + ignoring);
return ignoring;
} else {
Log.i(TAG, "BATT_OPTIM: old sdk version=="+Build.VERSION.SDK_INT);
Log.i(TAG, "BATT_OPTIM: old sdk version==" + Build.VERSION.SDK_INT);
return false;
}
}
@ -626,12 +641,12 @@ public class I2PDActivity extends Activity {
//moveTaskToBack(true);
finish();
}
}catch (Throwable tr) {
} catch (Throwable tr) {
Log.e(TAG, "", tr);
}
try{
try {
daemon.stopDaemon();
}catch (Throwable tr) {
} catch (Throwable tr) {
Log.e(TAG, "", tr);
}
System.exit(0);

View File

@ -16,10 +16,14 @@ public class I2PD_JNI {
public static native void startAcceptingTunnels();
public static native void reloadTunnelsConfigs();
public static native void onNetworkStateChanged(boolean isConnected);
public static native void setDataDir(String jdataDir);
public static native int GetTransitTunnelsCount();
public static void loadLibraries() {
//System.loadLibrary("c++_shared");
System.loadLibrary("i2pd");

View File

@ -1,4 +1,4 @@
version: 2.30.0.{build}
version: 2.32.0.{build}
pull_requests:
do_not_increment_build_number: true
branches:
@ -14,34 +14,25 @@ environment:
CHERE_INVOKING: enabled_from_arguments
matrix:
- MSYSTEM: MINGW64
MSYS_PACKAGES: mingw-w64-x86_64-boost mingw-w64-x86_64-miniupnpc
MSYS_BITNESS: 64
- MSYSTEM: MINGW32
MSYS_PACKAGES: mingw-w64-i686-boost mingw-w64-i686-miniupnpc
MSYS_BITNESS: 32
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"
# 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"
- 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"
)
# update packages and install required
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu ${MSYS_PACKAGES}"
build_script:
- cmd: >-
cd \projects\i2pd
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
- echo MSYSTEM = %MSYSTEM%, bitness = %MSYS_BITNESS%
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes -j3"
- 7z a -tzip -mx9 -mmt i2pd-mingw-win%MSYS_BITNESS%.zip i2pd.exe
test: off

View File

@ -1,28 +1,32 @@
cmake_minimum_required ( VERSION 2.8.12 )
cmake_minimum_required(VERSION 2.8.12)
# this addresses CMP0059 with CMake > 3.3 for PCH flags
cmake_policy( VERSION 2.8.12 )
project ( "i2pd" )
cmake_policy(VERSION 2.8.12)
project("i2pd")
# for debugging
#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
option(WITH_AESNI "Use AES-NI instructions set" OFF)
option(WITH_AVX "Use AVX instructions" OFF)
option(WITH_HARDENING "Use hardening compiler flags" OFF)
option(WITH_LIBRARY "Build library" ON)
option(WITH_BINARY "Build binary" ON)
option(WITH_STATIC "Static build" OFF)
option(WITH_UPNP "Include support for UPnP client" 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_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
option(WITH_AESNI "Use AES-NI instructions set" OFF)
option(WITH_AVX "Use AVX instructions" OFF)
option(WITH_HARDENING "Use hardening compiler flags" OFF)
option(WITH_LIBRARY "Build library" ON)
option(WITH_BINARY "Build binary" ON)
option(WITH_STATIC "Static build" OFF)
option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_PCH "Use precompiled header" OFF)
option(WITH_MESHNET "Build for cjdns test network" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
# paths
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
set ( CMAKE_SOURCE_DIR ".." )
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "..")
# architecture
include(TargetArch)
@ -30,67 +34,65 @@ target_architecture(ARCHITECTURE)
set(LIBI2PD_SRC_DIR ../libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
set(DAEMON_SRC_DIR ../daemon)
include_directories(${LIBI2PD_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}/ChaCha20.cpp"
"${LIBI2PD_SRC_DIR}/Config.cpp"
"${LIBI2PD_SRC_DIR}/CPU.cpp"
"${LIBI2PD_SRC_DIR}/Crypto.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}/Gost.cpp"
"${LIBI2PD_SRC_DIR}/Gzip.cpp"
"${LIBI2PD_SRC_DIR}/HTTP.cpp"
"${LIBI2PD_SRC_DIR}/I2NPProtocol.cpp"
"${LIBI2PD_SRC_DIR}/Identity.cpp"
"${LIBI2PD_SRC_DIR}/LeaseSet.cpp"
"${LIBI2PD_SRC_DIR}/FS.cpp"
"${LIBI2PD_SRC_DIR}/Log.cpp"
"${LIBI2PD_SRC_DIR}/NTCPSession.cpp"
"${LIBI2PD_SRC_DIR}/NetDbRequests.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}/Reseed.cpp"
"${LIBI2PD_SRC_DIR}/RouterContext.cpp"
"${LIBI2PD_SRC_DIR}/RouterInfo.cpp"
"${LIBI2PD_SRC_DIR}/Signature.cpp"
"${LIBI2PD_SRC_DIR}/SSU.cpp"
"${LIBI2PD_SRC_DIR}/SSUData.cpp"
"${LIBI2PD_SRC_DIR}/SSUSession.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}/api.cpp"
"${LIBI2PD_SRC_DIR}/Gost.cpp"
"${LIBI2PD_SRC_DIR}/ChaCha20.cpp"
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
"${LIBI2PD_SRC_DIR}/Ed25519.cpp"
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
"${LIBI2PD_SRC_DIR}/Blinding.cpp"
"${LIBI2PD_SRC_DIR}/Elligator.cpp"
"${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"
"${LIBI2PD_SRC_DIR}/TransitTunnel.cpp"
"${LIBI2PD_SRC_DIR}/Transports.cpp"
"${LIBI2PD_SRC_DIR}/Tunnel.cpp"
"${LIBI2PD_SRC_DIR}/TunnelEndpoint.cpp"
"${LIBI2PD_SRC_DIR}/TunnelGateway.cpp"
"${LIBI2PD_SRC_DIR}/TunnelPool.cpp"
"${LIBI2PD_SRC_DIR}/util.cpp"
)
if (WIN32 OR MSYS)
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
endif ()
add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "")
if (WITH_LIBRARY)
if(WITH_LIBRARY)
install(TARGETS libi2pd
EXPORT libi2pd
ARCHIVE DESTINATION lib
@ -101,7 +103,7 @@ if (WITH_LIBRARY)
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
set (CLIENT_SRC
set(CLIENT_SRC
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/BOB.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/ClientContext.cpp"
@ -117,7 +119,7 @@ set (CLIENT_SRC
add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
if (WITH_LIBRARY)
if(WITH_LIBRARY)
install(TARGETS libi2pdclient
EXPORT libi2pdclient
ARCHIVE DESTINATION lib
@ -125,9 +127,7 @@ if (WITH_LIBRARY)
COMPONENT Libraries)
endif()
set(DAEMON_SRC_DIR ../daemon)
set (DAEMON_SRC
set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
"${DAEMON_SRC_DIR}/I2PControl.cpp"
@ -135,37 +135,20 @@ set (DAEMON_SRC
"${DAEMON_SRC_DIR}/UPnP.cpp"
)
if (WITH_MESHNET)
if(WITH_MESHNET)
add_definitions(-DMESHNET)
endif ()
endif()
if (WITH_UPNP)
if(WITH_UPNP)
add_definitions(-DUSE_UPNP)
if (NOT MSVC AND NOT MSYS)
set(DL_LIB ${CMAKE_DL_LIBS})
endif ()
endif ()
endif()
# compiler flags customization (by vendor)
if (MSVC)
add_definitions( -DWIN32_LEAN_AND_MEAN -DNOMINMAX )
# TODO Check & report to Boost dev, there should be no need for these two
add_definitions( -DBOOST_THREAD_NO_LIB -DBOOST_CHRONO_NO_LIB )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL" )
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 ()
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
# check for c++17 & c++11 support
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?")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
if (WITH_HARDENING)
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} -fstack-protector --param ssp-buffer-size=4" )
endif ()
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
if(WITH_HARDENING)
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} -fstack-protector --param ssp-buffer-size=4")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# more tweaks
if (LINUX)
set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++" ) # required for <atomic>
if(LINUX)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++") # required for <atomic>
list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++
endif()
if (NOT (MSVC OR MSYS OR APPLE))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions")
endif()
endif ()
endif()
if (WITH_HARDENING AND MSVC)
# Most security options like dynamic base, buffer & stack checks are ON by default
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /guard:cf" )
endif ()
# 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))
# 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
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")
add_definitions("-D_GLIBCXX_USE_NANOSLEEP=1")
endif()
endif()
if (WITH_THREADSANITIZER)
if (WITH_ADDRSANITIZER)
message( FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer")
elseif (NOT MSVC)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread" )
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread" )
else ()
message( SEND_ERROR "MSVC does not support address sanitizer option")
if(WITH_AESNI)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
add_definitions(-DAESNI)
endif()
if(WITH_AVX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
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()
@ -253,141 +217,87 @@ endif()
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
# use imported Threads::Threads instead
set(THREADS_PREFER_PTHREAD_FLAG ON)
if (IOS)
if(IOS)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
else()
find_package ( Threads REQUIRED )
find_package(Threads REQUIRED)
endif()
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
if (WITH_STATIC)
if(WITH_STATIC)
set(Boost_USE_STATIC_LIBS 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)
if (${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
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,-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 ()
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
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,-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()
else()
if (NOT WIN32 AND NOT MSYS)
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
# No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
endif ()
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
# No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
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})
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)
get_directory_property(DEFS DEFINITIONS)
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
add_custom_command(TARGET stdafx PRE_BUILD
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
)
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
endif()
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
get_directory_property(DEFS DEFINITIONS)
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
add_custom_command(TARGET stdafx PRE_BUILD
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
)
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
target_link_libraries(libi2pd stdafx)
endif()
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)
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
endif()
find_package ( OpenSSL REQUIRED )
find_package(OpenSSL REQUIRED)
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
endif()
if (WITH_UPNP)
find_package ( MiniUPnPc REQUIRED )
include_directories( SYSTEM ${MINIUPNPC_INCLUDE_DIR} )
if(WITH_UPNP)
find_package(MiniUPnPc REQUIRED)
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()
find_package ( ZLIB )
if (NOT 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()
find_package(ZLIB)
if(ZLIB_FOUND)
link_directories(${ZLIB_ROOT}/lib)
endif ()
if (WITH_STATIC AND (MSVC OR MSYS))
set ( ZLIB_LIBRARY debug zlibstaticd optimized zlibstatic CACHE STRING "zlib libraries" FORCE)
endif ()
endif()
# 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
if (WITH_MESHNET)
if(WITH_MESHNET)
message(STATUS "Building for testnet")
message(WARNING "This build will NOT work on mainline i2p")
endif()
include(CheckAtomic)
if(NOT MSYS)
include(CheckAtomic)
endif()
# show summary
message(STATUS "---------------------------------------")
@ -414,32 +324,24 @@ message(STATUS "---------------------------------------")
#Handle paths nicely
include(GNUInstallDirs)
if (WITH_BINARY)
add_executable ( "${PROJECT_NAME}" ${DAEMON_SRC} )
if (WIN32 AND WITH_GUI)
set_target_properties("${PROJECT_NAME}" PROPERTIES WIN32_EXECUTABLE TRUE )
endif()
if(NOT MSVC)
if (WITH_STATIC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static" )
endif ()
if(WITH_BINARY)
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
if(WITH_STATIC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif()
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)
endif()
if(WITH_PCH)
target_compile_options("${PROJECT_NAME}" PRIVATE -include libi2pd/stdafx.h)
endif()
if (WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT MSYS AND NOT MINGW)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" )
endif ()
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
endif()
if (WITH_UPNP)
target_link_libraries("${PROJECT_NAME}" "${MINIUPNPC_LIBRARY}")
endif ()
if(WITH_UPNP)
set(UPNP_LIB ${MINIUPNPC_LIBRARY})
endif()
# 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)
@ -447,128 +349,15 @@ if (WITH_BINARY)
list(REMOVE_AT Boost_LIBRARIES -1)
endif()
if (MSYS OR MINGW)
set (MINGW_EXTRA -lws2_32 -lmswsock -liphlpapi )
endif ()
if (WITH_STATIC)
if(WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS})
endif()
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)
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")
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 "")
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")
endif()
set(CPACK_PACKAGE_EXECUTABLES "i2pd" "C++ I2P daemon")
set(CPACK_SOURCE_GENERATOR "TGZ")
include(CPack)

View 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

View File

@ -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()

View File

@ -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...

View File

@ -19,6 +19,7 @@
/etc/nsswitch.conf r,
/etc/resolv.conf r,
/run/resolvconf/resolv.conf r,
/run/systemd/resolve/resolv.conf r,
/run/systemd/resolve/stub-resolv.conf r,
# path specific (feel free to modify if you have another paths)

View 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-----

View File

@ -1,2 +1,2 @@
d /var/run/i2pd 0755 i2pd i2pd - -
d /run/i2pd 0755 i2pd i2pd - -
d /var/log/i2pd 0755 i2pd i2pd - -

View File

@ -36,9 +36,9 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib
&& cd /usr/local/bin \
&& strip i2pd \
&& 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-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \
libtool g++ gcc pkgconfig
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 pcre2 \
libtool g++ gcc
# 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++

View File

@ -13,10 +13,10 @@
## Tunnels config files path
## Use that path to store separated tunnels in different config files.
## 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)
# pidfile = /var/run/i2pd.pid
## Where to write pidfile (default: i2pd.pid, not used in Windows)
# pidfile = /run/i2pd.pid
## Logging configuration section
## By default logs go to stdout with level 'info' and higher
@ -27,10 +27,10 @@
## * syslog - use syslog, see man 3 syslog
# log = file
## Path to logfile (default - autodetect)
# logfile = /var/log/i2pd.log
## Log messages above this level (debug, *info, warn, error, none)
# logfile = /var/log/i2pd/i2pd.log
## Log messages above this level (debug, info, *warn, error, none)
## 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)
# logclftime = true

9
contrib/i2pd.logrotate Normal file
View File

@ -0,0 +1,9 @@
"/var/log/i2pd/*.log" {
copytruncate
daily
rotate 5
compress
delaycompress
missingok
notifempty
}

View File

@ -11,9 +11,9 @@ RuntimeDirectoryMode=0700
LogsDirectory=i2pd
LogsDirectoryMode=0700
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
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/var/run/i2pd/i2pd.pid
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/sh -c "kill -HUP $MAINPID"
PIDFile=/run/i2pd/i2pd.pid
### Uncomment, if auto restart needed
#Restart=on-failure
@ -27,7 +27,6 @@ KillSignal=SIGQUIT
LimitNOFILE=4096
# To enable write of coredump uncomment this
#LimitCORE=infinity
PrivateDevices=yes
[Install]
WantedBy=multi-user.target

View File

@ -1,31 +1,32 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.30.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
Name: i2pd-git
Version: 2.32.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
License: BSD
URL: https://github.com/PurpleI2P/i2pd
Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz
License: BSD
URL: https://github.com/PurpleI2P/i2pd
Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz
%if 0%{?rhel} == 7
BuildRequires: cmake3
%if 0%{?rhel} == 7
BuildRequires: cmake3
%else
BuildRequires: cmake
BuildRequires: cmake
%endif
BuildRequires: chrpath
BuildRequires: gcc-c++
BuildRequires: zlib-devel
BuildRequires: boost-devel
BuildRequires: openssl-devel
BuildRequires: miniupnpc-devel
BuildRequires: systemd-units
BuildRequires: chrpath
BuildRequires: gcc-c++
BuildRequires: zlib-devel
BuildRequires: boost-devel
BuildRequires: openssl-devel
BuildRequires: miniupnpc-devel
BuildRequires: systemd-units
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
@ -73,16 +74,17 @@ pushd build
chrpath -d 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 %{_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 755 %{buildroot}%{_datadir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name}
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates
%{__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/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
@ -108,16 +110,30 @@ getent passwd i2pd >/dev/null || \
%files
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
%{_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
%{_mandir}/man1/i2pd.1*
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
%{_datadir}/%{name}/certificates
%{_datadir}/i2pd/certificates
%{_sharedstatedir}/i2pd/certificates
%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
- update to 2.30.0

View File

@ -1 +0,0 @@
../i2pd.service

View File

@ -1,29 +1,30 @@
Name: i2pd
Version: 2.30.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
Name: i2pd
Version: 2.32.0
Release: 2%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
License: BSD
URL: https://github.com/PurpleI2P/i2pd
Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz
License: BSD
URL: https://github.com/PurpleI2P/i2pd
Source0: https://github.com/PurpleI2P/i2pd/archive/%{version}/%name-%version.tar.gz
%if 0%{?rhel} == 7
BuildRequires: cmake3
%if 0%{?rhel} == 7
BuildRequires: cmake3
%else
BuildRequires: cmake
BuildRequires: cmake
%endif
BuildRequires: chrpath
BuildRequires: gcc-c++
BuildRequires: zlib-devel
BuildRequires: boost-devel
BuildRequires: openssl-devel
BuildRequires: miniupnpc-devel
BuildRequires: systemd-units
BuildRequires: chrpath
BuildRequires: gcc-c++
BuildRequires: zlib-devel
BuildRequires: boost-devel
BuildRequires: openssl-devel
BuildRequires: miniupnpc-devel
BuildRequires: systemd-units
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
@ -70,18 +71,19 @@ pushd build
%endif
chrpath -d 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 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
install -d -m 755 %{buildroot}%{_datadir}/i2pd
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
%{__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/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}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
%pre
@ -104,18 +106,32 @@ getent passwd i2pd >/dev/null || \
%files
%doc LICENSE README.md
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
%{_sbindir}/i2pd
%{_datadir}/i2pd/certificates
%config(noreplace) %{_sysconfdir}/i2pd/*
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
/%{_unitdir}/i2pd.service
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/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
%{_mandir}/man1/i2pd.1*
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
%{_datadir}/i2pd/certificates
%{_sharedstatedir}/i2pd/certificates
%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
- update to 2.30.0

View File

@ -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 <memory>
@ -71,18 +79,13 @@ namespace i2p
i2p::fs::Init();
datadir = i2p::fs::GetDataDir();
// TODO: drop old name detection in v2.8.0
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");
if (!i2p::fs::Exists (config)) {
// use i2pd.conf only if exists
config = ""; /* reset */
}
config = i2p::fs::DataDirPath("i2pd.conf");
if (!i2p::fs::Exists (config)) {
// use i2pd.conf only if exists
config = ""; /* reset */
}
}
@ -132,8 +135,8 @@ namespace i2p
i2p::context.SetNetID (netID);
i2p::context.Init ();
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
#ifdef MESHNET
// manual override for meshnet
ipv4 = false;
@ -148,7 +151,7 @@ namespace i2p
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2)
@ -177,10 +180,13 @@ namespace i2p
SetMaxNumTransitTunnels (transitTunnels);
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) {
if (isFloodfill)
{
LogPrint(eLogInfo, "Daemon: router will be floodfill");
i2p::context.SetFloodfill (true);
} else {
}
else
{
i2p::context.SetFloodfill (false);
}
@ -248,7 +254,8 @@ namespace i2p
i2p::transport::transports.RestrictRoutesToFamilies(fams);
restricted = fams.size() > 0;
}
if (routers.length() > 0) {
if (routers.length() > 0)
{
std::set<i2p::data::IdentHash> idents;
size_t pos = 0, comma;
do
@ -265,7 +272,7 @@ namespace i2p
restricted = idents.size() > 0;
}
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);
@ -284,7 +291,8 @@ namespace i2p
i2p::data::netdb.Start();
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->Start ();
}
@ -297,7 +305,7 @@ namespace i2p
}
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
bool ssu; i2p::config::GetOption("ssu", ssu);
bool ssu; i2p::config::GetOption("ssu", ssu);
LogPrint(eLogInfo, "Daemon: starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
@ -315,15 +323,23 @@ namespace i2p
}
bool http; i2p::config::GetOption("http.enabled", http);
if (http) {
if (http)
{
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
d.httpServer->Start();
uint16_t httpPort; i2p::config::GetOption("http.port", 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->Start();
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
}
}
LogPrint(eLogInfo, "Daemon: starting Tunnels");
i2p::tunnel::tunnels.Start();
@ -336,8 +352,16 @@ namespace i2p
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
d.m_I2PControlService->Start ();
try
{
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
d.m_I2PControlService->Start ();
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
}
}
return true;
}

View File

@ -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__
#define DAEMON_H__
@ -13,9 +21,10 @@ namespace util
class Daemon_Singleton
{
public:
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init(int argc, char* argv[]);
virtual bool start();
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init(int argc, char* argv[]);
virtual bool start();
virtual bool stop();
virtual void run () {};
@ -23,6 +32,7 @@ namespace util
bool running;
protected:
Daemon_Singleton();
virtual ~Daemon_Singleton();
@ -39,6 +49,7 @@ namespace util
class DaemonQT: public i2p::util::Daemon_Singleton
{
public:
static DaemonQT& Instance()
{
static DaemonQT instance;
@ -51,6 +62,7 @@ namespace util
class DaemonWin32 : public Daemon_Singleton
{
public:
static DaemonWin32& Instance()
{
static DaemonWin32 instance;
@ -72,6 +84,7 @@ namespace util
class DaemonAndroid: public i2p::util::Daemon_Singleton
{
public:
static DaemonAndroid& Instance()
{
static DaemonAndroid instance;
@ -83,6 +96,7 @@ namespace util
class DaemonLinux : public Daemon_Singleton
{
public:
static DaemonLinux& Instance()
{
static DaemonLinux instance;
@ -94,10 +108,12 @@ namespace util
void run ();
private:
std::string pidfile;
int pidFH;
public:
int gracefulShutdownInterval; // in seconds
};
#endif

View File

@ -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 <sstream>
#include <thread>
@ -22,6 +30,7 @@
#include "HTTPServer.h"
#include "Daemon.h"
#include "util.h"
#include "ECIESX25519AEADRatchetSession.h"
#ifdef WIN32_APP
#include "Win32/Win32App.h"
#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"
" a, .slide label { text-decoration: none; color: #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"
" .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\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_LOGLEVEL[] = "set_loglevel";
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
@ -397,18 +407,36 @@ namespace http {
}
}
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 ()) {
std::stringstream tmp_s; uint32_t out_tags = 0;
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";
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"
<< "<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
s << "Outgoing: <i>0</i><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)
@ -580,14 +608,25 @@ namespace http {
else
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
#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 << " <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 << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><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 << "<b>Logging level</b><br>\r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \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)
@ -861,8 +900,8 @@ namespace http {
void HTTPConnection::Receive ()
{
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
}
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
@ -1125,6 +1164,19 @@ namespace http {
res.add_header("Refresh", redirect.c_str());
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>:&nbsp;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
{
res.code = 400;
@ -1182,8 +1234,9 @@ namespace http {
i2p::config::SetOption("http.pass", pass);
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
}
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 ();
Accept ();
}

View File

@ -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__
#define HTTP_SERVER_H__
@ -79,17 +87,17 @@ namespace http
std::string m_Hostname;
};
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
enum OutputFormatEnum { forWebConsole, forQtUi };
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
void ShowLocalDestinations (std::stringstream& s);
void ShowLeasesSets(std::stringstream& s);
void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
enum OutputFormatEnum { forWebConsole, forQtUi };
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
void ShowLocalDestinations (std::stringstream& s);
void ShowLeasesSets(std::stringstream& s);
void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
} // http
} // i2p

View File

@ -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 <sstream>
#include <openssl/x509.h>
@ -59,29 +67,28 @@ namespace client
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
// handlers
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
// I2PControl
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
// RouterInfo
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
&I2PControlService::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
@ -97,10 +104,10 @@ namespace client
// ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
}
I2PControlService::~I2PControlService ()
@ -500,7 +507,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode)
{
{
Daemon.running = 0;
});
}
@ -514,7 +521,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode)
{
{
Daemon.running = 0;
});
}

View File

@ -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__
#define I2P_CONTROL_H__
@ -27,6 +35,7 @@ namespace client
class I2PControlService
{
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
public:
I2PControlService (const std::string& address, int port);

View File

@ -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
#include <string>
#include <thread>
@ -80,10 +88,10 @@ namespace transport
void UPnP::Discover ()
{
bool isError;
int err;
int err;
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNPDISCOVER_SUCCESS;
err = UPNPDISCOVER_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 14)
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
@ -92,9 +100,9 @@ namespace transport
#endif
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;
#endif // MINIUPNPC_API_VERSION >= 8
{
@ -105,15 +113,15 @@ namespace transport
if (isError)
{
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
return;
}
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)
{
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
@ -124,14 +132,14 @@ namespace transport
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0])
{
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
return;
}
}
}
else
{
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
return;
}
@ -182,7 +190,7 @@ namespace transport
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
@ -202,7 +210,7 @@ namespace transport
}
else
{
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return;
}
}
@ -219,14 +227,14 @@ namespace transport
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
if(!m_upnpUrlsInitialized) {
return;
}
if(!m_upnpUrlsInitialized) {
return;
}
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int err = UPNPCOMMAND_SUCCESS;
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS)
if (err == UPNPCOMMAND_SUCCESS)
{
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
@ -237,11 +245,11 @@ namespace transport
{
freeUPNPDevlist (m_Devlist);
m_Devlist = 0;
if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{

View File

@ -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__
#define __UPNP_H__
@ -33,41 +41,41 @@ namespace transport
{
public:
UPnP ();
~UPnP ();
void Close ();
UPnP ();
~UPnP ();
void Close ();
void Start ();
void Stop ();
void Start ();
void Stop ();
private:
void Discover ();
int CheckMapping (const char* port, const char* type);
void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping ();
void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void Discover ();
int CheckMapping (const char* port, const char* type);
void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping ();
void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void Run ();
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void Run ();
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
private:
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started;
std::mutex m_StartedMutex;
boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer;
bool m_upnpUrlsInitialized=false;
struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData;
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started;
std::mutex m_StartedMutex;
boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer;
bool m_upnpUrlsInitialized = false;
struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData;
// For miniupnpc
struct UPNPDev * m_Devlist = 0;
char m_NetworkAddr[64];
char m_externalIPAddress[40];
// For miniupnpc
struct UPNPDev * m_Devlist = 0;
char m_NetworkAddr[64];
char m_externalIPAddress[40];
};
}
}
@ -79,10 +87,10 @@ namespace transport {
class UPnP {
public:
UPnP () {};
~UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
void Stop () {};
UPnP () {};
~UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
void Stop () {};
};
}
}

View File

@ -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"
#ifndef _WIN32
@ -175,7 +183,6 @@ namespace i2p
bool DaemonLinux::stop()
{
i2p::fs::Remove(pidfile);
return Daemon_Singleton::stop();
}
@ -197,5 +204,4 @@ namespace i2p
}
}
}
#endif

View File

@ -1,24 +1,31 @@
/*
* 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 "Daemon.h"
#if defined(QT_GUI_LIB)
namespace i2p
{
namespace qt
{
int RunQT (int argc, char* argv[]);
int RunQT (int argc, char* argv[]);
}
}
int main( int argc, char* argv[] )
{
return i2p::qt::RunQT (argc, argv);
}
int main( int argc, char* argv[] )
{
return i2p::qt::RunQT (argc, argv);
}
#else
int main( int argc, char* argv[] )
{
if (Daemon.init(argc, argv))
if (Daemon.init(argc, argv))
{
if (Daemon.start())
Daemon.run ();

15
debian/changelog vendored
View File

@ -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
* updated to version 2.30.0/0.9.45

6
debian/copyright vendored
View File

@ -3,7 +3,7 @@ Upstream-Name: i2pd
Source: https://github.com/PurpleI2P
Files: *
Copyright: 2013-2017 PurpleI2P
Copyright: 2013-2020 PurpleI2P
License: BSD-3-clause
Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl
@ -16,8 +16,8 @@ License: BSD-2-Clause
Files: debian/*
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
2014-2016 hagen <hagen@i2pmail.org>
2016-2017 R4SAS <r4sas@i2pmail.org>
2017-2018 Yangfl <mmyangfl@gmail.com>
2016-2020 R4SAS <r4sas@i2pmail.org>
2017-2020 Yangfl <mmyangfl@gmail.com>
License: GPL-2+
License: BSD-3-clause

View File

@ -1,9 +0,0 @@
/var/log/i2pd/i2pd.log {
rotate 6
daily
missingok
notifempty
compress
delaycompress
copytruncate
}

1
debian/i2pd.logrotate vendored Symbolic link
View File

@ -0,0 +1 @@
../contrib/i2pd.logrotate

View File

@ -1,17 +1,15 @@
diff --git a/Makefile b/Makefile
index bdadfe0..2f71eec 100644
--- a/Makefile
+++ b/Makefile
@@ -9,10 +9,10 @@ DEPS := obj/make.dep
Index: i2pd/Makefile
===================================================================
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -13,8 +13,8 @@ DAEMON_SRC_DIR := daemon
include filelist.mk
-USE_AESNI := yes
+USE_AESNI := no
-USE_AVX := yes
+USE_AESNI := no
+USE_AVX := no
USE_STATIC := no
USE_MESHNET := no
USE_UPNP := no
DEBUG := yes

View File

@ -4,10 +4,12 @@ Author: r4sas <r4sas@i2pmail.org>
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2018-08-25
Last-Update: 2020-05-25
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
Index: i2pd/contrib/i2pd.service
===================================================================
--- i2pd.orig/contrib/i2pd.service
+++ i2pd/contrib/i2pd.service
@@ -6,10 +6,10 @@ After=network.target
[Service]
User=i2pd
@ -21,5 +23,5 @@ Last-Update: 2018-08-25
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
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
ExecReload=/bin/kill -HUP $MAINPID
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/sh -c "kill -HUP $MAINPID"

2
debian/postrm vendored
View File

@ -6,7 +6,7 @@ if [ "$1" = "purge" ]; then
rm -rf /etc/i2pd
rm -rf /var/lib/i2pd
rm -rf /var/log/i2pd
rm -rf /var/run/i2pd
rm -rf /run/i2pd
fi
#DEBHELPER#

View File

@ -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 <string.h>
@ -7,7 +15,8 @@ namespace i2p
{
namespace data
{
static const char T32[32] = {
static const char T32[32] =
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
@ -29,15 +38,16 @@ namespace data
* Direct Substitution Table
*/
static const char T64[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '-', '~'
static const char T64[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '-', '~'
};
const char * GetBase64SubstitutionTable ()
@ -67,14 +77,12 @@ namespace data
*
*/
size_t /* Number of bytes in the encoded buffer */
ByteStreamToBase64 (
const uint8_t * InBuffer, /* Input buffer, binary data */
size_t InCount, /* Number of bytes in the input buffer */
char * OutBuffer, /* output buffer */
size_t len /* length of output buffer */
size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */
const uint8_t * InBuffer, /* Input buffer, binary data */
size_t InCount, /* Number of bytes in the input buffer */
char * OutBuffer, /* output buffer */
size_t len /* length of output buffer */
)
{
unsigned char * ps;
unsigned char * pd;
@ -83,55 +91,60 @@ namespace data
int i;
int n;
int m;
size_t outCount;
size_t outCount;
ps = (unsigned char *)InBuffer;
n = InCount/3;
m = InCount%3;
n = InCount / 3;
m = InCount % 3;
if (!m)
outCount = 4*n;
outCount = 4 * n;
else
outCount = 4*(n+1);
outCount = 4 * (n + 1);
if (outCount > len) return 0;
pd = (unsigned char *)OutBuffer;
for ( i = 0; i<n; i++ ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x30;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<=2;
acc_2 = *ps++;
acc_1 |= acc_2>>6; /* base64 digit #3 */
*pd++ = T64[acc_1];
acc_2 &= 0x3f; /* base64 digit #4 */
*pd++ = T64[acc_2];
for ( i = 0; i < n; i++ )
{
acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x30;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<= 2;
acc_2 = *ps++;
acc_1 |= acc_2 >> 6; /* base64 digit #3 */
*pd++ = T64[acc_1];
acc_2 &= 0x3f; /* base64 digit #4 */
*pd++ = T64[acc_2];
}
if ( m == 1 ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
*pd++ = T64[acc_2];
*pd++ = P64;
*pd++ = P64;
if ( m == 1 )
{
acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
*pd++ = T64[acc_2];
*pd++ = P64;
*pd++ = P64;
}
else if ( m == 2 ){
acc_1 = *ps++;
acc_2 = (acc_1<<4)&0x3f;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<=2; /* base64 digit #3 */
*pd++ = T64[acc_1];
*pd++ = P64;
else if ( m == 2 )
{
acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x3f;
acc_1 >>= 2; /* base64 digit #1 */
*pd++ = T64[acc_1];
acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
*pd++ = T64[acc_2];
acc_1 &= 0x0f;
acc_1 <<= 2; /* base64 digit #3 */
*pd++ = T64[acc_1];
*pd++ = P64;
}
return outCount;
@ -147,12 +160,11 @@ namespace data
*
*/
size_t /* Number of output bytes */
Base64ToByteStream (
const char * InBuffer, /* BASE64 encoded buffer */
size_t InCount, /* Number of input bytes */
uint8_t * OutBuffer, /* output buffer length */
size_t len /* length of output buffer */
size_t Base64ToByteStream ( /* Number of output bytes */
const char * InBuffer, /* BASE64 encoded buffer */
size_t InCount, /* Number of input bytes */
uint8_t * OutBuffer, /* output buffer length */
size_t len /* length of output buffer */
)
{
unsigned char * ps;
@ -162,42 +174,52 @@ namespace data
int i;
int n;
int m;
size_t outCount;
size_t outCount;
if (isFirstTime)
iT64Build();
n = InCount / 4;
m = InCount % 4;
if (isFirstTime) iT64Build();
n = InCount/4;
m = InCount%4;
if (InCount && !m)
outCount = 3*n;
else {
outCount = 0;
return 0;
outCount = 3 * n;
else
{
outCount = 0;
return 0;
}
ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 ) outCount--;
while ( *ps-- == P64 )
outCount--;
ps = (unsigned char *)InBuffer;
if (outCount > len) return -1;
if (outCount > len)
return -1;
pd = OutBuffer;
auto endOfOutBuffer = OutBuffer + outCount;
for ( i = 0; i < n; i++ ){
acc_1 = iT64[*ps++];
acc_2 = iT64[*ps++];
acc_1 <<= 2;
acc_1 |= acc_2>>4;
*pd++ = acc_1;
if (pd >= endOfOutBuffer) break;
for ( i = 0; i < n; i++ )
{
acc_1 = iT64[*ps++];
acc_2 = iT64[*ps++];
acc_1 <<= 2;
acc_1 |= acc_2 >> 4;
*pd++ = acc_1;
if (pd >= endOfOutBuffer)
break;
acc_2 <<= 4;
acc_1 = iT64[*ps++];
acc_2 |= acc_1 >> 2;
*pd++ = acc_2;
if (pd >= endOfOutBuffer) break;
acc_2 <<= 4;
acc_1 = iT64[*ps++];
acc_2 |= acc_1 >> 2;
*pd++ = acc_2;
if (pd >= endOfOutBuffer)
break;
acc_2 = iT64[*ps++];
acc_2 |= acc_1 << 6;
*pd++ = acc_2;
acc_2 = iT64[*ps++];
acc_2 |= acc_1 << 6;
*pd++ = acc_2;
}
return outCount;
@ -206,20 +228,25 @@ namespace data
size_t Base64EncodingBufferSize (const size_t input_size)
{
auto d = div (input_size, 3);
if (d.rem) d.quot++;
return 4*d.quot;
if (d.rem)
d.quot++;
return 4 * d.quot;
}
std::string ToBase64Standard (const std::string& in)
{
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);
str[l] = 0;
// replace '-' by '+' and '~' by '/'
for (size_t i = 0; i < l; i++)
if (str[i] == '-') str[i] = '+';
else if (str[i] == '~') str[i] = '/';
if (str[i] == '-')
str[i] = '+';
else if (str[i] == '~')
str[i] = '/';
std::string s(str);
delete[] str;
return s;
@ -236,10 +263,10 @@ namespace data
static void iT64Build()
{
int i;
int i;
isFirstTime = 0;
for ( i=0; i<256; i++ ) iT64[i] = -1;
for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
for ( i = 0; i < 256; i++ ) iT64[i] = -1;
for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i;
iT64[(int)P64] = 0;
}
@ -302,4 +329,3 @@ namespace data
}
}
}

View File

@ -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__
#define BASE_H__
@ -15,9 +23,9 @@ namespace data {
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
/**
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
/**
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
size_t Base64EncodingBufferSize(const size_t input_size);
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization

View File

@ -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 <openssl/sha.h>
#include <openssl/hmac.h>
@ -314,4 +322,3 @@ namespace data
}
}

View File

@ -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__
#define BLINDING_H__

View File

@ -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 "I2PEndian.h"
#include <array>

View File

@ -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_
#define BLOOM_FILTER_H_
#include <memory>

View File

@ -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"
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>

View File

@ -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
#define LIBI2PD_CPU_H
@ -5,10 +13,10 @@ namespace i2p
{
namespace cpu
{
extern bool aesni;
extern bool avx;
extern bool aesni;
extern bool avx;
void Detect();
void Detect();
}
}

View File

@ -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
*
@ -21,34 +21,34 @@ namespace chacha
{
void u32t8le(uint32_t v, uint8_t * p)
{
p[0] = v & 0xff;
p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff;
p[0] = v & 0xff;
p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff;
}
uint32_t u8t32le(const uint8_t * p)
{
uint32_t value = p[3];
uint32_t value = p[3];
value = (value << 8) | p[2];
value = (value << 8) | p[1];
value = (value << 8) | p[0];
value = (value << 8) | p[2];
value = (value << 8) | p[1];
value = (value << 8) | p[0];
return value;
return value;
}
uint32_t rotl32(uint32_t x, int n)
{
return x << n | (x >> (-n & 31));
return x << n | (x >> (-n & 31));
}
void quarterround(uint32_t *x, int a, int b, int c, int d)
{
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
}
@ -61,24 +61,23 @@ void Chacha20Block::operator << (const Chacha20State & st)
void block (Chacha20State &input, int rounds)
{
int i;
Chacha20State x;
x.Copy(input);
for (i = rounds; i > 0; i -= 2)
{
quarterround(x.data, 0, 4, 8, 12);
quarterround(x.data, 1, 5, 9, 13);
quarterround(x.data, 2, 6, 10, 14);
quarterround(x.data, 3, 7, 11, 15);
quarterround(x.data, 0, 5, 10, 15);
quarterround(x.data, 1, 6, 11, 12);
quarterround(x.data, 2, 7, 8, 13);
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
input.block << x;
int i;
Chacha20State x;
x.Copy(input);
for (i = rounds; i > 0; i -= 2)
{
quarterround(x.data, 0, 4, 8, 12);
quarterround(x.data, 1, 5, 9, 13);
quarterround(x.data, 2, 6, 10, 14);
quarterround(x.data, 3, 7, 11, 15);
quarterround(x.data, 0, 5, 10, 15);
quarterround(x.data, 1, 6, 11, 12);
quarterround(x.data, 2, 7, 8, 13);
quarterround(x.data, 3, 4, 9, 14);
}
x += input;
input.block << x;
}
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
@ -88,11 +87,11 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t *
state.data[2] = 0x79622d32;
state.data[3] = 0x6b206574;
for (size_t i = 0; i < 8; i++)
state.data[4 + i] = chacha::u8t32le(key + i * 4);
state.data[4 + i] = chacha::u8t32le(key + i * 4);
state.data[12] = htole32 (counter);
for (size_t i = 0; i < 3; i++)
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
}
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
@ -117,22 +116,22 @@ void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
}
for (size_t i = 0; i < sz; i += chacha::blocksize)
{
chacha::block(state, chacha::rounds);
state.data[12]++;
for (size_t j = i; j < i + chacha::blocksize; j++)
{
if (j >= sz)
chacha::block(state, chacha::rounds);
state.data[12]++;
for (size_t j = i; j < i + chacha::blocksize; j++)
{
if (j >= sz)
{
state.offset = j & 0x3F; // % 64
break;
}
buf[j] ^= state.block.data[j - i];
}
buf[j] ^= state.block.data[j - i];
}
}
}
} // namespace chacha
} // namespace crypto
} // namespace i2p
}
}
#endif

View File

@ -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
*
@ -21,8 +21,8 @@ namespace i2p
{
namespace crypto
{
const std::size_t CHACHA20_KEY_BYTES = 32;
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
const std::size_t CHACHA20_KEY_BYTES = 32;
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
namespace chacha
{
@ -32,12 +32,12 @@ namespace chacha
struct Chacha20State;
struct Chacha20Block
{
Chacha20Block () {};
Chacha20Block (Chacha20Block &&) = delete;
Chacha20Block () {};
Chacha20Block (Chacha20Block &&) = delete;
uint8_t data[blocksize];
uint8_t data[blocksize];
void operator << (const Chacha20State & st);
void operator << (const Chacha20State & st);
};
struct Chacha20State
@ -54,7 +54,7 @@ namespace chacha
void Copy(const Chacha20State & other)
{
memcpy(data, other.data, sizeof(uint32_t) * 16);
memcpy(data, other.data, sizeof(uint32_t) * 16);
}
uint32_t data[16];
Chacha20Block block;
@ -64,9 +64,9 @@ namespace chacha
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
}
}
}
#endif
} // namespace chacha
} // namespace crypto
} // namespace i2p
#endif
#endif

View File

@ -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
*
@ -35,11 +35,11 @@ namespace config {
("version", "Show i2pd version")
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
("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)")
("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)")
("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, ...)")
@ -58,7 +58,7 @@ namespace config {
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
("ntcp", value<bool>()->default_value(false), "Enable NTCP transport (default: disabled)")
("ssu", value<bool>()->default_value(true), "Enable SSU transport (default: enabled)")
("ntcpproxy", value<std::string>()->default_value(""), "Proxy URL for NTCP transport")
#ifdef _WIN32
@ -88,7 +88,7 @@ namespace config {
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
;
options_description httpproxy("HTTP Proxy options");
@ -97,7 +97,8 @@ namespace config {
("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.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.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")
@ -106,6 +107,8 @@ namespace config {
("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.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");
@ -114,7 +117,8 @@ namespace config {
("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.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.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")
@ -124,6 +128,8 @@ namespace config {
("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.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");
@ -131,7 +137,7 @@ namespace config {
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
;
options_description bob("BOB options");
@ -190,16 +196,13 @@ namespace config {
("reseed.urls", value<std::string>()->default_value(
"https://reseed.i2p-projekt.de/,"
"https://i2p.mooo.com/netDb/,"
"https://netdb.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.i2p2.no/,"
"https://reseed-fr.i2pd.xyz/,"
"https://reseed.memcpy.io/,"
"https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/,"
"https://i2p.novg.net/"
"https://reseed.i2pgit.org/,"
"https://i2p.novg.net/"
), "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?")
;
// 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");
exploratory.add_options()
("exploratory.inbound.length", value<int>()->default_value(2), "Exploratory inbound tunnel length")
@ -228,29 +239,29 @@ namespace config {
options_description ntcp2("NTCP2 Options");
ntcp2.add_options()
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
("ntcp2.published", value<bool>()->default_value(true), "Publish NTCP2 (default: enabled)")
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
("ntcp2.published", value<bool>()->default_value(true), "Publish NTCP2 (default: enabled)")
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to bind NTCP2 on")
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
;
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.ntpservers", value<std::string>()->default_value(
"0.pool.ntp.org,"
"1.pool.ntp.org,"
"2.pool.ntp.org,"
"3.pool.ntp.org"
), "Comma separated list of NTCP servers")
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
), "Comma separated list of NTCP servers")
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
;
options_description persist("Network information persisting options");
persist.add_options()
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
("persist.addressbook", value<bool>()->default_value(true), "Persist full addresses (default: true)")
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
("persist.addressbook", value<bool>()->default_value(true), "Persist full addresses (default: true)")
;
m_OptionsDesc
@ -268,6 +279,7 @@ namespace config {
.add(reseed)
.add(addressbook)
.add(trust)
.add(websocket) // deprecated
.add(exploratory)
.add(ntcp2)
.add(nettime)

View File

@ -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
#define CONFIG_H
@ -18,98 +26,101 @@
namespace i2p {
namespace config {
extern boost::program_options::variables_map m_Options;
extern boost::program_options::variables_map m_Options;
/**
* @brief Initialize list of acceptable parameters
*
* Should be called before any Parse* functions.
*/
void Init();
/**
* @brief Initialize list of acceptable parameters
*
* Should be called before any Parse* functions.
*/
void Init();
/**
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
*
* If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0.
*
* In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option,
* and then terminate the program with exitcode 1.
*
* Other exceptions will be passed to higher level.
*/
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
/**
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
*
* If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0.
*
* In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option,
* and then terminate the program with exitcode 1.
*
* Other exceptions will be passed to higher level.
*/
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
/**
* @brief Load and parse given config file
* @param path Path to config file
*
* If error occurred when opening file path is points to,
* we show the error message and terminate program.
*
* In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option,
* and then terminate program with exitcode 1.
*
* Other exceptions will be passed to higher level.
*/
void ParseConfig(const std::string& path);
/**
* @brief Load and parse given config file
* @param path Path to config file
*
* If error occurred when opening file path is points to,
* we show the error message and terminate program.
*
* In case of parameter misuse boost throws an exception.
* We internally handle type boost::program_options::unknown_option,
* and then terminate program with exitcode 1.
*
* Other exceptions will be passed to higher level.
*/
void ParseConfig(const std::string& path);
/**
* @brief Used to combine options from cmdline, config and default values
*/
void Finalize();
/**
* @brief Used to combine options from cmdline, config and default values
*/
void Finalize();
/* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @return this function returns false if parameter not found
*
* Example: uint16_t port; GetOption("sam.port", port);
*/
template<typename T>
bool GetOption(const char *name, T& value) {
if (!m_Options.count(name))
return false;
value = m_Options[name].as<T>();
return true;
}
/**
* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @return this function returns false if parameter not found
*
* Example: uint16_t port; GetOption("sam.port", port);
*/
template<typename T>
bool GetOption(const char *name, T& value)
{
if (!m_Options.count(name))
return false;
value = m_Options[name].as<T>();
return true;
}
template<typename T>
bool GetOption(const std::string& name, T& value)
{
return GetOption (name.c_str (), value);
}
template<typename T>
bool GetOption(const std::string& name, T& value)
{
return GetOption (name.c_str (), value);
}
bool GetOptionAsAny(const char *name, boost::any& value);
bool GetOptionAsAny(const std::string& name, boost::any& value);
bool GetOptionAsAny(const char *name, boost::any& value);
bool GetOptionAsAny(const std::string& name, boost::any& value);
/**
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @return true if value set up successful, false otherwise
*
* Example: uint16_t port = 2827; SetOption("bob.port", port);
*/
template<typename T>
bool SetOption(const char *name, const T& value) {
if (!m_Options.count(name))
return false;
m_Options.at(name).value() = value;
notify(m_Options);
return true;
}
/**
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @return true if value set up successful, false otherwise
*
* Example: uint16_t port = 2827; SetOption("bob.port", port);
*/
template<typename T>
bool SetOption(const char *name, const T& value)
{
if (!m_Options.count(name))
return false;
m_Options.at(name).value() = value;
notify(m_Options);
return true;
}
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false otherwise
*/
bool IsDefault(const char *name);
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false otherwise
*/
bool IsDefault(const char *name);
}
}

View File

@ -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>
#include <vector>
@ -681,12 +689,12 @@ namespace crypto
// AES
#ifdef __AES__
#ifdef ARM64AES
void init_aesenc(void){
#ifdef ARM64AES
void init_aesenc(void){
// TODO: Implementation
}
}
#endif
#endif
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
@ -884,7 +892,6 @@ namespace crypto
}
}
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{
#ifdef __AES__
@ -1364,4 +1371,3 @@ namespace crypto
}
}
}

View File

@ -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__
#define CRYPTO_H__
@ -28,13 +36,13 @@
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif
#endif

View File

@ -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 "Log.h"
#include "Gost.h"
@ -178,4 +186,3 @@ namespace crypto
}
}
}

View File

@ -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__
#define CRYPTO_KEY_H__
@ -126,7 +134,7 @@ namespace crypto
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
~ECIESX25519AEADRatchetEncryptor () {};
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
// copies m_PublicKey to pub
// copies m_PublicKey to pub
private:
@ -153,4 +161,3 @@ namespace crypto
}
#endif

View File

@ -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_
#define CRYPTO_WORKER_H_
@ -77,5 +85,4 @@ namespace worker
}
}
#endif

View File

@ -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 <vector>
#include "Crypto.h"
#include "Log.h"
#include "TunnelBase.h"
@ -11,9 +18,13 @@ namespace i2p
{
namespace datagram
{
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner):
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr)
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
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 ()
@ -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)
{
auto owner = m_Owner;
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)
if (m_Owner->GetIdentity ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
{
uint8_t hash[32];
SHA256(buf1, len, hash);
owner->Sign (hash, 32, signature);
SHA256(payload, len, hash);
m_Owner->Sign (hash, 32, m_Signature.data ());
}
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 msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}},
fromPort, toPort, false, !session->IsRatchets ()); // datagram
session->SendMsg(msg);
}
void DatagramDestination::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 msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw
session->SendMsg(msg);
}
@ -121,13 +122,15 @@ namespace datagram
LogPrint (eLogWarning, "Datagram: decompression failed");
}
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort, bool isRaw)
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
{
auto msg = NewI2NPMessage ();
uint8_t * buf = msg->GetPayload ();
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)
{
htobe32buf (msg->GetPayload (), size); // length
@ -135,7 +138,7 @@ namespace datagram
htobe16buf (buf + 6, toPort); // destination port
buf[9] = isRaw ? i2p::client::PROTOCOL_TYPE_RAW : i2p::client::PROTOCOL_TYPE_DATAGRAM; // raw or datagram protocol
msg->len += size + 4;
msg->FillI2NPMessageHeader (eI2NPData);
msg->FillI2NPMessageHeader (eI2NPData, 0, checksum);
}
else
msg = nullptr;
@ -190,7 +193,7 @@ namespace datagram
}
DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
const i2p::data::IdentHash & remoteIdent) :
const i2p::data::IdentHash & remoteIdent) :
m_LocalDestination(localDestination),
m_RemoteIdent(remoteIdent),
m_SendQueueTimer(localDestination->GetService()),
@ -247,11 +250,14 @@ namespace datagram
auto path = GetSharedRoutingPath();
if(path)
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 ()
{
if(!m_RoutingSession) {
if (!m_RoutingSession || !m_RoutingSession->GetOwner ())
{
if(!m_RemoteLeaseSet) {
m_RemoteLeaseSet = m_LocalDestination->FindLeaseSet(m_RemoteIdent);
}
@ -352,14 +358,14 @@ namespace datagram
void DatagramSession::HandleSend(std::shared_ptr<I2NPMessage> msg)
{
m_SendQueue.push_back(msg);
if (msg || m_SendQueue.empty ())
m_SendQueue.push_back(msg);
// flush queue right away if full
if(m_SendQueue.size() >= DATAGRAM_SEND_QUEUE_MAX_SIZE) FlushSendQueue();
}
void DatagramSession::FlushSendQueue ()
{
std::vector<i2p::tunnel::TunnelMessageBlock> send;
auto routingPath = GetSharedRoutingPath();
// if we don't have a routing path we will drop all queued messages
@ -368,7 +374,8 @@ namespace datagram
for (const auto & msg : m_SendQueue)
{
auto m = m_RoutingSession->WrapSingleMessage(msg);
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
if (m)
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
}
routingPath->outboundTunnel->SendTunnelDataMsg(send);
}
@ -385,4 +392,3 @@ namespace datagram
}
}
}

View File

@ -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__
#define DATAGRAM_H__
@ -5,6 +13,7 @@
#include <memory>
#include <functional>
#include <map>
#include <vector>
#include "Base.h"
#include "Identity.h"
#include "LeaseSet.h"
@ -31,25 +40,29 @@ namespace datagram
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
// milliseconds minimum time between path switches
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
// max 64 messages buffered in send queue for each datagram session
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
// max 64 messages buffered in send queue for each datagram session
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
{
public:
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
void Start ();
void Stop ();
public:
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
void Start ();
void Stop ();
/** @brief ack the garlic routing path */
void Ack();
/** @brief ack the garlic routing path */
void Ack();
/** send an i2np message to remote endpoint for this session */
void SendMsg(std::shared_ptr<I2NPMessage> msg);
/** get the last time in milliseconds for when we used this datagram session */
uint64_t LastActivity() const { return m_LastUse; }
/** send an i2np message to remote endpoint for this session */
void SendMsg(std::shared_ptr<I2NPMessage> msg);
/** get the last time in milliseconds for when we used this datagram session */
uint64_t LastActivity() const { return m_LastUse; }
bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
struct Info
{
@ -57,40 +70,41 @@ namespace datagram
std::shared_ptr<const i2p::data::IdentHash> OBEP;
const uint64_t activity;
Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
activity(a) {
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
else IBGW = nullptr;
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
else OBEP = nullptr;
}
};
Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
activity(a) {
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
else IBGW = nullptr;
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
else OBEP = nullptr;
}
};
Info GetSessionInfo() const;
Info GetSessionInfo() const;
private:
private:
void FlushSendQueue();
void ScheduleFlushSendQueue();
void FlushSendQueue();
void ScheduleFlushSendQueue();
void HandleSend(std::shared_ptr<I2NPMessage> msg);
void HandleSend(std::shared_ptr<I2NPMessage> msg);
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
private:
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
boost::asio::deadline_timer m_SendQueueTimer;
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
uint64_t m_LastUse;
bool m_RequestingLS;
private:
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
i2p::data::IdentHash m_RemoteIdent;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
boost::asio::deadline_timer m_SendQueueTimer;
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
uint64_t m_LastUse;
bool m_RequestingLS;
};
typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
@ -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 (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
public:
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner);
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
~DatagramDestination ();
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
@ -128,9 +140,10 @@ namespace datagram
private:
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 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;
Receiver m_Receiver; // default
RawReceiver m_RawReceiver; // default
bool m_Gzip; // gzip compression of data messages
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
std::mutex m_ReceiversMutex;
@ -150,6 +164,7 @@ namespace datagram
i2p::data::GzipInflator m_Inflator;
i2p::data::GzipDeflator m_Deflator;
std::vector<uint8_t> m_From, m_Signature;
};
}
}

View File

@ -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 <cassert>
#include <string>
#include <set>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "Crypto.h"
#include "Log.h"
#include "FS.h"
@ -13,7 +24,7 @@ namespace i2p
namespace client
{
LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
bool isPublic, const std::map<std::string, std::string> * params):
bool isPublic, const std::map<std::string, std::string> * params):
m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0),
m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
@ -157,7 +168,6 @@ namespace client
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
{
auto itr = params.find("i2cp.dontPublishLeaseSet");
if (itr != params.end())
{
@ -412,7 +422,8 @@ namespace client
auto it2 = m_LeaseSetRequests.find (key);
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 ())
{
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
@ -561,12 +572,12 @@ namespace client
m_PublishReplyToken = 0;
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
Publish ();
}
else
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
// Java floodfill never sends confirmation back for unknown crypto type
// assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
@ -716,7 +727,7 @@ namespace client
}
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
{
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
@ -779,7 +790,7 @@ namespace client
}
else
{
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
done = true;
}
@ -824,8 +835,8 @@ namespace client
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
{
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
return 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_RATCHET;
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
}
@ -839,23 +850,53 @@ namespace client
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
m_EncryptionKeyType = GetIdentity ()->GetCryptoKeyType ();
// 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);
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);
memset (m_EncryptionPublicKey, 0, 256);
if (isPublic)
PersistTemporaryKeys ();
else
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
for (auto& it: encryptionKeyTypes)
{
auto encryptionKey = new EncryptionKey (it);
if (isPublic)
PersistTemporaryKeys (encryptionKey, isSingleKey);
else
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)
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
@ -1071,10 +1112,10 @@ namespace client
return dest;
}
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
{
if (m_DatagramDestination == nullptr)
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ());
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
return m_DatagramDestination;
}
@ -1092,27 +1133,29 @@ namespace client
return ret;
}
void ClientDestination::PersistTemporaryKeys ()
void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey)
{
if (!keys) return;
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);
if (f) {
f.read ((char *)m_EncryptionPublicKey, 256);
f.read ((char *)m_EncryptionPrivateKey, 256);
f.read ((char *)keys->pub, 256);
f.read ((char *)keys->priv, 256);
return;
}
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
memset (m_EncryptionPrivateKey, 0, 256);
memset (m_EncryptionPublicKey, 0, 256);
i2p::data::PrivateKeys::GenerateCryptoKeyPair (m_EncryptionKeyType, m_EncryptionPrivateKey, m_EncryptionPublicKey);
memset (keys->priv, 0, 256);
memset (keys->pub, 0, 256);
keys->GenerateKeys ();
// TODO:: persist crypto key type
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
if (f1) {
f1.write ((char *)m_EncryptionPublicKey, 256);
f1.write ((char *)m_EncryptionPrivateKey, 256);
f1.write ((char *)keys->pub, 256);
f1.write ((char *)keys->priv, 256);
return;
}
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
@ -1123,18 +1166,27 @@ namespace client
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
{
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_EncryptionPublicKey, tunnels);
// sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
if (m_StandardEncryptionKey)
{
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_StandardEncryptionKey->pub, tunnels);
// sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
}
else
LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1");
}
else
{
// 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;
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} },
tunnels, IsPublic (), isPublishedEncrypted);
m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted);
if (isPublishedEncrypted) // encrypt if type 5
ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
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
{
if (m_Decryptor)
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
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
LogPrint (eLogError, "Destinations: decryptor is not set");
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)
{
for (auto it: *params)

View File

@ -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__
#define DESTINATION_H__
#include <string.h>
#include <thread>
#include <mutex>
#include <memory>
@ -93,7 +102,6 @@ namespace client
}
};
public:
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
@ -111,7 +119,7 @@ namespace client
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
std::shared_ptr<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
@ -154,7 +162,7 @@ namespace client
void HandleDeliveryStatusMessage (uint32_t msgID);
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets ();
@ -192,6 +200,17 @@ namespace client
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:
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
@ -223,14 +242,14 @@ namespace client
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
// implements LocalDestination
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 (); };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; };
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const;
protected:
@ -244,15 +263,14 @@ namespace client
std::shared_ptr<ClientDestination> GetSharedFromThis () {
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);
private:
i2p::data::PrivateKeys m_Keys;
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
i2p::data::CryptoKeyType m_EncryptionKeyType;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
std::unique_ptr<EncryptionKey> m_StandardEncryptionKey;
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
int m_StreamingAckDelay;
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default

File diff suppressed because it is too large Load Diff

View File

@ -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__
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__
@ -7,81 +15,115 @@
#include <memory>
#include <vector>
#include <list>
#include <unordered_map>
#include "Identity.h"
#include "Crypto.h"
#include "Garlic.h"
#include "Tag.h"
namespace i2p
{
namespace garlic
{
class RatchetTagSet
{
public:
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;
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
uint64_t GetNextSessionTag ();
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
class ECIESX25519AEADRatchetSession;
class RatchetTagSet
{
public:
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
uint64_t GetNextSessionTag ();
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
int GetNextIndex () const { return m_NextIndex; };
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:
union
{
uint64_t ll[8];
uint8_t buf[64];
union
{
uint64_t ll[8];
uint8_t buf[64];
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
} m_KeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64];
int m_NextIndex, m_NextSymmKeyIndex;
};
enum ECIESx25519BlockType
{
eECIESx25519BlkDateTime = 0,
eECIESx25519BlkSessionID = 1,
eECIESx25519BlkTermination = 4,
eECIESx25519BlkOptions = 5,
eECIESx25519BlkNextSessionKey = 7,
eECIESx25519BlkAck = 8,
eECIESx25519BlkAckRequest = 9,
eECIESx25519BlkGalicClove = 11,
eECIESx25519BlkPadding = 254
} m_KeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
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
{
eECIESx25519BlkDateTime = 0,
eECIESx25519BlkSessionID = 1,
eECIESx25519BlkTermination = 4,
eECIESx25519BlkOptions = 5,
eECIESx25519BlkNextKey = 7,
eECIESx25519BlkAck = 8,
eECIESx25519BlkAckRequest = 9,
eECIESx25519BlkGalicClove = 11,
eECIESx25519BlkPadding = 254
};
const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second of inactivity we should restart after
const int ECIESX25519_EXPIRATION_TIMEOUT = 600; // in seconds
const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
{
enum SessionState
{
eSessionStateNew =0,
eSessionStateNewSessionReceived,
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
{
enum SessionState
{
eSessionStateNew = 0,
eSessionStateNewSessionReceived,
eSessionStateNewSessionSent,
eSessionStateNewSessionReplySent,
eSessionStateEstablished
};
};
public:
struct DHRatchet
{
int keyID = 0;
i2p::crypto::X25519Keys key;
uint8_t remote[32]; // last remote public key
bool newKey = true;
};
ECIESX25519AEADRatchetSession (GarlicDestination * owner);
~ECIESX25519AEADRatchetSession ();
public:
bool HandleNextMessage (const uint8_t * buf, size_t len, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
~ECIESX25519AEADRatchetSession ();
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
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);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
@ -90,44 +132,60 @@ namespace garlic
}
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); }
private:
bool IsRatchets () const { return true; };
private:
void ResetKeys ();
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);
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
uint64_t CreateNewSessionTag () const;
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
bool HandleNewOutgoingSessionReply (const uint8_t * buf, size_t len);
bool HandleExistingSessionMessage (const uint8_t * buf, size_t len, int index);
void HandlePayload (const uint8_t * buf, size_t len, int index = 0);
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
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 NewSessionReplyMessage (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 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);
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
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);
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 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_NSRHeader[56], m_NSRKey[32]; // new session reply, for incoming only
i2p::crypto::X25519Keys m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
uint64_t m_LastActivityTimestamp = 0; // incoming
RatchetTagSet m_SendTagset, m_ReceiveTagset;
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
i2p::crypto::X25519Keys m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0; // incoming
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
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);
}

View File

@ -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 "Log.h"
#include "Crypto.h"
@ -597,4 +605,3 @@ namespace crypto
}
}
}

View File

@ -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__
#define ED25519_H__
@ -128,6 +136,4 @@ namespace crypto
}
}
#endif

View File

@ -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 "Crypto.h"
#include "Elligator.h"
@ -41,7 +49,7 @@ namespace crypto
}
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
{
{
bool ret = true;
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
@ -63,11 +71,11 @@ namespace crypto
if (Legendre (uxxA, ctx) != -1)
{
uint8_t randByte = 0; // random highest bits and high y
uint8_t randByte = 0; // random highest bits and high y
if (random)
{
RAND_bytes (&randByte, 1);
highY = randByte & 0x01;
RAND_bytes (&randByte, 1);
highY = randByte & 0x01;
}
BIGNUM * r = BN_CTX_get (ctx);
@ -87,7 +95,7 @@ namespace crypto
bn2buf (r, encoded, 32);
if (random)
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
for (size_t i = 0; i < 16; i++) // To Little Endian
{
uint8_t tmp = encoded[i];
@ -115,7 +123,7 @@ namespace crypto
encoded1[i] = encoded[31 - i];
encoded1[31 - i] = encoded[i];
}
encoded1[0] &= 0x3F; // drop two highest bits
encoded1[0] &= 0x3F; // drop two highest bits
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
@ -184,7 +192,7 @@ namespace crypto
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
if (BN_is_word(r, 1))
return 1;
else if (BN_is_zero(r))
else if (BN_is_zero(r))
return 0;
return -1;
}
@ -204,4 +212,3 @@ namespace crypto
}
}
}

View File

@ -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__
#define ELLIGATOR_H__
@ -35,5 +43,3 @@ namespace crypto
}
#endif

View File

@ -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
*

View File

@ -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
*
@ -17,133 +17,136 @@
namespace i2p {
namespace fs {
extern std::string dirSep;
extern std::string dirSep;
/**
* @brief Class to work with NetDb & Router profiles
*
* Usage:
*
* const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
* auto h = HashedStorage("name", "y", "z-", ".txt");
* h.SetPlace("/tmp/hs-test");
* h.GetName() -> gives "name"
* h.GetRoot() -> gives "/tmp/hs-test/name"
* h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
* h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt
* h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
* std::vector<std::string> files;
* h.Traverse(files); <- finds all files in storage and saves in given vector
*/
class HashedStorage {
protected:
std::string root; /**< path to storage with it's name included */
std::string name; /**< name of the storage */
std::string prefix1; /**< hashed directory prefix */
std::string prefix2; /**< prefix of file in storage */
std::string suffix; /**< suffix of file in storage (extension) */
/**
* @brief Class to work with NetDb & Router profiles
*
* Usage:
*
* const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
* auto h = HashedStorage("name", "y", "z-", ".txt");
* h.SetPlace("/tmp/hs-test");
* h.GetName() -> gives "name"
* h.GetRoot() -> gives "/tmp/hs-test/name"
* h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
* h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt
* h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
* std::vector<std::string> files;
* h.Traverse(files); <- finds all files in storage and saves in given vector
*/
class HashedStorage
{
protected:
public:
typedef std::function<void(const std::string &)> FilenameVisitor;
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
std::string root; /**< path to storage with it's name included */
std::string name; /**< name of the storage */
std::string prefix1; /**< hashed directory prefix */
std::string prefix2; /**< prefix of file in storage */
std::string suffix; /**< suffix of file in storage (extension) */
/** create subdirs in storage */
bool Init(const char* chars, size_t cnt);
const std::string & GetRoot() const { return root; }
const std::string & GetName() const { return name; }
/** set directory where to place storage directory */
void SetPlace(const std::string & path);
/** path to file with given ident */
std::string Path(const std::string & ident) const;
/** remove file by ident */
void Remove(const std::string & ident);
/** find all files in storage and store list in provided vector */
void Traverse(std::vector<std::string> & files);
/** visit every file in this storage with a visitor */
void Iterate(FilenameVisitor v);
};
public:
/** @brief Returns current application name, default 'i2pd' */
typedef std::function<void(const std::string &)> FilenameVisitor;
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
/** create subdirs in storage */
bool Init(const char* chars, size_t cnt);
const std::string & GetRoot() const { return root; }
const std::string & GetName() const { return name; }
/** set directory where to place storage directory */
void SetPlace(const std::string & path);
/** path to file with given ident */
std::string Path(const std::string & ident) const;
/** remove file by ident */
void Remove(const std::string & ident);
/** find all files in storage and store list in provided vector */
void Traverse(std::vector<std::string> & files);
/** visit every file in this storage with a visitor */
void Iterate(FilenameVisitor v);
};
/** @brief Returns current application name, default 'i2pd' */
const std::string & GetAppName ();
/** @brief Set application name, affects autodetection of datadir */
/** @brief Set application name, affects autodetection of datadir */
void SetAppName (const std::string& name);
/** @brief Returns datadir path */
const std::string & GetDataDir();
/** @brief Returns datadir path */
const std::string & GetDataDir();
/**
* @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
*
* Examples of autodetected paths:
*
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
*/
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
/**
* @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
*
* Examples of autodetected paths:
*
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
*/
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
/**
* @brief Create subdirectories inside datadir
*/
bool Init();
/**
* @brief Create subdirectories inside datadir
*/
bool Init();
/**
* @brief Get list of files in directory
* @param path Path to directory
* @param files Vector to store found files
* @return true on success and false if directory not exists
*/
bool ReadDir(const std::string & path, std::vector<std::string> & files);
/**
* @brief Get list of files in directory
* @param path Path to directory
* @param files Vector to store found files
* @return true on success and false if directory not exists
*/
bool ReadDir(const std::string & path, std::vector<std::string> & files);
/**
* @brief Remove file with given path
* @param path Absolute path to file
* @return true on success, false if file not exists, throws exception on error
*/
bool Remove(const std::string & path);
/**
* @brief Remove file with given path
* @param path Absolute path to file
* @return true on success, false if file not exists, throws exception on error
*/
bool Remove(const std::string & path);
/**
* @brief Check existence of file
* @param path Absolute path to file
* @return true if file exists, false otherwise
*/
bool Exists(const std::string & path);
/**
* @brief Check existence of file
* @param path Absolute path to file
* @return true if file exists, false otherwise
*/
bool Exists(const std::string & path);
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
bool CreateDirectory (const std::string& path);
bool CreateDirectory (const std::string& path);
template<typename T>
void _ExpandPath(std::stringstream & path, T c) {
path << i2p::fs::dirSep << c;
}
template<typename T>
void _ExpandPath(std::stringstream & path, T c) {
path << i2p::fs::dirSep << c;
}
template<typename T, typename ... Other>
void _ExpandPath(std::stringstream & path, T c, Other ... other) {
_ExpandPath(path, c);
_ExpandPath(path, other ...);
}
template<typename T, typename ... Other>
void _ExpandPath(std::stringstream & path, T c, Other ... other) {
_ExpandPath(path, c);
_ExpandPath(path, other ...);
}
/**
* @brief Get path relative to datadir
*
* Examples (with datadir = "/tmp/i2pd"):
*
* i2p::fs::Path("test") -> '/tmp/i2pd/test'
* i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
*/
template<typename ... Other>
std::string DataDirPath(Other ... components) {
std::stringstream s("");
s << i2p::fs::GetDataDir();
_ExpandPath(s, components ...);
/**
* @brief Get path relative to datadir
*
* Examples (with datadir = "/tmp/i2pd"):
*
* i2p::fs::Path("test") -> '/tmp/i2pd/test'
* i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
*/
template<typename ... Other>
std::string DataDirPath(Other ... components) {
std::stringstream s("");
s << i2p::fs::GetDataDir();
_ExpandPath(s, components ...);
return s.str();
}
return s.str();
}
template<typename Storage, typename... Filename>
std::string StorageRootPath (const Storage& storage, Filename... filenames)

View File

@ -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 <openssl/evp.h>
#include <openssl/ssl.h>
@ -113,9 +121,9 @@ namespace data
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
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);
if (len + 32 > 50)
if (len + 32 > 100)
{
LogPrint (eLogError, "Family: ", family, " is too long");
return false;
@ -179,4 +187,3 @@ namespace data
}
}
}

View File

@ -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__
#define FAMILY_H__

View File

@ -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 "I2PEndian.h"
#include <map>
@ -38,9 +46,9 @@ namespace garlic
if (!m_SharedRoutingPath) return nullptr;
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
m_SharedRoutingPath = nullptr;
if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
return m_SharedRoutingPath;
@ -96,10 +104,10 @@ namespace garlic
return msg;
}
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet),
m_Destination (destination), m_NumTags (numTags)
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet),
m_Destination (destination), m_NumTags (numTags)
{
// create new session tags and session key
RAND_bytes (m_SessionKey, 32);
@ -115,7 +123,7 @@ namespace garlic
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
}
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
@ -181,7 +189,7 @@ namespace garlic
return m;
}
size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
{
size_t blockSize = 0;
bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
@ -353,7 +361,7 @@ namespace garlic
return size;
}
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
{
auto tags = new UnconfirmedTags (m_NumTags);
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
@ -466,8 +474,9 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
return;
}
auto mod = length & 0x0f; // %16
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
if (it != m_Tags.end ())
{
@ -487,25 +496,48 @@ namespace garlic
}
else
{
// tag not found. Handle depending on encryption type
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
bool found = false;
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
{
HandleECIESx25519 (buf, length);
return;
// try ECIESx25519 tag
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
ElGamalBlock elGamal;
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
if (!found) // assume new session
{
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv);
decryption->SetIV (iv);
decryption->Decrypt(buf + 514, length - 514, buf + 514);
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
// AES tag not found. Handle depending on encryption type
// try ElGamal/AES first if leading block is 514
ElGamalBlock 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);
uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv);
decryption->SetIV (iv);
decryption->Decrypt(buf + 514, length - 514, buf + 514);
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
LogPrint (eLogError, "Garlic: Failed to decrypt message");
}
else
LogPrint (eLogError, "Garlic: Failed to decrypt message");
}
}
@ -679,41 +711,48 @@ namespace garlic
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
{
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET &&
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
{
ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey);
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
{
ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
session = it->second;
if (!session)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this);
session = it->second;
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
{
LogPrint (eLogDebug, "Garlic: session restarted");
session = nullptr;
}
}
if (!session)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
session->SetRemoteStaticKey (staticKey);
}
session->SetDestination (destination->GetIdentHash ()); // TODO: remove
return session;
}
else
{
ElGamalAESSessionPtr session;
{
std::unique_lock<std::mutex> l(m_SessionsMutex);
auto it = m_Sessions.find (destination->GetIdentHash ());
if (it != m_Sessions.end ())
session = it->second;
}
if (!session)
{
session = std::make_shared<ElGamalAESSession> (this, destination,
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
std::unique_lock<std::mutex> l(m_SessionsMutex);
m_Sessions[destination->GetIdentHash ()] = session;
}
return session;
}
return session;
}
else
{
ElGamalAESSessionPtr session;
{
std::unique_lock<std::mutex> l(m_SessionsMutex);
auto it = m_Sessions.find (destination->GetIdentHash ());
if (it != m_Sessions.end ())
session = it->second;
}
if (!session)
{
session = std::make_shared<ElGamalAESSession> (this, destination,
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
std::unique_lock<std::mutex> l(m_SessionsMutex);
m_Sessions[destination->GetIdentHash ()] = session;
}
return session;
}
}
void GarlicDestination::CleanupExpiredTags ()
@ -764,7 +803,7 @@ namespace garlic
// ECIESx25519
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);
else
++it;
@ -901,40 +940,20 @@ namespace garlic
std::vector<std::string> files;
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it: files)
for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it);
}
void GarlicDestination::HandleECIESx25519 (const uint8_t * buf, size_t len)
void GarlicDestination::HandleECIESx25519GarlicClove (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)
{
const uint8_t * buf1 = buf;
const uint8_t * buf1 = buf;
uint8_t flag = buf[0]; buf++; // flag
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
switch (deliveryType)
{
case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination");
LogPrint (eLogDebug, "Garlic: type destination");
buf += 32; // TODO: check destination
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
@ -942,7 +961,7 @@ namespace garlic
// no break here
case eGarlicDeliveryTypeLocal:
{
LogPrint (eLogDebug, "Garlic: type local");
LogPrint (eLogDebug, "Garlic: type local");
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration
ptrdiff_t offset = buf - buf1;
@ -953,8 +972,8 @@ namespace garlic
break;
}
case eGarlicDeliveryTypeTunnel:
{
LogPrint (eLogDebug, "Garlic: type tunnel");
{
LogPrint (eLogDebug, "Garlic: type tunnel");
// gwHash and gwTunnel sequence is reverted
const uint8_t * gwHash = buf;
buf += 32;
@ -965,30 +984,32 @@ namespace garlic
break;
}
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration
offset += 13;
offset += 13;
if (GetTunnelPool ())
{
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel)
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
{
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel)
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
}
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
}
else
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
break;
}
break;
}
default:
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
}
}
}
void GarlicDestination::AddECIESx25519SessionTag (int index, uint64_t tag, ECIESX25519AEADRatchetSessionPtr session)
{
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexSession{index, session, i2p::util::GetSecondsSinceEpoch ()});
}
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
{
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)
{
@ -997,7 +1018,10 @@ namespace garlic
if (it != m_ECIESx25519Sessions.end ())
{
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
{
it->second->SetOwner (nullptr); // detach
m_ECIESx25519Sessions.erase (it);
}
else
{
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
@ -1007,5 +1031,14 @@ namespace garlic
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);
}
}
}
}

View File

@ -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__
#define GARLIC_H__
@ -87,7 +95,7 @@ namespace garlic
class GarlicDestination;
class GarlicRoutingSession
{
protected:
protected:
enum LeaseSetUpdateStatus
{
@ -103,8 +111,9 @@ namespace garlic
GarlicRoutingSession ();
virtual ~GarlicRoutingSession ();
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 IsRatchets () const { return false; };
void SetLeaseSetUpdated ()
{
@ -121,13 +130,13 @@ namespace garlic
GarlicDestination * GetOwner () const { return m_Owner; }
void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
protected:
protected:
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID);
@ -142,38 +151,39 @@ namespace garlic
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
public:
// for HTTP only
virtual size_t GetNumOutgoingTags () const { return 0; };
};
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
{
struct UnconfirmedTags
{
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
~UnconfirmedTags () { delete[] sessionTags; };
uint32_t msgID;
int numTags;
SessionTag * sessionTags;
uint32_t tagsCreationTime;
};
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
{
struct UnconfirmedTags
{
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
~UnconfirmedTags () { delete[] sessionTags; };
uint32_t msgID;
int numTags;
SessionTag * sessionTags;
uint32_t tagsCreationTime;
};
public:
public:
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
int numTags, bool attachLeaseSet);
ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
~ElGamalAESSession () {};
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
bool MessageConfirmed (uint32_t msgID);
bool MessageConfirmed (uint32_t msgID);
bool CleanupExpiredTags (); // returns true if something left
bool CleanupUnconfirmedTags (); // returns true if something has been deleted
private:
private:
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
@ -183,29 +193,32 @@ namespace garlic
void TagsConfirmed (uint32_t msgID);
UnconfirmedTags * GenerateSessionTags ();
private:
private:
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
i2p::crypto::AESKey m_SessionKey;
i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags;
int m_NumTags;
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
i2p::crypto::CBCEncryption m_Encryption;
i2p::crypto::CBCEncryption m_Encryption;
public:
public:
// for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
};
};
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
class ECIESX25519AEADRatchetSession;
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
struct ECIESX25519AEADRatchetIndexSession
class ECIESX25519AEADRatchetSession;
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
class RatchetTagSet;
typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
struct ECIESX25519AEADRatchetIndexTagset
{
int index;
ECIESX25519AEADRatchetSessionPtr session;
RatchetTagSetPtr tagset;
uint64_t creationTime; // seconds since epoch
};
@ -223,13 +236,14 @@ namespace garlic
void CleanupExpiredTags ();
void RemoveDeliveryStatusSession (uint32_t msgID);
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
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
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 RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
@ -255,9 +269,6 @@ namespace garlic
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:
BN_CTX * m_Ctx; // incoming
@ -265,10 +276,10 @@ namespace garlic
int m_NumTags;
std::mutex m_SessionsMutex;
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
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
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
std::mutex m_DeliveryStatusSessionsMutex;
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
@ -277,7 +288,9 @@ namespace garlic
// for HTTP only
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_ECIESx25519Sessions)& GetECIESx25519Sessions () const { return m_ECIESx25519Sessions; }
};
void CleanUpTagsFiles ();

View File

@ -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 <array>
#include <openssl/bn.h>

View File

@ -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__
#define GOST_H__
@ -13,11 +21,11 @@ namespace crypto
enum GOSTR3410ParamSet
{
eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1
eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1
// XchA = A, XchB = C
//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1
//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1
eGOSTR3410NumParamSets
};

View File

@ -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
*
@ -10,6 +10,7 @@
#include <string.h> /* memset */
#include <iostream>
#include "Log.h"
#include "I2PEndian.h"
#include "Gzip.h"
namespace i2p
@ -31,18 +32,34 @@ namespace data
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
{
if (m_IsDirty) inflateReset (&m_Inflator);
m_IsDirty = true;
m_Inflator.next_in = const_cast<uint8_t *>(in);
m_Inflator.avail_in = inLen;
m_Inflator.next_out = out;
m_Inflator.avail_out = outLen;
int err;
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
return outLen - m_Inflator.avail_out;
// else
LogPrint (eLogError, "Gzip: Inflate error ", err);
return 0;
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);
m_IsDirty = true;
m_Inflator.next_in = const_cast<uint8_t *>(in);
m_Inflator.avail_in = inLen;
m_Inflator.next_out = out;
m_Inflator.avail_out = outLen;
int err;
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
return outLen - m_Inflator.avail_out;
// else
LogPrint (eLogError, "Gzip: Inflate error ", err);
return 0;
}
}
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
@ -106,10 +123,79 @@ namespace data
m_Deflator.avail_out = outLen;
int err;
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END)
{
out[9] = 0xff; // OS is always unknown
return outLen - m_Deflator.avail_out;
}
// else
LogPrint (eLogError, "Gzip: Deflate error ", err);
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
} // i2p

View File

@ -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__
#define GZIP_H__
#include <zlib.h>
#include <vector>
namespace i2p {
namespace data {
namespace i2p
{
namespace data
{
class GzipInflator
{
public:
@ -32,12 +43,16 @@ namespace data {
void SetCompressionLevel (int level);
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:
z_stream m_Deflator;
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
} // i2p

Some files were not shown because too many files have changed in this diff Show More