Compare commits

...

115 Commits

Author SHA1 Message Date
Mikal
6cc3021baa MSVC13 Fix
Fixed build issue on MSVC13. Bumping to v0.3.0 as we release binaries
and SU3 is added.
2014-11-20 23:46:36 -08:00
orignal
0f4e4a7944 return shared_ptr to RI 2014-11-20 16:20:02 -05:00
orignal
683c97d5c8 shared pointer for local RI 2014-11-20 15:48:28 -05:00
orignal
af2a5b93f2 SU3 file parser 2014-11-20 14:29:22 -05:00
orignal
f9ec60265a support of RI with EcDSA 2014-11-20 12:21:27 -05:00
orignal
a449dc1377 read RI from buffer 2014-11-19 16:21:40 -05:00
orignal
f6849442a9 encrypted delivery status 2014-11-19 14:56:47 -05:00
orignal
c3e329e406 fixed misalignment 2014-11-19 11:01:04 -05:00
orignal
69cbd71fe0 receive buffers aligned to 16 2014-11-18 12:37:04 -05:00
orignal
dd1a798128 AES buffer aligned to 16 bytes 2014-11-18 12:11:45 -05:00
orignal
96387aecbd store RIs as shared pointers 2014-11-18 11:08:10 -05:00
orignal
77b7fff5ed streaming api functions added 2014-11-18 09:33:58 -05:00
orignal
72c0d8443a create local destination through API 2014-11-17 17:00:30 -05:00
orignal
2988395b81 specify application name 2014-11-17 15:28:52 -05:00
orignal
439b8798c9 start/stop/init through api 2014-11-17 14:42:45 -05:00
orignal
7cf19f5784 api added 2014-11-17 12:37:40 -05:00
orignal
b9e2b7bf64 delete single message routing session immediately 2014-11-16 15:41:54 -05:00
Mikal
cc14b526cd Adding Icon for windows
Adding icon for windows executable.
2014-11-11 02:46:35 +01:00
Mikal
5e67bc62c1 Adding windows installer 2014-11-11 02:21:05 +01:00
Kill Your TV
692cde5151 Remove "DLL-Output" from README's example
This is not required to build i2pd.
2014-11-09 22:32:17 +00:00
Kill Your TV
4fbb823391 Merge branch 'master' into proposed_build_fixes
Conflicts:
	Win32/i2pd.vcxproj
2014-11-08 13:45:10 +00:00
Kill Your TV
d636d55cc8 Adding Windows build instructions 2014-11-08 13:29:15 +00:00
apekatten
901eb10125 Removed required admin-level for running 2014-11-08 13:44:18 +01:00
Kill Your TV
4b0001b442 innosetup: Add i2pd to PATH 2014-11-07 15:04:33 +00:00
Kill Your TV
3cd1281167 updates to innosetup script
* support installation of both x64 and x86 binaries
* add readme
* add function to convert line endings. The README.md file currently has
  Windows line endings, but if that ever changes this function will
  automatically make the file "Windows friendly".
2014-11-07 15:04:33 +00:00
Kill Your TV
33f9918854 minor updates to readme
* grammar fixes
* note working VS2013 version
* change tabs to spaces to ensure proper viewing on systems with
* different tab settings
2014-11-07 15:04:33 +00:00
Kill Your TV
a518d6063c update vcxproj.filters 2014-11-07 15:04:33 +00:00
Kill Your TV
1232278c46 Various changes to Windows build
- No hard coded dependency paths. These are better set with environment
  variables or property pages.
- Don't require admin rights to run
- Add support for running on Windows XP (note that Boost and Crypto++
  *also* need to be built targetting XP).
- Explicitly set type to console application
- Initial stubs for building x64 version
- Turn off sending error reports to Microsoft
- spaces, not tabs (matches the default when saved by VS2013 itself)
- disable multibyte
- re-enable SDL checks
2014-11-07 15:04:33 +00:00
Kill Your TV
dd4283b7c1 Revert "fixed typo" and "fixed crash for Windows"
This reverts commits c8a80a497d and f7791e5289

This didn't actually fix Windows crash problem. In fact, it still
crashed without --log=0 being set. Changes to the i2pd.vcxproj file
fixed the crashes with VS 2013 > update 1.  i2pd now works with VS 2013
Update 3 and Update 4 RC.

Since these changes didn't have the intended effect, let's remove them.
2014-11-07 14:58:27 +00:00
Kill Your TV
3e826cd6dc easier static builds (STATIC=yes)
This will also disable AESNI
2014-11-07 14:49:16 +00:00
Kill Your TV
2f8c37b132 Allow setting the LIBDIR at build time 2014-11-07 14:48:49 +00:00
Kill Your TV
e914d1640c allow AESNI to be disabled 2014-11-07 14:17:24 +00:00
Kill Your TV
25b5068f5e allow LDFLAGS to be set by user
Move old LDFLAGS variable to LDLIBS. By doing ths, a user can set their
own LDFLAGS without breaking the build. A case in which this can be
useful is hardening with debian, e.g.

    $ dpkg-buildflags --get LDFLAGS
    -Wl,-z,relro
2014-11-04 02:37:12 +00:00
orignal
38b901484a check for SSU packet size 2014-11-03 10:15:01 -05:00
orignal
c8a80a497d fixed typo 2014-11-02 08:28:28 -05:00
orignal
faf1fe7a7c aligned AES keys 2014-11-01 21:53:45 -04:00
orignal
f7791e5289 fixed crash for Windows 2014-11-01 21:48:26 -04:00
orignal
a8acb8ebb4 fixed double deletion 2014-11-01 17:15:59 -04:00
orignal
4334007688 aligned AES and MAC keys 2014-11-01 14:56:13 -04:00
orignal
7a976dd5f2 specify actual mtu in our RI for i2pv6 2014-10-31 18:27:51 -04:00
orignal
f28376bf71 DATAGRAM RECEIVED message 2014-10-31 16:44:44 -04:00
orignal
3b435f1e1d get local MTU for Linux 2014-10-31 14:34:08 -04:00
orignal
a314feff33 get local MTU for Linux 2014-10-31 14:17:52 -04:00
orignal
0b77c9651b 0.2.0 2014-10-30 18:04:17 -04:00
orignal
6b860c8c88 split SSU to SSU and SSUSession 2014-10-30 15:13:29 -04:00
orignal
0cd04c23c5 split SSU to SSU and SSUSession 2014-10-30 15:13:12 -04:00
orignal
51c908ab55 Merge pull request #106 from kytvi2p/fix_makefiles
Makefile updates
2014-10-30 10:36:33 -04:00
orignal
c0482319e5 always specify mtu for ipv6 address 2014-10-30 10:07:39 -04:00
Kill Your TV
38eaea121f recognize clang in linux 2014-10-30 13:53:55 +00:00
Kill Your TV
6681e25513 allow CXXFLAGS to be set without overwriting needed flags 2014-10-30 13:53:47 +00:00
Kill Your TV
5acbc6a23e use standard make variables 2014-10-30 13:50:29 +00:00
Kill Your TV
524b2e9f8a check for 64-bit compiler 2014-10-30 13:50:18 +00:00
orignal
6320572917 find SSU V6 sessions 2014-10-29 21:56:45 -04:00
orignal
54ec71d30d select proper SSU address for incoming sessions 2014-10-29 21:16:27 -04:00
orignal
67001e1696 incoming ipv6 SSU sessions 2014-10-29 18:46:35 -04:00
orignal
21aff9f9f7 check router identity certificate 2014-10-29 16:27:42 -04:00
orignal
a53457e8c1 delete SSU V6 address 2014-10-29 16:08:01 -04:00
orignal
f0e6b414e8 don't verify signature for RI loaded from file 2014-10-29 16:03:07 -04:00
orignal
8403c17c59 incoming SSU V6 sessions 2014-10-29 15:02:48 -04:00
orignal
a3fd338fab pass our address as boost's address 2014-10-29 13:49:21 -04:00
orignal
d513f20225 handle ipv6 adrresses 2014-10-29 12:28:44 -04:00
orignal
d84a7ebc7e MTU for ipv6 2014-10-29 11:17:30 -04:00
orignal
7e82686818 signature size for SessionCreated 2014-10-28 22:02:21 -04:00
orignal
faf093c474 process ipv6 addresses in SessionCreated 2014-10-28 21:32:32 -04:00
orignal
b6bc49c33a process ipv6 addresses in SessionCreated 2014-10-28 21:26:55 -04:00
orignal
39644d3bb2 send actual identity in SessionConfirmed message 2014-10-28 18:56:11 -04:00
orignal
1f69d1b890 different log levels 2014-10-28 17:55:58 -04:00
orignal
11a0bbc368 different log levels 2014-10-28 16:36:17 -04:00
orignal
fe4de7c8ac use SignedData class for signing/verification 2014-10-28 14:17:29 -04:00
orignal
7f93c680fd added missing line 2014-10-28 11:47:28 -04:00
orignal
659edf2590 common code for signing and verifing exchanged data 2014-10-28 11:34:50 -04:00
orignal
b89daaa58b Merge branch 'master' of https://github.com/orignal/i2pd 2014-10-27 20:38:17 -04:00
orignal
7900e9b126 accept v6 only for v6 acceptor 2014-10-27 20:36:03 -04:00
Meeh
af0bdc2a5e Merge branch 'master' of github-meeh420:PrivacySolutions/i2pd
Note; we use _MSC_VER instead of _WIN32 for MSVC spesific code.

* 'master' of github-meeh420:PrivacySolutions/i2pd: (35 commits)
  handle incoming datagramms
  send datagram through destination's thread
  incoming ipv6 connections
  support ipv6 for outgoing NTCP connections
  some cleanup
  Update Daemon.cpp
  Add Upstart job to debian packaging
  Implement reload in init script
  Rename init.d to i2pd.init
  Decouple logging and daemonization
  verify signature through remore identity
  moved remote RI and identity to TransportSession
  set unreachable trough NetDb
  moved AddressBook to ClientContext
  initialize router identity
  don't specify RI for inbound NTCP connections
  use remote router indentity
  take identity of local RI from private keys
  send datagram from SAM
  fixed windows build
  ...

Conflicts:
	SAM.cpp
2014-10-27 22:56:31 +01:00
Meeh
88fb8a217d Fix for build error in msvc12 2014-10-27 22:53:01 +01:00
orignal
2dfd351e7a handle incoming datagramms 2014-10-27 16:30:56 -04:00
orignal
35d4692f5f send datagram through destination's thread 2014-10-27 16:01:22 -04:00
orignal
f2434d66fc incoming ipv6 connections 2014-10-27 15:08:50 -04:00
orignal
7fb7341502 support ipv6 for outgoing NTCP connections 2014-10-26 21:32:06 -04:00
orignal
1408422da9 some cleanup 2014-10-25 22:23:28 -04:00
orignal
a20cc97fa3 Update Daemon.cpp
rollback
2014-10-25 22:11:31 -04:00
orignal
51b2b5676c Merge pull request #105 from CameronNemo/daemon
Various init script and daemonization fixups
2014-10-25 22:10:06 -04:00
Cameron Norman
e768e33ddd Add Upstart job to debian packaging 2014-10-25 18:42:35 -07:00
Cameron Norman
ced4149679 Implement reload in init script 2014-10-25 18:41:04 -07:00
Cameron Norman
61932ff49f Rename init.d to i2pd.init 2014-10-25 18:40:11 -07:00
Cameron Norman
65c13f1758 Decouple logging and daemonization 2014-10-25 18:25:03 -07:00
orignal
2308f854b1 verify signature through remore identity 2014-10-24 21:51:55 -04:00
orignal
6281fa625a moved remote RI and identity to TransportSession 2014-10-24 15:50:48 -04:00
orignal
c9abb62988 set unreachable trough NetDb 2014-10-24 15:39:53 -04:00
orignal
af997473b2 moved AddressBook to ClientContext 2014-10-24 15:22:36 -04:00
orignal
a96d70a94c initialize router identity 2014-10-24 14:24:48 -04:00
orignal
8d75d51803 don't specify RI for inbound NTCP connections 2014-10-24 13:36:55 -04:00
orignal
f81a122223 use remote router indentity 2014-10-24 13:04:14 -04:00
orignal
39bdfa8791 take identity of local RI from private keys 2014-10-24 11:25:07 -04:00
orignal
47fb6f6e04 send datagram from SAM 2014-10-23 21:14:17 -04:00
orignal
336fa8eed7 fixed windows build 2014-10-23 19:04:46 -04:00
orignal
61d36ea8c3 send datagram 2014-10-23 16:56:50 -04:00
orignal
65719ae645 send destination port for streaming 2014-10-22 21:36:11 -04:00
orignal
4ae8c3c62c create datagram destination through SAM 2014-10-22 16:42:26 -04:00
orignal
78d8d34e3b Datagram added 2014-10-22 15:30:25 -04:00
orignal
3da35c592f moved Data payload processing to StreamingDestination 2014-10-22 15:01:30 -04:00
orignal
b11877d002 create streams through ClientDestination 2014-10-22 14:01:23 -04:00
orignal
4d97b0e206 moved StreamingDestination inside ClientDestination 2014-10-22 11:46:54 -04:00
orignal
ab843b6552 cleaned up from duplicated methods 2014-10-21 15:44:28 -04:00
orignal
e96ffd4189 don't block HTTP server/proxy for 10 seconds anymore 2014-10-21 14:28:56 -04:00
orignal
7b768ccb26 moved transports to 'transport' namespace 2014-10-21 12:25:53 -04:00
orignal
165af090b6 Update README.md 2014-10-21 07:44:48 -04:00
orignal
898c81b5d6 better packaging 2014-10-20 21:39:32 -04:00
orignal
43a989872d fixed typo 2014-10-20 16:57:18 -04:00
orignal
c4dda06cde TransportSession added 2014-10-20 16:09:59 -04:00
orignal
a8871d9f98 moved DHKeysPair to Transport 2014-10-20 15:19:56 -04:00
orignal
8e8eb3b588 Merge pull request #102 from herrniemand/patch-1
Update BUILD_NOTES.md
2014-10-20 07:45:40 -04:00
Ackermann Yuriy
e7031e02e7 Update BUILD_NOTES.md 2014-10-20 20:52:45 +13:00
orignal
9b3ac19b58 show queue size 2014-10-18 15:50:34 -04:00
orignal
fcd3680547 delete expired incoming tags 2014-10-17 22:15:42 -04:00
86 changed files with 4171 additions and 1825 deletions

View File

@@ -11,14 +11,14 @@
namespace i2p namespace i2p
{ {
namespace data namespace client
{ {
AddressBook::AddressBook (): m_IsLoaded (false), m_IsDowloading (false) AddressBook::AddressBook (): m_IsLoaded (false), m_IsDowloading (false)
{ {
} }
bool AddressBook::GetIdentHash (const std::string& address, IdentHash& ident) bool AddressBook::GetIdentHash (const std::string& address, i2p::data::IdentHash& ident)
{ {
auto pos = address.find(".b32.i2p"); auto pos = address.find(".b32.i2p");
if (pos != std::string::npos) if (pos != std::string::npos)
@@ -42,7 +42,7 @@ namespace data
return false; return false;
} }
const IdentHash * AddressBook::FindAddress (const std::string& address) const i2p::data::IdentHash * AddressBook::FindAddress (const std::string& address)
{ {
if (!m_IsLoaded) if (!m_IsLoaded)
LoadHosts (); LoadHosts ();
@@ -57,7 +57,7 @@ namespace data
void AddressBook::InsertAddress (const std::string& address, const std::string& base64) void AddressBook::InsertAddress (const std::string& address, const std::string& base64)
{ {
IdentityEx ident; i2p::data::IdentityEx ident;
ident.FromBase64 (base64); ident.FromBase64 (base64);
m_Addresses[address] = ident.GetIdentHash (); m_Addresses[address] = ident.GetIdentHash ();
LogPrint (address,"->",ident.GetIdentHash ().ToBase32 (), ".b32.i2p added"); LogPrint (address,"->",ident.GetIdentHash ().ToBase32 (), ".b32.i2p added");
@@ -118,7 +118,7 @@ namespace data
std::string name = s.substr(0, pos++); std::string name = s.substr(0, pos++);
std::string addr = s.substr(pos); std::string addr = s.substr(pos);
IdentityEx ident; i2p::data::IdentityEx ident;
ident.FromBase64(addr); ident.FromBase64(addr);
m_Addresses[name] = ident.GetIdentHash (); m_Addresses[name] = ident.GetIdentHash ();
numAddresses++; numAddresses++;

View File

@@ -11,15 +11,15 @@
namespace i2p namespace i2p
{ {
namespace data namespace client
{ {
class AddressBook class AddressBook
{ {
public: public:
AddressBook (); AddressBook ();
bool GetIdentHash (const std::string& address, IdentHash& ident); bool GetIdentHash (const std::string& address, i2p::data::IdentHash& ident);
const IdentHash * FindAddress (const std::string& address); const i2p::data::IdentHash * FindAddress (const std::string& address);
void InsertAddress (const std::string& address, const std::string& base64); // for jump service void InsertAddress (const std::string& address, const std::string& base64); // for jump service
private: private:
@@ -27,7 +27,7 @@ namespace data
void LoadHosts (); void LoadHosts ();
void LoadHostsFromI2P (); void LoadHostsFromI2P ();
std::map<std::string, IdentHash> m_Addresses; std::map<std::string, i2p::data::IdentHash> m_Addresses;
bool m_IsLoaded, m_IsDowloading; bool m_IsLoaded, m_IsDowloading;
}; };
} }

View File

@@ -27,7 +27,7 @@ namespace client
{ {
if (!m_SharedLocalDestination) if (!m_SharedLocalDestination)
{ {
m_SharedLocalDestination = new i2p::stream::StreamingDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA m_SharedLocalDestination = new ClientDestination (false, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // non-public, DSA
m_Destinations[m_SharedLocalDestination->GetIdentity ().GetIdentHash ()] = m_SharedLocalDestination; m_Destinations[m_SharedLocalDestination->GetIdentity ().GetIdentHash ()] = m_SharedLocalDestination;
m_SharedLocalDestination->Start (); m_SharedLocalDestination->Start ();
} }
@@ -41,7 +41,7 @@ namespace client
std::string ircDestination = i2p::util::config::GetArg("-ircdest", ""); std::string ircDestination = i2p::util::config::GetArg("-ircdest", "");
if (ircDestination.length () > 0) // ircdest is presented if (ircDestination.length () > 0) // ircdest is presented
{ {
i2p::stream::StreamingDestination * localDestination = nullptr; ClientDestination * localDestination = nullptr;
std::string ircKeys = i2p::util::config::GetArg("-irckeys", ""); std::string ircKeys = i2p::util::config::GetArg("-irckeys", "");
if (ircKeys.length () > 0) if (ircKeys.length () > 0)
localDestination = i2p::client::context.LoadLocalDestination (ircKeys, false); localDestination = i2p::client::context.LoadLocalDestination (ircKeys, false);
@@ -125,7 +125,7 @@ namespace client
#else #else
it->path(); it->path();
#endif #endif
auto localDestination = new i2p::stream::StreamingDestination (fullPath, true); auto localDestination = new ClientDestination (fullPath, true);
m_Destinations[localDestination->GetIdentHash ()] = localDestination; m_Destinations[localDestination->GetIdentHash ()] = localDestination;
numDestinations++; numDestinations++;
} }
@@ -134,25 +134,25 @@ namespace client
LogPrint (numDestinations, " local destinations loaded"); LogPrint (numDestinations, " local destinations loaded");
} }
i2p::stream::StreamingDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic) ClientDestination * ClientContext::LoadLocalDestination (const std::string& filename, bool isPublic)
{ {
auto localDestination = new i2p::stream::StreamingDestination (i2p::util::filesystem::GetFullPath (filename), isPublic); auto localDestination = new ClientDestination (i2p::util::filesystem::GetFullPath (filename), isPublic);
std::unique_lock<std::mutex> l(m_DestinationsMutex); std::unique_lock<std::mutex> l(m_DestinationsMutex);
m_Destinations[localDestination->GetIdentHash ()] = localDestination; m_Destinations[localDestination->GetIdentHash ()] = localDestination;
localDestination->Start (); localDestination->Start ();
return localDestination; return localDestination;
} }
i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType) ClientDestination * ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType)
{ {
auto localDestination = new i2p::stream::StreamingDestination (isPublic, sigType); auto localDestination = new ClientDestination (isPublic, sigType);
std::unique_lock<std::mutex> l(m_DestinationsMutex); std::unique_lock<std::mutex> l(m_DestinationsMutex);
m_Destinations[localDestination->GetIdentHash ()] = localDestination; m_Destinations[localDestination->GetIdentHash ()] = localDestination;
localDestination->Start (); localDestination->Start ();
return localDestination; return localDestination;
} }
void ClientContext::DeleteLocalDestination (i2p::stream::StreamingDestination * destination) void ClientContext::DeleteLocalDestination (ClientDestination * destination)
{ {
if (!destination) return; if (!destination) return;
auto it = m_Destinations.find (destination->GetIdentHash ()); auto it = m_Destinations.find (destination->GetIdentHash ());
@@ -168,7 +168,7 @@ namespace client
} }
} }
i2p::stream::StreamingDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic) ClientDestination * ClientContext::CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic)
{ {
auto it = m_Destinations.find (keys.GetPublic ().GetIdentHash ()); auto it = m_Destinations.find (keys.GetPublic ().GetIdentHash ());
if (it != m_Destinations.end ()) if (it != m_Destinations.end ())
@@ -181,14 +181,14 @@ namespace client
} }
return nullptr; return nullptr;
} }
auto localDestination = new i2p::stream::StreamingDestination (keys, isPublic); auto localDestination = new ClientDestination (keys, isPublic);
std::unique_lock<std::mutex> l(m_DestinationsMutex); std::unique_lock<std::mutex> l(m_DestinationsMutex);
m_Destinations[keys.GetPublic ().GetIdentHash ()] = localDestination; m_Destinations[keys.GetPublic ().GetIdentHash ()] = localDestination;
localDestination->Start (); localDestination->Start ();
return localDestination; return localDestination;
} }
i2p::stream::StreamingDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const ClientDestination * ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const
{ {
auto it = m_Destinations.find (destination); auto it = m_Destinations.find (destination);
if (it != m_Destinations.end ()) if (it != m_Destinations.end ())

View File

@@ -7,6 +7,7 @@
#include "SOCKS.h" #include "SOCKS.h"
#include "I2PTunnel.h" #include "I2PTunnel.h"
#include "SAM.h" #include "SAM.h"
#include "AddressBook.h"
namespace i2p namespace i2p
{ {
@@ -22,12 +23,14 @@ namespace client
void Start (); void Start ();
void Stop (); void Stop ();
i2p::stream::StreamingDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; }; ClientDestination * GetSharedLocalDestination () const { return m_SharedLocalDestination; };
i2p::stream::StreamingDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient ClientDestination * CreateNewLocalDestination (bool isPublic = true, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient
i2p::stream::StreamingDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true); ClientDestination * CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true);
void DeleteLocalDestination (i2p::stream::StreamingDestination * destination); void DeleteLocalDestination (ClientDestination * destination);
i2p::stream::StreamingDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const; ClientDestination * FindLocalDestination (const i2p::data::IdentHash& destination) const;
i2p::stream::StreamingDestination * LoadLocalDestination (const std::string& filename, bool isPublic); ClientDestination * LoadLocalDestination (const std::string& filename, bool isPublic);
AddressBook& GetAddressBook () { return m_AddressBook; };
private: private:
@@ -36,8 +39,10 @@ namespace client
private: private:
std::mutex m_DestinationsMutex; std::mutex m_DestinationsMutex;
std::map<i2p::data::IdentHash, i2p::stream::StreamingDestination *> m_Destinations; std::map<i2p::data::IdentHash, ClientDestination *> m_Destinations;
i2p::stream::StreamingDestination * m_SharedLocalDestination; ClientDestination * m_SharedLocalDestination;
AddressBook m_AddressBook;
i2p::proxy::HTTPProxy * m_HttpProxy; i2p::proxy::HTTPProxy * m_HttpProxy;
i2p::proxy::SOCKSProxy * m_SocksProxy; i2p::proxy::SOCKSProxy * m_SocksProxy;

View File

@@ -67,11 +67,13 @@ namespace i2p
i2p::context.UpdatePort (port); i2p::context.UpdatePort (port);
const char * host = i2p::util::config::GetCharArg("-host", ""); const char * host = i2p::util::config::GetCharArg("-host", "");
if (host && host[0]) if (host && host[0])
i2p::context.UpdateAddress (host); i2p::context.UpdateAddress (boost::asio::ip::address::from_string (host));
if (i2p::util::config::GetArg("-unreachable", 0)) if (i2p::util::config::GetArg("-unreachable", 0))
i2p::context.SetUnreachable (); i2p::context.SetUnreachable ();
i2p::context.SetSupportsV6 (i2p::util::config::GetArg("-v6", 0));
LogPrint("CMD parameters:"); LogPrint("CMD parameters:");
for (int i = 0; i < argc; ++i) for (int i = 0; i < argc; ++i)
LogPrint(i, " ", argv[i]); LogPrint(i, " ", argv[i]);
@@ -103,7 +105,7 @@ namespace i2p
LogPrint("HTTP Server started"); LogPrint("HTTP Server started");
i2p::data::netdb.Start(); i2p::data::netdb.Start();
LogPrint("NetDB started"); LogPrint("NetDB started");
i2p::transports.Start(); i2p::transport::transports.Start();
LogPrint("Transports started"); LogPrint("Transports started");
i2p::tunnel::tunnels.Start(); i2p::tunnel::tunnels.Start();
LogPrint("Tunnels started"); LogPrint("Tunnels started");
@@ -120,7 +122,7 @@ namespace i2p
LogPrint("Client stoped"); LogPrint("Client stoped");
i2p::tunnel::tunnels.Stop(); i2p::tunnel::tunnels.Stop();
LogPrint("Tunnels stoped"); LogPrint("Tunnels stoped");
i2p::transports.Stop(); i2p::transport::transports.Stop();
LogPrint("Transports stoped"); LogPrint("Transports stoped");
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
LogPrint("NetDB stoped"); LogPrint("NetDB stoped");

135
Datagram.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include <string.h>
#include <vector>
#include <cryptopp/sha.h>
#include <cryptopp/gzip.h>
#include "Log.h"
#include "TunnelBase.h"
#include "RouterContext.h"
#include "Destination.h"
#include "Datagram.h"
namespace i2p
{
namespace datagram
{
DatagramDestination::DatagramDestination (i2p::client::ClientDestination& owner):
m_Owner (owner), m_Receiver (nullptr)
{
}
void DatagramDestination::SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote)
{
uint8_t buf[MAX_DATAGRAM_SIZE];
auto identityLen = m_Owner.GetIdentity ().ToBuffer (buf, MAX_DATAGRAM_SIZE);
uint8_t * signature = buf + identityLen;
auto signatureLen = m_Owner.GetIdentity ().GetSignatureLen ();
uint8_t * buf1 = signature + signatureLen;
size_t headerLen = identityLen + signatureLen;
memcpy (buf1, payload, len);
if (m_Owner.GetIdentity ().GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
{
uint8_t hash[32];
CryptoPP::SHA256().CalculateDigest (hash, buf1, len);
m_Owner.Sign (hash, 32, signature);
}
else
m_Owner.Sign (buf1, len, signature);
auto service = m_Owner.GetService ();
if (service)
service->post (boost::bind (&DatagramDestination::SendMsg, this,
CreateDataMessage (buf, len + headerLen), remote));
else
LogPrint (eLogWarning, "Failed to send datagram. Destination is not running");
}
void DatagramDestination::SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote)
{
auto leases = remote.GetNonExpiredLeases ();
if (!leases.empty ())
{
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
uint32_t i = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (0, leases.size () - 1);
auto garlic = m_Owner.WrapMessage (remote, msg, true);
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeTunnel,
leases[i].tunnelGateway, leases[i].tunnelID,
garlic
});
m_Owner.SendTunnelDataMsgs (msgs);
}
else
{
LogPrint (eLogWarning, "Failed to send datagram. All leases expired");
DeleteI2NPMessage (msg);
}
}
void DatagramDestination::HandleDatagram (const uint8_t * buf, size_t len)
{
i2p::data::IdentityEx identity;
size_t identityLen = identity.FromBuffer (buf, len);
const uint8_t * signature = buf + identityLen;
size_t headerLen = identityLen + identity.GetSignatureLen ();
bool verified = false;
if (identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1)
{
uint8_t hash[32];
CryptoPP::SHA256().CalculateDigest (hash, buf + headerLen, len - headerLen);
verified = identity.Verify (hash, 32, signature);
}
else
verified = identity.Verify (buf + headerLen, len - headerLen, signature);
if (verified)
{
if (m_Receiver != nullptr)
m_Receiver (identity, buf + headerLen, len -headerLen);
else
LogPrint (eLogWarning, "Receiver for datagram is not set");
}
else
LogPrint (eLogWarning, "Datagram signature verification failed");
}
void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len)
{
// unzip it
CryptoPP::Gunzip decompressor;
decompressor.Put (buf, len);
decompressor.MessageEnd();
uint8_t uncompressed[MAX_DATAGRAM_SIZE];
auto uncompressedLen = decompressor.MaxRetrievable ();
if (uncompressedLen <= MAX_DATAGRAM_SIZE)
{
decompressor.Get (uncompressed, uncompressedLen);
HandleDatagram (uncompressed, uncompressedLen);
}
else
LogPrint ("Received datagram size ", uncompressedLen, " exceeds max size");
}
I2NPMessage * DatagramDestination::CreateDataMessage (const uint8_t * payload, size_t len)
{
I2NPMessage * msg = NewI2NPMessage ();
CryptoPP::Gzip compressor; // default level
compressor.Put (payload, len);
compressor.MessageEnd();
int size = compressor.MaxRetrievable ();
uint8_t * buf = msg->GetPayload ();
*(uint32_t *)buf = htobe32 (size); // length
buf += 4;
compressor.Get (buf, size);
memset (buf + 4, 0, 4); // source and destination are zeroes
buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol
msg->len += size + 4;
FillI2NPMessageHeader (msg, eI2NPData);
return msg;
}
}
}

49
Datagram.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef DATAGRAM_H__
#define DATAGRAM_H__
#include <inttypes.h>
#include <functional>
#include "Identity.h"
#include "LeaseSet.h"
#include "I2NPProtocol.h"
namespace i2p
{
namespace client
{
class ClientDestination;
}
namespace datagram
{
const size_t MAX_DATAGRAM_SIZE = 32768;
class DatagramDestination
{
typedef std::function<void (const i2p::data::IdentityEx& ident, const uint8_t *, size_t)> Receiver;
public:
DatagramDestination (i2p::client::ClientDestination& owner);
~DatagramDestination () {};
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::LeaseSet& remote);
void HandleDataMessagePayload (const uint8_t * buf, size_t len);
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
void ResetReceiver () { m_Receiver = nullptr; };
private:
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
void SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote);
void HandleDatagram (const uint8_t * buf, size_t len);
private:
i2p::client::ClientDestination& m_Owner;
Receiver m_Receiver;
};
}
}
#endif

View File

@@ -1,7 +1,6 @@
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <cryptopp/dh.h> #include <cryptopp/dh.h>
#include <cryptopp/gzip.h>
#include "Log.h" #include "Log.h"
#include "util.h" #include "util.h"
#include "NetDb.h" #include "NetDb.h"
@@ -13,7 +12,8 @@ namespace client
{ {
ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType): ClientDestination::ClientDestination (bool isPublic, i2p::data::SigningKeyType sigType):
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
m_DatagramDestination (nullptr)
{ {
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
@@ -21,11 +21,13 @@ namespace client
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
if (m_IsPublic) if (m_IsPublic)
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created"); LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
} }
ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic): ClientDestination::ClientDestination (const std::string& fullPath, bool isPublic):
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
m_DatagramDestination (nullptr)
{ {
std::ifstream s(fullPath.c_str (), std::ifstream::binary); std::ifstream s(fullPath.c_str (), std::ifstream::binary);
if (s.is_open ()) if (s.is_open ())
@@ -56,17 +58,20 @@ namespace client
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
} }
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic): ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr), m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic) m_Keys (keys), m_CurrentOutboundTunnel (nullptr), m_LeaseSet (nullptr), m_IsPublic (isPublic),
m_DatagramDestination (nullptr)
{ {
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey); dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
if (m_IsPublic) if (m_IsPublic)
LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created"); LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
} }
ClientDestination::~ClientDestination () ClientDestination::~ClientDestination ()
@@ -79,6 +84,8 @@ namespace client
delete m_LeaseSet; delete m_LeaseSet;
delete m_Work; delete m_Work;
delete m_Service; delete m_Service;
delete m_StreamingDestination;
delete m_DatagramDestination;
} }
void ClientDestination::Run () void ClientDestination::Run ()
@@ -94,10 +101,18 @@ namespace client
m_Pool->SetActive (true); m_Pool->SetActive (true);
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&ClientDestination::Run, this)); m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
m_StreamingDestination->Start ();
} }
void ClientDestination::Stop () void ClientDestination::Stop ()
{ {
m_StreamingDestination->Stop ();
if (m_DatagramDestination)
{
auto d = m_DatagramDestination;
m_DatagramDestination = nullptr;
delete d;
}
if (m_Pool) if (m_Pool)
i2p::tunnel::tunnels.StopTunnelPool (m_Pool); i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
m_IsRunning = false; m_IsRunning = false;
@@ -238,135 +253,58 @@ namespace client
uint32_t length = be32toh (*(uint32_t *)buf); uint32_t length = be32toh (*(uint32_t *)buf);
buf += 4; buf += 4;
// we assume I2CP payload // we assume I2CP payload
if (buf[9] == 6) // streaming protocol switch (buf[9])
{
// unzip it
CryptoPP::Gunzip decompressor;
decompressor.Put (buf, length);
decompressor.MessageEnd();
i2p::stream::Packet * uncompressed = new i2p::stream::Packet;
uncompressed->offset = 0;
uncompressed->len = decompressor.MaxRetrievable ();
if (uncompressed->len <= i2p::stream::MAX_PACKET_SIZE)
{
decompressor.Get (uncompressed->buf, uncompressed->len);
HandleNextPacket (uncompressed);
}
else
{
LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped");
decompressor.Skip ();
delete uncompressed;
}
}
else
LogPrint ("Data: unexpected protocol ", buf[9]);
}
I2NPMessage * ClientDestination::CreateDataMessage (const uint8_t * payload, size_t len)
{
I2NPMessage * msg = NewI2NPShortMessage ();
CryptoPP::Gzip compressor;
if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)
compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL);
else
compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL);
compressor.Put (payload, len);
compressor.MessageEnd();
int size = compressor.MaxRetrievable ();
uint8_t * buf = msg->GetPayload ();
*(uint32_t *)buf = htobe32 (size); // length
buf += 4;
compressor.Get (buf, size);
memset (buf + 4, 0, 4); // source and destination ports. TODO: fill with proper values later
buf[9] = 6; // streaming protocol
msg->len += size + 4;
FillI2NPMessageHeader (msg, eI2NPData);
return msg;
}
}
namespace stream
{
void StreamingDestination::Start ()
{
ClientDestination::Start ();
}
void StreamingDestination::Stop ()
{
ResetAcceptor ();
{ {
std::unique_lock<std::mutex> l(m_StreamsMutex); case PROTOCOL_TYPE_STREAMING:
for (auto it: m_Streams) // streaming protocol
delete it.second; if (m_StreamingDestination)
m_Streams.clear (); m_StreamingDestination->HandleDataMessagePayload (buf, length);
}
ClientDestination::Stop ();
}
void StreamingDestination::HandleNextPacket (Packet * packet)
{
uint32_t sendStreamID = packet->GetSendStreamID ();
if (sendStreamID)
{
auto it = m_Streams.find (sendStreamID);
if (it != m_Streams.end ())
it->second->HandleNextPacket (packet);
else
{
LogPrint ("Unknown stream ", sendStreamID);
delete packet;
}
}
else // new incoming stream
{
auto incomingStream = CreateNewIncomingStream ();
incomingStream->HandleNextPacket (packet);
if (m_Acceptor != nullptr)
m_Acceptor (incomingStream);
else
{
LogPrint ("Acceptor for incoming stream is not set");
DeleteStream (incomingStream);
}
}
}
Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote)
{
Stream * s = new Stream (*GetService (), *this, remote);
std::unique_lock<std::mutex> l(m_StreamsMutex);
m_Streams[s->GetRecvStreamID ()] = s;
return s;
}
Stream * StreamingDestination::CreateNewIncomingStream ()
{
Stream * s = new Stream (*GetService (), *this);
std::unique_lock<std::mutex> l(m_StreamsMutex);
m_Streams[s->GetRecvStreamID ()] = s;
return s;
}
void StreamingDestination::DeleteStream (Stream * stream)
{
if (stream)
{
std::unique_lock<std::mutex> l(m_StreamsMutex);
auto it = m_Streams.find (stream->GetRecvStreamID ());
if (it != m_Streams.end ())
{
m_Streams.erase (it);
if (GetService ())
GetService ()->post ([stream](void) { delete stream; });
else else
delete stream; LogPrint ("Missing streaming destination");
} break;
} case PROTOCOL_TYPE_DATAGRAM:
// datagram protocol
if (m_DatagramDestination)
m_DatagramDestination->HandleDataMessagePayload (buf, length);
else
LogPrint ("Missing streaming destination");
break;
default:
LogPrint ("Data: unexpected protocol ", buf[9]);
}
} }
}
i2p::stream::Stream * ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port)
{
if (m_StreamingDestination)
return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
return nullptr;
}
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
{
if (m_StreamingDestination)
m_StreamingDestination->SetAcceptor (acceptor);
}
void ClientDestination::StopAcceptingStreams ()
{
if (m_StreamingDestination)
m_StreamingDestination->ResetAcceptor ();
}
bool ClientDestination::IsAcceptingStreams () const
{
if (m_StreamingDestination)
return m_StreamingDestination->IsAcceptorSet ();
return false;
}
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
{
if (!m_DatagramDestination)
m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
return m_DatagramDestination;
}
}
} }

View File

@@ -9,11 +9,16 @@
#include "LeaseSet.h" #include "LeaseSet.h"
#include "Garlic.h" #include "Garlic.h"
#include "Streaming.h" #include "Streaming.h"
#include "Datagram.h"
namespace i2p namespace i2p
{ {
namespace client namespace client
{ {
const uint8_t PROTOCOL_TYPE_STREAMING = 6;
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
const uint8_t PROTOCOL_TYPE_RAW = 18;
class ClientDestination: public i2p::garlic::GarlicDestination class ClientDestination: public i2p::garlic::GarlicDestination
{ {
public: public:
@@ -34,6 +39,17 @@ namespace client
const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident); const i2p::data::LeaseSet * FindLeaseSet (const i2p::data::IdentHash& ident);
void SendTunnelDataMsgs (const std::vector<i2p::tunnel::TunnelMessageBlock>& msgs); void SendTunnelDataMsgs (const std::vector<i2p::tunnel::TunnelMessageBlock>& msgs);
// streaming
i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; };
i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote, int port = 0);
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
void StopAcceptingStreams ();
bool IsAcceptingStreams () const;
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
// implements LocalDestination // implements LocalDestination
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
@@ -50,11 +66,6 @@ namespace client
// I2CP // I2CP
void HandleDataMessage (const uint8_t * buf, size_t len); void HandleDataMessage (const uint8_t * buf, size_t len);
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
protected:
virtual void HandleNextPacket (i2p::stream::Packet * packet) = 0; // TODO
private: private:
@@ -77,55 +88,15 @@ namespace client
i2p::data::LeaseSet * m_LeaseSet; i2p::data::LeaseSet * m_LeaseSet;
bool m_IsPublic; bool m_IsPublic;
i2p::stream::StreamingDestination * m_StreamingDestination;
i2p::datagram::DatagramDestination * m_DatagramDestination;
public: public:
// for HTTP only // for HTTP only
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); }; int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
}; };
} }
namespace stream
{
class StreamingDestination: public i2p::client::ClientDestination
{
public:
StreamingDestination (bool isPublic, i2p::data::SigningKeyType sigType):
ClientDestination (isPublic, sigType) {};
StreamingDestination (const std::string& fullPath, bool isPublic):
ClientDestination (fullPath, isPublic) {};
StreamingDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
ClientDestination (keys, isPublic) {};
~StreamingDestination () {};
void Start ();
void Stop ();
Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote);
void DeleteStream (Stream * stream);
void SetAcceptor (const std::function<void (Stream *)>& acceptor) { m_Acceptor = acceptor; };
void ResetAcceptor () { m_Acceptor = nullptr; };
bool IsAcceptorSet () const { return m_Acceptor != nullptr; };
// ClientDestination
void HandleNextPacket (Packet * packet);
private:
Stream * CreateNewIncomingStream ();
private:
std::mutex m_StreamsMutex;
std::map<uint32_t, Stream *> m_Streams;
std::function<void (Stream *)> m_Acceptor;
public:
// for HTTP only
const decltype(m_Streams)& GetStreams () const { return m_Streams; };
};
}
} }
#endif #endif

View File

@@ -148,7 +148,7 @@ namespace garlic
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg) size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg)
{ {
size_t blockSize = 0; size_t blockSize = 0;
bool createNewTags = m_Owner && ((int)m_SessionTags.size () <= m_NumTags/4); bool createNewTags = m_Owner && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags/2);
UnconfirmedTags * newTags = createNewTags ? GenerateSessionTags () : nullptr; UnconfirmedTags * newTags = createNewTags ? GenerateSessionTags () : nullptr;
*(uint16_t *)buf = newTags ? htobe16 (newTags->numTags) : 0; // tag count *(uint16_t *)buf = newTags ? htobe16 (newTags->numTags) : 0; // tag count
blockSize += 2; blockSize += 2;
@@ -272,6 +272,16 @@ namespace garlic
size += 4; size += 4;
// create msg // create msg
I2NPMessage * msg = CreateDeliveryStatusMsg (msgID); I2NPMessage * msg = CreateDeliveryStatusMsg (msgID);
if (m_Owner)
{
//encrypt
uint8_t key[32], tag[32];
m_Rnd.GenerateBlock (key, 32); // random session key
m_Rnd.GenerateBlock (tag, 32); // random session tag
m_Owner->AddSessionKey (key, tag);
GarlicRoutingSession garlic (key, tag);
msg = garlic.WrapSingleMessage (msg);
}
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
size += msg->GetLength (); size += msg->GetLength ();
DeleteI2NPMessage (msg); DeleteI2NPMessage (msg);
@@ -304,9 +314,10 @@ namespace garlic
{ {
if (key) if (key)
{ {
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>(); auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
decryption->SetKey (key); decryption->SetKey (key);
m_Tags[SessionTag(tag)] = decryption; m_Tags[SessionTag(tag, ts)] = decryption;
} }
} }
@@ -314,7 +325,7 @@ namespace garlic
{ {
uint8_t * buf = msg->GetPayload (); uint8_t * buf = msg->GetPayload ();
uint32_t length = be32toh (*(uint32_t *)buf); uint32_t length = be32toh (*(uint32_t *)buf);
buf += 4; // lentgh buf += 4; // length
auto it = m_Tags.find (SessionTag(buf)); auto it = m_Tags.find (SessionTag(buf));
if (it != m_Tags.end ()) if (it != m_Tags.end ())
{ {
@@ -343,7 +354,29 @@ namespace garlic
else else
LogPrint ("Failed to decrypt garlic"); LogPrint ("Failed to decrypt garlic");
} }
DeleteI2NPMessage (msg); DeleteI2NPMessage (msg);
// cleanup expired tags
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts > m_LastTagsCleanupTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
if (m_LastTagsCleanupTime)
{
int numExpiredTags = 0;
for (auto it = m_Tags.begin (); it != m_Tags.end ();)
{
if (ts > it->first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
numExpiredTags++;
it = m_Tags.erase (it);
}
else
it++;
}
LogPrint (numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ());
}
m_LastTagsCleanupTime = ts;
}
} }
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption, void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
@@ -447,8 +480,16 @@ namespace garlic
I2NPMessage * GarlicDestination::WrapMessage (const i2p::data::RoutingDestination& destination, I2NPMessage * GarlicDestination::WrapMessage (const i2p::data::RoutingDestination& destination,
I2NPMessage * msg, bool attachLeaseSet) I2NPMessage * msg, bool attachLeaseSet)
{ {
auto session = GetRoutingSession (destination, attachLeaseSet ? 32 : 0); // don't use tag if no LeaseSet if (attachLeaseSet) // we should maintain this session
return session->WrapSingleMessage (msg); {
auto session = GetRoutingSession (destination, 32); // 32 tags by default
return session->WrapSingleMessage (msg);
}
else // one time session
{
GarlicRoutingSession session (this, &destination, 0); // don't use tag if no LeaseSet
return session.WrapSingleMessage (msg);
}
} }
GarlicRoutingSession * GarlicDestination::GetRoutingSession ( GarlicRoutingSession * GarlicDestination::GetRoutingSession (
@@ -466,7 +507,7 @@ namespace garlic
} }
return session; return session;
} }
void GarlicDestination::DeliveryStatusSent (GarlicRoutingSession * session, uint32_t msgID) void GarlicDestination::DeliveryStatusSent (GarlicRoutingSession * session, uint32_t msgID)
{ {
m_CreatedSessions[msgID] = session; m_CreatedSessions[msgID] = session;

View File

@@ -37,7 +37,7 @@ namespace garlic
}; };
#pragma pack() #pragma pack()
const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 900; // 15 minutes const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes
const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes
struct SessionTag: public i2p::data::Tag<32> struct SessionTag: public i2p::data::Tag<32>
@@ -88,7 +88,7 @@ namespace garlic
GarlicDestination * m_Owner; GarlicDestination * m_Owner;
const i2p::data::RoutingDestination * m_Destination; const i2p::data::RoutingDestination * m_Destination;
uint8_t m_SessionKey[32]; i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags; std::list<SessionTag> m_SessionTags;
int m_NumTags; int m_NumTags;
std::map<uint32_t, UnconfirmedTags *> m_UnconfirmedTagsMsgs; std::map<uint32_t, UnconfirmedTags *> m_UnconfirmedTagsMsgs;
@@ -102,7 +102,7 @@ namespace garlic
{ {
public: public:
GarlicDestination () {}; GarlicDestination (): m_LastTagsCleanupTime (0) {};
~GarlicDestination (); ~GarlicDestination ();
GarlicRoutingSession * GetRoutingSession (const i2p::data::RoutingDestination& destination, int numTags); GarlicRoutingSession * GetRoutingSession (const i2p::data::RoutingDestination& destination, int numTags);
@@ -136,7 +136,8 @@ namespace garlic
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, GarlicRoutingSession *> m_Sessions; std::map<i2p::data::IdentHash, GarlicRoutingSession *> m_Sessions;
// incoming // incoming
std::map<SessionTag, std::shared_ptr<i2p::crypto::CBCDecryption>> m_Tags; std::map<SessionTag, std::shared_ptr<i2p::crypto::CBCDecryption>> m_Tags;
uint32_t m_LastTagsCleanupTime;
// DeliveryStatus // DeliveryStatus
std::map<uint32_t, GarlicRoutingSession *> m_CreatedSessions; // msgID -> session std::map<uint32_t, GarlicRoutingSession *> m_CreatedSessions; // msgID -> session
}; };

View File

@@ -1,7 +1,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include "NetDb.h" #include "ClientContext.h"
#include "HTTPProxy.h" #include "HTTPProxy.h"
namespace i2p namespace i2p
@@ -52,10 +52,11 @@ namespace proxy
} }
path=m[4].str(); path=m[4].str();
} }
LogPrint("server is: ",server, "\n path is: ",path); LogPrint("server is: ",server, " port is: ", port, "\n path is: ",path);
r.uri = path; r.uri = path;
r.method = method; r.method = method;
r.host = server; r.host = server;
r.port = boost::lexical_cast<int>(port);
} }
@@ -73,12 +74,12 @@ namespace proxy
{ {
LogPrint ("Jump service for ", r.host, " found. Inserting to address book"); LogPrint ("Jump service for ", r.host, " found. Inserting to address book");
auto base64 = r.uri.substr (addressPos + 1); auto base64 = r.uri.substr (addressPos + 1);
i2p::data::netdb.GetAddressBook ().InsertAddress (r.host, base64); i2p::client::context.GetAddressBook ().InsertAddress (r.host, base64);
} }
} }
LogPrint("Requesting ", r.host, " with path ", r.uri, " and method ", r.method); LogPrint("Requesting ", r.host, ":", r.port, " with path ", r.uri, " and method ", r.method);
SendToAddress (r.host, m_Buffer, m_BufferLen); SendToAddress (r.host, r.port, m_Buffer, m_BufferLen);
} }
} }

View File

@@ -517,7 +517,7 @@ namespace util
if (m_Stream) if (m_Stream)
{ {
m_Stream->Close (); m_Stream->Close ();
i2p::client::context.GetSharedLocalDestination ()->DeleteStream (m_Stream); i2p::stream::DeleteStream (m_Stream);
m_Stream = nullptr; m_Stream = nullptr;
} }
m_Socket->close (); m_Socket->close ();
@@ -644,10 +644,16 @@ namespace util
switch (address.transportStyle) switch (address.transportStyle)
{ {
case i2p::data::RouterInfo::eTransportNTCP: case i2p::data::RouterInfo::eTransportNTCP:
s << "NTCP&nbsp;&nbsp;"; if (address.host.is_v6 ())
s << "NTCP6&nbsp;&nbsp;";
else
s << "NTCP&nbsp;&nbsp;";
break; break;
case i2p::data::RouterInfo::eTransportSSU: case i2p::data::RouterInfo::eTransportSSU:
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; if (address.host.is_v6 ())
s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
else
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
break; break;
default: default:
s << "Unknown&nbsp;&nbsp;"; s << "Unknown&nbsp;&nbsp;";
@@ -699,14 +705,14 @@ namespace util
void HTTPConnection::ShowTransports (std::stringstream& s) void HTTPConnection::ShowTransports (std::stringstream& s)
{ {
s << "NTCP<br>"; s << "NTCP<br>";
for (auto it: i2p::transports.GetNTCPSessions ()) for (auto it: i2p::transport::transports.GetNTCPSessions ())
{ {
// RouterInfo of incoming connection doesn't have address if (it.second && it.second->IsEstablished ())
bool outgoing = it.second->GetRemoteRouterInfo ().GetNTCPAddress ();
if (it.second->IsEstablished ())
{ {
// incoming connection doesn't have remote RI
bool outgoing = it.second->GetRemoteRouter ();
if (outgoing) s << "-->"; if (outgoing) s << "-->";
s << it.second->GetRemoteRouterInfo ().GetIdentHashAbbreviation () << ": " s << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": "
<< it.second->GetSocket ().remote_endpoint().address ().to_string (); << it.second->GetSocket ().remote_endpoint().address ().to_string ();
if (!outgoing) s << "-->"; if (!outgoing) s << "-->";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
@@ -714,7 +720,7 @@ namespace util
} }
s << std::endl; s << std::endl;
} }
auto ssuServer = i2p::transports.GetSSUServer (); auto ssuServer = i2p::transport::transports.GetSSUServer ();
if (ssuServer) if (ssuServer)
{ {
s << "<br>SSU<br>"; s << "<br>SSU<br>";
@@ -813,10 +819,11 @@ namespace util
} }
} }
s << "<br><b>Streams:</b><br>"; s << "<br><b>Streams:</b><br>";
for (auto it: dest->GetStreams ()) for (auto it: dest->GetStreamingDestination ()->GetStreams ())
{ {
s << it.first << "->" << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase32 () << ".b32.i2p "; s << it.first << "->" << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase32 () << ".b32.i2p ";
s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]"; s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
s << " [out:" << it.second->GetSendQueueSize () << "][in:" << it.second->GetReceiveQueueSize () << "]";
s << "<br>"<< std::endl; s << "<br>"<< std::endl;
} }
} }
@@ -838,45 +845,56 @@ namespace util
{ {
std::string request = "GET " + uri + " HTTP/1.1\r\nHost:" + address + "\r\n"; std::string request = "GET " + uri + " HTTP/1.1\r\nHost:" + address + "\r\n";
LogPrint("HTTP Client Request: ", request); LogPrint("HTTP Client Request: ", request);
SendToAddress (address, request.c_str (), request.size ()); SendToAddress (address, 80, request.c_str (), request.size ());
} }
void HTTPConnection::SendToAddress (const std::string& address, const char * buf, size_t len) void HTTPConnection::SendToAddress (const std::string& address, int port, const char * buf, size_t len)
{ {
i2p::data::IdentHash destination; i2p::data::IdentHash destination;
if (!i2p::data::netdb.GetAddressBook ().GetIdentHash (address, destination)) if (!i2p::client::context.GetAddressBook ().GetIdentHash (address, destination))
{ {
LogPrint ("Unknown address ", address); LogPrint ("Unknown address ", address);
SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>", 404); SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>", 404);
return; return;
} }
SendToDestination (destination, buf, len);
}
void HTTPConnection::SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len)
{
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) if (leaseSet && leaseSet->HasNonExpiredLeases ())
SendToDestination (leaseSet, port, buf, len);
else
{ {
i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ()); i2p::data::netdb.RequestDestination (destination, true, i2p::client::context.GetSharedLocalDestination ()->GetTunnelPool ());
std::this_thread::sleep_for (std::chrono::seconds(10)); // wait for 10 seconds m_Timer.expires_from_now (boost::posix_time::seconds(HTTP_DESTINATION_REQUEST_TIMEOUT));
leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination); m_Timer.async_wait (boost::bind (&HTTPConnection::HandleDestinationRequestTimeout,
if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet this, boost::asio::placeholders::error, destination, port, buf, len));
{
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504);
return;
}
} }
}
void HTTPConnection::HandleDestinationRequestTimeout (const boost::system::error_code& ecode,
i2p::data::IdentHash destination, int port, const char * buf, size_t len)
{
if (ecode != boost::asio::error::operation_aborted)
{
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
if (leaseSet && leaseSet->HasNonExpiredLeases ())
SendToDestination (leaseSet, port, buf, len);
else
// still no LeaseSet
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504);
}
}
void HTTPConnection::SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len)
{
if (!m_Stream) if (!m_Stream)
m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream (*leaseSet); m_Stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (*remote, port);
if (m_Stream) if (m_Stream)
{ {
m_Stream->Send ((uint8_t *)buf, len); m_Stream->Send ((uint8_t *)buf, len);
AsyncStreamReceive (); AsyncStreamReceive ();
} }
} }
void HTTPConnection::AsyncStreamReceive () void HTTPConnection::AsyncStreamReceive ()
{ {
if (m_Stream) if (m_Stream)

View File

@@ -5,6 +5,7 @@
#include <thread> #include <thread>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#include "LeaseSet.h"
#include "Streaming.h" #include "Streaming.h"
namespace i2p namespace i2p
@@ -12,6 +13,7 @@ namespace i2p
namespace util namespace util
{ {
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
const int HTTP_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
class HTTPConnection class HTTPConnection
{ {
protected: protected:
@@ -27,6 +29,7 @@ namespace util
std::string method; std::string method;
std::string uri; std::string uri;
std::string host; std::string host;
int port;
int http_version_major; int http_version_major;
int http_version_minor; int http_version_minor;
std::vector<header> headers; std::vector<header> headers;
@@ -43,7 +46,8 @@ namespace util
public: public:
HTTPConnection (boost::asio::ip::tcp::socket * socket): HTTPConnection (boost::asio::ip::tcp::socket * socket):
m_Socket (socket), m_Stream (nullptr), m_BufferLen (0) { Receive (); }; m_Socket (socket), m_Timer (socket->get_io_service ()),
m_Stream (nullptr), m_BufferLen (0) { Receive (); };
virtual ~HTTPConnection() { delete m_Socket; } virtual ~HTTPConnection() { delete m_Socket; }
private: private:
@@ -74,6 +78,7 @@ namespace util
protected: protected:
boost::asio::ip::tcp::socket * m_Socket; boost::asio::ip::tcp::socket * m_Socket;
boost::asio::deadline_timer m_Timer;
i2p::stream::Stream * m_Stream; i2p::stream::Stream * m_Stream;
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1], m_StreamBuffer[HTTP_CONNECTION_BUFFER_SIZE + 1]; char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1], m_StreamBuffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
size_t m_BufferLen; size_t m_BufferLen;
@@ -84,8 +89,10 @@ namespace util
virtual void RunRequest (); virtual void RunRequest ();
void HandleDestinationRequest(const std::string& address, const std::string& uri); void HandleDestinationRequest(const std::string& address, const std::string& uri);
void SendToAddress (const std::string& address, const char * buf, size_t len); void SendToAddress (const std::string& address, int port, const char * buf, size_t len);
void SendToDestination (const i2p::data::IdentHash& destination, const char * buf, size_t len); void HandleDestinationRequestTimeout (const boost::system::error_code& ecode,
i2p::data::IdentHash destination, int port, const char * buf, size_t len);
void SendToDestination (const i2p::data::LeaseSet * remote, int port, const char * buf, size_t len);
public: public:

View File

@@ -13,9 +13,10 @@
#include "Garlic.h" #include "Garlic.h"
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
using namespace i2p::transport;
namespace i2p namespace i2p
{ {
I2NPMessage * NewI2NPMessage () I2NPMessage * NewI2NPMessage ()
{ {
return new I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE>(); return new I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE>();
@@ -289,7 +290,7 @@ namespace i2p
{ {
LogPrint ("Record ",i," is ours"); LogPrint ("Record ",i," is ours");
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKey (), records[i].encrypted, (uint8_t *)&clearText); i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), records[i].encrypted, (uint8_t *)&clearText);
// replace record to reply // replace record to reply
I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i); I2NPBuildResponseRecord * reply = (I2NPBuildResponseRecord *)(records + i);
if (i2p::context.AcceptsTunnels ()) if (i2p::context.AcceptsTunnels ())
@@ -353,13 +354,13 @@ namespace i2p
if (clearText.flag & 0x40) // we are endpoint of outboud tunnel if (clearText.flag & 0x40) // we are endpoint of outboud tunnel
{ {
// so we send it to reply tunnel // so we send it to reply tunnel
i2p::transports.SendMessage (clearText.nextIdent, transports.SendMessage (clearText.nextIdent,
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
eI2NPVariableTunnelBuildReply, buf, len, eI2NPVariableTunnelBuildReply, buf, len,
be32toh (clearText.nextMessageID))); be32toh (clearText.nextMessageID)));
} }
else else
i2p::transports.SendMessage (clearText.nextIdent, transports.SendMessage (clearText.nextIdent,
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
} }
} }
@@ -373,13 +374,13 @@ namespace i2p
if (clearText.flag & 0x40) // we are endpoint of outbound tunnel if (clearText.flag & 0x40) // we are endpoint of outbound tunnel
{ {
// so we send it to reply tunnel // so we send it to reply tunnel
i2p::transports.SendMessage (clearText.nextIdent, transports.SendMessage (clearText.nextIdent,
CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel), CreateTunnelGatewayMsg (be32toh (clearText.nextTunnel),
eI2NPTunnelBuildReply, buf, len, eI2NPTunnelBuildReply, buf, len,
be32toh (clearText.nextMessageID))); be32toh (clearText.nextMessageID)));
} }
else else
i2p::transports.SendMessage (clearText.nextIdent, transports.SendMessage (clearText.nextIdent,
CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID))); CreateI2NPMessage (eI2NPTunnelBuild, buf, len, be32toh (clearText.nextMessageID)));
} }
} }

View File

@@ -34,6 +34,14 @@ uint16_t be16toh(uint16_t big16);
uint32_t be32toh(uint32_t big32); uint32_t be32toh(uint32_t big32);
uint64_t be64toh(uint64_t big64); uint64_t be64toh(uint64_t big64);
// assume LittleEndine
#define htole16
#define htole32
#define htole64
#define le16toh
#define le32toh
#define le64toh
#endif #endif
#endif // I2PENDIAN_H__ #endif // I2PENDIAN_H__

View File

@@ -14,7 +14,7 @@ namespace client
boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet): boost::asio::ip::tcp::socket * socket, const i2p::data::LeaseSet * leaseSet):
m_Socket (socket), m_Owner (owner) m_Socket (socket), m_Owner (owner)
{ {
m_Stream = m_Owner->GetLocalDestination ()->CreateNewOutgoingStream (*leaseSet); m_Stream = m_Owner->GetLocalDestination ()->CreateStream (*leaseSet);
m_Stream->Send (m_Buffer, 0); // connect m_Stream->Send (m_Buffer, 0); // connect
StreamReceive (); StreamReceive ();
Receive (); Receive ();
@@ -39,7 +39,7 @@ namespace client
if (m_Stream) if (m_Stream)
{ {
m_Stream->Close (); m_Stream->Close ();
m_Owner->GetLocalDestination ()->DeleteStream (m_Stream); i2p::stream::DeleteStream (m_Stream);
m_Stream = nullptr; m_Stream = nullptr;
} }
m_Socket->close (); m_Socket->close ();
@@ -115,7 +115,7 @@ namespace client
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
if (m_Stream) m_Stream->Close (); if (m_Stream) m_Stream->Close ();
m_Owner->GetLocalDestination ()->DeleteStream (m_Stream); i2p::stream::DeleteStream (m_Stream);
m_Stream = nullptr; m_Stream = nullptr;
} }
} }
@@ -145,7 +145,7 @@ namespace client
} }
I2PClientTunnel::I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, I2PClientTunnel::I2PClientTunnel (boost::asio::io_service& service, const std::string& destination,
int port, i2p::stream::StreamingDestination * localDestination): int port, ClientDestination * localDestination):
I2PTunnel (service, localDestination ? localDestination : I2PTunnel (service, localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)), i2p::client::context.CreateNewLocalDestination (false, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256)),
m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)), m_Acceptor (service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port)),
@@ -162,7 +162,7 @@ namespace client
void I2PClientTunnel::Start () void I2PClientTunnel::Start ()
{ {
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash)) if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash))
m_DestinationIdentHash = new i2p::data::IdentHash (identHash); m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
if (!m_DestinationIdentHash) if (!m_DestinationIdentHash)
LogPrint ("I2PTunnel unknown destination ", m_Destination); LogPrint ("I2PTunnel unknown destination ", m_Destination);
@@ -192,7 +192,7 @@ namespace client
if (!m_DestinationIdentHash) if (!m_DestinationIdentHash)
{ {
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
if (i2p::data::netdb.GetAddressBook ().GetIdentHash (m_Destination, identHash)) if (i2p::client::context.GetAddressBook ().GetIdentHash (m_Destination, identHash))
m_DestinationIdentHash = new i2p::data::IdentHash (identHash); m_DestinationIdentHash = new i2p::data::IdentHash (identHash);
} }
if (m_DestinationIdentHash) if (m_DestinationIdentHash)
@@ -251,7 +251,7 @@ namespace client
} }
I2PServerTunnel::I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port, I2PServerTunnel::I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
i2p::stream::StreamingDestination * localDestination): I2PTunnel (service, localDestination), ClientDestination * localDestination): I2PTunnel (service, localDestination),
m_Endpoint (boost::asio::ip::address::from_string (address), port) m_Endpoint (boost::asio::ip::address::from_string (address), port)
{ {
} }
@@ -270,7 +270,7 @@ namespace client
{ {
auto localDestination = GetLocalDestination (); auto localDestination = GetLocalDestination ();
if (localDestination) if (localDestination)
localDestination->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); localDestination->AcceptStreams (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1));
else else
LogPrint ("Local destination not set for server tunnel"); LogPrint ("Local destination not set for server tunnel");
} }

View File

@@ -6,6 +6,7 @@
#include <set> #include <set>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Identity.h" #include "Identity.h"
#include "Destination.h"
#include "Streaming.h" #include "Streaming.h"
namespace i2p namespace i2p
@@ -51,22 +52,22 @@ namespace client
{ {
public: public:
I2PTunnel (boost::asio::io_service& service, i2p::stream::StreamingDestination * localDestination): I2PTunnel (boost::asio::io_service& service, ClientDestination * localDestination):
m_Service (service), m_LocalDestination (localDestination) {}; m_Service (service), m_LocalDestination (localDestination) {};
virtual ~I2PTunnel () { ClearConnections (); }; virtual ~I2PTunnel () { ClearConnections (); };
void AddConnection (I2PTunnelConnection * conn); void AddConnection (I2PTunnelConnection * conn);
void RemoveConnection (I2PTunnelConnection * conn); void RemoveConnection (I2PTunnelConnection * conn);
void ClearConnections (); void ClearConnections ();
i2p::stream::StreamingDestination * GetLocalDestination () { return m_LocalDestination; }; ClientDestination * GetLocalDestination () { return m_LocalDestination; };
void SetLocalDestination (i2p::stream::StreamingDestination * dest) { m_LocalDestination = dest; }; void SetLocalDestination (ClientDestination * dest) { m_LocalDestination = dest; };
boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetService () { return m_Service; };
private: private:
boost::asio::io_service& m_Service; boost::asio::io_service& m_Service;
i2p::stream::StreamingDestination * m_LocalDestination; ClientDestination * m_LocalDestination;
std::set<I2PTunnelConnection *> m_Connections; std::set<I2PTunnelConnection *> m_Connections;
}; };
@@ -75,7 +76,7 @@ namespace client
public: public:
I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, int port, I2PClientTunnel (boost::asio::io_service& service, const std::string& destination, int port,
i2p::stream::StreamingDestination * localDestination = nullptr); ClientDestination * localDestination = nullptr);
~I2PClientTunnel (); ~I2PClientTunnel ();
void Start (); void Start ();
@@ -102,7 +103,7 @@ namespace client
public: public:
I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port, I2PServerTunnel (boost::asio::io_service& service, const std::string& address, int port,
i2p::stream::StreamingDestination * localDestination); ClientDestination * localDestination);
void Start (); void Start ();
void Stop (); void Stop ();

View File

@@ -2,7 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include <cryptopp/sha.h> #include <cryptopp/sha.h>
#include <cryptopp/osrng.h> #include <cryptopp/osrng.h>
#include <cryptopp/dh.h>
#include <cryptopp/dsa.h> #include <cryptopp/dsa.h>
#include "base64.h" #include "base64.h"
#include "CryptoConst.h" #include "CryptoConst.h"
@@ -101,7 +100,7 @@ namespace data
m_ExtendedBuffer = nullptr; m_ExtendedBuffer = nullptr;
delete m_Verifier; delete m_Verifier;
CreateVerifier (); m_Verifier = nullptr;
return *this; return *this;
} }
@@ -116,7 +115,7 @@ namespace data
m_ExtendedLen = 0; m_ExtendedLen = 0;
delete m_Verifier; delete m_Verifier;
CreateVerifier (); m_Verifier = nullptr;
return *this; return *this;
} }
@@ -140,7 +139,7 @@ namespace data
CryptoPP::SHA256().CalculateDigest(m_IdentHash, buf, GetFullLen ()); CryptoPP::SHA256().CalculateDigest(m_IdentHash, buf, GetFullLen ());
delete m_Verifier; delete m_Verifier;
CreateVerifier (); m_Verifier = nullptr;
return GetFullLen (); return GetFullLen ();
} }
@@ -162,19 +161,22 @@ namespace data
size_t IdentityEx::GetSigningPublicKeyLen () const size_t IdentityEx::GetSigningPublicKeyLen () const
{ {
if (m_Verifier) if (!m_Verifier) CreateVerifier ();
if (m_Verifier)
return m_Verifier->GetPublicKeyLen (); return m_Verifier->GetPublicKeyLen ();
return 128; return 128;
} }
size_t IdentityEx::GetSignatureLen () const size_t IdentityEx::GetSignatureLen () const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetSignatureLen (); return m_Verifier->GetSignatureLen ();
return 40; return 40;
} }
bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->Verify (buf, len, signature); return m_Verifier->Verify (buf, len, signature);
return false; return false;
@@ -187,7 +189,7 @@ namespace data
return SIGNING_KEY_TYPE_DSA_SHA1; return SIGNING_KEY_TYPE_DSA_SHA1;
} }
void IdentityEx::CreateVerifier () void IdentityEx::CreateVerifier () const
{ {
auto keyType = GetSigningKeyType (); auto keyType = GetSigningKeyType ();
switch (keyType) switch (keyType)
@@ -293,14 +295,6 @@ namespace data
return keys; return keys;
} }
void CreateRandomDHKeysPair (DHKeysPair * keys)
{
if (!keys) return;
CryptoPP::AutoSeededRandomPool rnd;
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
dh.GenerateKeyPair(rnd, keys->privateKey, keys->publicKey);
}
IdentHash CreateRoutingKey (const IdentHash& ident) IdentHash CreateRoutingKey (const IdentHash& ident)
{ {
uint8_t buf[41]; // ident + yyyymmdd uint8_t buf[41]; // ident + yyyymmdd

View File

@@ -67,13 +67,6 @@ namespace data
typedef Tag<32> IdentHash; typedef Tag<32> IdentHash;
#pragma pack(1) #pragma pack(1)
struct DHKeysPair // transient keys for transport sessions
{
uint8_t publicKey[256];
uint8_t privateKey[256];
};
struct Keys struct Keys
{ {
uint8_t privateKey[256]; uint8_t privateKey[256];
@@ -82,7 +75,6 @@ namespace data
uint8_t signingKey[128]; uint8_t signingKey[128];
}; };
const uint8_t CERTIFICATE_TYPE_NULL = 0; const uint8_t CERTIFICATE_TYPE_NULL = 0;
const uint8_t CERTIFICATE_TYPE_HASHCASH = 1; const uint8_t CERTIFICATE_TYPE_HASHCASH = 1;
const uint8_t CERTIFICATE_TYPE_HIDDEN = 2; const uint8_t CERTIFICATE_TYPE_HIDDEN = 2;
@@ -105,7 +97,10 @@ namespace data
Identity& operator=(const Keys& keys); Identity& operator=(const Keys& keys);
size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (const uint8_t * buf, size_t len);
IdentHash Hash () const; IdentHash Hash () const;
}; };
#pragma pack()
Keys CreateRandomKeys ();
const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
@@ -139,13 +134,13 @@ namespace data
private: private:
void CreateVerifier (); void CreateVerifier () const;
private: private:
Identity m_StandardIdentity; Identity m_StandardIdentity;
IdentHash m_IdentHash; IdentHash m_IdentHash;
i2p::crypto::Verifier * m_Verifier; mutable i2p::crypto::Verifier * m_Verifier;
size_t m_ExtendedLen; size_t m_ExtendedLen;
uint8_t * m_ExtendedBuffer; uint8_t * m_ExtendedBuffer;
}; };
@@ -183,11 +178,6 @@ namespace data
uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes
i2p::crypto::Signer * m_Signer; i2p::crypto::Signer * m_Signer;
}; };
#pragma pack()
Keys CreateRandomKeys ();
void CreateRandomDHKeysPair (DHKeysPair * keys); // for transport sessions
// kademlia // kademlia
struct XORMetric struct XORMetric

11
Log.cpp
View File

@@ -3,9 +3,18 @@
Log * g_Log = nullptr; Log * g_Log = nullptr;
static const char * g_LogLevelStr[eNumLogLevels] =
{
"error", // eLogError
"warn", // eLogWarning
"info", // eLogInfo
"debug" // eLogDebug
};
void LogMsg::Process() void LogMsg::Process()
{ {
output << boost::posix_time::second_clock::local_time().time_of_day () << " - "; output << boost::posix_time::second_clock::local_time().time_of_day () <<
"/" << g_LogLevelStr[level] << " - ";
output << s.str(); output << s.str();
} }

23
Log.h
View File

@@ -8,12 +8,22 @@
#include <functional> #include <functional>
#include "Queue.h" #include "Queue.h"
enum LogLevel
{
eLogError = 0,
eLogWarning,
eLogInfo,
eLogDebug,
eNumLogLevels
};
struct LogMsg struct LogMsg
{ {
std::stringstream s; std::stringstream s;
std::ostream& output; std::ostream& output;
LogLevel level;
LogMsg (std::ostream& o = std::cout): output (o) {}; LogMsg (std::ostream& o = std::cout, LogLevel l = eLogInfo): output (o), level (l) {};
void Process(); void Process();
}; };
@@ -72,9 +82,10 @@ void LogPrint (std::stringstream& s, TValue arg, TArgs... args)
} }
template<typename... TArgs> template<typename... TArgs>
void LogPrint (TArgs... args) void LogPrint (LogLevel level, TArgs... args)
{ {
LogMsg * msg = (g_Log && g_Log->GetLogFile ()) ? new LogMsg (*g_Log->GetLogFile ()) : new LogMsg (); LogMsg * msg = (g_Log && g_Log->GetLogFile ()) ? new LogMsg (*g_Log->GetLogFile (), level) :
new LogMsg (std::cout, level);
LogPrint (msg->s, args...); LogPrint (msg->s, args...);
msg->s << std::endl; msg->s << std::endl;
if (g_Log) if (g_Log)
@@ -84,6 +95,12 @@ void LogPrint (TArgs... args)
msg->Process (); msg->Process ();
delete msg; delete msg;
} }
}
template<typename... TArgs>
void LogPrint (TArgs... args)
{
LogPrint (eLogInfo, args...);
} }
#endif #endif

View File

@@ -11,13 +11,13 @@ endif
all: obj i2p all: obj i2p
i2p: $(OBJECTS:obj/%=obj/%) i2p: $(OBJECTS:obj/%=obj/%)
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) $(LIBS)
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .c .cc .C .cpp .o .SUFFIXES: .c .cc .C .cpp .o
obj/%.o : %.cpp obj/%.o : %.cpp
$(CC) -o $@ $< -c $(CFLAGS) $(INCFLAGS) $(CPU_FLAGS) $(CXX) -o $@ $< -c $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(CPU_FLAGS)
obj: obj:
mkdir -p obj mkdir -p obj

View File

@@ -1,6 +1,8 @@
CC = g++ CXX = g++
CFLAGS = -std=c++11 -O2 CXXFLAGS = -O2
NEEDED_CXXFLAGS = -std=c++11
include filelist.mk include filelist.mk
INCFLAGS = -I/usr/include/ -I/usr/local/include/ INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDLIBS = -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
LIBS = LIBS =

View File

@@ -1,25 +1,43 @@
CC = g++ CXXFLAGS = -g -Wall
CFLAGS = -g -Wall CXXVER := $(shell $(CXX) -dumpversion)
CXXVER := $(shell ${CC} -dumpversion)
FGREP = fgrep
IS_64 := $(shell $(CXX) -dumpmachine 2>&1 | $(FGREP) -c "64")
USE_AESNI := yes
ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # >= 4.10 ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # >= 4.10
CFLAGS += -std=c++11 NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7 else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7
CFLAGS += -std=c++11 NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6 else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6
CFLAGS += -std=c++0x NEEDED_CXXFLAGS += -std=c++0x
else ifeq ($(shell expr match $(CXX) 'clang'),5)
NEEDED_CXXFLAGS += -std=c++11
else # not supported else # not supported
$(error Compiler too old) $(error Compiler too old)
endif endif
LIBDIR := /usr/lib
include filelist.mk include filelist.mk
INCFLAGS = INCFLAGS =
LDFLAGS = -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread ifeq ($(STATIC),yes)
LDLIBS += $(LIBDIR)/libcryptopp.a $(LIBDIR)/libboost_system.a
LDLIBS += $(LIBDIR)/libboost_date_time.a $(LIBDIR)/libboost_filesystem.a
LDLIBS += $(LIBDIR)/libboost_regex.a $(LIBDIR)/libboost_program_options.a
LDLIBS += -lpthread -static-libstdc++ -static-libgcc
USE_AESNI := no
else
LDLIBS = -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
endif
LIBS = LIBS =
ifeq ($(USE_AESNI),yes)
ifeq ($(IS_64),1)
#check if AES-NI is supported by CPU #check if AES-NI is supported by CPU
ifneq ($(shell grep -c aes /proc/cpuinfo),0) ifneq ($(shell grep -c aes /proc/cpuinfo),0)
CPU_FLAGS = -maes -DAESNI CPU_FLAGS = -maes -DAESNI
endif endif
endif
endif

View File

@@ -1,15 +1,16 @@
CC = clang++ CXX = clang++
CFLAGS = -g -Wall -std=c++11 -lstdc++ -I/usr/local/include CXXFLAGS = -g -Wall -std=c++11 -lstdc++ -I/usr/local/include
include filelist.mk include filelist.mk
INCFLAGS = -DCRYPTOPP_DISABLE_ASM INCFLAGS = -DCRYPTOPP_DISABLE_ASM
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDLIBS = -lcryptopp -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
LIBS = LIBS =
# OSX Notes # OSX Notes
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html # http://www.hutsby.net/2011/08/macs-with-aes-ni.html
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2 # Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic # Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
CFLAGS += -DAESNI CXXFLAGS += -maes -DAESNI
# Apple Mac OSX # Apple Mac OSX
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)

View File

@@ -3,7 +3,6 @@
#include "I2PEndian.h" #include "I2PEndian.h"
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <cryptopp/dh.h> #include <cryptopp/dh.h>
#include <cryptopp/dsa.h>
#include "base64.h" #include "base64.h"
#include "Log.h" #include "Log.h"
#include "Timestamp.h" #include "Timestamp.h"
@@ -11,28 +10,27 @@
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "RouterContext.h" #include "RouterContext.h"
#include "Transports.h" #include "Transports.h"
#include "NetDb.h"
#include "NTCPSession.h" #include "NTCPSession.h"
using namespace i2p::crypto; using namespace i2p::crypto;
namespace i2p namespace i2p
{ {
namespace ntcp namespace transport
{ {
NTCPSession::NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo): NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter):
m_Socket (service), m_TerminationTimer (service), m_IsEstablished (false), TransportSession (in_RemoteRouter), m_Socket (service),
m_DHKeysPair (nullptr), m_RemoteRouterInfo (in_RemoteRouterInfo), m_TerminationTimer (service), m_IsEstablished (false), m_ReceiveBufferOffset (0),
m_ReceiveBufferOffset (0), m_NextMessage (nullptr), m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0)
m_NumSentBytes (0), m_NumReceivedBytes (0)
{ {
m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); m_DHKeysPair = transports.GetNextDHKeysPair ();
m_Establisher = new Establisher; m_Establisher = new Establisher;
} }
NTCPSession::~NTCPSession () NTCPSession::~NTCPSession ()
{ {
delete m_Establisher; delete m_Establisher;
delete m_DHKeysPair;
if (m_NextMessage) if (m_NextMessage)
i2p::DeleteI2NPMessage (m_NextMessage); i2p::DeleteI2NPMessage (m_NextMessage);
for (auto it :m_DelayedMessages) for (auto it :m_DelayedMessages)
@@ -40,7 +38,7 @@ namespace ntcp
m_DelayedMessages.clear (); m_DelayedMessages.clear ();
} }
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey) void NTCPSession::CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key)
{ {
CryptoPP::DH dh (elgp, elgg); CryptoPP::DH dh (elgp, elgg);
uint8_t sharedKey[256]; uint8_t sharedKey[256];
@@ -51,6 +49,7 @@ namespace ntcp
return; return;
}; };
uint8_t * aesKey = key;
if (sharedKey[0] & 0x80) if (sharedKey[0] & 0x80)
{ {
aesKey[0] = 0; aesKey[0] = 0;
@@ -79,12 +78,13 @@ namespace ntcp
{ {
m_IsEstablished = false; m_IsEstablished = false;
m_Socket.close (); m_Socket.close ();
i2p::transports.RemoveNTCPSession (this); transports.RemoveNTCPSession (this);
int numDelayed = 0; int numDelayed = 0;
for (auto it :m_DelayedMessages) for (auto it :m_DelayedMessages)
{ {
// try to send them again // try to send them again
i2p::transports.SendMessage (m_RemoteRouterInfo.GetIdentHash (), it); if (m_RemoteRouter)
transports.SendMessage (m_RemoteRouter->GetIdentHash (), it);
numDelayed++; numDelayed++;
} }
m_DelayedMessages.clear (); m_DelayedMessages.clear ();
@@ -121,12 +121,12 @@ namespace ntcp
void NTCPSession::ClientLogin () void NTCPSession::ClientLogin ()
{ {
if (!m_DHKeysPair) if (!m_DHKeysPair)
m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); m_DHKeysPair = transports.GetNextDHKeysPair ();
// send Phase1 // send Phase1
const uint8_t * x = m_DHKeysPair->publicKey; const uint8_t * x = m_DHKeysPair->publicKey;
memcpy (m_Establisher->phase1.pubKey, x, 256); memcpy (m_Establisher->phase1.pubKey, x, 256);
CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256); CryptoPP::SHA256().CalculateDigest(m_Establisher->phase1.HXxorHI, x, 256);
const uint8_t * ident = m_RemoteRouterInfo.GetIdentHash (); const uint8_t * ident = m_RemoteIdentity.GetIdentHash ();
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
m_Establisher->phase1.HXxorHI[i] ^= ident[i]; m_Establisher->phase1.HXxorHI[i] ^= ident[i];
@@ -191,7 +191,7 @@ namespace ntcp
void NTCPSession::SendPhase2 () void NTCPSession::SendPhase2 ()
{ {
if (!m_DHKeysPair) if (!m_DHKeysPair)
m_DHKeysPair = i2p::transports.GetNextDHKeysPair (); m_DHKeysPair = transports.GetNextDHKeysPair ();
const uint8_t * y = m_DHKeysPair->publicKey; const uint8_t * y = m_DHKeysPair->publicKey;
memcpy (m_Establisher->phase2.pubKey, y, 256); memcpy (m_Establisher->phase2.pubKey, y, 256);
uint8_t xy[512]; uint8_t xy[512];
@@ -202,7 +202,7 @@ namespace ntcp
m_Establisher->phase2.encrypted.timestamp = tsB; m_Establisher->phase2.encrypted.timestamp = tsB;
// TODO: fill filler // TODO: fill filler
uint8_t aesKey[32]; i2p::crypto::AESKey aesKey;
CreateAESKey (m_Establisher->phase1.pubKey, aesKey); CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
m_Encryption.SetKey (aesKey); m_Encryption.SetKey (aesKey);
m_Encryption.SetIV (y + 240); m_Encryption.SetIV (y + 240);
@@ -239,8 +239,9 @@ namespace ntcp
LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed"); LogPrint ("Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
GetRemoteRouterInfo ().SetUnreachable (true); // this RouterInfo is not valid // this RI is not valid
i2p::transports.ReuseDHKeysPair (m_DHKeysPair); i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
transports.ReuseDHKeysPair (m_DHKeysPair);
m_DHKeysPair = nullptr; m_DHKeysPair = nullptr;
Terminate (); Terminate ();
} }
@@ -249,7 +250,7 @@ namespace ntcp
{ {
LogPrint ("Phase 2 received: ", bytes_transferred); LogPrint ("Phase 2 received: ", bytes_transferred);
uint8_t aesKey[32]; i2p::crypto::AESKey aesKey;
CreateAESKey (m_Establisher->phase2.pubKey, aesKey); CreateAESKey (m_Establisher->phase2.pubKey, aesKey);
m_Decryption.SetKey (aesKey); m_Decryption.SetKey (aesKey);
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240); m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
@@ -265,7 +266,7 @@ namespace ntcp
if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32)) if (memcmp (hxy, m_Establisher->phase2.encrypted.hxy, 32))
{ {
LogPrint ("Incorrect hash"); LogPrint ("Incorrect hash");
i2p::transports.ReuseDHKeysPair (m_DHKeysPair); transports.ReuseDHKeysPair (m_DHKeysPair);
m_DHKeysPair = nullptr; m_DHKeysPair = nullptr;
Terminate (); Terminate ();
return ; return ;
@@ -277,17 +278,17 @@ namespace ntcp
void NTCPSession::SendPhase3 () void NTCPSession::SendPhase3 ()
{ {
m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE); m_Establisher->phase3.size = htons (i2p::data::DEFAULT_IDENTITY_SIZE);
memcpy (&m_Establisher->phase3.ident, &i2p::context.GetRouterIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE); memcpy (&m_Establisher->phase3.ident, &i2p::context.GetIdentity ().GetStandardIdentity (), i2p::data::DEFAULT_IDENTITY_SIZE); // TODO:
uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ()); uint32_t tsA = htobe32 (i2p::util::GetSecondsSinceEpoch ());
m_Establisher->phase3.timestamp = tsA; m_Establisher->phase3.timestamp = tsA;
SignedData s; SignedData s;
memcpy (s.x, m_Establisher->phase1.pubKey, 256); s.Insert (m_Establisher->phase1.pubKey, 256); // x
memcpy (s.y, m_Establisher->phase2.pubKey, 256); s.Insert (m_Establisher->phase2.pubKey, 256); // y
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); s.Insert (m_RemoteIdentity.GetIdentHash (), 32); // ident
s.tsA = tsA; s.Insert (tsA); // tsA
s.tsB = m_Establisher->phase2.encrypted.timestamp; s.Insert (m_Establisher->phase2.encrypted.timestamp); // tsB
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase3.signature); s.Sign (i2p::context.GetPrivateKeys (), m_Establisher->phase3.signature);
m_Encryption.Encrypt((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3); m_Encryption.Encrypt((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
@@ -324,19 +325,15 @@ namespace ntcp
{ {
LogPrint ("Phase 3 received: ", bytes_transferred); LogPrint ("Phase 3 received: ", bytes_transferred);
m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3); m_Decryption.Decrypt ((uint8_t *)&m_Establisher->phase3, sizeof(NTCPPhase3), (uint8_t *)&m_Establisher->phase3);
m_RemoteRouterInfo.SetRouterIdentity (m_Establisher->phase3.ident); m_RemoteIdentity = m_Establisher->phase3.ident;
SignedData s; SignedData s;
memcpy (s.x, m_Establisher->phase1.pubKey, 256); s.Insert (m_Establisher->phase1.pubKey, 256); // x
memcpy (s.y, m_Establisher->phase2.pubKey, 256); s.Insert (m_Establisher->phase2.pubKey, 256); // y
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32); s.Insert (i2p::context.GetRouterInfo ().GetIdentHash (), 32); // ident
s.tsA = m_Establisher->phase3.timestamp; s.Insert (m_Establisher->phase3.timestamp); // tsA
s.tsB = tsB; s.Insert (tsB); // tsB
if (!s.Verify (m_RemoteIdentity, m_Establisher->phase3.signature))
CryptoPP::DSA::PublicKey pubKey;
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
CryptoPP::DSA::Verifier verifier (pubKey);
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase3.signature, 40))
{ {
LogPrint ("signature verification failed"); LogPrint ("signature verification failed");
Terminate (); Terminate ();
@@ -350,12 +347,12 @@ namespace ntcp
void NTCPSession::SendPhase4 (uint32_t tsB) void NTCPSession::SendPhase4 (uint32_t tsB)
{ {
SignedData s; SignedData s;
memcpy (s.x, m_Establisher->phase1.pubKey, 256); s.Insert (m_Establisher->phase1.pubKey, 256); // x
memcpy (s.y, m_Establisher->phase2.pubKey, 256); s.Insert (m_Establisher->phase2.pubKey, 256); // y
memcpy (s.ident, m_RemoteRouterInfo.GetIdentHash (), 32); s.Insert (m_RemoteIdentity.GetIdentHash (), 32); // ident
s.tsA = m_Establisher->phase3.timestamp; s.Insert (m_Establisher->phase3.timestamp); // tsA
s.tsB = tsB; s.Insert (tsB); // tsB
i2p::context.Sign ((uint8_t *)&s, sizeof (s), m_Establisher->phase4.signature); s.Sign (i2p::context.GetPrivateKeys (), m_Establisher->phase4.signature);
m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase4, sizeof(NTCPPhase4), (uint8_t *)&m_Establisher->phase4); m_Encryption.Encrypt ((uint8_t *)&m_Establisher->phase4, sizeof(NTCPPhase4), (uint8_t *)&m_Establisher->phase4);
boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase4, sizeof (NTCPPhase4)), boost::asio::transfer_all (), boost::asio::async_write (m_Socket, boost::asio::buffer (&m_Establisher->phase4, sizeof (NTCPPhase4)), boost::asio::transfer_all (),
@@ -387,7 +384,8 @@ namespace ntcp
LogPrint ("Phase 4 read error: ", ecode.message ()); LogPrint ("Phase 4 read error: ", ecode.message ());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
GetRemoteRouterInfo ().SetUnreachable (true); // this router doesn't like us // this router doesn't like us
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
Terminate (); Terminate ();
} }
} }
@@ -398,16 +396,13 @@ namespace ntcp
// verify signature // verify signature
SignedData s; SignedData s;
memcpy (s.x, m_Establisher->phase1.pubKey, 256); s.Insert (m_Establisher->phase1.pubKey, 256); // x
memcpy (s.y, m_Establisher->phase2.pubKey, 256); s.Insert (m_Establisher->phase2.pubKey, 256); // y
memcpy (s.ident, i2p::context.GetRouterInfo ().GetIdentHash (), 32); s.Insert (i2p::context.GetRouterInfo ().GetIdentHash (), 32); // ident
s.tsA = tsA; s.Insert (tsA); // tsA
s.tsB = m_Establisher->phase2.encrypted.timestamp; s.Insert (m_Establisher->phase2.encrypted.timestamp); // tsB
CryptoPP::DSA::PublicKey pubKey; if (!s.Verify (m_RemoteIdentity, m_Establisher->phase4.signature))
pubKey.Initialize (dsap, dsaq, dsag, CryptoPP::Integer (m_RemoteRouterInfo.GetRouterIdentity ().signingKey, 128));
CryptoPP::DSA::Verifier verifier (pubKey);
if (!verifier.VerifyMessage ((uint8_t *)&s, sizeof(s), m_Establisher->phase4.signature, 40))
{ {
LogPrint ("signature verification failed"); LogPrint ("signature verification failed");
Terminate (); Terminate ();
@@ -433,7 +428,7 @@ namespace ntcp
if (ecode) if (ecode)
{ {
LogPrint ("Read error: ", ecode.message ()); LogPrint ("Read error: ", ecode.message ());
if (ecode != boost::asio::error::operation_aborted) //if (ecode != boost::asio::error::operation_aborted)
Terminate (); Terminate ();
} }
else else
@@ -595,15 +590,15 @@ namespace ntcp
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
LogPrint ("No activity fo ", NTCP_TERMINATION_TIMEOUT, " seconds"); LogPrint ("No activity fo ", NTCP_TERMINATION_TIMEOUT, " seconds");
Terminate (); //Terminate ();
m_Socket.close ();// invoke Terminate () from HandleReceive
} }
} }
NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, NTCPClient::NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address,
int port, i2p::data::RouterInfo& in_RouterInfo): int port, const i2p::data::RouterInfo& in_RouterInfo):
NTCPSession (service, in_RouterInfo), NTCPSession (service, &in_RouterInfo), m_Endpoint (address, port)
m_Endpoint (address, port)
{ {
Connect (); Connect ();
} }
@@ -622,13 +617,15 @@ namespace ntcp
LogPrint ("Connect error: ", ecode.message ()); LogPrint ("Connect error: ", ecode.message ());
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
GetRemoteRouterInfo ().SetUnreachable (true); i2p::data::netdb.SetUnreachable (GetRemoteIdentity ().GetIdentHash (), true);
Terminate (); Terminate ();
} }
} }
else else
{ {
LogPrint ("Connected"); LogPrint ("Connected");
if (GetSocket ().local_endpoint ().protocol () == boost::asio::ip::tcp::v6()) // ipv6
context.UpdateNTCPV6Address (GetSocket ().local_endpoint ().address ());
ClientLogin (); ClientLogin ();
} }
} }
@@ -636,11 +633,8 @@ namespace ntcp
void NTCPServerConnection::Connected () void NTCPServerConnection::Connected ()
{ {
LogPrint ("NTCP server session connected"); LogPrint ("NTCP server session connected");
SetIsEstablished (true); transports.AddNTCPSession (this);
i2p::transports.AddNTCPSession (this); NTCPSession::Connected ();
SendTimeSyncMessage ();
SendI2NPMessage (CreateDatabaseStoreMsg ()); // we tell immediately who we are
} }
} }
} }

View File

@@ -11,10 +11,11 @@
#include "Identity.h" #include "Identity.h"
#include "RouterInfo.h" #include "RouterInfo.h"
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "TransportSession.h"
namespace i2p namespace i2p
{ {
namespace ntcp namespace transport
{ {
#pragma pack(1) #pragma pack(1)
@@ -50,31 +51,22 @@ namespace ntcp
uint8_t signature[40]; uint8_t signature[40];
uint8_t padding[8]; uint8_t padding[8];
}; };
struct SignedData // used for signature in Phase3 and Phase4
{
uint8_t x[256];
uint8_t y[256];
uint8_t ident[32];
uint32_t tsA;
uint32_t tsB;
};
#pragma pack() #pragma pack()
const size_t NTCP_MAX_MESSAGE_SIZE = 16384; const size_t NTCP_MAX_MESSAGE_SIZE = 16384;
const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028) const size_t NTCP_BUFFER_SIZE = 1040; // fits one tunnel message (1028)
const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes const int NTCP_TERMINATION_TIMEOUT = 120; // 2 minutes
class NTCPSession
class NTCPSession: public TransportSession
{ {
public: public:
NTCPSession (boost::asio::io_service& service, i2p::data::RouterInfo& in_RemoteRouterInfo); NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter = nullptr);
virtual ~NTCPSession (); ~NTCPSession ();
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
bool IsEstablished () const { return m_IsEstablished; }; bool IsEstablished () const { return m_IsEstablished; };
i2p::data::RouterInfo& GetRemoteRouterInfo () { return m_RemoteRouterInfo; };
void ClientLogin (); void ClientLogin ();
void ServerLogin (); void ServerLogin ();
@@ -92,7 +84,7 @@ namespace ntcp
private: private:
void CreateAESKey (uint8_t * pubKey, uint8_t * aesKey); void CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key);
// client // client
void SendPhase3 (); void SendPhase3 ();
@@ -127,13 +119,10 @@ namespace ntcp
boost::asio::ip::tcp::socket m_Socket; boost::asio::ip::tcp::socket m_Socket;
boost::asio::deadline_timer m_TerminationTimer; boost::asio::deadline_timer m_TerminationTimer;
bool m_IsEstablished; bool m_IsEstablished;
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
i2p::crypto::CBCDecryption m_Decryption; i2p::crypto::CBCDecryption m_Decryption;
i2p::crypto::CBCEncryption m_Encryption; i2p::crypto::CBCEncryption m_Encryption;
CryptoPP::Adler32 m_Adler; CryptoPP::Adler32 m_Adler;
i2p::data::RouterInfo& m_RemoteRouterInfo;
struct Establisher struct Establisher
{ {
@@ -157,7 +146,7 @@ namespace ntcp
{ {
public: public:
NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, i2p::data::RouterInfo& in_RouterInfo); NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, const i2p::data::RouterInfo& in_RouterInfo);
private: private:
@@ -174,15 +163,11 @@ namespace ntcp
public: public:
NTCPServerConnection (boost::asio::io_service& service): NTCPServerConnection (boost::asio::io_service& service):
NTCPSession (service, m_DummyRemoteRouterInfo) {}; NTCPSession (service) {};
protected: protected:
virtual void Connected (); virtual void Connected ();
private:
i2p::data::RouterInfo m_DummyRemoteRouterInfo;
}; };
} }
} }

View File

@@ -15,6 +15,8 @@
#include "Reseed.h" #include "Reseed.h"
#include "util.h" #include "util.h"
using namespace i2p::transport;
namespace i2p namespace i2p
{ {
namespace data namespace data
@@ -69,8 +71,6 @@ namespace data
Stop (); Stop ();
for (auto l:m_LeaseSets) for (auto l:m_LeaseSets)
delete l.second; delete l.second;
for (auto r:m_RouterInfos)
delete r.second;
for (auto r:m_RequestedDestinations) for (auto r:m_RequestedDestinations)
delete r.second; delete r.second;
} }
@@ -179,7 +179,7 @@ namespace data
else else
{ {
LogPrint ("New RouterInfo added"); LogPrint ("New RouterInfo added");
RouterInfo * r = new RouterInfo (buf, len); auto r = std::make_shared<RouterInfo> (buf, len);
m_RouterInfos[r->GetIdentHash ()] = r; m_RouterInfos[r->GetIdentHash ()] = r;
if (r->IsFloodfill ()) if (r->IsFloodfill ())
{ {
@@ -213,7 +213,7 @@ namespace data
{ {
auto it = m_RouterInfos.find (ident); auto it = m_RouterInfos.find (ident);
if (it != m_RouterInfos.end ()) if (it != m_RouterInfos.end ())
return it->second; return it->second.get ();
else else
return nullptr; return nullptr;
} }
@@ -227,6 +227,13 @@ namespace data
return nullptr; return nullptr;
} }
void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable)
{
auto it = m_RouterInfos.find (ident);
if (it != m_RouterInfos.end ())
return it->second->SetUnreachable (unreachable);
}
// TODO: Move to reseed and/or scheduled tasks. (In java version, scheduler fix this as well as sort RIs.) // TODO: Move to reseed and/or scheduled tasks. (In java version, scheduler fix this as well as sort RIs.)
bool NetDb::CreateNetDb(boost::filesystem::path directory) bool NetDb::CreateNetDb(boost::filesystem::path directory)
{ {
@@ -262,8 +269,6 @@ namespace data
if (!CreateNetDb(p)) return; if (!CreateNetDb(p)) return;
} }
// make sure we cleanup netDb from previous attempts // make sure we cleanup netDb from previous attempts
for (auto r: m_RouterInfos)
delete r.second;
m_RouterInfos.clear (); m_RouterInfos.clear ();
m_Floodfills.clear (); m_Floodfills.clear ();
@@ -282,7 +287,7 @@ namespace data
#else #else
const std::string& fullPath = it1->path(); const std::string& fullPath = it1->path();
#endif #endif
RouterInfo * r = new RouterInfo(fullPath); auto r = std::make_shared<RouterInfo>(fullPath);
if (!r->IsUnreachable () && (!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour if (!r->IsUnreachable () && (!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour
{ {
r->DeleteBuffer (); r->DeleteBuffer ();
@@ -295,7 +300,6 @@ namespace data
{ {
if (boost::filesystem::exists (fullPath)) if (boost::filesystem::exists (fullPath))
boost::filesystem::remove (fullPath); boost::filesystem::remove (fullPath);
delete r;
} }
} }
} }
@@ -332,7 +336,7 @@ namespace data
{ {
if (it.second->IsUpdated ()) if (it.second->IsUpdated ())
{ {
it.second->SaveToFile (GetFilePath(fullDirectory, it.second)); it.second->SaveToFile (GetFilePath(fullDirectory, it.second.get ()));
it.second->SetUpdated (false); it.second->SetUpdated (false);
it.second->DeleteBuffer (); it.second->DeleteBuffer ();
count++; count++;
@@ -350,9 +354,9 @@ namespace data
if (it.second->IsUnreachable ()) if (it.second->IsUnreachable ())
{ {
if (boost::filesystem::exists (GetFilePath (fullDirectory, it.second))) if (boost::filesystem::exists (GetFilePath (fullDirectory, it.second.get ())))
{ {
boost::filesystem::remove (GetFilePath (fullDirectory, it.second)); boost::filesystem::remove (GetFilePath (fullDirectory, it.second.get ()));
deletedCount++; deletedCount++;
} }
} }
@@ -403,7 +407,7 @@ namespace data
RequestedDestination * dest = CreateRequestedDestination (destination, false, false, pool); RequestedDestination * dest = CreateRequestedDestination (destination, false, false, pool);
auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ()); auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ());
if (floodfill) if (floodfill)
i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
} }
} }
@@ -655,10 +659,10 @@ namespace data
if (outbound) if (outbound)
outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg); outbound->SendTunnelDataMsg (buf+32, replyTunnelID, replyMsg);
else else
i2p::transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg)); transports.SendMessage (buf+32, i2p::CreateTunnelGatewayMsg (replyTunnelID, replyMsg));
} }
else else
i2p::transports.SendMessage (buf+32, replyMsg); transports.SendMessage (buf+32, replyMsg);
} }
i2p::DeleteI2NPMessage (msg); i2p::DeleteI2NPMessage (msg);
} }
@@ -712,7 +716,7 @@ namespace data
}); });
} }
else else
i2p::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
} }
else else
DeleteRequestedDestination (dest); DeleteRequestedDestination (dest);
@@ -774,37 +778,37 @@ namespace data
} }
} }
const RouterInfo * NetDb::GetRandomRouter () const std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter () const
{ {
return GetRandomRouter ( return GetRandomRouter (
[](const RouterInfo * router)->bool [](std::shared_ptr<const RouterInfo> router)->bool
{ {
return !router->IsHidden (); return !router->IsHidden ();
}); });
} }
const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith) const std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (const RouterInfo * compatibleWith) const
{ {
return GetRandomRouter ( return GetRandomRouter (
[compatibleWith](const RouterInfo * router)->bool [compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
{ {
return !router->IsHidden () && router != compatibleWith && return !router->IsHidden () && router.get () != compatibleWith &&
router->IsCompatible (*compatibleWith); router->IsCompatible (*compatibleWith);
}); });
} }
const RouterInfo * NetDb::GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const
{ {
return GetRandomRouter ( return GetRandomRouter (
[compatibleWith](const RouterInfo * router)->bool [compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
{ {
return !router->IsHidden () && router != compatibleWith && return !router->IsHidden () && router.get () != compatibleWith &&
router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth); router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth);
}); });
} }
template<typename Filter> template<typename Filter>
const RouterInfo * NetDb::GetRandomRouter (Filter filter) const std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (Filter filter) const
{ {
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator (); CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1); uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1);
@@ -848,7 +852,7 @@ namespace data
if (m < minMetric) if (m < minMetric)
{ {
minMetric = m; minMetric = m;
r = it; r = it.get ();
} }
} }
} }

18
NetDb.h
View File

@@ -15,7 +15,6 @@
#include "LeaseSet.h" #include "LeaseSet.h"
#include "Tunnel.h" #include "Tunnel.h"
#include "TunnelPool.h" #include "TunnelPool.h"
#include "AddressBook.h"
namespace i2p namespace i2p
{ {
@@ -67,7 +66,6 @@ namespace data
void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from); void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from);
RouterInfo * FindRouter (const IdentHash& ident) const; RouterInfo * FindRouter (const IdentHash& ident) const;
LeaseSet * FindLeaseSet (const IdentHash& destination) const; LeaseSet * FindLeaseSet (const IdentHash& destination) const;
AddressBook& GetAddressBook () { return m_AddressBook; };// TODO: move AddressBook away from NetDb
void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool); void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool);
void RequestDestination (const IdentHash& destination, bool isLeaseSet = false, void RequestDestination (const IdentHash& destination, bool isLeaseSet = false,
@@ -77,10 +75,11 @@ namespace data
void HandleDatabaseSearchReplyMsg (I2NPMessage * msg); void HandleDatabaseSearchReplyMsg (I2NPMessage * msg);
void HandleDatabaseLookupMsg (I2NPMessage * msg); void HandleDatabaseLookupMsg (I2NPMessage * msg);
const RouterInfo * GetRandomRouter () const; std::shared_ptr<const RouterInfo> GetRandomRouter () const;
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith) const; std::shared_ptr<const RouterInfo> GetRandomRouter (const RouterInfo * compatibleWith) const;
const RouterInfo * GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const; std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const;
void SetUnreachable (const IdentHash& ident, bool unreachable);
void PostI2NPMsg (I2NPMessage * msg); void PostI2NPMsg (I2NPMessage * msg);
// for web interface // for web interface
@@ -105,14 +104,14 @@ namespace data
void DeleteRequestedDestination (RequestedDestination * dest); void DeleteRequestedDestination (RequestedDestination * dest);
template<typename Filter> template<typename Filter>
const RouterInfo * GetRandomRouter (Filter filter) const; std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
private: private:
std::map<IdentHash, LeaseSet *> m_LeaseSets; std::map<IdentHash, LeaseSet *> m_LeaseSets;
std::map<IdentHash, RouterInfo *> m_RouterInfos; std::map<IdentHash, std::shared_ptr<RouterInfo> > m_RouterInfos;
mutable std::mutex m_FloodfillsMutex; mutable std::mutex m_FloodfillsMutex;
std::vector<RouterInfo *> m_Floodfills; std::vector<std::shared_ptr<RouterInfo> > m_Floodfills;
std::mutex m_RequestedDestinationsMutex; std::mutex m_RequestedDestinationsMutex;
std::map<IdentHash, RequestedDestination *> m_RequestedDestinations; std::map<IdentHash, RequestedDestination *> m_RequestedDestinations;
@@ -120,7 +119,6 @@ namespace data
int m_ReseedRetries; int m_ReseedRetries;
std::thread * m_Thread; std::thread * m_Thread;
i2p::util::Queue<I2NPMessage> m_Queue; // of I2NPDatabaseStoreMsg i2p::util::Queue<I2NPMessage> m_Queue; // of I2NPDatabaseStoreMsg
AddressBook m_AddressBook;
static const char m_NetDbPath[]; static const char m_NetDbPath[];
}; };

View File

@@ -1,21 +1,28 @@
i2pd i2pd
==== ====
i2p router for Linux written on C++ I2P router written in C++
Requires gcc 4.6 and higher, boost 1.46 and higher, crypto++ Requirements for Linux/FreeBSD/OSX
----------------------------------
on Windows GCC 4.6 or newer, Boost 1.46 or newer, crypto++. Clang can be used instead of
GCC.
Requires msvs2013 (require Visual C++ Compiler November 2013 CTP update), boost 1.46 and higher, crypto++ Requirements for Windows
------------------------
VS2013 (known to work with 12.0.21005.1 or newer), Boost 1.46 or newer,
crypto++ 5.62. See Win32/README-Build.txt for instructions on how to build i2pd
and its dependencies.
Build Statuses Build Statuses
--------------- ---------------
- Linux x64 - [![Build Status](https://jenkins.nordcloud.no/buildStatus/icon?job=i2pd-linux)](https://jenkins.nordcloud.no/job/i2pd-linux/) - Linux x64 - [![Build Status](https://jenkins.nordcloud.no/buildStatus/icon?job=i2pd-linux)](https://jenkins.nordcloud.no/job/i2pd-linux/)
- Linux ARM - Too be added - Linux ARM - To be added
- Mac OS X - Too be added - Mac OS X - To be added
- Microsoft VC13 - Too be added - Microsoft VC13 - To be added
Testing Testing
@@ -35,10 +42,10 @@ $ ./i2p --host=YOUR_PUBLIC_IP
The client should now reseed by itself. The client should now reseed by itself.
To visit an I2P page, you need to find the b32 address of your destination. To visit an I2P page, you need to find the b32 address of your destination.
After that, go to the webconsole and add it behind the url. (Remove http:// and b32.i2p from the address) After that, go to the webconsole and add it behind the url. (Remove http:// from the address)
This should resulting in for example: This should resulting in for example:
http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa http://localhost:7070/4oes3rlgrpbkmzv4lqcfili23h3cvpwslqcfjlk6vvguxyggspwa.b32.i2p
Options Options
@@ -51,13 +58,14 @@ Options
* --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no. * --daemon= - Enable or disable daemon mode. 1 for yes, 0 for no.
* --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd). * --service= - 1 if uses system folders (/var/run/i2pd.pid, /var/log/i2pd.log, /var/lib/i2pd).
* --unreachable= - 1 if router is declared as unreachable and works through introducers. * --unreachable= - 1 if router is declared as unreachable and works through introducers.
* --v6= - 1 if supports communication through ipv6, off by default
* --httpproxyport= - The port to listen on (HTTP Proxy) * --httpproxyport= - The port to listen on (HTTP Proxy)
* --socksproxyport= - The port to listen on (SOCKS Proxy) * --socksproxyport= - The port to listen on (SOCKS Proxy)
* --ircport= - The local port of IRC tunnel to listen on. 6668 by default * --ircport= - The local port of IRC tunnel to listen on. 6668 by default
* --ircdest= - I2P destination address of IRC server. For example irc.postman.i2p * --ircdest= - I2P destination address of IRC server. For example irc.postman.i2p
* --irckeys= - optional keys file for local destination * --irckeys= - optional keys file for local destination
* --eepkeys= - File name containing destination keys. For example privKeys.dat * --eepkeys= - File name containing destination keys. For example privKeys.dat
* --eephost= - Address incoming trafic forward to. 127.0.0.1 by default * --eephost= - Address incoming trafic forward to. 127.0.0.1 by default
* --eepport= - Port incoming trafic forward to. 80 by default * --eepport= - Port incoming trafic forward to. 80 by default
* --samport= - Port of SAM bridge. Usually 7656. SAM is off if not specified * --samport= - Port of SAM bridge. Usually 7656. SAM is off if not specified

View File

@@ -2,6 +2,8 @@
#include <fstream> #include <fstream>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <cryptopp/gzip.h>
#include "I2PEndian.h"
#include "Reseed.h" #include "Reseed.h"
#include "Log.h" #include "Log.h"
#include "util.h" #include "util.h"
@@ -119,6 +121,59 @@ namespace data
return false; return false;
} }
void ProcessSU3File (const char * filename)
{
static uint32_t headerSignature = htole32 (0x04044B50);
std::ifstream s(filename, std::ifstream::binary);
if (s.is_open ())
{
while (!s.eof ())
{
uint32_t signature;
s.read ((char *)&signature, 4);
if (signature == headerSignature)
{
// next local file
s.seekg (14, std::ios::cur); // skip field we don't care about
uint32_t compressedSize, uncompressedSize;
s.read ((char *)&compressedSize, 4);
compressedSize = le32toh (compressedSize);
s.read ((char *)&uncompressedSize, 4);
uncompressedSize = le32toh (uncompressedSize);
uint16_t fileNameLength, extraFieldLength;
s.read ((char *)&fileNameLength, 2);
fileNameLength = le32toh (fileNameLength);
s.read ((char *)&extraFieldLength, 2);
extraFieldLength = le32toh (extraFieldLength);
char localFileName[255];
s.read (localFileName, fileNameLength);
localFileName[fileNameLength] = 0;
s.seekg (extraFieldLength, std::ios::cur);
uint8_t * compressed = new uint8_t[compressedSize];
s.read ((char *)compressed, compressedSize);
CryptoPP::Gunzip decompressor;
decompressor.Put (compressed, compressedSize);
delete[] compressed;
if (decompressor.MaxRetrievable () <= uncompressedSize)
{
uint8_t * uncompressed = new uint8_t[uncompressedSize];
decompressor.Get (uncompressed, decompressor.MaxRetrievable ());
// TODO: save file
delete[] uncompressed;
}
else
LogPrint (eLogError, "Actual uncompressed size ", decompressor.MaxRetrievable (), " exceed ", uncompressedSize, " from header");
}
else
break; // no more files
}
}
else
LogPrint (eLogError, "Can't open file ", filename);
}
} }
} }

View File

@@ -17,7 +17,8 @@ namespace data
bool reseedNow(); bool reseedNow();
}; };
void ProcessSU3File (const char * filename);
} }
} }
#endif #endif

View File

@@ -34,7 +34,7 @@ namespace i2p
void RouterContext::NewRouterInfo () void RouterContext::NewRouterInfo ()
{ {
i2p::data::RouterInfo routerInfo; i2p::data::RouterInfo routerInfo;
routerInfo.SetRouterIdentity (GetIdentity ().GetStandardIdentity ()); routerInfo.SetRouterIdentity (GetIdentity ());
int port = i2p::util::config::GetArg("-port", 0); int port = i2p::util::config::GetArg("-port", 0);
if (!port) if (!port)
port = m_Rnd.GenerateWord32 (9111, 30777); // I2P network ports range port = m_Rnd.GenerateWord32 (9111, 30777); // I2P network ports range
@@ -72,15 +72,14 @@ namespace i2p
UpdateRouterInfo (); UpdateRouterInfo ();
} }
void RouterContext::UpdateAddress (const char * host) void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
{ {
bool updated = false; bool updated = false;
auto newAddress = boost::asio::ip::address::from_string (host);
for (auto& address : m_RouterInfo.GetAddresses ()) for (auto& address : m_RouterInfo.GetAddresses ())
{ {
if (address.host != newAddress) if (address.host != host && address.IsCompatible (host))
{ {
address.host = newAddress; address.host = host;
updated = true; updated = true;
} }
} }
@@ -130,7 +129,52 @@ namespace i2p
// update // update
UpdateRouterInfo (); UpdateRouterInfo ();
} }
void RouterContext::SetSupportsV6 (bool supportsV6)
{
if (supportsV6)
m_RouterInfo.EnableV6 ();
else
m_RouterInfo.DisableV6 ();
UpdateRouterInfo ();
}
void RouterContext::UpdateNTCPV6Address (const boost::asio::ip::address& host)
{
bool updated = false, found = false;
int port = 0;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses)
{
if (addr.host.is_v6 () && addr.transportStyle == i2p::data::RouterInfo::eTransportNTCP)
{
if (addr.host != host)
{
addr.host = host;
updated = true;
}
found = true;
}
else
port = addr.port;
}
if (!found)
{
// create new address
m_RouterInfo.AddNTCPAddress (host.to_string ().c_str (), port);
auto mtu = i2p::util::net::GetMTU (host);
if (mtu)
{
LogPrint ("Our v6 MTU=", mtu);
if (mtu > 1472) mtu = 1472;
}
m_RouterInfo.AddSSUAddress (host.to_string ().c_str (), port, GetIdentHash (), mtu ? mtu : 1472); // TODO
updated = true;
}
if (updated)
UpdateRouterInfo ();
}
bool RouterContext::Load () bool RouterContext::Load ()
{ {
std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in); std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in);

View File

@@ -2,6 +2,9 @@
#define ROUTER_CONTEXT_H__ #define ROUTER_CONTEXT_H__
#include <inttypes.h> #include <inttypes.h>
#include <string>
#include <memory>
#include <boost/asio.hpp>
#include <cryptopp/dsa.h> #include <cryptopp/dsa.h>
#include <cryptopp/osrng.h> #include <cryptopp/osrng.h>
#include "Identity.h" #include "Identity.h"
@@ -22,19 +25,24 @@ namespace i2p
void Init (); void Init ();
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
const uint8_t * GetPrivateKey () const { return m_Keys.GetPrivateKey (); }; std::shared_ptr<const i2p::data::RouterInfo> GetSharedRouterInfo () const
const i2p::data::Identity& GetRouterIdentity () const { return m_RouterInfo.GetRouterIdentity (); }; {
const i2p::data::IdentHash& GetRouterIdentHash () const { return m_RouterInfo.GetIdentHash (); }; return std::shared_ptr<const i2p::data::RouterInfo> (&m_RouterInfo,
[](const i2p::data::RouterInfo *) {});
}
CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; }; CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; };
void UpdatePort (int port); // called from Daemon void UpdatePort (int port); // called from Daemon
void UpdateAddress (const char * host); // called from SSU or Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
bool AddIntroducer (const i2p::data::RouterInfo& routerInfo, uint32_t tag); bool AddIntroducer (const i2p::data::RouterInfo& routerInfo, uint32_t tag);
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
bool IsUnreachable () const { return m_IsUnreachable; }; bool IsUnreachable () const { return m_IsUnreachable; };
void SetUnreachable (); void SetUnreachable ();
bool AcceptsTunnels () const { return m_AcceptsTunnels; }; bool AcceptsTunnels () const { return m_AcceptsTunnels; };
void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; }; void SetAcceptsTunnels (bool acceptsTunnels) { m_AcceptsTunnels = acceptsTunnels; };
bool SupportsV6 () const { return m_RouterInfo.IsV6 (); };
void SetSupportsV6 (bool supportsV6);
void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session
// implements LocalDestination // implements LocalDestination
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };

View File

@@ -31,7 +31,7 @@ namespace data
m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE];
memcpy (m_Buffer, buf, len); memcpy (m_Buffer, buf, len);
m_BufferLen = len; m_BufferLen = len;
ReadFromBuffer (); ReadFromBuffer (true);
} }
RouterInfo::~RouterInfo () RouterInfo::~RouterInfo ()
@@ -51,15 +51,13 @@ namespace data
m_Properties.clear (); m_Properties.clear ();
memcpy (m_Buffer, buf, len); memcpy (m_Buffer, buf, len);
m_BufferLen = len; m_BufferLen = len;
ReadFromBuffer (); ReadFromBuffer (true);
// don't delete buffer until save to file // don't delete buffer until save to file
} }
void RouterInfo::SetRouterIdentity (const Identity& identity) void RouterInfo::SetRouterIdentity (const IdentityEx& identity)
{ {
m_RouterIdentity = identity; m_RouterIdentity = identity;
m_IdentHash = m_RouterIdentity.Hash ();
UpdateIdentHashBase64 ();
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
} }
@@ -72,7 +70,7 @@ namespace data
m_BufferLen = s.tellg (); m_BufferLen = s.tellg ();
if (m_BufferLen < 40) if (m_BufferLen < 40)
{ {
LogPrint("File", m_FullPath, " is malformed"); LogPrint(eLogError, "File", m_FullPath, " is malformed");
return false; return false;
} }
s.seekg(0, std::ios::beg); s.seekg(0, std::ios::beg);
@@ -82,7 +80,7 @@ namespace data
} }
else else
{ {
LogPrint ("Can't open file ", m_FullPath); LogPrint (eLogError, "Can't open file ", m_FullPath);
return false; return false;
} }
return true; return true;
@@ -91,27 +89,25 @@ namespace data
void RouterInfo::ReadFromFile () void RouterInfo::ReadFromFile ()
{ {
if (LoadFile ()) if (LoadFile ())
ReadFromBuffer (); ReadFromBuffer (false);
} }
void RouterInfo::ReadFromBuffer () void RouterInfo::ReadFromBuffer (bool verifySignature)
{ {
std::stringstream str (std::string ((char *)m_Buffer, m_BufferLen)); size_t identityLen = m_RouterIdentity.FromBuffer (m_Buffer, m_BufferLen);
std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen));
ReadFromStream (str); ReadFromStream (str);
// verify signature if (verifySignature)
CryptoPP::DSA::PublicKey pubKey;
pubKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag, CryptoPP::Integer (m_RouterIdentity.signingKey, 128));
CryptoPP::DSA::Verifier verifier (pubKey);
int l = m_BufferLen - 40;
if (!verifier.VerifyMessage ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l, 40))
{ {
LogPrint ("signature verification failed"); // verify signature
int l = m_BufferLen - m_RouterIdentity.GetSignatureLen ();
if (!m_RouterIdentity.Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l))
LogPrint (eLogError, "signature verification failed");
} }
} }
void RouterInfo::ReadFromStream (std::istream& s) void RouterInfo::ReadFromStream (std::istream& s)
{ {
s.read ((char *)&m_RouterIdentity, sizeof (m_RouterIdentity));
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
m_Timestamp = be64toh (m_Timestamp); m_Timestamp = be64toh (m_Timestamp);
// read addresses // read addresses
@@ -151,7 +147,7 @@ namespace data
if (ecode) if (ecode)
{ {
// TODO: we should try to resolve address here // TODO: we should try to resolve address here
LogPrint ("Unexpected address ", value); LogPrint (eLogWarning, "Unexpected address ", value);
isValidAddress = false; isValidAddress = false;
} }
else else
@@ -224,9 +220,6 @@ namespace data
if (!strcmp (key, "caps")) if (!strcmp (key, "caps"))
ExtractCaps (value); ExtractCaps (value);
} }
CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity));
UpdateIdentHashBase64 ();
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers)) if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
SetUnreachable (true); SetUnreachable (true);
@@ -279,18 +272,9 @@ namespace data
SetProperty ("caps", caps.c_str ()); SetProperty ("caps", caps.c_str ());
} }
void RouterInfo::UpdateIdentHashBase64 ()
{
size_t l = i2p::data::ByteStreamToBase64 (m_IdentHash, 32, m_IdentHashBase64, 48);
m_IdentHashBase64[l] = 0;
memcpy (m_IdentHashAbbreviation, m_IdentHashBase64, 4);
m_IdentHashAbbreviation[4] = 0;
}
void RouterInfo::WriteToStream (std::ostream& s) void RouterInfo::WriteToStream (std::ostream& s)
{ {
s.write ((char *)&m_RouterIdentity, sizeof (m_RouterIdentity));
uint64_t ts = htobe64 (m_Timestamp); uint64_t ts = htobe64 (m_Timestamp);
s.write ((char *)&ts, sizeof (ts)); s.write ((char *)&ts, sizeof (ts));
@@ -376,6 +360,14 @@ namespace data
value[l] = 0; value[l] = 0;
WriteString (value, properties); WriteString (value, properties);
properties << ';'; properties << ';';
// write mtu
if (address.mtu)
{
WriteString ("mtu", properties);
properties << '=';
WriteString (boost::lexical_cast<std::string>(address.mtu), properties);
properties << ';';
}
} }
WriteString ("port", properties); WriteString ("port", properties);
properties << '='; properties << '=';
@@ -410,7 +402,7 @@ namespace data
if (!m_Buffer) if (!m_Buffer)
{ {
if (LoadFile ()) if (LoadFile ())
LogPrint ("Buffer for ", m_IdentHashAbbreviation, " loaded from file"); LogPrint ("Buffer for ", GetIdentHashAbbreviation (), " loaded from file");
} }
return m_Buffer; return m_Buffer;
} }
@@ -419,6 +411,9 @@ namespace data
{ {
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp
std::stringstream s; std::stringstream s;
uint8_t ident[1024];
auto identLen = privateKeys.GetPublic ().ToBuffer (ident, 1024);
s.write ((char *)ident, identLen);
WriteToStream (s); WriteToStream (s);
m_BufferLen = s.str ().size (); m_BufferLen = s.str ().size ();
if (!m_Buffer) if (!m_Buffer)
@@ -438,7 +433,7 @@ namespace data
f.write ((char *)m_Buffer, m_BufferLen); f.write ((char *)m_Buffer, m_BufferLen);
} }
else else
LogPrint ("Can't save to file"); LogPrint (eLogError, "Can't save to file");
} }
size_t RouterInfo::ReadString (char * str, std::istream& s) size_t RouterInfo::ReadString (char * str, std::istream& s)
@@ -465,11 +460,12 @@ namespace data
addr.transportStyle = eTransportNTCP; addr.transportStyle = eTransportNTCP;
addr.cost = 2; addr.cost = 2;
addr.date = 0; addr.date = 0;
addr.mtu = 0;
m_Addresses.push_back(addr); m_Addresses.push_back(addr);
m_SupportedTransports |= eNTCPV4; m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eNTCPV4;
} }
void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key) void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu)
{ {
Address addr; Address addr;
addr.host = boost::asio::ip::address::from_string (host); addr.host = boost::asio::ip::address::from_string (host);
@@ -477,9 +473,10 @@ namespace data
addr.transportStyle = eTransportSSU; addr.transportStyle = eTransportSSU;
addr.cost = 10; // NTCP should have priority over SSU addr.cost = 10; // NTCP should have priority over SSU
addr.date = 0; addr.date = 0;
addr.mtu = mtu;
memcpy (addr.key, key, 32); memcpy (addr.key, key, 32);
m_Addresses.push_back(addr); m_Addresses.push_back(addr);
m_SupportedTransports |= eSSUV4; m_SupportedTransports |= addr.host.is_v6 () ? eNTCPV6 : eSSUV4;
m_Caps |= eSSUTesting; m_Caps |= eSSUTesting;
m_Caps |= eSSUIntroducer; m_Caps |= eSSUIntroducer;
} }
@@ -568,6 +565,47 @@ namespace data
return m_SupportedTransports & (eSSUV4 | eSSUV6); return m_SupportedTransports & (eSSUV4 | eSSUV6);
} }
bool RouterInfo::IsV6 () const
{
return m_SupportedTransports & (eNTCPV6 | eSSUV6);
}
void RouterInfo::EnableV6 ()
{
if (!IsV6 ())
m_SupportedTransports |= eNTCPV6 | eSSUV6;
}
void RouterInfo::DisableV6 ()
{
if (IsV6 ())
{
// NTCP
m_SupportedTransports &= ~eNTCPV6;
for (size_t i = 0; i < m_Addresses.size (); i++)
{
if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportNTCP &&
m_Addresses[i].host.is_v6 ())
{
m_Addresses.erase (m_Addresses.begin () + i);
break;
}
}
// SSU
m_SupportedTransports &= ~eSSUV6;
for (size_t i = 0; i < m_Addresses.size (); i++)
{
if (m_Addresses[i].transportStyle == i2p::data::RouterInfo::eTransportSSU &&
m_Addresses[i].host.is_v6 ())
{
m_Addresses.erase (m_Addresses.begin () + i);
break;
}
}
}
}
bool RouterInfo::UsesIntroducer () const bool RouterInfo::UsesIntroducer () const
{ {
return m_Caps & Caps::eUnreachable; // non-reachable return m_Caps & Caps::eUnreachable; // non-reachable
@@ -583,13 +621,18 @@ namespace data
return GetAddress (eTransportSSU, v4only); return GetAddress (eTransportSSU, v4only);
} }
const RouterInfo::Address * RouterInfo::GetAddress (TransportStyle s, bool v4only) const const RouterInfo::Address * RouterInfo::GetSSUV6Address () const
{
return GetAddress (eTransportSSU, false, true);
}
const RouterInfo::Address * RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const
{ {
for (auto& address : m_Addresses) for (auto& address : m_Addresses)
{ {
if (address.transportStyle == s) if (address.transportStyle == s)
{ {
if (!v4only || address.host.is_v4 ()) if ((!v4only || address.host.is_v4 ()) && (!v6only || address.host.is_v6 ()))
return &address; return &address;
} }
} }

View File

@@ -75,26 +75,33 @@ namespace data
// SSU only // SSU only
Tag<32> key; // intro key for SSU Tag<32> key; // intro key for SSU
std::vector<Introducer> introducers; std::vector<Introducer> introducers;
bool IsCompatible (const boost::asio::ip::address& other) const
{
return (host.is_v4 () && other.is_v4 ()) ||
(host.is_v6 () && other.is_v6 ());
}
}; };
RouterInfo (const std::string& fullPath); RouterInfo (const std::string& fullPath);
RouterInfo (): m_Buffer (nullptr) { m_IdentHashBase64[0] = 0; m_IdentHashAbbreviation[0] = 0; }; RouterInfo (): m_Buffer (nullptr) { };
RouterInfo (const RouterInfo& ) = default; RouterInfo (const RouterInfo& ) = default;
RouterInfo& operator=(const RouterInfo& ) = default; RouterInfo& operator=(const RouterInfo& ) = default;
RouterInfo (const uint8_t * buf, int len); RouterInfo (const uint8_t * buf, int len);
~RouterInfo (); ~RouterInfo ();
const Identity& GetRouterIdentity () const { return m_RouterIdentity; }; const IdentityEx& GetRouterIdentity () const { return m_RouterIdentity; };
void SetRouterIdentity (const Identity& identity); void SetRouterIdentity (const IdentityEx& identity);
const char * GetIdentHashBase64 () const { return m_IdentHashBase64; }; std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
const char * GetIdentHashAbbreviation () const { return m_IdentHashAbbreviation; }; std::string GetIdentHashAbbreviation () const { return GetIdentHash ().ToBase64 ().substr (0, 4); };
uint64_t GetTimestamp () const { return m_Timestamp; }; uint64_t GetTimestamp () const { return m_Timestamp; };
std::vector<Address>& GetAddresses () { return m_Addresses; }; std::vector<Address>& GetAddresses () { return m_Addresses; };
const Address * GetNTCPAddress (bool v4only = true) const; const Address * GetNTCPAddress (bool v4only = true) const;
const Address * GetSSUAddress (bool v4only = true) const; const Address * GetSSUAddress (bool v4only = true) const;
const Address * GetSSUV6Address () const;
void AddNTCPAddress (const char * host, int port); void AddNTCPAddress (const char * host, int port);
void AddSSUAddress (const char * host, int port, const uint8_t * key); void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
bool AddIntroducer (const Address * address, uint32_t tag); bool AddIntroducer (const Address * address, uint32_t tag);
bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); bool RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
void SetProperty (const char * key, const char * value); void SetProperty (const char * key, const char * value);
@@ -102,6 +109,9 @@ namespace data
bool IsFloodfill () const; bool IsFloodfill () const;
bool IsNTCP (bool v4only = true) const; bool IsNTCP (bool v4only = true) const;
bool IsSSU (bool v4only = true) const; bool IsSSU (bool v4only = true) const;
bool IsV6 () const;
void EnableV6 ();
void DisableV6 ();
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; }; bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
bool UsesIntroducer () const; bool UsesIntroducer () const;
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; }; bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
@@ -128,8 +138,8 @@ namespace data
void DeleteBuffer () { delete m_Buffer; m_Buffer = nullptr; }; void DeleteBuffer () { delete m_Buffer; m_Buffer = nullptr; };
// implements RoutingDestination // implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_IdentHash; }; const IdentHash& GetIdentHash () const { return m_RouterIdentity.GetIdentHash (); };
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.publicKey; }; const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.GetStandardIdentity ().publicKey; };
bool IsDestination () const { return false; }; bool IsDestination () const { return false; };
@@ -138,21 +148,18 @@ namespace data
bool LoadFile (); bool LoadFile ();
void ReadFromFile (); void ReadFromFile ();
void ReadFromStream (std::istream& s); void ReadFromStream (std::istream& s);
void ReadFromBuffer (); void ReadFromBuffer (bool verifySignature);
void WriteToStream (std::ostream& s); void WriteToStream (std::ostream& s);
size_t ReadString (char * str, std::istream& s); size_t ReadString (char * str, std::istream& s);
void WriteString (const std::string& str, std::ostream& s); void WriteString (const std::string& str, std::ostream& s);
void ExtractCaps (const char * value); void ExtractCaps (const char * value);
void UpdateIdentHashBase64 (); const Address * GetAddress (TransportStyle s, bool v4only, bool v6only = false) const;
const Address * GetAddress (TransportStyle s, bool v4only) const;
void UpdateCapsProperty (); void UpdateCapsProperty ();
private: private:
std::string m_FullPath; std::string m_FullPath;
Identity m_RouterIdentity; IdentityEx m_RouterIdentity;
IdentHash m_IdentHash;
char m_IdentHashBase64[48], m_IdentHashAbbreviation[5];
uint8_t * m_Buffer; uint8_t * m_Buffer;
int m_BufferLen; int m_BufferLen;
uint64_t m_Timestamp; uint64_t m_Timestamp;

135
SAM.cpp
View File

@@ -1,5 +1,8 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <stdlib.h>
#endif
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include "base64.h" #include "base64.h"
#include "Identity.h" #include "Identity.h"
@@ -25,8 +28,8 @@ namespace client
if (m_Stream) if (m_Stream)
{ {
m_Stream->Close (); m_Stream->Close ();
if (m_Session && m_Session->localDestination) i2p::stream::DeleteStream (m_Stream);
m_Session->localDestination->DeleteStream (m_Stream); m_Stream = nullptr;
} }
} }
@@ -35,8 +38,7 @@ namespace client
if (m_Stream) if (m_Stream)
{ {
m_Stream->Close (); m_Stream->Close ();
if (m_Session && m_Session->localDestination) i2p::stream::DeleteStream (m_Stream);
m_Session->localDestination->DeleteStream (m_Stream);
m_Stream = nullptr; m_Stream = nullptr;
} }
switch (m_SocketType) switch (m_SocketType)
@@ -55,7 +57,7 @@ namespace client
if (m_Session) if (m_Session)
{ {
m_Session->sockets.remove (this); m_Session->sockets.remove (this);
m_Session->localDestination->ResetAcceptor (); m_Session->localDestination->StopAcceptingStreams ();
} }
break; break;
} }
@@ -207,6 +209,7 @@ namespace client
LogPrint ("SAM session create: ", buf); LogPrint ("SAM session create: ", buf);
std::map<std::string, std::string> params; std::map<std::string, std::string> params;
ExtractParams (buf, len, params); ExtractParams (buf, len, params);
std::string& style = params[SAM_PARAM_STYLE];
std::string& id = params[SAM_PARAM_ID]; std::string& id = params[SAM_PARAM_ID];
std::string& destination = params[SAM_PARAM_DESTINATION]; std::string& destination = params[SAM_PARAM_DESTINATION];
m_ID = id; m_ID = id;
@@ -221,7 +224,15 @@ namespace client
{ {
m_SocketType = eSAMSocketTypeSession; m_SocketType = eSAMSocketTypeSession;
if (m_Session->localDestination->IsReady ()) if (m_Session->localDestination->IsReady ())
{
if (style == SAM_VALUE_DATAGRAM)
{
auto dest = m_Session->localDestination->CreateDatagramDestination ();
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
SendSessionCreateReplyOk (); SendSessionCreateReplyOk ();
}
else else
{ {
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
@@ -255,7 +266,11 @@ namespace client
size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024);
priv[l1] = 0; priv[l1] = 0;
#ifdef _MSC_VER
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
#else
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv);
#endif
SendMessageReply (m_Buffer, l2, false); SendMessageReply (m_Buffer, l2, false);
} }
@@ -295,7 +310,7 @@ namespace client
{ {
m_SocketType = eSAMSocketTypeStream; m_SocketType = eSAMSocketTypeStream;
m_Session->sockets.push_back (this); m_Session->sockets.push_back (this);
m_Stream = m_Session->localDestination->CreateNewOutgoingStream (remote); m_Stream = m_Session->localDestination->CreateStream (remote);
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
I2PReceive (); I2PReceive ();
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
@@ -326,7 +341,11 @@ namespace client
else else
{ {
LogPrint ("SAM name destination not found"); LogPrint ("SAM name destination not found");
#ifdef _MSC_VER
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_KEY_NOT_FOUND, (ident.ToBase32 () + ".b32.i2p").c_str ());
#else
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_KEY_NOT_FOUND, (ident.ToBase32 () + ".b32.i2p").c_str ()); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_KEY_NOT_FOUND, (ident.ToBase32 () + ".b32.i2p").c_str ());
#endif
SendMessageReply (m_Buffer, len, false); SendMessageReply (m_Buffer, len, false);
} }
} }
@@ -344,11 +363,11 @@ namespace client
m_Session = m_Owner.FindSession (id); m_Session = m_Owner.FindSession (id);
if (m_Session) if (m_Session)
{ {
if (!m_Session->localDestination->IsAcceptorSet ()) if (!m_Session->localDestination->IsAcceptingStreams ())
{ {
m_SocketType = eSAMSocketTypeAcceptor; m_SocketType = eSAMSocketTypeAcceptor;
m_Session->sockets.push_back (this); m_Session->sockets.push_back (this);
m_Session->localDestination->SetAcceptor (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1)); m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1));
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
} }
else else
@@ -373,7 +392,11 @@ namespace client
l = localDestination->GetIdentity ().ToBuffer (buf, 1024); l = localDestination->GetIdentity ().ToBuffer (buf, 1024);
l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024); l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
pub[l1] = 0; pub[l1] = 0;
#ifdef _MSC_VER
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
#else
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, pub, priv);
#endif
SendMessageReply (m_Buffer, len, true); SendMessageReply (m_Buffer, len, true);
} }
else else
@@ -389,7 +412,7 @@ namespace client
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
if (name == "ME") if (name == "ME")
SendNamingLookupReply (nullptr); SendNamingLookupReply (nullptr);
else if (m_Session && i2p::data::netdb.GetAddressBook ().GetIdentHash (name, ident)) else if (m_Session && context.GetAddressBook ().GetIdentHash (name, ident))
{ {
auto leaseSet = m_Session->localDestination->FindLeaseSet (ident); auto leaseSet = m_Session->localDestination->FindLeaseSet (ident);
if (leaseSet) if (leaseSet)
@@ -404,7 +427,11 @@ namespace client
} }
else else
{ {
#ifdef _MSC_VER
size_t len = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
#else
size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str()); size_t len = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY_INVALID_KEY, name.c_str());
#endif
SendMessageReply (m_Buffer, len, false); SendMessageReply (m_Buffer, len, false);
} }
} }
@@ -417,7 +444,11 @@ namespace client
size_t l = identity.ToBuffer (buf, 1024); size_t l = identity.ToBuffer (buf, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024); size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, pub, 1024);
pub[l1] = 0; pub[l1] = 0;
#ifdef _MSC_VER
size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
#else
size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub); size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, pub);
#endif
SendMessageReply (m_Buffer, l2, false); SendMessageReply (m_Buffer, l2, false);
} }
@@ -507,7 +538,7 @@ namespace client
m_Stream = stream; m_Stream = stream;
auto session = m_Owner.FindSession (m_ID); auto session = m_Owner.FindSession (m_ID);
if (session) if (session)
session->localDestination->ResetAcceptor (); session->localDestination->StopAcceptingStreams ();
if (!m_IsSilent) if (!m_IsSilent)
{ {
// send remote peer address // send remote peer address
@@ -521,10 +552,32 @@ namespace client
} }
} }
void SAMSocket::HandleI2PDatagramReceive (const i2p::data::IdentityEx& ident, const uint8_t * buf, size_t len)
{
uint8_t identBuf[1024];
size_t l = ident.ToBuffer (identBuf, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (identBuf, l, m_Buffer, SAM_SOCKET_BUFFER_SIZE);
m_Buffer[l1] = 0;
#ifdef _MSC_VER
size_t l2 = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, m_Buffer, len);
#else
size_t l2 = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, m_Buffer, len);
#endif
if (len < SAM_SOCKET_BUFFER_SIZE - l2)
{
memcpy (m_StreamBuffer + l2, buf, len);
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l2),
boost::bind (&SAMSocket::HandleWriteI2PData, this, boost::asio::placeholders::error));
}
else
LogPrint (eLogWarning, "Datagram size ", len," exceeds buffer");
}
SAMBridge::SAMBridge (int port): SAMBridge::SAMBridge (int port):
m_IsRunning (false), m_Thread (nullptr), m_IsRunning (false), m_Thread (nullptr),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
m_NewSocket (nullptr) m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint),
m_NewSocket (nullptr)
{ {
} }
@@ -537,6 +590,7 @@ namespace client
void SAMBridge::Start () void SAMBridge::Start ()
{ {
Accept (); Accept ();
ReceiveDatagram ();
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&SAMBridge::Run, this)); m_Thread = new std::thread (std::bind (&SAMBridge::Run, this));
} }
@@ -595,7 +649,7 @@ namespace client
SAMSession * SAMBridge::CreateSession (const std::string& id, const std::string& destination) SAMSession * SAMBridge::CreateSession (const std::string& id, const std::string& destination)
{ {
i2p::stream::StreamingDestination * localDestination = nullptr; ClientDestination * localDestination = nullptr;
if (destination != "") if (destination != "")
{ {
uint8_t * buf = new uint8_t[destination.length ()]; uint8_t * buf = new uint8_t[destination.length ()];
@@ -642,5 +696,62 @@ namespace client
return &it->second; return &it->second;
return nullptr; return nullptr;
} }
void SAMBridge::ReceiveDatagram ()
{
m_DatagramSocket.async_receive_from (
boost::asio::buffer (m_DatagramReceiveBuffer, i2p::datagram::MAX_DATAGRAM_SIZE),
m_SenderEndpoint,
boost::bind (&SAMBridge::HandleReceivedDatagram, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void SAMBridge::HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (!ecode)
{
m_DatagramReceiveBuffer[bytes_transferred] = 0;
char * eol = strchr ((char *)m_DatagramReceiveBuffer, '\n');
*eol = 0; eol++;
size_t payloadLen = bytes_transferred - ((uint8_t *)eol - m_DatagramReceiveBuffer);
LogPrint ("SAM datagram received ", m_DatagramReceiveBuffer," size=", payloadLen);
char * sessionID = strchr ((char *)m_DatagramReceiveBuffer, ' ');
if (sessionID)
{
sessionID++;
char * destination = strchr (sessionID, ' ');
if (destination)
{
*destination = 0; destination++;
auto session = FindSession (sessionID);
if (session)
{
uint8_t ident[1024];
size_t l = i2p::data::Base64ToByteStream (destination, strlen(destination), ident, 1024);
i2p::data::IdentityEx dest;
dest.FromBuffer (ident, l);
auto leaseSet = i2p::data::netdb.FindLeaseSet (dest.GetIdentHash ());
if (leaseSet)
session->localDestination->GetDatagramDestination ()->
SendDatagramTo ((uint8_t *)eol, payloadLen, *leaseSet);
else
{
LogPrint ("SAM datagram destination not found");
i2p::data::netdb.RequestDestination (dest.GetIdentHash (), true,
session->localDestination->GetTunnelPool ());
}
}
else
LogPrint ("Session ", sessionID, " not found");
}
else
LogPrint ("Missing destination key");
}
else
LogPrint ("Missing sessionID");
ReceiveDatagram ();
}
else
LogPrint ("SAM datagram receive error: ", ecode.message ());
}
} }
} }

14
SAM.h
View File

@@ -11,6 +11,7 @@
#include "Identity.h" #include "Identity.h"
#include "LeaseSet.h" #include "LeaseSet.h"
#include "Streaming.h" #include "Streaming.h"
#include "Destination.h"
namespace i2p namespace i2p
{ {
@@ -38,6 +39,7 @@ namespace client
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n"; const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP"; const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n"; const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM_RECEIVED DESTINATION=%s SIZE=%i\n";
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n"; const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n"; const char SAM_NAMING_REPLY_KEY_NOT_FOUND[] = "NAMING REPLY RESULT=INVALID_KEY_NOT_FOUND NAME=%s\n";
const char SAM_PARAM_STYLE[] = "STYLE"; const char SAM_PARAM_STYLE[] = "STYLE";
@@ -46,6 +48,9 @@ namespace client
const char SAM_PARAM_DESTINATION[] = "DESTINATION"; const char SAM_PARAM_DESTINATION[] = "DESTINATION";
const char SAM_PARAM_NAME[] = "NAME"; const char SAM_PARAM_NAME[] = "NAME";
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
const char SAM_VALUE_STREAM[] = "STREAM";
const char SAM_VALUE_DATAGRAM[] = "DATAGRAM";
const char SAM_VALUE_RAW[] = "RAW";
const char SAM_VALUE_TRUE[] = "true"; const char SAM_VALUE_TRUE[] = "true";
const char SAM_VALUE_FALSE[] = "false"; const char SAM_VALUE_FALSE[] = "false";
@@ -84,6 +89,7 @@ namespace client
void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleI2PAccept (i2p::stream::Stream * stream); void HandleI2PAccept (i2p::stream::Stream * stream);
void HandleWriteI2PData (const boost::system::error_code& ecode); void HandleWriteI2PData (const boost::system::error_code& ecode);
void HandleI2PDatagramReceive (const i2p::data::IdentityEx& ident, const uint8_t * buf, size_t len);
void ProcessSessionCreate (char * buf, size_t len); void ProcessSessionCreate (char * buf, size_t len);
void ProcessStreamConnect (char * buf, size_t len); void ProcessStreamConnect (char * buf, size_t len);
@@ -115,7 +121,7 @@ namespace client
struct SAMSession struct SAMSession
{ {
i2p::stream::StreamingDestination * localDestination; ClientDestination * localDestination;
std::list<SAMSocket *> sockets; std::list<SAMSocket *> sockets;
}; };
@@ -141,15 +147,21 @@ namespace client
void Accept (); void Accept ();
void HandleAccept(const boost::system::error_code& ecode); void HandleAccept(const boost::system::error_code& ecode);
void ReceiveDatagram ();
void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred);
private: private:
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::ip::tcp::acceptor m_Acceptor; boost::asio::ip::tcp::acceptor m_Acceptor;
boost::asio::ip::udp::endpoint m_DatagramEndpoint, m_SenderEndpoint;
boost::asio::ip::udp::socket m_DatagramSocket;
SAMSocket * m_NewSocket; SAMSocket * m_NewSocket;
std::mutex m_SessionsMutex; std::mutex m_SessionsMutex;
std::map<std::string, SAMSession> m_Sessions; std::map<std::string, SAMSession> m_Sessions;
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1];
}; };
} }
} }

View File

@@ -224,7 +224,7 @@ namespace proxy
void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode) void SOCKS4AHandler::SentConnectionSuccess(const boost::system::error_code & ecode)
{ {
LogPrint("--- socks4a making connection"); LogPrint("--- socks4a making connection");
m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateNewOutgoingStream(*m_ls); m_stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream(*m_ls);
m_state = OKAY; m_state = OKAY;
LogPrint("--- socks4a state is ", m_state); LogPrint("--- socks4a state is ", m_state);
AsyncSockRead(); AsyncSockRead();

996
SSU.cpp

File diff suppressed because it is too large Load Diff

141
SSU.h
View File

@@ -13,139 +13,16 @@
#include "Identity.h" #include "Identity.h"
#include "RouterInfo.h" #include "RouterInfo.h"
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "SSUData.h" #include "SSUSession.h"
namespace i2p namespace i2p
{ {
namespace ssu namespace transport
{ {
#pragma pack(1)
struct SSUHeader
{
uint8_t mac[16];
uint8_t iv[16];
uint8_t flag;
uint32_t time;
uint8_t GetPayloadType () const { return flag >> 4; };
};
#pragma pack()
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds
const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
const size_t SSU_MAX_NUM_INTRODUCERS = 3; const size_t SSU_MAX_NUM_INTRODUCERS = 3;
// payload types (4 bits)
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
const uint8_t PAYLOAD_TYPE_SESSION_CREATED = 1;
const uint8_t PAYLOAD_TYPE_SESSION_CONFIRMED = 2;
const uint8_t PAYLOAD_TYPE_RELAY_REQUEST = 3;
const uint8_t PAYLOAD_TYPE_RELAY_RESPONSE = 4;
const uint8_t PAYLOAD_TYPE_RELAY_INTRO = 5;
const uint8_t PAYLOAD_TYPE_DATA = 6;
const uint8_t PAYLOAD_TYPE_PEER_TEST = 7;
const uint8_t PAYLOAD_TYPE_SESSION_DESTROYED = 8;
enum SessionState
{
eSessionStateUnknown,
eSessionStateIntroduced,
eSessionStateEstablished,
eSessionStateFailed
};
class SSUServer;
class SSUSession
{
public:
SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
const i2p::data::RouterInfo * router = nullptr, bool peerTest = false);
void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
~SSUSession ();
void Connect ();
void Introduce (uint32_t iTag, const uint8_t * iKey);
void WaitForIntroduction ();
void Close ();
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
const i2p::data::RouterInfo * GetRemoteRouter () const { return m_RemoteRouter; };
void SendI2NPMessage (I2NPMessage * msg);
void SendPeerTest (); // Alice
SessionState GetState () const { return m_State; };
size_t GetNumSentBytes () const { return m_NumSentBytes; };
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
void SendKeepAlive ();
uint32_t GetRelayTag () const { return m_RelayTag; };
uint32_t GetCreationTime () const { return m_CreationTime; };
private:
void CreateAESandMacKey (const uint8_t * pubKey);
void PostI2NPMessage (I2NPMessage * msg);
void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session
void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void SendSessionRequest ();
void SendRelayRequest (uint32_t iTag, const uint8_t * iKey);
void ProcessSessionCreated (uint8_t * buf, size_t len);
void SendSessionCreated (const uint8_t * x);
void ProcessSessionConfirmed (uint8_t * buf, size_t len);
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress);
void ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from);
void SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to);
void SendRelayIntro (SSUSession * session, const boost::asio::ip::udp::endpoint& from);
void ProcessRelayResponse (uint8_t * buf, size_t len);
void ProcessRelayIntro (uint8_t * buf, size_t len);
void Established ();
void Failed ();
void ScheduleConnectTimer ();
void HandleConnectTimer (const boost::system::error_code& ecode);
void ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void SendPeerTest (uint32_t nonce, uint32_t address, uint16_t port, const uint8_t * introKey, bool toAddress = true);
void ProcessData (uint8_t * buf, size_t len);
void SendSesionDestroyed ();
void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key
void Send (const uint8_t * buf, size_t size);
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey);
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key
void Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey);
void DecryptSessionKey (uint8_t * buf, size_t len);
bool Validate (uint8_t * buf, size_t len, const uint8_t * macKey);
const uint8_t * GetIntroKey () const;
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
private:
friend class SSUData; // TODO: change in later
SSUServer& m_Server;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
const i2p::data::RouterInfo * m_RemoteRouter;
i2p::data::IdentHash m_RemoteIdent; // if m_RemoteRouter is null
boost::asio::deadline_timer m_Timer;
i2p::data::DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
bool m_PeerTest;
SessionState m_State;
bool m_IsSessionKey;
uint32_t m_RelayTag;
std::set<uint32_t> m_PeerTestNonces;
i2p::crypto::CBCEncryption m_SessionKeyEncryption;
i2p::crypto::CBCDecryption m_SessionKeyDecryption;
uint8_t m_SessionKey[32], m_MacKey[32];
std::list<i2p::I2NPMessage *> m_DelayedMessages;
SSUData m_Data;
size_t m_NumSentBytes, m_NumReceivedBytes;
uint32_t m_CreationTime; // seconds since epoch
};
class SSUServer class SSUServer
{ {
public: public:
@@ -171,7 +48,10 @@ namespace ssu
void Run (); void Run ();
void Receive (); void Receive ();
void HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred); void ReceiveV6 ();
void HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleReceivedBuffer (boost::asio::ip::udp::endpoint& from, uint8_t * buf, std::size_t bytes_transferred);
template<typename Filter> template<typename Filter>
SSUSession * GetRandomSession (Filter filter); SSUSession * GetRandomSession (Filter filter);
@@ -186,12 +66,13 @@ namespace ssu
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::io_service::work m_Work; boost::asio::io_service::work m_Work;
boost::asio::ip::udp::endpoint m_Endpoint; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6;
boost::asio::ip::udp::socket m_Socket; boost::asio::ip::udp::socket m_Socket, m_SocketV6;
boost::asio::ip::udp::endpoint m_SenderEndpoint; boost::asio::ip::udp::endpoint m_SenderEndpoint, m_SenderEndpointV6;
boost::asio::deadline_timer m_IntroducersUpdateTimer; boost::asio::deadline_timer m_IntroducersUpdateTimer;
std::list<boost::asio::ip::udp::endpoint> m_Introducers; // introducers we are connected to std::list<boost::asio::ip::udp::endpoint> m_Introducers; // introducers we are connected to
uint8_t m_ReceiveBuffer[2*SSU_MTU]; i2p::crypto::AESAlignedBuffer<2*SSU_MTU_V4> m_ReceiveBuffer;
i2p::crypto::AESAlignedBuffer<2*SSU_MTU_V6> m_ReceiveBufferV6;
std::map<boost::asio::ip::udp::endpoint, SSUSession *> m_Sessions; std::map<boost::asio::ip::udp::endpoint, SSUSession *> m_Sessions;
std::map<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer std::map<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer

View File

@@ -8,12 +8,13 @@
namespace i2p namespace i2p
{ {
namespace ssu namespace transport
{ {
SSUData::SSUData (SSUSession& session): SSUData::SSUData (SSUSession& session):
m_Session (session), m_ResendTimer (session.m_Server.GetService ()) m_Session (session), m_ResendTimer (session.m_Server.GetService ())
{ {
m_PacketSize = SSU_MAX_PACKET_SIZE; m_MaxPacketSize = session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE;
m_PacketSize = m_MaxPacketSize;
auto remoteRouter = session.GetRemoteRouter (); auto remoteRouter = session.GetRemoteRouter ();
if (remoteRouter) if (remoteRouter)
AdjustPacketSize (*remoteRouter); AdjustPacketSize (*remoteRouter);
@@ -36,19 +37,22 @@ namespace ssu
auto ssuAddress = remoteRouter.GetSSUAddress (); auto ssuAddress = remoteRouter.GetSSUAddress ();
if (ssuAddress && ssuAddress->mtu) if (ssuAddress && ssuAddress->mtu)
{ {
m_PacketSize = ssuAddress->mtu - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; if (m_Session.IsV6 ())
m_PacketSize = ssuAddress->mtu - IPV6_HEADER_SIZE - UDP_HEADER_SIZE;
else
m_PacketSize = ssuAddress->mtu - IPV4_HEADER_SIZE - UDP_HEADER_SIZE;
if (m_PacketSize > 0) if (m_PacketSize > 0)
{ {
// make sure packet size multiple of 16 // make sure packet size multiple of 16
m_PacketSize >>= 4; m_PacketSize >>= 4;
m_PacketSize <<= 4; m_PacketSize <<= 4;
if (m_PacketSize > (int)SSU_MAX_PACKET_SIZE) m_PacketSize = SSU_MAX_PACKET_SIZE; if (m_PacketSize > m_MaxPacketSize) m_PacketSize = m_MaxPacketSize;
LogPrint ("MTU=", ssuAddress->mtu, " packet size=", m_PacketSize); LogPrint ("MTU=", ssuAddress->mtu, " packet size=", m_PacketSize);
} }
else else
{ {
LogPrint ("Unexpected MTU ", ssuAddress->mtu); LogPrint (eLogWarning, "Unexpected MTU ", ssuAddress->mtu);
m_PacketSize = SSU_MAX_PACKET_SIZE; m_PacketSize = m_MaxPacketSize;
} }
} }
} }
@@ -143,7 +147,12 @@ namespace ssu
uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13 uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13
bool isLast = fragmentInfo & 0x010000; // bit 16 bool isLast = fragmentInfo & 0x010000; // bit 16
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
LogPrint ("SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last"); LogPrint (eLogDebug, "SSU data fragment ", (int)fragmentNum, " of message ", msgID, " size=", (int)fragmentSize, isLast ? " last" : " non-last");
if (fragmentSize >= SSU_V4_MAX_PACKET_SIZE)
{
LogPrint (eLogError, "Fragment size ", fragmentSize, "exceeds max SSU packet size");
return;
}
// find message with msgID // find message with msgID
I2NPMessage * msg = nullptr; I2NPMessage * msg = nullptr;
@@ -190,22 +199,22 @@ namespace ssu
break; break;
} }
if (isLast) if (isLast)
LogPrint ("Message ", msgID, " complete"); LogPrint (eLogDebug, "Message ", msgID, " complete");
} }
} }
else else
{ {
if (fragmentNum < incompleteMessage->nextFragmentNum) if (fragmentNum < incompleteMessage->nextFragmentNum)
// duplicate fragment // duplicate fragment
LogPrint ("Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ". Ignored"); LogPrint (eLogWarning, "Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ". Ignored");
else else
{ {
// missing fragment // missing fragment
LogPrint ("Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID); LogPrint (eLogWarning, "Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast); auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast);
if (!incompleteMessage->savedFragments.insert (savedFragment).second) if (!incompleteMessage->savedFragments.insert (savedFragment).second)
{ {
LogPrint ("Fragment ", (int)fragmentNum, " of message ", msgID, " already saved"); LogPrint (eLogWarning, "Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
delete savedFragment; delete savedFragment;
} }
} }
@@ -230,7 +239,7 @@ namespace ssu
} }
else else
{ {
LogPrint ("SSU message ", msgID, " already received"); LogPrint (eLogWarning, "SSU message ", msgID, " already received");
i2p::DeleteI2NPMessage (msg); i2p::DeleteI2NPMessage (msg);
} }
} }
@@ -243,7 +252,7 @@ namespace ssu
m_Session.Established (); m_Session.Established ();
} }
else else
LogPrint ("SSU unexpected message ", (int)msg->GetHeader ()->typeID); LogPrint (eLogError, "SSU unexpected message ", (int)msg->GetHeader ()->typeID);
DeleteI2NPMessage (msg); DeleteI2NPMessage (msg);
} }
} }
@@ -258,7 +267,7 @@ namespace ssu
//uint8_t * start = buf; //uint8_t * start = buf;
uint8_t flag = *buf; uint8_t flag = *buf;
buf++; buf++;
LogPrint ("Process SSU data flags=", (int)flag); LogPrint (eLogDebug, "Process SSU data flags=", (int)flag);
// process acks if presented // process acks if presented
if (flag & (DATA_FLAG_ACK_BITFIELDS_INCLUDED | DATA_FLAG_EXPLICIT_ACKS_INCLUDED)) if (flag & (DATA_FLAG_ACK_BITFIELDS_INCLUDED | DATA_FLAG_EXPLICIT_ACKS_INCLUDED))
ProcessAcks (buf, flag); ProcessAcks (buf, flag);
@@ -267,7 +276,7 @@ namespace ssu
{ {
uint8_t extendedDataSize = *buf; uint8_t extendedDataSize = *buf;
buf++; // size buf++; // size
LogPrint ("SSU extended data of ", extendedDataSize, " bytes presented"); LogPrint (eLogDebug, "SSU extended data of ", extendedDataSize, " bytes presented");
buf += extendedDataSize; buf += extendedDataSize;
} }
// process data // process data
@@ -279,7 +288,7 @@ namespace ssu
uint32_t msgID = msg->ToSSU (); uint32_t msgID = msg->ToSSU ();
if (m_SentMessages.count (msgID) > 0) if (m_SentMessages.count (msgID) > 0)
{ {
LogPrint ("SSU message ", msgID, " already sent"); LogPrint (eLogWarning, "SSU message ", msgID, " already sent");
DeleteI2NPMessage (msg); DeleteI2NPMessage (msg);
return; return;
} }
@@ -363,7 +372,7 @@ namespace ssu
{ {
if (fragmentNum > 64) if (fragmentNum > 64)
{ {
LogPrint ("Fragment number ", fragmentNum, " exceeds 64"); LogPrint (eLogWarning, "Fragment number ", fragmentNum, " exceeds 64");
return; return;
} }
uint8_t buf[64 + 18]; uint8_t buf[64 + 18];

View File

@@ -13,13 +13,16 @@
namespace i2p namespace i2p
{ {
namespace ssu namespace transport
{ {
const size_t SSU_MTU = 1484; const size_t SSU_MTU_V4 = 1484;
const size_t SSU_MTU_V6 = 1472;
const size_t IPV4_HEADER_SIZE = 20; const size_t IPV4_HEADER_SIZE = 20;
const size_t IPV6_HEADER_SIZE = 40;
const size_t UDP_HEADER_SIZE = 8; const size_t UDP_HEADER_SIZE = 8;
const size_t SSU_MAX_PACKET_SIZE = SSU_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; // 1456 const size_t SSU_V4_MAX_PACKET_SIZE = SSU_MTU_V4 - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; // 1456
const size_t SSU_V6_MAX_PACKET_SIZE = SSU_MTU_V6 - IPV6_HEADER_SIZE - UDP_HEADER_SIZE; // 1424
const int RESEND_INTERVAL = 3; // in seconds const int RESEND_INTERVAL = 3; // in seconds
const int MAX_NUM_RESENDS = 5; const int MAX_NUM_RESENDS = 5;
// data flags // data flags
@@ -35,7 +38,7 @@ namespace ssu
int fragmentNum; int fragmentNum;
size_t len; size_t len;
bool isLast; bool isLast;
uint8_t buf[SSU_MAX_PACKET_SIZE + 18]; uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18]; // use biggest
Fragment () = default; Fragment () = default;
Fragment (int n, const uint8_t * b, int l, bool last): Fragment (int n, const uint8_t * b, int l, bool last):
@@ -102,7 +105,7 @@ namespace ssu
std::map<uint32_t, SentMessage *> m_SentMessages; std::map<uint32_t, SentMessage *> m_SentMessages;
std::set<uint32_t> m_ReceivedMessages; std::set<uint32_t> m_ReceivedMessages;
boost::asio::deadline_timer m_ResendTimer; boost::asio::deadline_timer m_ResendTimer;
int m_PacketSize; int m_MaxPacketSize, m_PacketSize;
}; };
} }
} }

1012
SSUSession.cpp Normal file

File diff suppressed because it is too large Load Diff

145
SSUSession.h Normal file
View File

@@ -0,0 +1,145 @@
#ifndef SSU_SESSION_H__
#define SSU_SESSION_H__
#include <inttypes.h>
#include <set>
#include <list>
#include <boost/asio.hpp>
#include "aes.h"
#include "hmac.h"
#include "I2NPProtocol.h"
#include "TransportSession.h"
#include "SSUData.h"
namespace i2p
{
namespace transport
{
#pragma pack(1)
struct SSUHeader
{
uint8_t mac[16];
uint8_t iv[16];
uint8_t flag;
uint32_t time;
uint8_t GetPayloadType () const { return flag >> 4; };
};
#pragma pack()
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
// payload types (4 bits)
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
const uint8_t PAYLOAD_TYPE_SESSION_CREATED = 1;
const uint8_t PAYLOAD_TYPE_SESSION_CONFIRMED = 2;
const uint8_t PAYLOAD_TYPE_RELAY_REQUEST = 3;
const uint8_t PAYLOAD_TYPE_RELAY_RESPONSE = 4;
const uint8_t PAYLOAD_TYPE_RELAY_INTRO = 5;
const uint8_t PAYLOAD_TYPE_DATA = 6;
const uint8_t PAYLOAD_TYPE_PEER_TEST = 7;
const uint8_t PAYLOAD_TYPE_SESSION_DESTROYED = 8;
enum SessionState
{
eSessionStateUnknown,
eSessionStateIntroduced,
eSessionStateEstablished,
eSessionStateFailed
};
class SSUServer;
class SSUSession: public TransportSession
{
public:
SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint,
const i2p::data::RouterInfo * router = nullptr, bool peerTest = false);
void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
~SSUSession ();
void Connect ();
void Introduce (uint32_t iTag, const uint8_t * iKey);
void WaitForIntroduction ();
void Close ();
boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
void SendI2NPMessage (I2NPMessage * msg);
void SendPeerTest (); // Alice
SessionState GetState () const { return m_State; };
size_t GetNumSentBytes () const { return m_NumSentBytes; };
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
void SendKeepAlive ();
uint32_t GetRelayTag () const { return m_RelayTag; };
uint32_t GetCreationTime () const { return m_CreationTime; };
private:
void CreateAESandMacKey (const uint8_t * pubKey);
void PostI2NPMessage (I2NPMessage * msg);
void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session
void ProcessSessionRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void SendSessionRequest ();
void SendRelayRequest (uint32_t iTag, const uint8_t * iKey);
void ProcessSessionCreated (uint8_t * buf, size_t len);
void SendSessionCreated (const uint8_t * x);
void ProcessSessionConfirmed (uint8_t * buf, size_t len);
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, size_t ourAddressLen);
void ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from);
void SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to);
void SendRelayIntro (SSUSession * session, const boost::asio::ip::udp::endpoint& from);
void ProcessRelayResponse (uint8_t * buf, size_t len);
void ProcessRelayIntro (uint8_t * buf, size_t len);
void Established ();
void Failed ();
void ScheduleConnectTimer ();
void HandleConnectTimer (const boost::system::error_code& ecode);
void ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint);
void SendPeerTest (uint32_t nonce, uint32_t address, uint16_t port, const uint8_t * introKey, bool toAddress = true);
void ProcessData (uint8_t * buf, size_t len);
void SendSesionDestroyed ();
void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key
void Send (const uint8_t * buf, size_t size);
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const uint8_t * aesKey, const uint8_t * iv, const uint8_t * macKey);
void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key
void Decrypt (uint8_t * buf, size_t len, const uint8_t * aesKey);
void DecryptSessionKey (uint8_t * buf, size_t len);
bool Validate (uint8_t * buf, size_t len, const uint8_t * macKey);
const uint8_t * GetIntroKey () const;
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
private:
friend class SSUData; // TODO: change in later
SSUServer& m_Server;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
boost::asio::deadline_timer m_Timer;
bool m_PeerTest;
SessionState m_State;
bool m_IsSessionKey;
uint32_t m_RelayTag;
std::set<uint32_t> m_PeerTestNonces;
i2p::crypto::CBCEncryption m_SessionKeyEncryption;
i2p::crypto::CBCDecryption m_SessionKeyDecryption;
i2p::crypto::AESKey m_SessionKey;
i2p::crypto::MACKey m_MacKey;
std::list<i2p::I2NPMessage *> m_DelayedMessages;
SSUData m_Data;
size_t m_NumSentBytes, m_NumReceivedBytes;
uint32_t m_CreationTime; // seconds since epoch
};
}
}
#endif

View File

@@ -1,3 +1,4 @@
#include <cryptopp/gzip.h>
#include "Log.h" #include "Log.h"
#include "RouterInfo.h" #include "RouterInfo.h"
#include "RouterContext.h" #include "RouterContext.h"
@@ -11,12 +12,12 @@ namespace i2p
namespace stream namespace stream
{ {
Stream::Stream (boost::asio::io_service& service, StreamingDestination& local, Stream::Stream (boost::asio::io_service& service, StreamingDestination& local,
const i2p::data::LeaseSet& remote): m_Service (service), m_SendStreamID (0), const i2p::data::LeaseSet& remote, int port): m_Service (service), m_SendStreamID (0),
m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_IsOpen (false), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), m_IsOpen (false),
m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_RemoteLeaseSet (&remote), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service), m_RemoteLeaseSet (&remote), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
m_NumReceivedBytes (0) m_NumReceivedBytes (0), m_Port (port)
{ {
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
UpdateCurrentRemoteLease (); UpdateCurrentRemoteLease ();
@@ -27,7 +28,7 @@ namespace stream
m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local), m_IsOpen (false), m_IsReset (false), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_RemoteLeaseSet (nullptr), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service), m_RemoteLeaseSet (nullptr), m_RoutingSession (nullptr), m_ReceiveTimer (m_Service),
m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0),
m_NumReceivedBytes (0) m_NumReceivedBytes (0), m_Port (0)
{ {
m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 (); m_RecvStreamID = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
} }
@@ -115,7 +116,7 @@ namespace stream
{ {
// we have received duplicate. Most likely our outbound tunnel is dead // we have received duplicate. Most likely our outbound tunnel is dead
LogPrint ("Duplicate message ", receivedSeqn, " received"); LogPrint ("Duplicate message ", receivedSeqn, " received");
m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel
UpdateCurrentRemoteLease (); // pick another lease UpdateCurrentRemoteLease (); // pick another lease
SendQuickAck (); // resend ack for previous message again SendQuickAck (); // resend ack for previous message again
delete packet; // packet dropped delete packet; // packet dropped
@@ -274,11 +275,11 @@ namespace stream
if (isNoAck) flags |= PACKET_FLAG_NO_ACK; if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
*(uint16_t *)(packet + size) = htobe16 (flags); *(uint16_t *)(packet + size) = htobe16 (flags);
size += 2; // flags size += 2; // flags
size_t identityLen = m_LocalDestination.GetIdentity ().GetFullLen (); size_t identityLen = m_LocalDestination.GetOwner ().GetIdentity ().GetFullLen ();
size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen (); size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen ();
*(uint16_t *)(packet + size) = htobe16 (identityLen + signatureLen + 2); // identity + signature + packet size *(uint16_t *)(packet + size) = htobe16 (identityLen + signatureLen + 2); // identity + signature + packet size
size += 2; // options size size += 2; // options size
m_LocalDestination.GetIdentity ().ToBuffer (packet + size, identityLen); m_LocalDestination.GetOwner ().GetIdentity ().ToBuffer (packet + size, identityLen);
size += identityLen; // from size += identityLen; // from
*(uint16_t *)(packet + size) = htobe16 (STREAMING_MTU); *(uint16_t *)(packet + size) = htobe16 (STREAMING_MTU);
size += 2; // max packet size size += 2; // max packet size
@@ -291,7 +292,7 @@ namespace stream
buf += sentLen; buf += sentLen;
len -= sentLen; len -= sentLen;
size += sentLen; // payload size += sentLen; // payload
m_LocalDestination.Sign (packet, size, signature); m_LocalDestination.GetOwner ().Sign (packet, size, signature);
} }
else else
{ {
@@ -362,13 +363,13 @@ namespace stream
size++; // resend delay size++; // resend delay
*(uint16_t *)(packet + size) = htobe16 (PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED); *(uint16_t *)(packet + size) = htobe16 (PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
size += 2; // flags size += 2; // flags
size_t signatureLen = m_LocalDestination.GetIdentity ().GetSignatureLen (); size_t signatureLen = m_LocalDestination.GetOwner ().GetIdentity ().GetSignatureLen ();
*(uint16_t *)(packet + size) = htobe16 (signatureLen); // signature only *(uint16_t *)(packet + size) = htobe16 (signatureLen); // signature only
size += 2; // options size size += 2; // options size
uint8_t * signature = packet + size; uint8_t * signature = packet + size;
memset (packet + size, 0, signatureLen); memset (packet + size, 0, signatureLen);
size += signatureLen; // signature size += signatureLen; // signature
m_LocalDestination.Sign (packet, size, signature); m_LocalDestination.GetOwner ().Sign (packet, size, signature);
p->len = size; p->len = size;
SendPacket (p); SendPacket (p);
@@ -412,6 +413,8 @@ namespace stream
if (isEmpty) if (isEmpty)
ScheduleResend (); ScheduleResend ();
} }
else
delete packet;
return true; return true;
} }
else else
@@ -438,8 +441,7 @@ namespace stream
std::vector<i2p::tunnel::TunnelMessageBlock> msgs; std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
for (auto it: packets) for (auto it: packets)
{ {
auto msg = m_RoutingSession->WrapSingleMessage ( auto msg = m_RoutingSession->WrapSingleMessage (CreateDataMessage (it->GetBuffer (), it->GetLength ()));
m_LocalDestination.CreateDataMessage (it->GetBuffer (), it->GetLength ()));
msgs.push_back (i2p::tunnel::TunnelMessageBlock msgs.push_back (i2p::tunnel::TunnelMessageBlock
{ {
i2p::tunnel::eDeliveryTypeTunnel, i2p::tunnel::eDeliveryTypeTunnel,
@@ -448,7 +450,7 @@ namespace stream
}); });
m_NumSentBytes += it->GetLength (); m_NumSentBytes += it->GetLength ();
} }
m_LocalDestination.SendTunnelDataMsgs (msgs); m_LocalDestination.GetOwner ().SendTunnelDataMsgs (msgs);
} }
else else
LogPrint ("All leases are expired"); LogPrint ("All leases are expired");
@@ -482,7 +484,7 @@ namespace stream
} }
if (packets.size () > 0) if (packets.size () > 0)
{ {
m_LocalDestination.ResetCurrentOutboundTunnel (); // pick another outbound tunnel m_LocalDestination.GetOwner ().ResetCurrentOutboundTunnel (); // pick another outbound tunnel
UpdateCurrentRemoteLease (); // pick another lease UpdateCurrentRemoteLease (); // pick another lease
SendPackets (packets); SendPackets (packets);
} }
@@ -504,14 +506,14 @@ namespace stream
{ {
if (!m_RemoteLeaseSet) if (!m_RemoteLeaseSet)
{ {
m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ());
if (!m_RemoteLeaseSet) if (!m_RemoteLeaseSet)
LogPrint ("LeaseSet ", m_RemoteIdentity.GetIdentHash ().ToBase64 (), " not found"); LogPrint ("LeaseSet ", m_RemoteIdentity.GetIdentHash ().ToBase64 (), " not found");
} }
if (m_RemoteLeaseSet) if (m_RemoteLeaseSet)
{ {
if (!m_RoutingSession) if (!m_RoutingSession)
m_RoutingSession = m_LocalDestination.GetRoutingSession (*m_RemoteLeaseSet, 32); m_RoutingSession = m_LocalDestination.GetOwner ().GetRoutingSession (*m_RemoteLeaseSet, 32);
auto leases = m_RemoteLeaseSet->GetNonExpiredLeases (); auto leases = m_RemoteLeaseSet->GetNonExpiredLeases ();
if (!leases.empty ()) if (!leases.empty ())
{ {
@@ -520,12 +522,139 @@ namespace stream
} }
else else
{ {
m_RemoteLeaseSet = m_LocalDestination.FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired m_RemoteLeaseSet = m_LocalDestination.GetOwner ().FindLeaseSet (m_RemoteIdentity.GetIdentHash ()); // re-request expired
m_CurrentRemoteLease.endDate = 0; m_CurrentRemoteLease.endDate = 0;
} }
} }
else else
m_CurrentRemoteLease.endDate = 0; m_CurrentRemoteLease.endDate = 0;
}
I2NPMessage * Stream::CreateDataMessage (const uint8_t * payload, size_t len)
{
I2NPMessage * msg = NewI2NPShortMessage ();
CryptoPP::Gzip compressor;
if (len <= i2p::stream::COMPRESSION_THRESHOLD_SIZE)
compressor.SetDeflateLevel (CryptoPP::Gzip::MIN_DEFLATE_LEVEL);
else
compressor.SetDeflateLevel (CryptoPP::Gzip::DEFAULT_DEFLATE_LEVEL);
compressor.Put (payload, len);
compressor.MessageEnd();
int size = compressor.MaxRetrievable ();
uint8_t * buf = msg->GetPayload ();
*(uint32_t *)buf = htobe32 (size); // length
buf += 4;
compressor.Get (buf, size);
*(uint16_t *)(buf + 4) = 0; // source port
*(uint16_t *)(buf + 6) = htobe16 (m_Port); // destination port
buf[9] = i2p::client::PROTOCOL_TYPE_STREAMING; // streaming protocol
msg->len += size + 4;
FillI2NPMessageHeader (msg, eI2NPData);
return msg;
}
void StreamingDestination::Start ()
{
}
void StreamingDestination::Stop ()
{
ResetAcceptor ();
{
std::unique_lock<std::mutex> l(m_StreamsMutex);
for (auto it: m_Streams)
delete it.second;
m_Streams.clear ();
}
}
void StreamingDestination::HandleNextPacket (Packet * packet)
{
uint32_t sendStreamID = packet->GetSendStreamID ();
if (sendStreamID)
{
auto it = m_Streams.find (sendStreamID);
if (it != m_Streams.end ())
it->second->HandleNextPacket (packet);
else
{
LogPrint ("Unknown stream ", sendStreamID);
delete packet;
}
}
else // new incoming stream
{
auto incomingStream = CreateNewIncomingStream ();
incomingStream->HandleNextPacket (packet);
if (m_Acceptor != nullptr)
m_Acceptor (incomingStream);
else
{
LogPrint ("Acceptor for incoming stream is not set");
DeleteStream (incomingStream);
}
}
}
Stream * StreamingDestination::CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port)
{
Stream * s = new Stream (*m_Owner.GetService (), *this, remote, port);
std::unique_lock<std::mutex> l(m_StreamsMutex);
m_Streams[s->GetRecvStreamID ()] = s;
return s;
}
Stream * StreamingDestination::CreateNewIncomingStream ()
{
Stream * s = new Stream (*m_Owner.GetService (), *this);
std::unique_lock<std::mutex> l(m_StreamsMutex);
m_Streams[s->GetRecvStreamID ()] = s;
return s;
}
void StreamingDestination::DeleteStream (Stream * stream)
{
if (stream)
{
std::unique_lock<std::mutex> l(m_StreamsMutex);
auto it = m_Streams.find (stream->GetRecvStreamID ());
if (it != m_Streams.end ())
{
m_Streams.erase (it);
if (m_Owner.GetService ())
m_Owner.GetService ()->post ([stream](void) { delete stream; });
else
delete stream;
}
}
} }
void StreamingDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len)
{
// unzip it
CryptoPP::Gunzip decompressor;
decompressor.Put (buf, len);
decompressor.MessageEnd();
Packet * uncompressed = new Packet;
uncompressed->offset = 0;
uncompressed->len = decompressor.MaxRetrievable ();
if (uncompressed->len <= MAX_PACKET_SIZE)
{
decompressor.Get (uncompressed->buf, uncompressed->len);
HandleNextPacket (uncompressed);
}
else
{
LogPrint ("Received packet size ", uncompressed->len, " exceeds max packet size. Skipped");
delete uncompressed;
}
}
void DeleteStream (Stream * stream)
{
if (stream)
stream->GetLocalDestination ().DeleteStream (stream);
}
} }
} }

View File

@@ -18,6 +18,10 @@
namespace i2p namespace i2p
{ {
namespace client
{
class ClientDestination;
}
namespace stream namespace stream
{ {
const uint16_t PACKET_FLAG_SYNCHRONIZE = 0x0001; const uint16_t PACKET_FLAG_SYNCHRONIZE = 0x0001;
@@ -78,7 +82,8 @@ namespace stream
{ {
public: public:
Stream (boost::asio::io_service& service, StreamingDestination& local, const i2p::data::LeaseSet& remote); // outgoing Stream (boost::asio::io_service& service, StreamingDestination& local,
const i2p::data::LeaseSet& remote, int port = 0); // outgoing
Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming
~Stream (); ~Stream ();
@@ -100,6 +105,8 @@ namespace stream
size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumSentBytes () const { return m_NumSentBytes; };
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
size_t GetSendQueueSize () const { return m_SentPackets.size (); };
size_t GetReceiveQueueSize () const { return m_ReceiveQueue.size (); };
private: private:
@@ -120,6 +127,8 @@ namespace stream
void ScheduleResend (); void ScheduleResend ();
void HandleResendTimer (const boost::system::error_code& ecode); void HandleResendTimer (const boost::system::error_code& ecode);
void HandleAckSendTimer (const boost::system::error_code& ecode); void HandleAckSendTimer (const boost::system::error_code& ecode);
I2NPMessage * CreateDataMessage (const uint8_t * payload, size_t len);
private: private:
@@ -137,8 +146,50 @@ namespace stream
std::set<Packet *, PacketCmp> m_SentPackets; std::set<Packet *, PacketCmp> m_SentPackets;
boost::asio::deadline_timer m_ReceiveTimer, m_ResendTimer, m_AckSendTimer; boost::asio::deadline_timer m_ReceiveTimer, m_ResendTimer, m_AckSendTimer;
size_t m_NumSentBytes, m_NumReceivedBytes; size_t m_NumSentBytes, m_NumReceivedBytes;
uint16_t m_Port;
}; };
class StreamingDestination
{
public:
typedef std::function<void (Stream *)> Acceptor;
StreamingDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {};
~StreamingDestination () {};
void Start ();
void Stop ();
Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port = 0);
void DeleteStream (Stream * stream);
void SetAcceptor (const Acceptor& acceptor) { m_Acceptor = acceptor; };
void ResetAcceptor () { m_Acceptor = nullptr; };
bool IsAcceptorSet () const { return m_Acceptor != nullptr; };
i2p::client::ClientDestination& GetOwner () { return m_Owner; };
void HandleDataMessagePayload (const uint8_t * buf, size_t len);
private:
void HandleNextPacket (Packet * packet);
Stream * CreateNewIncomingStream ();
private:
i2p::client::ClientDestination& m_Owner;
std::mutex m_StreamsMutex;
std::map<uint32_t, Stream *> m_Streams;
Acceptor m_Acceptor;
public:
// for HTTP only
const decltype(m_Streams)& GetStreams () const { return m_Streams; };
};
void DeleteStream (Stream * stream);
//------------------------------------------------- //-------------------------------------------------
template<typename Buffer, typename ReceiveHandler> template<typename Buffer, typename ReceiveHandler>

View File

@@ -34,7 +34,7 @@ namespace tunnel
*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID); *(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID);
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
i2p::transports.SendMessage (m_NextIdent, tunnelMsg); i2p::transport::transports.SendMessage (m_NextIdent, tunnelMsg);
} }
void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg) void TransitTunnel::SendTunnelDataMsg (i2p::I2NPMessage * msg)

75
TransportSession.h Normal file
View File

@@ -0,0 +1,75 @@
#ifndef TRANSPORT_SESSION_H__
#define TRANSPORT_SESSION_H__
#include <inttypes.h>
#include <iostream>
#include "Identity.h"
#include "RouterInfo.h"
namespace i2p
{
namespace transport
{
struct DHKeysPair // transient keys for transport sessions
{
uint8_t publicKey[256];
uint8_t privateKey[256];
};
class SignedData
{
public:
SignedData () {};
void Insert (const uint8_t * buf, size_t len)
{
m_Stream.write ((char *)buf, len);
}
template<typename T>
void Insert (T t)
{
m_Stream.write ((char *)&t, sizeof (T));
}
bool Verify (const i2p::data::IdentityEx& ident, const uint8_t * signature) const
{
return ident.Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature);
}
void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const
{
keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature);
}
private:
std::stringstream m_Stream;
};
class TransportSession
{
public:
TransportSession (const i2p::data::RouterInfo * in_RemoteRouter):
m_RemoteRouter (in_RemoteRouter), m_DHKeysPair (nullptr)
{
if (m_RemoteRouter)
m_RemoteIdentity = m_RemoteRouter->GetRouterIdentity ();
}
virtual ~TransportSession () { delete m_DHKeysPair; };
const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; };
const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; };
protected:
const i2p::data::RouterInfo * m_RemoteRouter;
i2p::data::IdentityEx m_RemoteIdentity;
DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
};
}
}
#endif

View File

@@ -1,5 +1,7 @@
#include <cryptopp/dh.h>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include "Log.h" #include "Log.h"
#include "CryptoConst.h"
#include "RouterContext.h" #include "RouterContext.h"
#include "I2NPProtocol.h" #include "I2NPProtocol.h"
#include "NetDb.h" #include "NetDb.h"
@@ -9,6 +11,13 @@ using namespace i2p::data;
namespace i2p namespace i2p
{ {
namespace transport
{
DHKeysPairSupplier::DHKeysPairSupplier (int size):
m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr)
{
}
DHKeysPairSupplier::~DHKeysPairSupplier () DHKeysPairSupplier::~DHKeysPairSupplier ()
{ {
Stop (); Stop ();
@@ -48,17 +57,18 @@ namespace i2p
{ {
if (num > 0) if (num > 0)
{ {
CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair (); i2p::transport::DHKeysPair * pair = new i2p::transport::DHKeysPair ();
i2p::data::CreateRandomDHKeysPair (pair); dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey);
std::unique_lock<std::mutex> l(m_AcquiredMutex); std::unique_lock<std::mutex> l(m_AcquiredMutex);
m_Queue.push (pair); m_Queue.push (pair);
} }
} }
} }
i2p::data::DHKeysPair * DHKeysPairSupplier::Acquire () DHKeysPair * DHKeysPairSupplier::Acquire ()
{ {
if (!m_Queue.empty ()) if (!m_Queue.empty ())
{ {
@@ -70,13 +80,14 @@ namespace i2p
} }
else // queue is empty, create new else // queue is empty, create new
{ {
i2p::data::DHKeysPair * pair = new i2p::data::DHKeysPair (); DHKeysPair * pair = new DHKeysPair ();
i2p::data::CreateRandomDHKeysPair (pair); CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
dh.GenerateKeyPair(m_Rnd, pair->privateKey, pair->publicKey);
return pair; return pair;
} }
} }
void DHKeysPairSupplier::Return (i2p::data::DHKeysPair * pair) void DHKeysPairSupplier::Return (DHKeysPair * pair)
{ {
std::unique_lock<std::mutex> l(m_AcquiredMutex); std::unique_lock<std::mutex> l(m_AcquiredMutex);
m_Queue.push (pair); m_Queue.push (pair);
@@ -85,7 +96,7 @@ namespace i2p
Transports transports; Transports transports;
Transports::Transports (): Transports::Transports ():
m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr), m_Thread (nullptr), m_Work (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys m_SSUServer (nullptr), m_DHKeysPairSupplier (5) // 5 pre-generated keys
{ {
} }
@@ -104,21 +115,35 @@ namespace i2p
auto addresses = context.GetRouterInfo ().GetAddresses (); auto addresses = context.GetRouterInfo ().GetAddresses ();
for (auto& address : addresses) for (auto& address : addresses)
{ {
if (address.transportStyle == RouterInfo::eTransportNTCP) if (address.transportStyle == RouterInfo::eTransportNTCP && address.host.is_v4 ())
{ {
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port)); boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address.port));
LogPrint ("Start listening TCP port ", address.port); LogPrint ("Start listening TCP port ", address.port);
auto conn = new i2p::ntcp::NTCPServerConnection (m_Service); auto conn = new NTCPServerConnection (m_Service);
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this, m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
conn, boost::asio::placeholders::error)); conn, boost::asio::placeholders::error));
if (context.SupportsV6 ())
{
m_NTCPV6Acceptor = new boost::asio::ip::tcp::acceptor (m_Service);
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address.port));
m_NTCPV6Acceptor->listen ();
LogPrint ("Start listening V6 TCP port ", address.port);
auto conn = new NTCPServerConnection (m_Service);
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6,
this, conn, boost::asio::placeholders::error));
}
} }
else if (address.transportStyle == RouterInfo::eTransportSSU) else if (address.transportStyle == RouterInfo::eTransportSSU && address.host.is_v4 ())
{ {
if (!m_SSUServer) if (!m_SSUServer)
{ {
m_SSUServer = new i2p::ssu::SSUServer (address.port); m_SSUServer = new SSUServer (address.port);
LogPrint ("Start listening UDP port ", address.port); LogPrint ("Start listening UDP port ", address.port);
m_SSUServer->Start (); m_SSUServer->Start ();
DetectExternalIP (); DetectExternalIP ();
@@ -143,6 +168,8 @@ namespace i2p
m_NTCPSessions.clear (); m_NTCPSessions.clear ();
delete m_NTCPAcceptor; delete m_NTCPAcceptor;
m_NTCPAcceptor = nullptr; m_NTCPAcceptor = nullptr;
delete m_NTCPV6Acceptor;
m_NTCPV6Acceptor = nullptr;
m_DHKeysPairSupplier.Stop (); m_DHKeysPairSupplier.Stop ();
m_IsRunning = false; m_IsRunning = false;
@@ -170,19 +197,19 @@ namespace i2p
} }
} }
void Transports::AddNTCPSession (i2p::ntcp::NTCPSession * session) void Transports::AddNTCPSession (NTCPSession * session)
{ {
if (session) if (session)
m_NTCPSessions[session->GetRemoteRouterInfo ().GetIdentHash ()] = session; m_NTCPSessions[session->GetRemoteIdentity ().GetIdentHash ()] = session;
} }
void Transports::RemoveNTCPSession (i2p::ntcp::NTCPSession * session) void Transports::RemoveNTCPSession (NTCPSession * session)
{ {
if (session) if (session)
m_NTCPSessions.erase (session->GetRemoteRouterInfo ().GetIdentHash ()); m_NTCPSessions.erase (session->GetRemoteIdentity ().GetIdentHash ());
} }
void Transports::HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error) void Transports::HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error)
{ {
if (!error) if (!error)
{ {
@@ -194,13 +221,31 @@ namespace i2p
if (error != boost::asio::error::operation_aborted) if (error != boost::asio::error::operation_aborted)
{ {
conn = new i2p::ntcp::NTCPServerConnection (m_Service); conn = new NTCPServerConnection (m_Service);
m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this, m_NTCPAcceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAccept, this,
conn, boost::asio::placeholders::error)); conn, boost::asio::placeholders::error));
} }
} }
i2p::ntcp::NTCPSession * Transports::GetNextNTCPSession () void Transports::HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error)
{
if (!error)
{
LogPrint ("Connected from ", conn->GetSocket ().remote_endpoint().address ().to_string ());
conn->ServerLogin ();
}
else
delete conn;
if (error != boost::asio::error::operation_aborted)
{
conn = new NTCPServerConnection (m_Service);
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), boost::bind (&Transports::HandleAcceptV6, this,
conn, boost::asio::placeholders::error));
}
}
NTCPSession * Transports::GetNextNTCPSession ()
{ {
for (auto session: m_NTCPSessions) for (auto session: m_NTCPSessions)
if (session.second->IsEstablished ()) if (session.second->IsEstablished ())
@@ -208,7 +253,7 @@ namespace i2p
return 0; return 0;
} }
i2p::ntcp::NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident) NTCPSession * Transports::FindNTCPSession (const i2p::data::IdentHash& ident)
{ {
auto it = m_NTCPSessions.find (ident); auto it = m_NTCPSessions.find (ident);
if (it != m_NTCPSessions.end ()) if (it != m_NTCPSessions.end ())
@@ -242,10 +287,10 @@ namespace i2p
{ {
// existing session not found. create new // existing session not found. create new
// try NTCP first if message size < 16K // try NTCP first if message size < 16K
auto address = r->GetNTCPAddress (); auto address = r->GetNTCPAddress (!context.SupportsV6 ());
if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < i2p::ntcp::NTCP_MAX_MESSAGE_SIZE) if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE)
{ {
auto s = new i2p::ntcp::NTCPClient (m_Service, address->host, address->port, *r); auto s = new NTCPClient (m_Service, address->host, address->port, *r);
AddNTCPSession (s); AddNTCPSession (s);
s->SendI2NPMessage (msg); s->SendI2NPMessage (msg);
} }
@@ -311,22 +356,23 @@ namespace i2p
void Transports::DetectExternalIP () void Transports::DetectExternalIP ()
{ {
for (int i = 0; i < 5; i ++) for (int i = 0; i < 5; i++)
{ {
auto router = i2p::data::netdb.GetRandomRouter (); auto router = i2p::data::netdb.GetRandomRouter ();
if (router && router->IsSSU () && m_SSUServer) if (router && router->IsSSU () && m_SSUServer)
m_SSUServer->GetSession (router, true); // peer test m_SSUServer->GetSession (router.get (), true); // peer test
} }
} }
DHKeysPair * Transports::GetNextDHKeysPair ()
i2p::data::DHKeysPair * Transports::GetNextDHKeysPair ()
{ {
return m_DHKeysPairSupplier.Acquire (); return m_DHKeysPairSupplier.Acquire ();
} }
void Transports::ReuseDHKeysPair (i2p::data::DHKeysPair * pair) void Transports::ReuseDHKeysPair (DHKeysPair * pair)
{ {
m_DHKeysPairSupplier.Return (pair); m_DHKeysPairSupplier.Return (pair);
} }
} }
}

View File

@@ -8,7 +8,9 @@
#include <map> #include <map>
#include <queue> #include <queue>
#include <string> #include <string>
#include <cryptopp/osrng.h>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "TransportSession.h"
#include "NTCPSession.h" #include "NTCPSession.h"
#include "SSU.h" #include "SSU.h"
#include "RouterInfo.h" #include "RouterInfo.h"
@@ -16,17 +18,19 @@
#include "Identity.h" #include "Identity.h"
namespace i2p namespace i2p
{
namespace transport
{ {
class DHKeysPairSupplier class DHKeysPairSupplier
{ {
public: public:
DHKeysPairSupplier (int size): m_QueueSize (size), m_IsRunning (false), m_Thread (nullptr) {}; DHKeysPairSupplier (int size);
~DHKeysPairSupplier (); ~DHKeysPairSupplier ();
void Start (); void Start ();
void Stop (); void Stop ();
i2p::data::DHKeysPair * Acquire (); DHKeysPair * Acquire ();
void Return (i2p::data::DHKeysPair * pair); void Return (DHKeysPair * pair);
private: private:
@@ -36,12 +40,13 @@ namespace i2p
private: private:
const int m_QueueSize; const int m_QueueSize;
std::queue<i2p::data::DHKeysPair *> m_Queue; std::queue<DHKeysPair *> m_Queue;
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread; std::thread * m_Thread;
std::condition_variable m_Acquired; std::condition_variable m_Acquired;
std::mutex m_AcquiredMutex; std::mutex m_AcquiredMutex;
CryptoPP::AutoSeededRandomPool m_Rnd;
}; };
class Transports class Transports
@@ -55,14 +60,14 @@ namespace i2p
void Stop (); void Stop ();
boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetService () { return m_Service; };
i2p::data::DHKeysPair * GetNextDHKeysPair (); i2p::transport::DHKeysPair * GetNextDHKeysPair ();
void ReuseDHKeysPair (i2p::data::DHKeysPair * pair); void ReuseDHKeysPair (DHKeysPair * pair);
void AddNTCPSession (i2p::ntcp::NTCPSession * session); void AddNTCPSession (NTCPSession * session);
void RemoveNTCPSession (i2p::ntcp::NTCPSession * session); void RemoveNTCPSession (NTCPSession * session);
i2p::ntcp::NTCPSession * GetNextNTCPSession (); NTCPSession * GetNextNTCPSession ();
i2p::ntcp::NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident); NTCPSession * FindNTCPSession (const i2p::data::IdentHash& ident);
void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); void SendMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
void CloseSession (const i2p::data::RouterInfo * router); void CloseSession (const i2p::data::RouterInfo * router);
@@ -70,7 +75,8 @@ namespace i2p
private: private:
void Run (); void Run ();
void HandleAccept (i2p::ntcp::NTCPServerConnection * conn, const boost::system::error_code& error); void HandleAccept (NTCPServerConnection * conn, const boost::system::error_code& error);
void HandleAcceptV6 (NTCPServerConnection * conn, const boost::system::error_code& error);
void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer, void HandleResendTimer (const boost::system::error_code& ecode, boost::asio::deadline_timer * timer,
const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg); void PostMessage (const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg);
@@ -84,10 +90,10 @@ namespace i2p
std::thread * m_Thread; std::thread * m_Thread;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::io_service::work m_Work; boost::asio::io_service::work m_Work;
boost::asio::ip::tcp::acceptor * m_NTCPAcceptor; boost::asio::ip::tcp::acceptor * m_NTCPAcceptor, * m_NTCPV6Acceptor;
std::map<i2p::data::IdentHash, i2p::ntcp::NTCPSession *> m_NTCPSessions; std::map<i2p::data::IdentHash, NTCPSession *> m_NTCPSessions;
i2p::ssu::SSUServer * m_SSUServer; SSUServer * m_SSUServer;
DHKeysPairSupplier m_DHKeysPairSupplier; DHKeysPairSupplier m_DHKeysPairSupplier;
@@ -95,10 +101,11 @@ namespace i2p
// for HTTP only // for HTTP only
const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; }; const decltype(m_NTCPSessions)& GetNTCPSessions () const { return m_NTCPSessions; };
const i2p::ssu::SSUServer * GetSSUServer () const { return m_SSUServer; }; const SSUServer * GetSSUServer () const { return m_SSUServer; };
}; };
extern Transports transports; extern Transports transports;
} }
}
#endif #endif

View File

@@ -92,7 +92,7 @@ namespace tunnel
if (outboundTunnel) if (outboundTunnel)
outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg); outboundTunnel->SendTunnelDataMsg (GetNextIdentHash (), 0, msg);
else else
i2p::transports.SendMessage (GetNextIdentHash (), msg); i2p::transport::transports.SendMessage (GetNextIdentHash (), msg);
} }
bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len) bool Tunnel::HandleTunnelBuildResponse (uint8_t * msg, size_t len)
@@ -468,7 +468,7 @@ namespace tunnel
CreateTunnel<OutboundTunnel> ( CreateTunnel<OutboundTunnel> (
new TunnelConfig (std::vector<const i2p::data::RouterInfo *> new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
{ {
i2p::data::netdb.GetRandomRouter () i2p::data::netdb.GetRandomRouter ().get ()
}, },
inboundTunnel->GetTunnelConfig ())); inboundTunnel->GetTunnelConfig ()));
} }
@@ -521,7 +521,7 @@ namespace tunnel
CreateTunnel<InboundTunnel> ( CreateTunnel<InboundTunnel> (
new TunnelConfig (std::vector<const i2p::data::RouterInfo *> new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
{ {
i2p::data::netdb.GetRandomRouter () i2p::data::netdb.GetRandomRouter ().get ()
})); }));
} }
} }

View File

@@ -235,7 +235,7 @@ namespace tunnel
i2p::HandleI2NPMessage (msg.data); i2p::HandleI2NPMessage (msg.data);
break; break;
case eDeliveryTypeTunnel: case eDeliveryTypeTunnel:
i2p::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); i2p::transport::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data));
break; break;
case eDeliveryTypeRouter: case eDeliveryTypeRouter:
if (msg.hash == i2p::context.GetRouterInfo ().GetIdentHash ()) // check if message is sent to us if (msg.hash == i2p::context.GetRouterInfo ().GetIdentHash ()) // check if message is sent to us
@@ -253,7 +253,7 @@ namespace tunnel
*ds = *(msg.data); *ds = *(msg.data);
i2p::data::netdb.PostI2NPMsg (ds); i2p::data::netdb.PostI2NPMsg (ds);
} }
i2p::transports.SendMessage (msg.hash, msg.data); i2p::transport::transports.SendMessage (msg.hash, msg.data);
} }
else // we shouldn't send this message. possible leakage else // we shouldn't send this message. possible leakage
{ {

View File

@@ -12,8 +12,12 @@ namespace tunnel
{ {
void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block) void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block)
{ {
bool messageCreated = false;
if (!m_CurrentTunnelDataMsg) if (!m_CurrentTunnelDataMsg)
{
CreateCurrentTunnelDataMessage (); CreateCurrentTunnelDataMessage ();
messageCreated = true;
}
// create delivery instructions // create delivery instructions
uint8_t di[43]; // max delivery instruction length is 43 for tunnel uint8_t di[43]; // max delivery instruction length is 43 for tunnel
@@ -33,7 +37,8 @@ namespace tunnel
// create fragments // create fragments
I2NPMessage * msg = block.data; I2NPMessage * msg = block.data;
if (diLen + msg->GetLength () + 2<= m_RemainingSize) auto fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
if (fullMsgLen <= m_RemainingSize)
{ {
// message fits. First and last fragment // message fits. First and last fragment
*(uint16_t *)(di + diLen) = htobe16 (msg->GetLength ()); *(uint16_t *)(di + diLen) = htobe16 (msg->GetLength ());
@@ -48,6 +53,18 @@ namespace tunnel
} }
else else
{ {
if (!messageCreated) // check if we should complete previous message
{
auto numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
// length of bytes don't fit full tunnel message
// every follow-on fragment adds 7 bytes
auto nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE;
if (!nonFit || nonFit > m_RemainingSize)
{
CompleteCurrentTunnelDataMessage ();
CreateCurrentTunnelDataMessage ();
}
}
if (diLen + 6 <= m_RemainingSize) if (diLen + 6 <= m_RemainingSize)
{ {
// delivery instructions fit // delivery instructions fit
@@ -169,7 +186,7 @@ namespace tunnel
{ {
m_Tunnel->EncryptTunnelMsg (tunnelMsg); m_Tunnel->EncryptTunnelMsg (tunnelMsg);
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData);
i2p::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg); i2p::transport::transports.SendMessage (m_Tunnel->GetNextIdentHash (), tunnelMsg);
m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; m_NumSentBytes += TUNNEL_DATA_MSG_SIZE;
} }
m_Buffer.ClearTunnelDataMsgs (); m_Buffer.ClearTunnelDataMsgs ();

View File

@@ -237,10 +237,10 @@ namespace tunnel
const i2p::data::RouterInfo * TunnelPool::SelectNextHop (const i2p::data::RouterInfo * prevHop) const const i2p::data::RouterInfo * TunnelPool::SelectNextHop (const i2p::data::RouterInfo * prevHop) const
{ {
auto hop = m_NumHops >= 3 ? i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop) : auto hop = m_NumHops >= 3 ? i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop).get () :
i2p::data::netdb.GetRandomRouter (prevHop); i2p::data::netdb.GetRandomRouter (prevHop).get ();
if (!hop) if (!hop)
hop = i2p::data::netdb.GetRandomRouter (); hop = i2p::data::netdb.GetRandomRouter ().get ();
return hop; return hop;
} }
@@ -257,7 +257,7 @@ namespace tunnel
{ {
// last hop // last hop
auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router; auto hop = outboundTunnel->GetTunnelConfig ()->GetFirstHop ()->router;
if (hop->GetIdentHash () != i2p::context.GetRouterIdentHash ()) // outbound shouldn't be zero-hop tunnel if (hop->GetIdentHash () != i2p::context.GetIdentHash ()) // outbound shouldn't be zero-hop tunnel
{ {
prevHop = hop; prevHop = hop;
hops.push_back (prevHop); hops.push_back (prevHop);

View File

@@ -33,7 +33,7 @@ namespace tunnel
const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); }; const uint8_t * GetEncryptionPublicKey () const { return m_LocalDestination.GetEncryptionPublicKey (); };
const i2p::data::LocalDestination& GetLocalDestination () const { return m_LocalDestination; }; const i2p::data::LocalDestination& GetLocalDestination () const { return m_LocalDestination; };
i2p::garlic::GarlicDestination& GetGarlicDestination () const { return m_LocalDestination; }; i2p::garlic::GarlicDestination& GetGarlicDestination () const { return m_LocalDestination; };
bool IsExploratory () const { return GetIdentHash () == i2p::context.GetRouterIdentHash (); }; bool IsExploratory () const { return GetIdentHash () == i2p::context.GetIdentHash (); };
void CreateTunnels (); void CreateTunnels ();
void TunnelCreated (InboundTunnel * createdTunnel); void TunnelCreated (InboundTunnel * createdTunnel);

282
Win32/PurpleI2P.nsi Normal file
View File

@@ -0,0 +1,282 @@
# NSIS Installer script. (Tested with NSIS 2.64 on Windows 7)
# Author: Mikal Villa (Meeh)
# Version: 1.0
Name PurpleI2P
RequestExecutionLevel highest
SetCompressor /SOLID lzma
ShowInstDetails show
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION 0.2.0.0
!define COMPANY "The Privacy Solutions Project"
!define URL "https://i2p.io"
# MUI Symbol Definitions
!define MUI_ICON "ictoopie.ico"
#!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_RIGHT
#!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp"
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
!define MUI_STARTMENUPAGE_DEFAULTFOLDER PurpleI2P
!define MUI_FINISHPAGE_RUN $INSTDIR\i2pd.exe
!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\Readme.txt
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
# Included files
!include Sections.nsh
!include MUI2.nsh
!include nsDialogs.nsh
!include winmessages.nsh
!include logiclib.nsh
# Local included files
!include nsi\helper_readme.nsh
;!include nsi\servicelib.nsh
# Variables
Var StartMenuGroup
# Installer pages
# Execution flow of installer windows
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_README "../Readme.md"
!insertmacro MUI_PAGE_DIRECTORY
# Disabled for now. Use the bat
;Page custom mode_selection # Meeh's hack for installing and starting service.
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
# Uninstall pages
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
# Installer languages
!insertmacro MUI_LANGUAGE English
# Installer attributes
OutFile PurpleI2P-0.2.0.0-win32-setup.exe
InstallDir $PROGRAMFILES\PurpleI2P
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
VIProductVersion 0.2.0.0
VIAddVersionKey ProductName PurpleI2P
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
VIAddVersionKey CompanyWebsite "${URL}"
VIAddVersionKey FileVersion "${VERSION}"
VIAddVersionKey FileDescription ""
VIAddVersionKey LegalCopyright ""
InstallDirRegKey HKCU "${REGKEY}" Path
ShowUninstDetails show
# Readme definitions
;--------------------------------
;Languages
;Set up install lang strings for 1st lang
${ReadmeLanguage} "${LANG_ENGLISH}" \
"Read Me" \
"Please review the following important information." \
"About $(^name):" \
"$\n Click on scrollbar arrows or press Page Down to review the entire text."
;Add 2nd language
!insertmacro MUI_LANGUAGE "Norwegian"
;set up install lang strings for second lang
${ReadmeLanguage} "${LANG_NORWEGIAN}" \
"Les meg!" \
"Vennligst les informasjonen om hvordan du skal bruke PurpleI2P." \
"Om $(^name):" \
"$\n Klikk på scrollbaren til høyre for å se hele innholdet."
;--------------------------------
# Installer sections
Section -Main SEC0000
SetOutPath $INSTDIR
SetOverwrite on
File /oname=i2pd.exe Release\i2pd.exe
File /oname=install_service.bat install_service.bat
File /oname=uninstall_service.bat uninstall_service.bat
File /oname=LICENSE.txt ..\LICENSE
File /oname=Readme.txt ..\README.md
SetOutPath $INSTDIR\src
File /r /x *.nsi /x *.rc /x *.exe /x *.obj /x *.nsh /x *.sln /x *.vcxproj /x *.tlog /x *.log /x *.res /x *.pdb /x *.suo /x *.opensdf /x *.filters /x *.sdf /x *.iss /x *.aps /x .gitignore /x *.o ../\*.*
SetOutPath $INSTDIR
RMDir /r /REBOOTOK $INSTDIR\src\.git # Remove git directory
RMDir /r /REBOOTOK $INSTDIR\src\Win32\Release # Removing release directory
RMDir /r /REBOOTOK $INSTDIR\src\Win32\nsi
WriteRegStr HKCU "${REGKEY}\Components" Main 1
SectionEnd
Section -post SEC0001
WriteRegStr HKCU "${REGKEY}" Path $INSTDIR
SetOutPath $INSTDIR
WriteUninstaller $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory $SMPROGRAMS\$StartMenuGroup
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\PurpleI2P.lnk" $INSTDIR\i2pd.exe
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Install PurpleI2P Service.lnk" $INSTDIR\install_service.bat
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall PurpleI2P Service.lnk" $INSTDIR\uninstall_service.bat
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall PurpleI2P.lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
WriteRegStr HKCR "i2pd" "URL Protocol" ""
WriteRegStr HKCR "i2pd" "" "URL:i2pd" # TODO: if a instance of own is found, relaunch with a proxyfied browser to open webage. (e.g i2pd://meeh.i2p)
WriteRegStr HKCR "i2pd\DefaultIcon" "" $INSTDIR\i2pd.exe
WriteRegStr HKCR "i2pd\shell\open\command" "" '"$INSTDIR\i2pd.exe" "%1"'
SectionEnd
# Macro for selecting uninstaller sections
!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
Push $R0
ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}"
StrCmp $R0 1 0 next${UNSECTION_ID}
!insertmacro SelectSection "${UNSECTION_ID}"
GoTo done${UNSECTION_ID}
next${UNSECTION_ID}:
!insertmacro UnselectSection "${UNSECTION_ID}"
done${UNSECTION_ID}:
Pop $R0
!macroend
# Uninstaller sections
Section /o -un.Main UNSEC0000
Delete /REBOOTOK $INSTDIR\i2pd.exe
Delete /REBOOTOK $INSTDIR\LICENSE.txt
Delete /REBOOTOK $INSTDIR\Readme.txt
Delete /REBOOTOK $INSTDIR\install_service.bat
Delete /REBOOTOK $INSTDIR\uninstall_service.bat
RMDir /r /REBOOTOK $INSTDIR\src
DeleteRegValue HKCU "${REGKEY}\Components" Main
SectionEnd
Section -un.post UNSEC0001
DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall PurpleI2P.lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\PurpleI2P.lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Install PurpleI2P Service.lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\UnInstall PurpleI2P Service.lnk"
Delete /REBOOTOK "$SMSTARTUP\PurpleI2P.lnk"
Delete /REBOOTOK $INSTDIR\uninstall.exe
Delete /REBOOTOK $INSTDIR\debug.log
DeleteRegValue HKCU "${REGKEY}" StartMenuGroup
DeleteRegValue HKCU "${REGKEY}" Path
DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
DeleteRegKey /IfEmpty HKCU "${REGKEY}"
DeleteRegKey HKCR "i2pd"
RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
RmDir /REBOOTOK $INSTDIR
Push $R0
StrCpy $R0 $StartMenuGroup 1
StrCmp $R0 ">" no_smgroup
no_smgroup:
Pop $R0
SectionEnd
; var hwndExecModeRadio
; var hwndRunServiceNowRadio
; Function mode_selection
; nsDialogs::Create 1018
; Pop $0
; ${NSD_CreateLabel} 0 10 75% 20u "How would you like PurpleI2P (i2pd) to run?"
; Pop $0
; ${NSD_CreateRadioButton} 20 60 80% 25u "Service Mode"
; Pop $hwndExecModeRadio
; ${NSD_AddStyle} $hwndExecModeRadio ${WS_GROUP}
; ${NSD_CreateRadioButton} 20 90 80% 25u "Command line Mode"
; Pop $0
; ${NSD_CreateButton} 20 150 -40 14u "Do it!"
; Pop $0
; ${NSD_OnClick} $0 perform_mode
; nsDialogs::Show
; FunctionEnd
; Function start_now_selection
; nsDialogs::Create 1018
; Pop $0
; ${NSD_CreateLabel} 0 10 75% 20u "Enable the service now?"
; Pop $0
; ${NSD_CreateRadioButton} 20 60 80% 25u "Yes"
; Pop $hwndRunServiceNowRadio
; ${NSD_AddStyle} $hwndRunServiceNowRadio ${WS_GROUP}
; ${NSD_CreateRadioButton} 20 90 80% 25u "No"
; Pop $0
; ${NSD_CreateButton} 20 150 -40 14u "Do it!"
; Pop $0
; ${NSD_OnClick} $0 perform_mode
; nsDialogs::Show
; FunctionEnd
; Function perform_mode
; ${NSD_GetState} $hwndExecModeRadio $0
; ${If} $0 = ${BST_CHECKED}
; Call service_mode
; ${EndIF}
; FunctionEnd
; Function start_now
; ${NSD_GetState} $hwndRunServiceNowRadio $0
; ${If} $0 = ${BST_CHECKED}
; Call start_now_selection
; ${EndIF}
; FunctionEnd
; Function service_mode
; Push "create"
; Push "PurpleI2P Service"
; Push "$INSTDIR\i2pd.exe;autostart=1;display=PurpleI2P"
; Call Service
; Pop $0 ; Actually more to write than !insertmacro, but much more fun :D
; Push "start"
; Push "PurpleI2P Service"
; Call Service
; Pop $0
; Call start_now
; !define MUI_FINISHPAGE_RUN_NOTCHECKED
; !define MUI_FINISHPAGE_RUN_TEXT "No need to run now since we already installed and launched it as a Windows service!"
; FunctionEnd
# Installer functions
Function .onInit
InitPluginsDir
!insertmacro MUI_LANGDLL_DISPLAY
FunctionEnd
# Uninstaller functions
Function un.onInit
ReadRegStr $INSTDIR HKCU "${REGKEY}" Path
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
!insertmacro SELECT_UNSECTION Main ${UNSEC0000}
!insertmacro MUI_UNGETLANGUAGE
FunctionEnd

84
Win32/README-Build.txt Normal file
View File

@@ -0,0 +1,84 @@
Building i2pd for Windows
=========================
Requirements for building:
* Visual Studio 2013 (tested with VS2013 Update 1, Update 3, and Update 4 RC)
* Boost (tested with 1.56 and 1.57)
* Crypto++ (tested with 5.6.2)
Building Boost (32-bit)
-----------------------
Open a Visual Studio x86 command prompt and run the following:
cd C:\path\to\boost\sources
bootstrap
b2 toolset=msvc-12.0 --build-type=complete --libdir=C:\Boost\lib\Win32 install --with-filesystem --with-program_options --with-regex --with-date_time
Building Boost (64-bit)
-----------------------
Open a Visual Studio x64 command prompt and run the following:
cd C:\path\to\boost\sources
bootstrap
b2 toolset=msvc-12.0 --build-type=complete --libdir=C:\Boost\lib\x64 architecture=x86 address-model=64 install --with-filesystem --with-program_options --with-regex --with-date_time
After Boost is compiled, set the environment variable `BOOST` to the directory
Boost was installed to. If you followed the instructions outlined here, you
should set it to `C:\Boost`. Additionally, set the BOOSTVER variable to the
version of Boost that you're using, but instead of a '.' use a '_'. For
example, I have `BOOSTVER` set to `1_57`.
Building Crypto++
-----------------
* Open the crypttest Solution in VS2013
* Visual Studio will ask to update the Solution/Project. Allow it.
* Build the `cryptopp` project, both the Debug and Release targets and for both
Win32 and x64.
* Create a folder called `cryptopp` in the crypto++ source directory, then copy
the header files to this new directory.
* Set the `CRYPTOPP` environment variable pointing to the Crypto++ source directory.
Building i2pd
-------------
## Prep work ##
I strongly advise setting up your own `INCLUDES` and `LIBS` instead of relying
on the settings in the i2pd project file. By using your own settings, if the
i2pd devs change the paths in the project file, your builds will still work.
To do this, create or edit the file
`%localappdata%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user`.
For comparison, my file is reproduced below:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets">
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<LibraryPath>$(CRYPTOPP)\$(Platform)\Output\$(Configuration);$(BOOST)\lib\$(Platform);$(LibraryPath)</LibraryPath>
<IncludePath>$(CRYPTOPP);$(BOOST)\include\boost-$(BOOSTVER);$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>
If you want to build x64 binaries as well, you'll want to edit or create the
file `%localappdata%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.x64.user`. If you
followed the steps outlined earlier you can copy (or link) the win32 file to
the x64 one.
## Anti-Climatic End ##
After following the above instructions, you'll be able to build Debug Win32,
Debug x64, Release Win32, and Release x64 i2pd binaries.

BIN
Win32/Resource.rc Normal file

Binary file not shown.

View File

@@ -1,27 +1,30 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013 # Visual Studio 2013
VisualStudioVersion = 12.0.30501.0 VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "i2pd", "i2pd.vcxproj", "{930568EC-31C9-406A-AD1C-9636DF5D8FAA}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "i2pd", "i2pd.vcxproj", "{930568EC-31C9-406A-AD1C-9636DF5D8FAA}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32 Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.ActiveCfg = Debug|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.ActiveCfg = Debug|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.Build.0 = Debug|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.Build.0 = Debug|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.Deploy.0 = Debug|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|Win32.Deploy.0 = Debug|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|x64.ActiveCfg = Debug|x64
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Debug|x64.Build.0 = Debug|x64
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.ActiveCfg = Release|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.ActiveCfg = Release|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.Build.0 = Release|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.Build.0 = Release|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.Deploy.0 = Release|Win32 {930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|Win32.Deploy.0 = Release|Win32
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|x64.ActiveCfg = Release|x64
{930568EC-31C9-406A-AD1C-9636DF5D8FAA}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal EndGlobal

View File

@@ -5,10 +5,18 @@
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\AddressBook.cpp" /> <ClCompile Include="..\AddressBook.cpp" />
@@ -34,8 +42,10 @@
<ClCompile Include="..\SAM.cpp" /> <ClCompile Include="..\SAM.cpp" />
<ClCompile Include="..\SSU.cpp" /> <ClCompile Include="..\SSU.cpp" />
<ClCompile Include="..\SSUData.cpp" /> <ClCompile Include="..\SSUData.cpp" />
<ClCompile Include="..\SSUSession.cpp" />
<ClCompile Include="..\Streaming.cpp" /> <ClCompile Include="..\Streaming.cpp" />
<ClCompile Include="..\Destination.cpp" /> <ClCompile Include="..\Datagram.cpp" />
<ClCompile Include="..\Destination.cpp" />
<ClCompile Include="..\TransitTunnel.cpp" /> <ClCompile Include="..\TransitTunnel.cpp" />
<ClCompile Include="..\Transports.cpp" /> <ClCompile Include="..\Transports.cpp" />
<ClCompile Include="..\Tunnel.cpp" /> <ClCompile Include="..\Tunnel.cpp" />
@@ -46,7 +56,7 @@
<ClCompile Include="..\util.cpp" /> <ClCompile Include="..\util.cpp" />
<ClCompile Include="..\SOCKS.cpp" /> <ClCompile Include="..\SOCKS.cpp" />
<ClCompile Include="..\I2PTunnel.cpp" /> <ClCompile Include="..\I2PTunnel.cpp" />
<ClCompile Include="..\ClientContext.cpp" /> <ClCompile Include="..\ClientContext.cpp" />
<ClCompile Include="Win32Service.cpp" /> <ClCompile Include="Win32Service.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -73,8 +83,10 @@
<ClInclude Include="..\SAM.h" /> <ClInclude Include="..\SAM.h" />
<ClInclude Include="..\SSU.h" /> <ClInclude Include="..\SSU.h" />
<ClInclude Include="..\SSUData.h" /> <ClInclude Include="..\SSUData.h" />
<ClInclude Include="..\SSUSession.h" />
<ClInclude Include="..\Streaming.h" /> <ClInclude Include="..\Streaming.h" />
<ClInclude Include="..\Destination.h" /> <ClInclude Include="..\Datagram.h" />
<ClInclude Include="..\Destination.h" />
<ClInclude Include="..\Timestamp.h" /> <ClInclude Include="..\Timestamp.h" />
<ClInclude Include="..\TransitTunnel.h" /> <ClInclude Include="..\TransitTunnel.h" />
<ClInclude Include="..\Transports.h" /> <ClInclude Include="..\Transports.h" />
@@ -91,8 +103,13 @@
<ClInclude Include="..\version.h" /> <ClInclude Include="..\version.h" />
<ClInclude Include="..\Signature.h" /> <ClInclude Include="..\Signature.h" />
<ClInclude Include="..\ClientContext.h" /> <ClInclude Include="..\ClientContext.h" />
<ClInclude Include="..\TransportSession.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Win32Service.h" /> <ClInclude Include="Win32Service.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resource.rc" />
</ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{930568EC-31C9-406A-AD1C-9636DF5D8FAA}</ProjectGuid> <ProjectGuid>{930568EC-31C9-406A-AD1C-9636DF5D8FAA}</ProjectGuid>
<RootNamespace>i2pd</RootNamespace> <RootNamespace>i2pd</RootNamespace>
@@ -101,15 +118,28 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset> <PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset> <PlatformToolset>v120_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@@ -117,19 +147,36 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>E:\build\cryptopp562;E:\build\boost_1_56_0;./..;$(IncludePath)</IncludePath> <IncludePath>./..;$(IncludePath);$(BOOST);$(CRYPTOPP);C:\build-lib\cryptopp;C:\build-lib\boost_1_57_0\</IncludePath>
<LibraryPath>E:\build\cryptopp562\Win32\Output\Debug;E:\build\boost_1_56_0\stage\lib;$(LibraryPath)</LibraryPath> <LibraryPath>$(BOOST)\stage\lib;C:\build-lib\cryptopp;C:\build-lib\boost_1_57_0\stage\lib;$(CRYPTOPP)\cryptopp\$(Platform)\Output\$(Configuration);$(LibraryPath)</LibraryPath>
<SourcePath>./..;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_d</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>./..;$(IncludePath);$(BOOST);$(CRYPTOPP)</IncludePath>
<LibraryPath>$(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\$(Platform)\Output\$(Configuration);$(LibraryPath)</LibraryPath>
<SourcePath>./..;$(VC_SourcePath);</SourcePath> <SourcePath>./..;$(VC_SourcePath);</SourcePath>
<TargetName>$(ProjectName)_d</TargetName> <TargetName>$(ProjectName)_d</TargetName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>E:\build\cryptopp562;E:\build\boost_1_56_0;./..;$(IncludePath)</IncludePath> <IncludePath>./..;$(IncludePath);$(BOOST);C:\build-lib\boost_1_57_0\;C:\build-lib</IncludePath>
<LibraryPath>E:\build\cryptopp562\Win32\Output\Release;E:\build\cryptopp562\Win32\cryptopp\Release;E:\build\boost_1_56_0\stage\lib;E:\build\cryptopp562\Win32\cryptlib\DLL-Import Release;$(LibraryPath)</LibraryPath> <LibraryPath>C:\build-lib\boost_1_57_0\stage\lib;C:\build-lib\cryptopp\$(Platform)\Output\$(Configuration);$(LibraryPath)</LibraryPath>
<SourcePath>./..;$(VC_SourcePath);</SourcePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>./..;$(IncludePath);$(BOOST);$(CRYPTOPP)</IncludePath>
<LibraryPath>$(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\$(Platform)\Output\$(Configuration);$(LibraryPath)</LibraryPath>
<SourcePath>./..;$(VC_SourcePath);</SourcePath> <SourcePath>./..;$(VC_SourcePath);</SourcePath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -144,26 +191,82 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel> <UACExecutionLevel>AsInvoker</UACExecutionLevel>
<Version>0.2</Version>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_MBCS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
<Version>0.2</Version>
<SubSystem>Console</SubSystem>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level2</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>false</OptimizeReferences>
<AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<UACExecutionLevel>AsInvoker</UACExecutionLevel>
<Version>
</Version>
<SubSystem>Console</SubSystem>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
</Link>
<Manifest>
<AssemblyIdentity>
</AssemblyIdentity>
<ComponentFileName>
</ComponentFileName>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<SDLCheck>true</SDLCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>false</OptimizeReferences> <OptimizeReferences>false</OptimizeReferences>
<AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel> <UACExecutionLevel>AsInvoker</UACExecutionLevel>
<Version> <Version>
</Version> </Version>
<SubSystem>Console</SubSystem>
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
<LinkErrorReporting>NoErrorReport</LinkErrorReporting>
</Link> </Link>
<Manifest> <Manifest>
<AssemblyIdentity> <AssemblyIdentity>
@@ -175,4 +278,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@@ -123,6 +123,18 @@
<ClCompile Include="..\SAM.cpp"> <ClCompile Include="..\SAM.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\SSUSession.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Datagram.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Destination.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ClientContext.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\Identity.h"> <ClInclude Include="..\Identity.h">
@@ -245,5 +257,28 @@
<ClInclude Include="..\SAM.h"> <ClInclude Include="..\SAM.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\SSUSession.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Datagram.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Destination.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ClientContext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\TransportSession.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resource.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

BIN
Win32/ictoopie.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@@ -1,10 +1,10 @@
#define I2Pd_AppName "i2pd" #define I2Pd_AppName "i2pd"
#define I2Pd_ver "0.1" #define I2Pd_ver "0.2"
[Setup] [Setup]
AppName={#I2Pd_AppName} AppName={#I2Pd_AppName}
AppVersion={#I2Pd_ver} AppVersion={#I2Pd_ver}
DefaultDirName={pf}\I2Pd DefaultDirName={pf}\I2Pd
DefaultGroupName=I2Pd DefaultGroupName=I2Pd
UninstallDisplayIcon={app}\I2Pd.exe UninstallDisplayIcon={app}\I2Pd.exe
@@ -13,27 +13,50 @@ SolidCompression=yes
OutputDir=. OutputDir=.
LicenseFile=.\..\LICENSE LicenseFile=.\..\LICENSE
OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver} OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver}
ArchitecturesInstallIn64BitMode=x64
[Files] [Files]
Source: "i2pd.exe"; DestDir: "{app}" Source: "x64\Release\i2pd.exe"; DestDir: "{app}"; DestName: "i2pd.exe"; Check: Is64BitInstallMode
Source: "Release\i2pd.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode
Source: "..\README.md"; DestDir: "{app}"; DestName: "Readme.txt"; AfterInstall: ConvertLineEndings
[Icons] [Icons]
Name: "{group}\I2Pd"; Filename: "{app}\i2pd.exe" Name: "{group}\I2Pd"; Filename: "{app}\i2pd.exe"
Name: "{group}\Readme"; Filename: "{app}\Readme.txt"
[Registry]
Root: HKCU; Subkey: "Environment"; ValueName: "Path"; ValueType: "string"; ValueData: "{app};{olddata}"; Check: NotOnPathAlready(); Flags: preservestringtype;
[Code] [Code]
var var
DefaultTop, DefaultTop,
DefaultLeft, DefaultLeft,
DefaultHeight, DefaultHeight,
DefaultBackTop, DefaultBackTop,
DefaultNextTop, DefaultNextTop,
DefaultCancelTop, DefaultCancelTop,
DefaultBevelTop, DefaultBevelTop,
DefaultOuterHeight: Integer; DefaultOuterHeight: Integer;
const const
LicenseHeight = 400; LicenseHeight = 400;
LF = #10;
CR = #13;
CRLF = CR + LF;
procedure ConvertLineEndings();
var
FilePath : String;
FileContents : String;
begin
FilePath := ExpandConstant(CurrentFileName)
LoadStringFromFile(FilePath, FileContents);
StringChangeEx(FileContents, LF, CRLF, False);
SaveStringToFile(FilePath, FileContents, False);
end;
procedure InitializeWizard(); procedure InitializeWizard();
begin begin
@@ -67,7 +90,7 @@ begin
WizardForm.BackButton.Top := DefaultBackTop + (LicenseHeight - DefaultHeight); WizardForm.BackButton.Top := DefaultBackTop + (LicenseHeight - DefaultHeight);
WizardForm.Bevel.Top := DefaultBevelTop + (LicenseHeight - DefaultHeight); WizardForm.Bevel.Top := DefaultBevelTop + (LicenseHeight - DefaultHeight);
end end
else else
begin begin
WizardForm.Top := DefaultTop; WizardForm.Top := DefaultTop;
WizardForm.Left := DefaultLeft; WizardForm.Left := DefaultLeft;
@@ -78,4 +101,49 @@ begin
WizardForm.BackButton.Top := DefaultBackTop; WizardForm.BackButton.Top := DefaultBackTop;
WizardForm.Bevel.Top := DefaultBevelTop; WizardForm.Bevel.Top := DefaultBevelTop;
end; end;
end; end;
function NotOnPathAlready(): Boolean;
var
BinDir, Path: String;
begin
Log('Checking if i2pd dir is already in the %PATH%');
if RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', Path) then
begin // Successfully read the value
Log('HKCUEnvironmentPATH = ' + Path);
BinDir := ExpandConstant('{app}');
Log('Looking for i2pd dir in %PATH%: ' + BinDir + ' in ' + Path);
if Pos(LowerCase(BinDir), Lowercase(Path)) = 0 then
begin
Log('Did not find i2pd dir in %PATH% so I will add it');
Result := True;
end
else
begin
Log('Found i2pd dir in %PATH% so will not add it again');
Result := False;
end
end
else // The key probably doesn't exist
begin
Log('Could not access HKCUEnvironmentPATH so I assume that it is OK to add it');
Result := True;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
BinDir, Path: String;
begin
if (CurUninstallStep = usPostUninstall)
and (RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'PATH', Path)) then
begin
BinDir := ExpandConstant('{app}');
if Pos(LowerCase(BinDir) + ';', Lowercase(Path)) <> 0 then
begin
StringChange(Path, BinDir + ';', '');
RegWriteStringValue(HKEY_CURRENT_USER, 'Environment', 'PATH', Path);
end;
end;
end;

View File

@@ -0,0 +1,57 @@
!verbose push
!verbose 3
!ifndef _MUI_EXTRAPAGES_NSH
!define _MUI_EXTRAPAGES_NSH
!ifmacrondef MUI_EXTRAPAGE_README & MUI_PAGE_README & MUI_UNPAGE_README & ReadmeLangStrings
!macro MUI_EXTRAPAGE_README UN ReadmeFile
!verbose push
!verbose 3
!define MUI_PAGE_HEADER_TEXT "$(${UN}ReadmeHeader)"
!define MUI_PAGE_HEADER_SUBTEXT "$(${UN}ReadmeSubHeader)"
!define MUI_LICENSEPAGE_TEXT_TOP "$(${UN}ReadmeTextTop)"
!define MUI_LICENSEPAGE_TEXT_BOTTOM "$(${UN}ReadmeTextBottom)"
!define MUI_LICENSEPAGE_BUTTON "$(^NextBtn)"
!insertmacro MUI_${UN}PAGE_LICENSE "${ReadmeFile}"
!verbose pop
!macroend
!define ReadmeRun "!insertmacro MUI_EXTRAPAGE_README"
!macro MUI_PAGE_README ReadmeFile
!verbose push
!verbose 3
${ReadmeRun} "" "${ReadmeFile}"
!verbose pop
!macroend
!macro MUI_UNPAGE_README ReadmeFile
!verbose push
!verbose 3
${ReadmeRun} "UN" "${ReadmeFile}"
!verbose pop
!macroend
!macro ReadmeLangStrings UN MUI_LANG ReadmeHeader ReadmeSubHeader ReadmeTextTop ReadmeTextBottom
!verbose push
!verbose 3
LangString ${UN}ReadmeHeader ${MUI_LANG} "${ReadmeHeader}"
LangString ${UN}ReadmeSubHeader ${MUI_LANG} "${ReadmeSubHeader}"
LangString ${UN}ReadmeTextTop ${MUI_LANG} "${ReadmeTextTop}"
LangString ${UN}ReadmeTextBottom ${MUI_LANG} "${ReadmeTextBottom}"
!verbose pop
!macroend
!define ReadmeLanguage `!insertmacro ReadmeLangStrings ""`
!define Un.ReadmeLanguage `!insertmacro ReadmeLangStrings "UN"`
!endif
!endif
!verbose pop

419
Win32/nsi/servicelib.nsh Normal file
View File

@@ -0,0 +1,419 @@
; NSIS SERVICE LIBRARY - servicelib.nsh
; Version 1.8.1 - Jun 21th, 2013
; Questions/Comments - dselkirk@hotmail.com
;
; Description:
; Provides an interface to window services
;
; Inputs:
; action - systemlib action ie. create, delete, start, stop, pause,
; continue, installed, running, status
; name - name of service to manipulate
; param - action parameters; usage: var1=value1;var2=value2;...etc.
; (don't forget to add a ';' after the last value!)
;
; Actions:
; create - creates a new windows service
; Parameters:
; path - path to service executable
; autostart - automatically start with system ie. 1|0
; interact - interact with the desktop ie. 1|0
; depend - service dependencies
; user - user that runs the service
; password - password of the above user
; display - display name in service's console
; description - Description of service
; starttype - start type (supersedes autostart)
; servicetype - service type (supersedes interact)
;
; delete - deletes a windows service
; start - start a stopped windows service
; stop - stops a running windows service
; pause - pauses a running windows service
; continue - continues a paused windows service
; installed - is the provided service installed
; Parameters:
; action - if true then invokes the specified action
; running - is the provided service running
; Parameters:
; action - if true then invokes the specified action
; status - check the status of the provided service
;
; Usage:
; Method 1:
; Push "action"
; Push "name"
; Push "param"
; Call Service
; Pop $0 ;response
;
; Method 2:
; !insertmacro SERVICE "action" "name" "param"
;
; History:
; 1.0 - 09/15/2003 - Initial release
; 1.1 - 09/16/2003 - Changed &l to i, thx brainsucker
; 1.2 - 02/29/2004 - Fixed documentation.
; 1.3 - 01/05/2006 - Fixed interactive flag and pop order (Kichik)
; 1.4 - 12/07/2006 - Added display and depend, fixed datatypes (Vitoco)
; 1.5 - 06/25/2008 - Added description of service.(DeSafe.com/liuqixing#gmail.com)
; 1.5.1 - 06/12/2009 - Added use of __UNINSTALL__
; 1.6 - 08/02/2010 - Fixed description implementation (Anders)
; 1.7 - 04/11/2010 - Added get running service process id (Nico)
; 1.8 - 24/03/2011 - Added starttype and servicetype (Sergius)
; 1.8.1 - 21/06/2013 - Added dynamic ASCII & Unicode support (Zinthose)
!ifndef SERVICELIB
!define SERVICELIB
!define SC_MANAGER_ALL_ACCESS 0x3F
!define SC_STATUS_PROCESS_INFO 0x0
!define SERVICE_ALL_ACCESS 0xF01FF
!define SERVICE_CONTROL_STOP 1
!define SERVICE_CONTROL_PAUSE 2
!define SERVICE_CONTROL_CONTINUE 3
!define SERVICE_STOPPED 0x1
!define SERVICE_START_PENDING 0x2
!define SERVICE_STOP_PENDING 0x3
!define SERVICE_RUNNING 0x4
!define SERVICE_CONTINUE_PENDING 0x5
!define SERVICE_PAUSE_PENDING 0x6
!define SERVICE_PAUSED 0x7
!define SERVICE_KERNEL_DRIVER 0x00000001
!define SERVICE_FILE_SYSTEM_DRIVER 0x00000002
!define SERVICE_WIN32_OWN_PROCESS 0x00000010
!define SERVICE_WIN32_SHARE_PROCESS 0x00000020
!define SERVICE_INTERACTIVE_PROCESS 0x00000100
!define SERVICE_BOOT_START 0x00000000
!define SERVICE_SYSTEM_START 0x00000001
!define SERVICE_AUTO_START 0x00000002
!define SERVICE_DEMAND_START 0x00000003
!define SERVICE_DISABLED 0x00000004
## Added by Zinthose for Native Unicode Support
!ifdef NSIS_UNICODE
!define APITAG "W"
!else
!define APITAG "A"
!endif
!macro SERVICE ACTION NAME PARAM
Push '${ACTION}'
Push '${NAME}'
Push '${PARAM}'
!ifdef __UNINSTALL__
Call un.Service
!else
Call Service
!endif
!macroend
!macro FUNC_GETPARAM
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
Push $7
Exch 8
Pop $1 ;name
Exch 8
Pop $2 ;source
StrCpy $0 ""
StrLen $7 $2
StrCpy $3 0
lbl_loop:
IntCmp $3 $7 0 0 lbl_done
StrLen $4 "$1="
StrCpy $5 $2 $4 $3
StrCmp $5 "$1=" 0 lbl_next
IntOp $5 $3 + $4
StrCpy $3 $5
lbl_loop2:
IntCmp $3 $7 0 0 lbl_done
StrCpy $6 $2 1 $3
StrCmp $6 ";" 0 lbl_next2
IntOp $6 $3 - $5
StrCpy $0 $2 $6 $5
Goto lbl_done
lbl_next2:
IntOp $3 $3 + 1
Goto lbl_loop2
lbl_next:
IntOp $3 $3 + 1
Goto lbl_loop
lbl_done:
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch 2
Pop $6
Pop $7
Exch $0
!macroend
!macro CALL_GETPARAM VAR NAME DEFAULT LABEL
Push $1
Push ${NAME}
Call ${UN}GETPARAM
Pop $6
StrCpy ${VAR} "${DEFAULT}"
StrCmp $6 "" "${LABEL}" 0
StrCpy ${VAR} $6
!macroend
!macro FUNC_SERVICE UN
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
Push $7
Exch 8
Pop $1 ;param
Exch 8
Pop $2 ;name
Exch 8
Pop $3 ;action
;$0 return
;$4 OpenSCManager
;$5 OpenService
StrCpy $0 "false"
System::Call 'advapi32::OpenSCManager${APITAG}(n, n, i ${SC_MANAGER_ALL_ACCESS}) i.r4'
IntCmp $4 0 lbl_done
StrCmp $3 "create" lbl_create
System::Call 'advapi32::OpenService${APITAG}(i r4, t r2, i ${SERVICE_ALL_ACCESS}) i.r5'
IntCmp $5 0 lbl_done
lbl_select:
StrCmp $3 "delete" lbl_delete
StrCmp $3 "start" lbl_start
StrCmp $3 "stop" lbl_stop
StrCmp $3 "pause" lbl_pause
StrCmp $3 "continue" lbl_continue
StrCmp $3 "installed" lbl_installed
StrCmp $3 "running" lbl_running
StrCmp $3 "status" lbl_status
StrCmp $3 "processid" lbl_processid
Goto lbl_done
; create service
lbl_create:
Push $R1 ;depend
Push $R2 ;user
Push $R3 ;password
Push $R4 ;servicetype/interact
Push $R5 ;starttype/autostart
Push $R6 ;path
Push $R7 ;display
Push $R8 ;description
!insertmacro CALL_GETPARAM $R1 "depend" "n" "lbl_depend"
StrCpy $R1 't "$R1"'
lbl_depend:
StrCmp $R1 "n" 0 lbl_machine ;old name of depend param
!insertmacro CALL_GETPARAM $R1 "machine" "n" "lbl_machine"
StrCpy $R1 't "$R1"'
lbl_machine:
!insertmacro CALL_GETPARAM $R2 "user" "n" "lbl_user"
StrCpy $R2 't "$R2"'
lbl_user:
!insertmacro CALL_GETPARAM $R3 "password" "n" "lbl_password"
StrCpy $R3 't "$R3"'
lbl_password:
!insertmacro CALL_GETPARAM $R4 "interact" "${SERVICE_WIN32_OWN_PROCESS}" "lbl_interact"
StrCpy $6 ${SERVICE_WIN32_OWN_PROCESS}
IntCmp $R4 0 +2
IntOp $6 $6 | ${SERVICE_INTERACTIVE_PROCESS}
StrCpy $R4 $6
lbl_interact:
!insertmacro CALL_GETPARAM $R4 "servicetype" "$R4" "lbl_servicetype"
lbl_servicetype:
!insertmacro CALL_GETPARAM $R5 "autostart" "${SERVICE_DEMAND_START}" "lbl_autostart"
StrCpy $6 ${SERVICE_DEMAND_START}
IntCmp $R5 0 +2
StrCpy $6 ${SERVICE_AUTO_START}
StrCpy $R5 $6
lbl_autostart:
!insertmacro CALL_GETPARAM $R5 "starttype" "$R5" "lbl_starttype"
lbl_starttype:
!insertmacro CALL_GETPARAM $R6 "path" "n" "lbl_path"
lbl_path:
!insertmacro CALL_GETPARAM $R7 "display" "$2" "lbl_display"
lbl_display:
!insertmacro CALL_GETPARAM $R8 "description" "$2" "lbl_description"
lbl_description:
System::Call 'advapi32::CreateService${APITAG}(i r4, t r2, t R7, i ${SERVICE_ALL_ACCESS}, \
i R4, i R5, i 0, t R6, n, n, $R1, $R2, $R3) i.r6'
; write description of service (SERVICE_CONFIG_DESCRIPTION)
System::Call 'advapi32::ChangeServiceConfig2${APITAG}(ir6,i1,*t "$R8")i.R7'
strcmp $R7 "error" 0 lbl_descriptioncomplete
WriteRegStr HKLM "SYSTEM\CurrentControlSet\Services\$2" "Description" $R8
lbl_descriptioncomplete:
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
StrCmp $6 0 lbl_done lbl_good
; delete service
lbl_delete:
System::Call 'advapi32::DeleteService(i r5) i.r6'
StrCmp $6 0 lbl_done lbl_good
; start service
lbl_start:
System::Call 'advapi32::StartService${APITAG}(i r5, i 0, i 0) i.r6'
StrCmp $6 0 lbl_done lbl_good
; stop service
lbl_stop:
Push $R1
System::Call '*(i,i,i,i,i,i,i) i.R1'
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_STOP}, i $R1) i'
System::Free $R1
Pop $R1
StrCmp $6 0 lbl_done lbl_good
; pause service
lbl_pause:
Push $R1
System::Call '*(i,i,i,i,i,i,i) i.R1'
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_PAUSE}, i $R1) i'
System::Free $R1
Pop $R1
StrCmp $6 0 lbl_done lbl_good
; continue service
lbl_continue:
Push $R1
System::Call '*(i,i,i,i,i,i,i) i.R1'
System::Call 'advapi32::ControlService(i r5, i ${SERVICE_CONTROL_CONTINUE}, i $R1) i'
System::Free $R1
Pop $R1
StrCmp $6 0 lbl_done lbl_good
; is installed
lbl_installed:
!insertmacro CALL_GETPARAM $7 "action" "" "lbl_good"
StrCpy $3 $7
Goto lbl_select
; is service running
lbl_running:
Push $R1
System::Call '*(i,i,i,i,i,i,i) i.R1'
System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i'
System::Call '*$R1(i, i.r6)'
System::Free $R1
Pop $R1
IntFmt $6 "0x%X" $6
StrCmp $6 ${SERVICE_RUNNING} 0 lbl_done
!insertmacro CALL_GETPARAM $7 "action" "" "lbl_good"
StrCpy $3 $7
Goto lbl_select
lbl_status:
Push $R1
System::Call '*(i,i,i,i,i,i,i) i.R1'
System::Call 'advapi32::QueryServiceStatus(i r5, i $R1) i'
System::Call '*$R1(i, i .r6)'
System::Free $R1
Pop $R1
IntFmt $6 "0x%X" $6
StrCpy $0 "running"
IntCmp $6 ${SERVICE_RUNNING} lbl_done
StrCpy $0 "stopped"
IntCmp $6 ${SERVICE_STOPPED} lbl_done
StrCpy $0 "start_pending"
IntCmp $6 ${SERVICE_START_PENDING} lbl_done
StrCpy $0 "stop_pending"
IntCmp $6 ${SERVICE_STOP_PENDING} lbl_done
StrCpy $0 "running"
IntCmp $6 ${SERVICE_RUNNING} lbl_done
StrCpy $0 "continue_pending"
IntCmp $6 ${SERVICE_CONTINUE_PENDING} lbl_done
StrCpy $0 "pause_pending"
IntCmp $6 ${SERVICE_PAUSE_PENDING} lbl_done
StrCpy $0 "paused"
IntCmp $6 ${SERVICE_PAUSED} lbl_done
StrCpy $0 "unknown"
Goto lbl_done
lbl_processid:
Push $R1
Push $R2
System::Call '*(i,i,i,i,i,i,i,i,i) i.R1'
System::Call '*(i 0) i.R2'
System::Call "advapi32::QueryServiceStatusEx(i r5, i ${SC_STATUS_PROCESS_INFO}, i $R1, i 36, i $R2) i"
System::Call "*$R1(i,i,i,i,i,i,i, i .r0)"
System::Free $R2
System::Free $R1
Pop $R2
Pop $R1
Goto lbl_done
lbl_good:
StrCpy $0 "true"
lbl_done:
IntCmp $5 0 +2
System::Call 'advapi32::CloseServiceHandle(i r5) n'
IntCmp $4 0 +2
System::Call 'advapi32::CloseServiceHandle(i r4) n'
Pop $4
Pop $3
Pop $2
Pop $1
Exch 3
Pop $5
Pop $7
Pop $6
Exch $0
!macroend
Function Service
!insertmacro FUNC_SERVICE ""
FunctionEnd
Function un.Service
!insertmacro FUNC_SERVICE "un."
FunctionEnd
Function GetParam
!insertmacro FUNC_GETPARAM
FunctionEnd
Function un.GetParam
!insertmacro FUNC_GETPARAM
FunctionEnd
!undef APITAG
!endif

BIN
Win32/resource.h Normal file

Binary file not shown.

20
aes.cpp
View File

@@ -8,14 +8,6 @@ namespace crypto
{ {
#ifdef AESNI #ifdef AESNI
ECBCryptoAESNI::ECBCryptoAESNI ()
{
m_KeySchedule = m_UnalignedBuffer;
uint8_t rem = ((uint64_t)m_KeySchedule) & 0x0f;
if (rem)
m_KeySchedule += (16 - rem);
}
#define KeyExpansion256(round0,round1) \ #define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \
@@ -40,7 +32,7 @@ namespace crypto
"pxor %%xmm2, %%xmm3 \n" \ "pxor %%xmm2, %%xmm3 \n" \
"movaps %%xmm3, "#round1"(%[sched]) \n" "movaps %%xmm3, "#round1"(%[sched]) \n"
void ECBCryptoAESNI::ExpandKey (const uint8_t * key) void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{ {
__asm__ __asm__
( (
@@ -73,7 +65,7 @@ namespace crypto
"pxor %%xmm2, %%xmm1 \n" "pxor %%xmm2, %%xmm1 \n"
"movups %%xmm1, 224(%[sched]) \n" "movups %%xmm1, 224(%[sched]) \n"
: // output : // output
: [key]"r"(key), [sched]"r"(m_KeySchedule) // input : [key]"r"((const uint8_t *)key), [sched]"r"(GetKeySchedule ()) // input
: "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged : "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged
); );
} }
@@ -102,7 +94,7 @@ namespace crypto
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
EncryptAES256(sched) EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
: : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0"
); );
} }
@@ -130,7 +122,7 @@ namespace crypto
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
DecryptAES256(sched) DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
: : [sched]"r"(m_KeySchedule), [in]"r"(in), [out]"r"(out) : "%xmm0" : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0"
); );
} }
@@ -139,7 +131,7 @@ namespace crypto
"aesimc %%xmm0, %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \
"movaps %%xmm0, "#offset"(%[shed]) \n" "movaps %%xmm0, "#offset"(%[shed]) \n"
void ECBDecryptionAESNI::SetKey (const uint8_t * key) void ECBDecryptionAESNI::SetKey (const AESKey& key)
{ {
ExpandKey (key); // expand encryption key first ExpandKey (key); // expand encryption key first
// then invert it using aesimc // then invert it using aesimc
@@ -158,7 +150,7 @@ namespace crypto
CallAESIMC(176) CallAESIMC(176)
CallAESIMC(192) CallAESIMC(192)
CallAESIMC(208) CallAESIMC(208)
: : [shed]"r"(m_KeySchedule) : "%xmm0" : : [shed]"r"(GetKeySchedule ()) : "%xmm0"
); );
} }

73
aes.h
View File

@@ -4,46 +4,83 @@
#include <inttypes.h> #include <inttypes.h>
#include <cryptopp/modes.h> #include <cryptopp/modes.h>
#include <cryptopp/aes.h> #include <cryptopp/aes.h>
#include "Identity.h"
namespace i2p namespace i2p
{ {
namespace crypto namespace crypto
{ {
union ChipherBlock struct ChipherBlock
{ {
uint8_t buf[16]; uint8_t buf[16];
uint64_t ll[2];
void operator^=(const ChipherBlock& other) // XOR void operator^=(const ChipherBlock& other) // XOR
{ {
ll[0] ^= other.ll[0]; #if defined(__x86_64__) // for Intel x64
ll[1] ^= other.ll[1]; __asm__
(
"movups (%[buf]), %%xmm0 \n"
"movups (%[other]), %%xmm1 \n"
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[buf]) \n"
:
: [buf]"r"(buf), [other]"r"(other.buf)
: "%xmm0", "%xmm1", "memory"
);
#else
// TODO: implement it better
for (int i = 0; i < 16; i++)
buf[i] ^= other.buf[i];
#endif
} }
}; };
typedef i2p::data::Tag<32> AESKey;
template<size_t sz>
class AESAlignedBuffer // 16 bytes alignment
{
public:
AESAlignedBuffer ()
{
m_Buf = m_UnalignedBuffer;
uint8_t rem = ((uint64_t)m_Buf) & 0x0f;
if (rem)
m_Buf += (16 - rem);
}
operator uint8_t * () { return m_Buf; };
operator const uint8_t * () const { return m_Buf; };
private:
uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment
uint8_t * m_Buf;
};
#ifdef AESNI #ifdef AESNI
class ECBCryptoAESNI class ECBCryptoAESNI
{ {
public: public:
ECBCryptoAESNI ();
uint8_t * GetKeySchedule () { return m_KeySchedule; }; uint8_t * GetKeySchedule () { return m_KeySchedule; };
protected: protected:
void ExpandKey (const uint8_t * key); void ExpandKey (const AESKey& key);
protected: private:
uint8_t * m_KeySchedule; // start of 16 bytes boundary of m_UnalignedBuffer AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes
uint8_t m_UnalignedBuffer[256]; // 14 rounds for AES-256, 240 + 16 bytes
}; };
class ECBEncryptionAESNI: public ECBCryptoAESNI class ECBEncryptionAESNI: public ECBCryptoAESNI
{ {
public: public:
void SetKey (const uint8_t * key) { ExpandKey (key); }; void SetKey (const AESKey& key) { ExpandKey (key); };
void Encrypt (const ChipherBlock * in, ChipherBlock * out); void Encrypt (const ChipherBlock * in, ChipherBlock * out);
}; };
@@ -51,7 +88,7 @@ namespace crypto
{ {
public: public:
void SetKey (const uint8_t * key); void SetKey (const AESKey& key);
void Decrypt (const ChipherBlock * in, ChipherBlock * out); void Decrypt (const ChipherBlock * in, ChipherBlock * out);
}; };
@@ -64,7 +101,7 @@ namespace crypto
{ {
public: public:
void SetKey (const uint8_t * key) void SetKey (const AESKey& key)
{ {
m_Encryption.SetKey (key, 32); m_Encryption.SetKey (key, 32);
} }
@@ -82,7 +119,7 @@ namespace crypto
{ {
public: public:
void SetKey (const uint8_t * key) void SetKey (const AESKey& key)
{ {
m_Decryption.SetKey (key, 32); m_Decryption.SetKey (key, 32);
} }
@@ -105,7 +142,7 @@ namespace crypto
CBCEncryption () { memset (m_LastBlock.buf, 0, 16); }; CBCEncryption () { memset (m_LastBlock.buf, 0, 16); };
void SetKey (const uint8_t * key) { m_ECBEncryption.SetKey (key); }; // 32 bytes void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes
void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes void SetIV (const uint8_t * iv) { memcpy (m_LastBlock.buf, iv, 16); }; // 16 bytes
void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); void Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
@@ -125,7 +162,7 @@ namespace crypto
CBCDecryption () { memset (m_IV.buf, 0, 16); }; CBCDecryption () { memset (m_IV.buf, 0, 16); };
void SetKey (const uint8_t * key) { m_ECBDecryption.SetKey (key); }; // 32 bytes void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes
void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes void SetIV (const uint8_t * iv) { memcpy (m_IV.buf, iv, 16); }; // 16 bytes
void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out); void Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
@@ -142,7 +179,7 @@ namespace crypto
{ {
public: public:
void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey) void SetKeys (const AESKey& layerKey, const AESKey& ivKey)
{ {
m_LayerEncryption.SetKey (layerKey); m_LayerEncryption.SetKey (layerKey);
m_IVEncryption.SetKey (ivKey); m_IVEncryption.SetKey (ivKey);
@@ -164,7 +201,7 @@ namespace crypto
{ {
public: public:
void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey) void SetKeys (const AESKey& layerKey, const AESKey& ivKey)
{ {
m_LayerDecryption.SetKey (layerKey); m_LayerDecryption.SetKey (layerKey);
m_IVDecryption.SetKey (ivKey); m_IVDecryption.SetKey (ivKey);

33
api/Makefile Normal file
View File

@@ -0,0 +1,33 @@
UNAME := $(shell uname -s)
ifeq ($(UNAME),Darwin)
include ../Makefile.osx
else ifeq ($(UNAME), FreeBSD)
include ../Makefile.bsd
else
include ../Makefile.linux
endif
SHARED_LIB = libi2pd.so
all: obj $(SHARED_LIB)
$(SHARED_LIB): $(OBJECTS:obj/%=obj/%)
$(CXX) -shared -o $(SHARED_LIB) $^
.SUFFIXES:
.SUFFIXES: .c .cc .C .cpp .o
obj/%.o : ../%.cpp
$(CXX) -o $@ $< -c $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -I.. -fPIC $(CPU_FLAGS)
obj/api.o: api.cpp
$(CXX) -o obj/api.o api.cpp -c $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -I.. -fPIC $(CPU_FLAGS)
obj:
mkdir -p obj
clean:
rm -fr obj $(SHARED_LIB)
.PHONY: all
.PHONY: clean

108
api/api.cpp Normal file
View File

@@ -0,0 +1,108 @@
#include <string>
#include <map>
#include "Log.h"
#include "NetDb.h"
#include "Transports.h"
#include "Tunnel.h"
#include "RouterContext.h"
#include "Identity.h"
#include "Destination.h"
#include "util.h"
#include "api.h"
namespace i2p
{
namespace api
{
void InitI2P (int argc, char* argv[], const char * appName)
{
i2p::util::filesystem::SetAppName (appName);
i2p::util::config::OptionParser(argc, argv);
i2p::context.Init ();
}
void StartI2P ()
{
StartLog (i2p::util::filesystem::GetAppName () + ".log");
i2p::data::netdb.Start();
LogPrint("NetDB started");
i2p::transport::transports.Start();
LogPrint("Transports started");
i2p::tunnel::tunnels.Start();
LogPrint("Tunnels started");
}
void StopI2P ()
{
LogPrint("Shutdown started.");
i2p::tunnel::tunnels.Stop();
LogPrint("Tunnels stoped");
i2p::transport::transports.Stop();
LogPrint("Transports stoped");
i2p::data::netdb.Stop();
LogPrint("NetDB stoped");
StopLog ();
}
i2p::client::ClientDestination * CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic)
{
auto localDestination = new i2p::client::ClientDestination (keys, isPublic);
localDestination->Start ();
return localDestination;
}
i2p::client::ClientDestination * CreateLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType)
{
auto localDestination = new i2p::client::ClientDestination (isPublic, sigType);
localDestination->Start ();
return localDestination;
}
void DestroyLocalDestination (i2p::client::ClientDestination * dest)
{
if (dest)
{
dest->Stop ();
delete dest;
}
}
void RequestLeaseSet (i2p::client::ClientDestination * dest, const i2p::data::IdentHash& remote)
{
if (dest)
i2p::data::netdb.RequestDestination (remote, true, dest->GetTunnelPool ());
}
i2p::stream::Stream * CreateStream (i2p::client::ClientDestination * dest, const i2p::data::IdentHash& remote)
{
auto leaseSet = i2p::data::netdb.FindLeaseSet (remote);
if (leaseSet)
{
auto stream = dest->CreateStream (*leaseSet);
stream->Send (nullptr, 0); // connect
return stream;
}
else
{
RequestLeaseSet (dest, remote);
return nullptr;
}
}
void AcceptStream (i2p::client::ClientDestination * dest, const i2p::stream::StreamingDestination::Acceptor& acceptor)
{
if (dest)
dest->AcceptStreams (acceptor);
}
void DestroyStream (i2p::stream::Stream * stream)
{
if (stream)
{
stream->Close ();
i2p::stream::DeleteStream (stream);
}
}
}
}

31
api/api.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef API_H__
#define API_H__
#include "Identity.h"
#include "Destination.h"
#include "Streaming.h"
namespace i2p
{
namespace api
{
// initialization start and stop
void InitI2P (int argc, char* argv[], const char * appName);
void StartI2P ();
void StopI2P ();
// destinations
i2p::client::ClientDestination * CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true);
i2p::client::ClientDestination * CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1); // transient destinations usually not published
void DestoroyLocalDestination (i2p::client::ClientDestination * dest);
// streams
void RequestLeaseSet (i2p::client::ClientDestination * dest, const i2p::data::IdentHash& remote);
i2p::stream::Stream * CreateStream (i2p::client::ClientDestination * dest, const i2p::data::IdentHash& remote);
void AcceptStream (i2p::client::ClientDestination * dest, const i2p::stream::StreamingDestination::Acceptor& acceptor);
void DestroyStream (i2p::stream::Stream * stream);
}
}
#endif

19
api/filelist.mk Normal file
View File

@@ -0,0 +1,19 @@
CPP_FILES := ../CryptoConst.cpp ../base64.cpp ../NTCPSession.cpp ../RouterInfo.cpp \
../Transports.cpp ../RouterContext.cpp ../NetDb.cpp ../LeaseSet.cpp Tunnel.cpp \
../TunnelEndpoint.cpp ../TunnelGateway.cpp ../TransitTunnel.cpp ../I2NPProtocol.cpp \
../Log.cpp ../Garlic.cpp ../Streaming.cpp ../Destination.cpp ../Identity.cpp \
../SSU.cpp ../SSUSession.cpp ../SSUData.cpp ../util.cpp ../Reseed.cpp ../SSUData.cpp \
../aes.cpp ../TunnelPool.cpp ../AddressBook.cpp ../Datagram.cpp api.cpp
H_FILES := ../CryptoConst.h ../base64.h ../NTCPSession.h ../RouterInfo.h ../Transports.h \
../RouterContext.h ../NetDb.h ../LeaseSet.h ../Tunnel.h ../TunnelEndpoint.h \
../TunnelGateway.h ../TransitTunnel.h ../I2NPProtocol.h ../Log.h ../Garlic.h \
../Streaming.h ../Destination.h ../Identity.h ../SSU.h ../SSUSession.h ../SSUData.h \
../util.h ../Reseed.h ../SSUData.h ../aes.h ../TunnelPool.h ../AddressBook.h ../version.h \
../Signature.h ../TransportSession.h ../Datagram.h api.h
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))

View File

@@ -3,11 +3,11 @@ Build notes
Common build/install process: Common build/install process:
git clone https://github.com/PrivacySolutions/i2pd.git * git clone https://github.com/PrivacySolutions/i2pd.git
cd i2pd/build * cd i2pd/build
cmake -DCMAKE_BUILD_TYPE=Release <more options> . * cmake -DCMAKE_BUILD_TYPE=Release <more options> .
make * make
make install * make install
Available cmake options: Available cmake options:
@@ -19,7 +19,6 @@ Debian
------ ------
Required "-dev" packages: Required "-dev" packages:
* cmake * cmake
* libboost-filesystem-dev * libboost-filesystem-dev
* libboost-program-options-dev * libboost-program-options-dev

View File

@@ -43,7 +43,8 @@ set (SOURCES
"${CMAKE_SOURCE_DIR}/i2p.cpp" "${CMAKE_SOURCE_DIR}/i2p.cpp"
"${CMAKE_SOURCE_DIR}/util.cpp" "${CMAKE_SOURCE_DIR}/util.cpp"
"${CMAKE_SOURCE_DIR}/SAM.cpp" "${CMAKE_SOURCE_DIR}/SAM.cpp"
"${CMAKE_SOURCE_DIR}/ClientContext.cpp" "${CMAKE_SOURCE_DIR}/ClientContext.cpp"
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
) )
file (GLOB HEADERS "${CMAKE_SOURCE_DIR}/*.h") file (GLOB HEADERS "${CMAKE_SOURCE_DIR}/*.h")

View File

@@ -114,7 +114,8 @@ am_i2p_OBJECTS = AddressBook.$(OBJEXT) CryptoConst.$(OBJEXT) \
Transports.$(OBJEXT) Tunnel.$(OBJEXT) TunnelEndpoint.$(OBJEXT) \ Transports.$(OBJEXT) Tunnel.$(OBJEXT) TunnelEndpoint.$(OBJEXT) \
TunnelGateway.$(OBJEXT) TunnelPool.$(OBJEXT) UPnP.$(OBJEXT) \ TunnelGateway.$(OBJEXT) TunnelPool.$(OBJEXT) UPnP.$(OBJEXT) \
aes.$(OBJEXT) base64.$(OBJEXT) i2p.$(OBJEXT) util.$(OBJEXT) \ aes.$(OBJEXT) base64.$(OBJEXT) i2p.$(OBJEXT) util.$(OBJEXT) \
SAM.$(OBJEXT) Destination.$(OBJEXT) SAM.$(OBJEXT) Destination.$(OBJEXT) ClientContext.$(OBJEXT) \
Datagram.$(OBJEXT) SSUSession.$(OBJEXT)
i2p_OBJECTS = $(am_i2p_OBJECTS) i2p_OBJECTS = $(am_i2p_OBJECTS)
i2p_LDADD = $(LDADD) i2p_LDADD = $(LDADD)
AM_V_P = $(am__v_P_@AM_V@) AM_V_P = $(am__v_P_@AM_V@)
@@ -325,7 +326,7 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \
Transports.cpp Tunnel.cpp TunnelEndpoint.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp \
TunnelGateway.cpp TunnelPool.cpp UPnP.cpp aes.cpp \ TunnelGateway.cpp TunnelPool.cpp UPnP.cpp aes.cpp \
base64.cpp i2p.cpp util.cpp SAM.cpp Destination.cpp \ base64.cpp i2p.cpp util.cpp SAM.cpp Destination.cpp \
ClientContext.cpp \ ClientContext.cpp DataFram.cpp SSUSession.cpp \
\ \
AddressBook.h CryptoConst.h Daemon.h ElGamal.h \ AddressBook.h CryptoConst.h Daemon.h ElGamal.h \
Garlic.h HTTPProxy.h HTTPServer.h I2NPProtocol.h \ Garlic.h HTTPProxy.h HTTPServer.h I2NPProtocol.h \
@@ -336,7 +337,8 @@ i2p_SOURCES = AddressBook.cpp CryptoConst.cpp Daemon.cpp \
TransitTunnel.h Transports.h Tunnel.h TunnelBase.h \ TransitTunnel.h Transports.h Tunnel.h TunnelBase.h \
TunnelConfig.h TunnelEndpoint.h TunnelGateway.h \ TunnelConfig.h TunnelEndpoint.h TunnelGateway.h \
TunnelPool.h UPnP.h aes.h base64.h config.h hmac.h \ TunnelPool.h UPnP.h aes.h base64.h config.h hmac.h \
util.h version.h Destination.h ClientContext.h util.h version.h Destination.h ClientContext.h \
TransportSession.h Datagram.h SSUSession.h
AM_LDFLAGS = @BOOST_DATE_TIME_LIB@ @BOOST_FILESYSTEM_LIB@ \ AM_LDFLAGS = @BOOST_DATE_TIME_LIB@ @BOOST_FILESYSTEM_LIB@ \
@BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_REGEX_LIB@ \ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_REGEX_LIB@ \
@@ -485,6 +487,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SAM.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SAM.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientContext.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientContext.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Datagram.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SSUSession.Po@am__quote@
.cpp.o: .cpp.o:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<

View File

@@ -57,10 +57,10 @@ do_stop()
} }
# Function that sends a SIGHUP to the daemon/service # Function that sends a SIGHUP to the daemon/service
#do_reload() { do_reload() {
# start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
# return 0 return 0
#} }
case "$1" in case "$1" in
start) start)
@@ -82,14 +82,12 @@ case "$1" in
status) status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;; ;;
#reload|force-reload) reload|force-reload)
#log_daemon_msg "Reloading $DESC" "$NAME" log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload do_reload
#log_end_msg $? log_end_msg $?
#;; ;;
restart|force-reload) restart)
# If the "reload" option is implemented then remove the
# 'force-reload' alias
log_daemon_msg "Restarting $DESC" "$NAME" log_daemon_msg "Restarting $DESC" "$NAME"
do_stop do_stop
case "$?" in case "$?" in

10
debian/i2pd.upstart vendored Normal file
View File

@@ -0,0 +1,10 @@
description "i2p client daemon"
start on runlevel [2345]
stop on runlevel [016] or unmounting-filesystem
# these can be overridden in /etc/init/i2pd.override
env I2P_HOST="1.2.3.4"
env I2P_PORT="4567"
exec /usr/sbin/i2pd --daemon=0 --log=1 --host=$I2P_HOST --port=$I2P_PORT

View File

@@ -1,8 +1,6 @@
diff --git a/Makefile b/Makefile
index 9b9425b..84de72f 100644
--- a/Makefile --- a/Makefile
+++ b/Makefile +++ b/Makefile
@@ -8,9 +8,9 @@ else @@ -10,9 +10,9 @@
include Makefile.linux include Makefile.linux
endif endif
@@ -11,10 +9,10 @@ index 9b9425b..84de72f 100644
-i2p: $(OBJECTS:obj/%=obj/%) -i2p: $(OBJECTS:obj/%=obj/%)
+i2pd: $(OBJECTS:obj/%=obj/%) +i2pd: $(OBJECTS:obj/%=obj/%)
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)
.SUFFIXES: .SUFFIXES:
@@ -23,7 +23,7 @@ obj: @@ -25,7 +25,7 @@
mkdir -p obj mkdir -p obj
clean: clean:

1
debian/rules vendored
View File

@@ -6,7 +6,6 @@
DPKG_EXPORT_BUILDFLAGS = 1 DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk include /usr/share/dpkg/buildflags.mk
CFLAGS+=$(CPPFLAGS)
CXXFLAGS+=$(CPPFLAGS) CXXFLAGS+=$(CPPFLAGS)
PREFIX=/usr PREFIX=/usr

View File

@@ -3,17 +3,17 @@
CPP_FILES := CryptoConst.cpp base64.cpp NTCPSession.cpp RouterInfo.cpp Transports.cpp \ CPP_FILES := CryptoConst.cpp base64.cpp NTCPSession.cpp RouterInfo.cpp Transports.cpp \
RouterContext.cpp NetDb.cpp LeaseSet.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelGateway.cpp \ RouterContext.cpp NetDb.cpp LeaseSet.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelGateway.cpp \
TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp \ TransitTunnel.cpp I2NPProtocol.cpp Log.cpp Garlic.cpp HTTPServer.cpp Streaming.cpp \
Destination.cpp Identity.cpp SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp \ Destination.cpp Identity.cpp SSU.cpp SSUSession.cpp SSUData.cpp util.cpp Reseed.cpp \
aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp \ DaemonLinux.cpp SSUData.cpp aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp \
I2PTunnel.cpp SAM.cpp ClientContext.cpp i2p.cpp AddressBook.cpp Daemon.cpp I2PTunnel.cpp SAM.cpp ClientContext.cpp Datagram.cpp i2p.cpp
H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \ H_FILES := CryptoConst.h base64.h NTCPSession.h RouterInfo.h Transports.h \
RouterContext.h NetDb.h LeaseSet.h Tunnel.h TunnelEndpoint.h TunnelGateway.h \ RouterContext.h NetDb.h LeaseSet.h Tunnel.h TunnelEndpoint.h TunnelGateway.h \
TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Destination.h \ TransitTunnel.h I2NPProtocol.h Log.h Garlic.h HTTPServer.h Streaming.h Destination.h \
Identity.h SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h \ Identity.h SSU.h SSUSession.h SSUData.h util.h Reseed.h DaemonLinux.h SSUData.h \
UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h version.h \ aes.h SOCKS.h UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h \
Signature.h SAM.h ClientContext.h version.h Signature.h SAM.h ClientContext.h TransportSession.h Datagram.h
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o))) OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))

21
hmac.h
View File

@@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <cryptopp/md5.h> #include <cryptopp/md5.h>
#include "Identity.h"
namespace i2p namespace i2p
{ {
@@ -13,17 +14,19 @@ namespace crypto
const uint64_t IPAD = 0x3636363636363636; const uint64_t IPAD = 0x3636363636363636;
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
inline void HMACMD5Digest (uint8_t * msg, size_t len, const uint8_t * key, uint8_t * digest) typedef i2p::data::Tag<32> MACKey;
inline void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
// key is 32 bytes // key is 32 bytes
// digest is 16 bytes // digest is 16 bytes
// block size is 64 bytes // block size is 64 bytes
{ {
uint64_t buf[256]; uint64_t buf[256];
// ikeypad // ikeypad
buf[0] = ((uint64_t *)key)[0] ^ IPAD; buf[0] = key.GetLL ()[0] ^ IPAD;
buf[1] = ((uint64_t *)key)[1] ^ IPAD; buf[1] = key.GetLL ()[1] ^ IPAD;
buf[2] = ((uint64_t *)key)[2] ^ IPAD; buf[2] = key.GetLL ()[2] ^ IPAD;
buf[3] = ((uint64_t *)key)[3] ^ IPAD; buf[3] = key.GetLL ()[3] ^ IPAD;
buf[4] = IPAD; buf[4] = IPAD;
buf[5] = IPAD; buf[5] = IPAD;
buf[6] = IPAD; buf[6] = IPAD;
@@ -35,10 +38,10 @@ namespace crypto
CryptoPP::Weak1::MD5().CalculateDigest (hash, (uint8_t *)buf, len + 64); CryptoPP::Weak1::MD5().CalculateDigest (hash, (uint8_t *)buf, len + 64);
// okeypad // okeypad
buf[0] = ((uint64_t *)key)[0] ^ OPAD; buf[0] = key.GetLL ()[0] ^ OPAD;
buf[1] = ((uint64_t *)key)[1] ^ OPAD; buf[1] = key.GetLL ()[1] ^ OPAD;
buf[2] = ((uint64_t *)key)[2] ^ OPAD; buf[2] = key.GetLL ()[2] ^ OPAD;
buf[3] = ((uint64_t *)key)[3] ^ OPAD; buf[3] = key.GetLL ()[3] ^ OPAD;
buf[4] = OPAD; buf[4] = OPAD;
buf[5] = OPAD; buf[5] = OPAD;
buf[6] = OPAD; buf[6] = OPAD;

View File

@@ -15,6 +15,11 @@
#include "util.h" #include "util.h"
#include "Log.h" #include "Log.h"
#if defined(__linux__) || defined(__FreeBSD_kernel__)
#include <sys/types.h>
#include <ifaddrs.h>
#endif
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> #include <Windows.h>
#include <shlobj.h> #include <shlobj.h>
@@ -96,6 +101,18 @@ namespace config
namespace filesystem namespace filesystem
{ {
std::string appName ("i2pd");
void SetAppName (const std::string& name)
{
appName = name;
}
std::string GetAppName ()
{
return appName;
}
const boost::filesystem::path &GetDataDir() const boost::filesystem::path &GetDataDir()
{ {
static boost::filesystem::path path; static boost::filesystem::path path;
@@ -173,10 +190,10 @@ namespace filesystem
// Windows // Windows
char localAppData[MAX_PATH]; char localAppData[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData); SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData);
return boost::filesystem::path(std::string(localAppData) + "\\i2pd"); return boost::filesystem::path(std::string(localAppData) + "\\" + appName);
#else #else
if (i2p::util::config::GetArg("-service", 0)) // use system folder if (i2p::util::config::GetArg("-service", 0)) // use system folder
return boost::filesystem::path("/var/lib/i2pd"); return boost::filesystem::path(std::string ("/var/lib/") + appName);
boost::filesystem::path pathRet; boost::filesystem::path pathRet;
char* pszHome = getenv("HOME"); char* pszHome = getenv("HOME");
if (pszHome == NULL || strlen(pszHome) == 0) if (pszHome == NULL || strlen(pszHome) == 0)
@@ -187,10 +204,10 @@ namespace filesystem
// Mac // Mac
pathRet /= "Library/Application Support"; pathRet /= "Library/Application Support";
boost::filesystem::create_directory(pathRet); boost::filesystem::create_directory(pathRet);
return pathRet / "i2pd"; return pathRet / appName;
#else #else
// Unix // Unix
return pathRet / ".i2pd"; return pathRet / (std::string (".") + appName);
#endif #endif
#endif #endif
} }
@@ -389,10 +406,65 @@ namespace http
query_.assign(query_i, url_s.end()); query_.assign(query_i, url_s.end());
} }
} }
namespace net
{
int GetMTU (const boost::asio::ip::address& localAddress)
{
#if defined(__linux__) || defined(__FreeBSD_kernel__)
ifaddrs * ifaddr, * ifa = nullptr;
if (getifaddrs(&ifaddr) == -1)
{
LogPrint (eLogError, "Can't excute getifaddrs");
return 0;
}
int family = 0;
// loook for interface matching local address
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr) continue;
family = ifa->ifa_addr->sa_family;
if (family == AF_INET && localAddress.is_v4 ())
{
sockaddr_in * sa = (sockaddr_in *)ifa->ifa_addr;
if (!memcmp (&sa->sin_addr, localAddress.to_v4 ().to_bytes ().data (), 4))
break; // address matches
}
else if (family == AF_INET6 && localAddress.is_v6 ())
{
sockaddr_in6 * sa = (sockaddr_in6 *)ifa->ifa_addr;
if (!memcmp (&sa->sin6_addr, localAddress.to_v6 ().to_bytes ().data (), 16))
break; // address matches
}
}
int mtu = 0;
if (ifa && family) // interface found?
{
int fd = socket (family, SOCK_DGRAM, 0);
if (fd > 0)
{
ifreq ifr;
strncpy (ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query
if (ioctl (fd, SIOCGIFMTU, &ifr) >= 0)
mtu = ifr.ifr_mtu; // MTU
else
LogPrint (eLogError, "Failed to run ioctl");
close (fd);
}
else
LogPrint (eLogError, "Failed to create datagram socket");
}
else
LogPrint (eLogWarning, "Interface for local address", localAddress.to_string (), " not found");
freeifaddrs (ifaddr);
return mtu;
#else
return 0;
#endif
}
}
} // util
} // Namespace end } // i2p
}

9
util.h
View File

@@ -3,6 +3,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
@@ -24,6 +25,9 @@ namespace util
namespace filesystem namespace filesystem
{ {
void SetAppName (const std::string& name);
std::string GetAppName ();
const boost::filesystem::path &GetDataDir(); const boost::filesystem::path &GetDataDir();
std::string GetFullPath (const std::string& filename); std::string GetFullPath (const std::string& filename);
boost::filesystem::path GetDefaultDataDir(); boost::filesystem::path GetDefaultDataDir();
@@ -49,6 +53,11 @@ namespace util
std::string pass_; std::string pass_;
}; };
} }
namespace net
{
int GetMTU (const boost::asio::ip::address& localAddress);
}
} }
} }

View File

@@ -2,7 +2,7 @@
#define _VERSION_H_ #define _VERSION_H_
#define CODENAME "Purple" #define CODENAME "Purple"
#define VERSION "0.1.0" #define VERSION "0.3.0"
#define I2P_VERSION "0.9.15" #define I2P_VERSION "0.9.16"
#endif #endif