Compare commits

..

56 Commits

Author SHA1 Message Date
Mikal Villa
335de27095 Merge branch 'master' of github.com:PrivacySolutions/i2pd
* 'master' of github.com:PrivacySolutions/i2pd:
  shared pointers for SAM sockets
2014-11-22 23:12:34 +01:00
Mikal Villa
fa461b1254 Added prefix support, which enables the homebrew package to work. 2014-11-22 23:12:05 +01:00
orignal
81c63b0c30 shared pointers for SAM sockets 2014-11-22 16:35:58 -05:00
orignal
dcefe7d221 fixed typo 2014-11-21 13:49:49 -05:00
orignal
ed3aaefe96 delete delete routers from memory 2014-11-21 13:29:19 -05:00
orignal
6042aefd17 delete dead floodfill 2014-11-21 13:02:46 -05:00
orignal
1c3f70056a use shared pointer of RI for transports 2014-11-21 12:34:17 -05:00
orignal
d8b9968aed use shared pointer for RI in requested destination 2014-11-21 11:37:17 -05:00
orignal
8a357ac46c store shared pointer to RI in tunnel config 2014-11-21 10:46:11 -05:00
Mikal
5187701af1 Updated NSI file
Forgot to update version in NSI installer script
2014-11-21 00:28:21 -08:00
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
63 changed files with 3001 additions and 1436 deletions

View File

@@ -13,7 +13,7 @@ namespace i2p
namespace datagram
{
DatagramDestination::DatagramDestination (i2p::client::ClientDestination& owner):
m_Owner (owner)
m_Owner (owner), m_Receiver (nullptr)
{
}
@@ -41,7 +41,7 @@ namespace datagram
service->post (boost::bind (&DatagramDestination::SendMsg, this,
CreateDataMessage (buf, len + headerLen), remote));
else
LogPrint ("Failed to send datagram. Destination is not running");
LogPrint (eLogWarning, "Failed to send datagram. Destination is not running");
}
void DatagramDestination::SendMsg (I2NPMessage * msg, const i2p::data::LeaseSet& remote)
@@ -62,7 +62,7 @@ namespace datagram
}
else
{
LogPrint ("Failed to send datagram. All leases expired");
LogPrint (eLogWarning, "Failed to send datagram. All leases expired");
DeleteI2NPMessage (msg);
}
}
@@ -86,10 +86,13 @@ namespace datagram
if (verified)
{
// TODO: invoke datagram handler
if (m_Receiver != nullptr)
m_Receiver (identity, buf + headerLen, len -headerLen);
else
LogPrint (eLogWarning, "Receiver for datagram is not set");
}
else
LogPrint ("Datagram signature verification failed");
LogPrint (eLogWarning, "Datagram signature verification failed");
}
void DatagramDestination::HandleDataMessagePayload (const uint8_t * buf, size_t len)

View File

@@ -2,6 +2,8 @@
#define DATAGRAM_H__
#include <inttypes.h>
#include <functional>
#include "Identity.h"
#include "LeaseSet.h"
#include "I2NPProtocol.h"
@@ -16,6 +18,8 @@ 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);
@@ -24,6 +28,9 @@ namespace datagram
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);
@@ -33,6 +40,7 @@ namespace datagram
private:
i2p::client::ClientDestination& m_Owner;
Receiver m_Receiver;
};
}
}

View File

@@ -107,6 +107,12 @@ namespace client
void ClientDestination::Stop ()
{
m_StreamingDestination->Stop ();
if (m_DatagramDestination)
{
auto d = m_DatagramDestination;
m_DatagramDestination = nullptr;
delete d;
}
if (m_Pool)
i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
m_IsRunning = false;
@@ -275,7 +281,7 @@ namespace client
return nullptr;
}
void ClientDestination::AcceptStreams (const std::function<void (i2p::stream::Stream *)>& acceptor)
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
{
if (m_StreamingDestination)
m_StreamingDestination->SetAcceptor (acceptor);
@@ -294,10 +300,11 @@ namespace client
return false;
}
void ClientDestination::CreateDatagramDestination ()
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
{
if (!m_DatagramDestination)
m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
return m_DatagramDestination;
}
}
}

View File

@@ -42,13 +42,13 @@ namespace client
// streaming
i2p::stream::StreamingDestination * GetStreamingDestination () const { return m_StreamingDestination; };
i2p::stream::Stream * CreateStream (const i2p::data::LeaseSet& remote, int port = 0);
void AcceptStreams (const std::function<void (i2p::stream::Stream *)>& acceptor);
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
void StopAcceptingStreams ();
bool IsAcceptingStreams () const;
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
void CreateDatagramDestination ();
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
// implements LocalDestination
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };

View File

@@ -148,7 +148,7 @@ namespace garlic
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg)
{
size_t blockSize = 0;
bool createNewTags = m_Owner && ((int)m_SessionTags.size () <= m_NumTags/2);
bool createNewTags = m_Owner && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags/2);
UnconfirmedTags * newTags = createNewTags ? GenerateSessionTags () : nullptr;
*(uint16_t *)buf = newTags ? htobe16 (newTags->numTags) : 0; // tag count
blockSize += 2;
@@ -272,6 +272,16 @@ namespace garlic
size += 4;
// create msg
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 ());
size += msg->GetLength ();
DeleteI2NPMessage (msg);
@@ -304,9 +314,10 @@ namespace garlic
{
if (key)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
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 ();
uint32_t length = be32toh (*(uint32_t *)buf);
buf += 4; // lentgh
buf += 4; // length
auto it = m_Tags.find (SessionTag(buf));
if (it != m_Tags.end ())
{
@@ -469,8 +480,16 @@ namespace garlic
I2NPMessage * GarlicDestination::WrapMessage (const i2p::data::RoutingDestination& destination,
I2NPMessage * msg, bool attachLeaseSet)
{
auto session = GetRoutingSession (destination, attachLeaseSet ? 32 : 0); // don't use tag if no LeaseSet
return session->WrapSingleMessage (msg);
if (attachLeaseSet) // we should maintain this session
{
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 (
@@ -488,7 +507,7 @@ namespace garlic
}
return session;
}
void GarlicDestination::DeliveryStatusSent (GarlicRoutingSession * session, uint32_t msgID)
{
m_CreatedSessions[msgID] = session;

View File

@@ -88,7 +88,7 @@ namespace garlic
GarlicDestination * m_Owner;
const i2p::data::RoutingDestination * m_Destination;
uint8_t m_SessionKey[32];
i2p::crypto::AESKey m_SessionKey;
std::list<SessionTag> m_SessionTags;
int m_NumTags;
std::map<uint32_t, UnconfirmedTags *> m_UnconfirmedTagsMsgs;

View File

@@ -710,7 +710,7 @@ namespace util
if (it.second && it.second->IsEstablished ())
{
// incoming connection doesn't have remote RI
bool outgoing = it.second->GetRemoteRouter ();
auto outgoing = it.second->GetRemoteRouter ();
if (outgoing) s << "-->";
s << it.second->GetRemoteIdentity ().GetIdentHash ().ToBase64 ().substr (0, 4) << ": "
<< it.second->GetSocket ().remote_endpoint().address ().to_string ();
@@ -727,7 +727,7 @@ namespace util
for (auto it: ssuServer->GetSessions ())
{
// incoming connections don't have remote router
bool outgoing = it.second->GetRemoteRouter ();
auto outgoing = it.second->GetRemoteRouter ();
auto endpoint = it.second->GetRemoteEndpoint ();
if (outgoing) s << "-->";
s << endpoint.address ().to_string () << ":" << endpoint.port ();

View File

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

View File

@@ -100,7 +100,7 @@ namespace data
m_ExtendedBuffer = nullptr;
delete m_Verifier;
CreateVerifier ();
m_Verifier = nullptr;
return *this;
}
@@ -115,7 +115,7 @@ namespace data
m_ExtendedLen = 0;
delete m_Verifier;
CreateVerifier ();
m_Verifier = nullptr;
return *this;
}
@@ -139,7 +139,7 @@ namespace data
CryptoPP::SHA256().CalculateDigest(m_IdentHash, buf, GetFullLen ());
delete m_Verifier;
CreateVerifier ();
m_Verifier = nullptr;
return GetFullLen ();
}
@@ -161,19 +161,22 @@ namespace data
size_t IdentityEx::GetSigningPublicKeyLen () const
{
if (m_Verifier)
if (!m_Verifier) CreateVerifier ();
if (m_Verifier)
return m_Verifier->GetPublicKeyLen ();
return 128;
}
size_t IdentityEx::GetSignatureLen () const
{
{
if (!m_Verifier) CreateVerifier ();
if (m_Verifier)
return m_Verifier->GetSignatureLen ();
return 40;
}
bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
if (!m_Verifier) CreateVerifier ();
if (m_Verifier)
return m_Verifier->Verify (buf, len, signature);
return false;
@@ -186,7 +189,7 @@ namespace data
return SIGNING_KEY_TYPE_DSA_SHA1;
}
void IdentityEx::CreateVerifier ()
void IdentityEx::CreateVerifier () const
{
auto keyType = GetSigningKeyType ();
switch (keyType)

View File

@@ -134,13 +134,13 @@ namespace data
private:
void CreateVerifier ();
void CreateVerifier () const;
private:
Identity m_StandardIdentity;
IdentHash m_IdentHash;
i2p::crypto::Verifier * m_Verifier;
mutable i2p::crypto::Verifier * m_Verifier;
size_t m_ExtendedLen;
uint8_t * m_ExtendedBuffer;
};

View File

@@ -11,7 +11,7 @@ endif
all: obj i2p
i2p: $(OBJECTS:obj/%=obj/%)
$(CXX) -o $@ $^ $(LDFLAGS) $(LIBS)
$(CXX) -o $@ $^ $(LDLIBS) $(LDFLAGS) $(LIBS)
.SUFFIXES:
.SUFFIXES: .c .cc .C .cpp .o

View File

@@ -3,5 +3,6 @@ CXXFLAGS = -O2
NEEDED_CXXFLAGS = -std=c++11
include filelist.mk
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 =

View File

@@ -3,7 +3,7 @@ CXXVER := $(shell $(CXX) -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
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7
@@ -16,17 +16,28 @@ else # not supported
$(error Compiler too old)
endif
LIBDIR := /usr/lib
include filelist.mk
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 =
ifeq ($(USE_AESNI),yes)
ifeq ($(IS_64),1)
#check if AES-NI is supported by CPU
ifneq ($(shell grep -c aes /proc/cpuinfo),0)
CPU_FLAGS = -maes -DAESNI
endif
endif
endif

View File

@@ -2,7 +2,8 @@ CXX = clang++
CXXFLAGS = -g -Wall -std=c++11 -lstdc++ -I/usr/local/include
include filelist.mk
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 =
# OSX Notes
@@ -11,6 +12,15 @@ LIBS =
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
CXXFLAGS += -maes -DAESNI
${PREFIX}:
install: all
mkdir -p ${PREFIX}/
cp -r i2p ${PREFIX}/
# Apple Mac OSX
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)

View File

@@ -19,7 +19,7 @@ namespace i2p
{
namespace transport
{
NTCPSession::NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter):
NTCPSession::NTCPSession (boost::asio::io_service& service, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
TransportSession (in_RemoteRouter), m_Socket (service),
m_TerminationTimer (service), m_IsEstablished (false), m_ReceiveBufferOffset (0),
m_NextMessage (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0)
@@ -38,7 +38,7 @@ namespace transport
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);
uint8_t sharedKey[256];
@@ -49,6 +49,7 @@ namespace transport
return;
};
uint8_t * aesKey = key;
if (sharedKey[0] & 0x80)
{
aesKey[0] = 0;
@@ -201,7 +202,7 @@ namespace transport
m_Establisher->phase2.encrypted.timestamp = tsB;
// TODO: fill filler
uint8_t aesKey[32];
i2p::crypto::AESKey aesKey;
CreateAESKey (m_Establisher->phase1.pubKey, aesKey);
m_Encryption.SetKey (aesKey);
m_Encryption.SetIV (y + 240);
@@ -249,7 +250,7 @@ namespace transport
{
LogPrint ("Phase 2 received: ", bytes_transferred);
uint8_t aesKey[32];
i2p::crypto::AESKey aesKey;
CreateAESKey (m_Establisher->phase2.pubKey, aesKey);
m_Decryption.SetKey (aesKey);
m_Decryption.SetIV (m_Establisher->phase2.pubKey + 240);
@@ -427,7 +428,7 @@ namespace transport
if (ecode)
{
LogPrint ("Read error: ", ecode.message ());
if (ecode != boost::asio::error::operation_aborted)
//if (ecode != boost::asio::error::operation_aborted)
Terminate ();
}
else
@@ -589,14 +590,15 @@ namespace transport
if (ecode != boost::asio::error::operation_aborted)
{
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,
int port, const i2p::data::RouterInfo& in_RouterInfo):
NTCPSession (service, &in_RouterInfo), m_Endpoint (address, port)
int port, std::shared_ptr<const i2p::data::RouterInfo> in_RouterInfo):
NTCPSession (service, in_RouterInfo), m_Endpoint (address, port)
{
Connect ();
}

View File

@@ -62,7 +62,7 @@ namespace transport
{
public:
NTCPSession (boost::asio::io_service& service, const i2p::data::RouterInfo * in_RemoteRouter = nullptr);
NTCPSession (boost::asio::io_service& service, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
~NTCPSession ();
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
@@ -84,7 +84,7 @@ namespace transport
private:
void CreateAESKey (uint8_t * pubKey, uint8_t * aesKey);
void CreateAESKey (uint8_t * pubKey, i2p::crypto::AESKey& key);
// client
void SendPhase3 ();
@@ -146,7 +146,7 @@ namespace transport
{
public:
NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, const i2p::data::RouterInfo& in_RouterInfo);
NTCPClient (boost::asio::io_service& service, const boost::asio::ip::address& address, int port, std::shared_ptr<const i2p::data::RouterInfo> in_RouterInfo);
private:

View File

@@ -21,7 +21,7 @@ namespace i2p
{
namespace data
{
I2NPMessage * RequestedDestination::CreateRequestMessage (const RouterInfo * router,
I2NPMessage * RequestedDestination::CreateRequestMessage (std::shared_ptr<const RouterInfo> router,
const i2p::tunnel::InboundTunnel * replyTunnel)
{
I2NPMessage * msg = i2p::CreateDatabaseLookupMsg (m_Destination,
@@ -71,8 +71,6 @@ namespace data
Stop ();
for (auto l:m_LeaseSets)
delete l.second;
for (auto r:m_RouterInfos)
delete r.second;
for (auto r:m_RequestedDestinations)
delete r.second;
}
@@ -169,24 +167,27 @@ namespace data
void NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
{
DeleteRequestedDestination (ident);
auto it = m_RouterInfos.find(ident);
if (it != m_RouterInfos.end ())
DeleteRequestedDestination (ident);
auto r = FindRouter (ident);
if (r)
{
auto ts = it->second->GetTimestamp ();
it->second->Update (buf, len);
if (it->second->GetTimestamp () > ts)
auto ts = r->GetTimestamp ();
r->Update (buf, len);
if (r->GetTimestamp () > ts)
LogPrint ("RouterInfo updated");
}
else
{
LogPrint ("New RouterInfo added");
RouterInfo * r = new RouterInfo (buf, len);
m_RouterInfos[r->GetIdentHash ()] = r;
if (r->IsFloodfill ())
auto newRouter = std::make_shared<RouterInfo> (buf, len);
{
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
m_RouterInfos[newRouter->GetIdentHash ()] = newRouter;
}
if (newRouter->IsFloodfill ())
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.push_back (r);
m_Floodfills.push_back (newRouter);
}
}
}
@@ -211,8 +212,9 @@ namespace data
}
}
RouterInfo * NetDb::FindRouter (const IdentHash& ident) const
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
{
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
auto it = m_RouterInfos.find (ident);
if (it != m_RouterInfos.end ())
return it->second;
@@ -271,8 +273,6 @@ namespace data
if (!CreateNetDb(p)) return;
}
// make sure we cleanup netDb from previous attempts
for (auto r: m_RouterInfos)
delete r.second;
m_RouterInfos.clear ();
m_Floodfills.clear ();
@@ -291,7 +291,7 @@ namespace data
#else
const std::string& fullPath = it1->path();
#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
{
r->DeleteBuffer ();
@@ -304,7 +304,6 @@ namespace data
{
if (boost::filesystem::exists (fullPath))
boost::filesystem::remove (fullPath);
delete r;
}
}
}
@@ -341,7 +340,7 @@ namespace data
{
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->DeleteBuffer ();
count++;
@@ -359,18 +358,36 @@ namespace data
if (it.second->IsUnreachable ())
{
if (boost::filesystem::exists (GetFilePath (fullDirectory, it.second)))
// delete RI file
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++;
}
// delete from floodfills list
if (it.second->IsFloodfill ())
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.remove (it.second);
}
}
}
}
if (count > 0)
LogPrint (count," new/updated routers saved");
if (deletedCount > 0)
{
LogPrint (deletedCount," routers deleted");
// clean up RouterInfos table
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();)
{
if (it->second->IsUnreachable ())
it = m_RouterInfos.erase (it);
else
it++;
}
}
}
void NetDb::RequestDestination (const IdentHash& destination, bool isLeaseSet, i2p::tunnel::TunnelPool * pool)
@@ -616,7 +633,7 @@ namespace data
LogPrint ("Requested RouterInfo ", key, " found");
router->LoadBuffer ();
if (router->GetBuffer ())
replyMsg = CreateDatabaseStoreMsg (router);
replyMsg = CreateDatabaseStoreMsg (router.get ());
}
}
if (!replyMsg)
@@ -638,7 +655,7 @@ namespace data
excludedRouters.insert (excluded);
excluded += 32;
}
replyMsg = CreateDatabaseSearchReply (buf, GetClosestFloodfill (buf, excludedRouters));
replyMsg = CreateDatabaseSearchReply (buf, GetClosestFloodfill (buf, excludedRouters).get ());
}
else
excluded += numExcluded*32; // we don't care about exluded
@@ -702,9 +719,9 @@ namespace data
rnd.GenerateBlock (randomHash, 32);
RequestedDestination * dest = CreateRequestedDestination (IdentHash (randomHash), false, true, exploratoryPool);
auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ());
if (floodfill && !floodfills.count (floodfill)) // request floodfill only once
if (floodfill && !floodfills.count (floodfill.get ())) // request floodfill only once
{
floodfills.insert (floodfill);
floodfills.insert (floodfill.get ());
if (throughTunnels)
{
msgs.push_back (i2p::tunnel::TunnelMessageBlock
@@ -783,29 +800,29 @@ namespace data
}
}
const RouterInfo * NetDb::GetRandomRouter () const
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter () const
{
return GetRandomRouter (
[](const RouterInfo * router)->bool
[](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden ();
});
}
const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith) const
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const
{
return GetRandomRouter (
[compatibleWith](const RouterInfo * router)->bool
[compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router != compatibleWith &&
router->IsCompatible (*compatibleWith);
});
}
const RouterInfo * NetDb::GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const
{
return GetRandomRouter (
[compatibleWith](const RouterInfo * router)->bool
[compatibleWith](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router != compatibleWith &&
router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth);
@@ -813,13 +830,14 @@ namespace data
}
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 ();
uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1);
for (int j = 0; j < 2; j++)
{
uint32_t i = 0;
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
for (auto it: m_RouterInfos)
{
if (i >= ind)
@@ -841,10 +859,10 @@ namespace data
if (msg) m_Queue.Put (msg);
}
const RouterInfo * NetDb::GetClosestFloodfill (const IdentHash& destination,
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
const std::set<IdentHash>& excluded) const
{
RouterInfo * r = nullptr;
std::shared_ptr<const RouterInfo> r;
XORMetric minMetric;
IdentHash destKey = CreateRoutingKey (destination);
minMetric.SetMax ();

27
NetDb.h
View File

@@ -4,7 +4,7 @@
#include <inttypes.h>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <string>
#include <thread>
#include <mutex>
@@ -27,19 +27,19 @@ namespace data
RequestedDestination (const IdentHash& destination, bool isLeaseSet,
bool isExploratory = false, i2p::tunnel::TunnelPool * pool = nullptr):
m_Destination (destination), m_IsLeaseSet (isLeaseSet), m_IsExploratory (isExploratory),
m_Pool (pool), m_LastRouter (nullptr), m_CreationTime (0) {};
m_Pool (pool), m_CreationTime (0) {};
const IdentHash& GetDestination () const { return m_Destination; };
int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); };
const std::set<IdentHash>& GetExcludedPeers () { return m_ExcludedPeers; };
void ClearExcludedPeers ();
const RouterInfo * GetLastRouter () const { return m_LastRouter; };
std::shared_ptr<const RouterInfo> GetLastRouter () const { return m_LastRouter; };
i2p::tunnel::TunnelPool * GetTunnelPool () { return m_Pool; };
bool IsExploratory () const { return m_IsExploratory; };
bool IsLeaseSet () const { return m_IsLeaseSet; };
bool IsExcluded (const IdentHash& ident) const { return m_ExcludedPeers.count (ident); };
uint64_t GetCreationTime () const { return m_CreationTime; };
I2NPMessage * CreateRequestMessage (const RouterInfo * router, const i2p::tunnel::InboundTunnel * replyTunnel);
I2NPMessage * CreateRequestMessage (std::shared_ptr<const RouterInfo>, const i2p::tunnel::InboundTunnel * replyTunnel);
I2NPMessage * CreateRequestMessage (const IdentHash& floodfill);
private:
@@ -48,7 +48,7 @@ namespace data
bool m_IsLeaseSet, m_IsExploratory;
i2p::tunnel::TunnelPool * m_Pool;
std::set<IdentHash> m_ExcludedPeers;
const RouterInfo * m_LastRouter;
std::shared_ptr<const RouterInfo> m_LastRouter;
uint64_t m_CreationTime;
};
@@ -64,7 +64,7 @@ namespace data
void AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, i2p::tunnel::InboundTunnel * from);
RouterInfo * FindRouter (const IdentHash& ident) const;
std::shared_ptr<RouterInfo> FindRouter (const IdentHash& ident) const;
LeaseSet * FindLeaseSet (const IdentHash& destination) const;
void PublishLeaseSet (const LeaseSet * leaseSet, i2p::tunnel::TunnelPool * pool);
@@ -75,9 +75,9 @@ namespace data
void HandleDatabaseSearchReplyMsg (I2NPMessage * msg);
void HandleDatabaseLookupMsg (I2NPMessage * msg);
const RouterInfo * GetRandomRouter () const;
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith) const;
const RouterInfo * GetHighBandwidthRandomRouter (const RouterInfo * compatibleWith) const;
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
void SetUnreachable (const IdentHash& ident, bool unreachable);
void PostI2NPMsg (I2NPMessage * msg);
@@ -95,7 +95,7 @@ namespace data
void Run (); // exploratory thread
void Explore (int numDestinations);
void Publish ();
const RouterInfo * GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
void ManageLeaseSets ();
RequestedDestination * CreateRequestedDestination (const IdentHash& dest,
@@ -104,14 +104,15 @@ namespace data
void DeleteRequestedDestination (RequestedDestination * dest);
template<typename Filter>
const RouterInfo * GetRandomRouter (Filter filter) const;
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
private:
std::map<IdentHash, LeaseSet *> m_LeaseSets;
std::map<IdentHash, RouterInfo *> m_RouterInfos;
mutable std::mutex m_RouterInfosMutex;
std::map<IdentHash, std::shared_ptr<RouterInfo> > m_RouterInfos;
mutable std::mutex m_FloodfillsMutex;
std::vector<RouterInfo *> m_Floodfills;
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
std::mutex m_RequestedDestinationsMutex;
std::map<IdentHash, RequestedDestination *> m_RequestedDestinations;

View File

@@ -1,21 +1,28 @@
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
---------------
- 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
- Mac OS X - Too be added
- Microsoft VC13 - Too be added
- Linux ARM - To be added
- Mac OS X - To be added
- Microsoft VC13 - To be added
Testing
@@ -51,14 +58,14 @@ Options
* --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).
* --unreachable= - 1 if router is declared as unreachable and works through introducers.
* --v6= - 1 if supports communication through ipv6, off by default
* --v6= - 1 if supports communication through ipv6, off by default
* --httpproxyport= - The port to listen on (HTTP Proxy)
* --socksproxyport= - The port to listen on (SOCKS Proxy)
* --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
* --irckeys= - optional keys file for local destination
* --eepkeys= - File name containing destination keys. For example privKeys.dat
* --eephost= - Address incoming trafic forward to. 127.0.0.1 by default
* --eepport= - Port incoming trafic forward to. 80 by default
* --samport= - Port of SAM bridge. Usually 7656. SAM is off if not specified
* --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
* --irckeys= - optional keys file for local destination
* --eepkeys= - File name containing destination keys. For example privKeys.dat
* --eephost= - Address incoming trafic forward to. 127.0.0.1 by default
* --eepport= - Port incoming trafic forward to. 80 by default
* --samport= - Port of SAM bridge. Usually 7656. SAM is off if not specified

View File

@@ -2,6 +2,8 @@
#include <fstream>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>
#include <cryptopp/gzip.h>
#include "I2PEndian.h"
#include "Reseed.h"
#include "Log.h"
#include "util.h"
@@ -119,6 +121,59 @@ namespace data
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();
};
void ProcessSU3File (const char * filename);
}
}
#endif
#endif

View File

@@ -34,7 +34,7 @@ namespace i2p
void RouterContext::NewRouterInfo ()
{
i2p::data::RouterInfo routerInfo;
routerInfo.SetRouterIdentity (GetIdentity ().GetStandardIdentity ());
routerInfo.SetRouterIdentity (GetIdentity ());
int port = i2p::util::config::GetArg("-port", 0);
if (!port)
port = m_Rnd.GenerateWord32 (9111, 30777); // I2P network ports range
@@ -162,7 +162,13 @@ namespace i2p
{
// create new address
m_RouterInfo.AddNTCPAddress (host.to_string ().c_str (), port);
m_RouterInfo.AddSSUAddress (host.to_string ().c_str (), port, GetIdentHash (), 1472); // TODO
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)

View File

@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <string>
#include <memory>
#include <boost/asio.hpp>
#include <cryptopp/dsa.h>
#include <cryptopp/osrng.h>
@@ -24,6 +25,11 @@ namespace i2p
void Init ();
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
std::shared_ptr<const i2p::data::RouterInfo> GetSharedRouterInfo () const
{
return std::shared_ptr<const i2p::data::RouterInfo> (&m_RouterInfo,
[](const i2p::data::RouterInfo *) {});
}
CryptoPP::RandomNumberGenerator& GetRandomNumberGenerator () { return m_Rnd; };
void UpdatePort (int port); // called from Daemon

View File

@@ -55,10 +55,9 @@ namespace data
// don't delete buffer until save to file
}
void RouterInfo::SetRouterIdentity (const Identity& identity)
void RouterInfo::SetRouterIdentity (const IdentityEx& identity)
{
m_RouterIdentity = identity;
m_IdentHash = m_RouterIdentity.Hash ();
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
}
@@ -95,31 +94,20 @@ namespace data
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);
if (verifySignature)
{
// verify signature
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))
{
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)
{
s.read ((char *)&m_RouterIdentity, DEFAULT_IDENTITY_SIZE);
if (m_RouterIdentity.certificate.type != CERTIFICATE_TYPE_NULL)
{
LogPrint (eLogError, "Certificate type ", m_RouterIdentity.certificate.type, " is not supported");
SetUnreachable (true);
return;
}
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp));
m_Timestamp = be64toh (m_Timestamp);
// read addresses
@@ -232,8 +220,6 @@ namespace data
if (!strcmp (key, "caps"))
ExtractCaps (value);
}
CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity));
if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers))
SetUnreachable (true);

View File

@@ -90,10 +90,10 @@ namespace data
RouterInfo (const uint8_t * buf, int len);
~RouterInfo ();
const Identity& GetRouterIdentity () const { return m_RouterIdentity; };
void SetRouterIdentity (const Identity& identity);
std::string GetIdentHashBase64 () const { return m_IdentHash.ToBase64 (); };
std::string GetIdentHashAbbreviation () const { return m_IdentHash.ToBase64 ().substr (0, 4); };
const IdentityEx& GetRouterIdentity () const { return m_RouterIdentity; };
void SetRouterIdentity (const IdentityEx& identity);
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
std::string GetIdentHashAbbreviation () const { return GetIdentHash ().ToBase64 ().substr (0, 4); };
uint64_t GetTimestamp () const { return m_Timestamp; };
std::vector<Address>& GetAddresses () { return m_Addresses; };
const Address * GetNTCPAddress (bool v4only = true) const;
@@ -138,8 +138,8 @@ namespace data
void DeleteBuffer () { delete m_Buffer; m_Buffer = nullptr; };
// implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_IdentHash; };
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.publicKey; };
const IdentHash& GetIdentHash () const { return m_RouterIdentity.GetIdentHash (); };
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity.GetStandardIdentity ().publicKey; };
bool IsDestination () const { return false; };
@@ -159,8 +159,7 @@ namespace data
private:
std::string m_FullPath;
Identity m_RouterIdentity;
IdentHash m_IdentHash;
IdentityEx m_RouterIdentity;
uint8_t * m_Buffer;
int m_BufferLen;
uint64_t m_Timestamp;

101
SAM.cpp
View File

@@ -26,21 +26,18 @@ namespace client
SAMSocket::~SAMSocket ()
{
if (m_Stream)
{
m_Stream->Close ();
i2p::stream::DeleteStream (m_Stream);
m_Stream = nullptr;
}
}
void SAMSocket::Terminate ()
{
if (m_Stream)
{
m_Stream->Close ();
i2p::stream::DeleteStream (m_Stream);
m_Stream = nullptr;
}
// TODO: make this swap atomic
auto session = m_Session;
m_Session = nullptr;
switch (m_SocketType)
{
case eSAMSocketTypeSession:
@@ -48,16 +45,16 @@ namespace client
break;
case eSAMSocketTypeStream:
{
if (m_Session)
m_Session->sockets.remove (this);
if (session)
session->sockets.remove (shared_from_this ());
break;
}
case eSAMSocketTypeAcceptor:
{
if (m_Session)
if (session)
{
m_Session->sockets.remove (this);
m_Session->localDestination->StopAcceptingStreams ();
session->sockets.remove (shared_from_this ());
session->localDestination->StopAcceptingStreams ();
}
break;
}
@@ -65,13 +62,12 @@ namespace client
;
}
m_Socket.close ();
// delete this;
}
void SAMSocket::ReceiveHandshake ()
{
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
boost::bind(&SAMSocket::HandleHandshakeReceived, this,
boost::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
@@ -91,7 +87,7 @@ namespace client
{
// TODO: check version
boost::asio::async_write (m_Socket, boost::asio::buffer (SAM_HANDSHAKE_REPLY, strlen (SAM_HANDSHAKE_REPLY)), boost::asio::transfer_all (),
boost::bind(&SAMSocket::HandleHandshakeReplySent, this,
boost::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else
@@ -113,7 +109,7 @@ namespace client
else
{
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
boost::bind(&SAMSocket::HandleMessage, this,
boost::bind(&SAMSocket::HandleMessage, shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
}
@@ -122,7 +118,7 @@ namespace client
{
if (!m_IsSilent || m_SocketType == eSAMSocketTypeAcceptor)
boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (),
boost::bind(&SAMSocket::HandleMessageReplySent, this,
boost::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, close));
else
{
@@ -226,14 +222,18 @@ namespace client
if (m_Session->localDestination->IsReady ())
{
if (style == SAM_VALUE_DATAGRAM)
m_Session->localDestination->CreateDatagramDestination ();
{
auto dest = m_Session->localDestination->CreateDatagramDestination ();
dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
SendSessionCreateReplyOk ();
}
else
{
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
m_Timer.async_wait (boost::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
this, boost::asio::placeholders::error));
shared_from_this (), boost::asio::placeholders::error));
}
}
else
@@ -250,7 +250,7 @@ namespace client
{
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL));
m_Timer.async_wait (boost::bind (&SAMSocket::HandleSessionReadinessCheckTimer,
this, boost::asio::placeholders::error));
shared_from_this (), boost::asio::placeholders::error));
}
}
}
@@ -295,7 +295,7 @@ namespace client
i2p::data::netdb.RequestDestination (dest.GetIdentHash (), true, m_Session->localDestination->GetTunnelPool ());
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_CONNECT_TIMEOUT));
m_Timer.async_wait (boost::bind (&SAMSocket::HandleStreamDestinationRequestTimer,
this, boost::asio::placeholders::error, dest.GetIdentHash ()));
shared_from_this (), boost::asio::placeholders::error, dest.GetIdentHash ()));
}
}
else
@@ -305,7 +305,7 @@ namespace client
void SAMSocket::Connect (const i2p::data::LeaseSet& remote)
{
m_SocketType = eSAMSocketTypeStream;
m_Session->sockets.push_back (this);
m_Session->sockets.push_back (shared_from_this ());
m_Stream = m_Session->localDestination->CreateStream (remote);
m_Stream->Send ((uint8_t *)m_Buffer, 0); // connect
I2PReceive ();
@@ -362,8 +362,8 @@ namespace client
if (!m_Session->localDestination->IsAcceptingStreams ())
{
m_SocketType = eSAMSocketTypeAcceptor;
m_Session->sockets.push_back (this);
m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, this, std::placeholders::_1));
m_Session->sockets.push_back (shared_from_this ());
m_Session->localDestination->AcceptStreams (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1));
SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false);
}
else
@@ -418,7 +418,7 @@ namespace client
i2p::data::netdb.RequestDestination (ident, true, m_Session->localDestination->GetTunnelPool ());
m_Timer.expires_from_now (boost::posix_time::seconds(SAM_NAMING_LOOKUP_TIMEOUT));
m_Timer.async_wait (boost::bind (&SAMSocket::HandleNamingLookupDestinationRequestTimer,
this, boost::asio::placeholders::error, ident));
shared_from_this (), boost::asio::placeholders::error, ident));
}
}
else
@@ -471,7 +471,7 @@ namespace client
{
m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE),
boost::bind((m_SocketType == eSAMSocketTypeSession) ? &SAMSocket::HandleMessage : &SAMSocket::HandleReceived,
this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
shared_from_this (), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void SAMSocket::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
@@ -494,7 +494,7 @@ namespace client
{
if (m_Stream)
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE),
boost::bind (&SAMSocket::HandleI2PReceive, this,
boost::bind (&SAMSocket::HandleI2PReceive, shared_from_this (),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred),
SAM_SOCKET_CONNECTION_MAX_IDLE);
}
@@ -510,7 +510,7 @@ namespace client
else
{
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
boost::bind (&SAMSocket::HandleWriteI2PData, this, boost::asio::placeholders::error));
boost::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), boost::asio::placeholders::error));
}
}
@@ -548,18 +548,37 @@ 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, shared_from_this (), boost::asio::placeholders::error));
}
else
LogPrint (eLogWarning, "Datagram size ", len," exceeds buffer");
}
SAMBridge::SAMBridge (int port):
m_IsRunning (false), m_Thread (nullptr),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint),
m_NewSocket (nullptr)
m_DatagramEndpoint (boost::asio::ip::udp::v4 (), port-1), m_DatagramSocket (m_Service, m_DatagramEndpoint)
{
}
SAMBridge::~SAMBridge ()
{
Stop ();
delete m_NewSocket;
}
void SAMBridge::Start ()
@@ -599,24 +618,20 @@ namespace client
void SAMBridge::Accept ()
{
m_NewSocket = new SAMSocket (*this);
m_Acceptor.async_accept (m_NewSocket->GetSocket (), boost::bind (&SAMBridge::HandleAccept, this,
boost::asio::placeholders::error));
auto newSocket = std::make_shared<SAMSocket> (*this);
m_Acceptor.async_accept (newSocket->GetSocket (), boost::bind (&SAMBridge::HandleAccept, this,
boost::asio::placeholders::error, newSocket));
}
void SAMBridge::HandleAccept(const boost::system::error_code& ecode)
void SAMBridge::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<SAMSocket> socket)
{
if (!ecode)
{
LogPrint ("New SAM connection from ", m_NewSocket->GetSocket ().remote_endpoint ());
m_NewSocket->ReceiveHandshake ();
LogPrint ("New SAM connection from ", socket->GetSocket ().remote_endpoint ());
socket->ReceiveHandshake ();
}
else
{
LogPrint ("SAM accept error: ", ecode.message ());
delete m_NewSocket;
m_NewSocket = nullptr;
}
if (ecode != boost::asio::error::operation_aborted)
Accept ();
@@ -655,8 +670,6 @@ namespace client
auto it = m_Sessions.find (id);
if (it != m_Sessions.end ())
{
for (auto it1 : it->second.sockets)
delete it1;
it->second.sockets.clear ();
it->second.localDestination->Stop ();
m_Sessions.erase (it);

10
SAM.h
View File

@@ -7,6 +7,7 @@
#include <list>
#include <thread>
#include <mutex>
#include <memory>
#include <boost/asio.hpp>
#include "Identity.h"
#include "LeaseSet.h"
@@ -39,6 +40,7 @@ namespace client
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM_RECEIVED DESTINATION=%s SIZE=%lu\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_PARAM_STYLE[] = "STYLE";
@@ -63,7 +65,7 @@ namespace client
class SAMBridge;
class SAMSession;
class SAMSocket
class SAMSocket: public std::enable_shared_from_this<SAMSocket>
{
public:
@@ -88,6 +90,7 @@ namespace client
void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleI2PAccept (i2p::stream::Stream * stream);
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 ProcessStreamConnect (char * buf, size_t len);
@@ -120,7 +123,7 @@ namespace client
struct SAMSession
{
ClientDestination * localDestination;
std::list<SAMSocket *> sockets;
std::list<std::shared_ptr<SAMSocket> > sockets;
};
class SAMBridge
@@ -143,7 +146,7 @@ namespace client
void Run ();
void Accept ();
void HandleAccept(const boost::system::error_code& ecode);
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<SAMSocket> socket);
void ReceiveDatagram ();
void HandleReceivedDatagram (const boost::system::error_code& ecode, std::size_t bytes_transferred);
@@ -156,7 +159,6 @@ namespace client
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;
std::mutex m_SessionsMutex;
std::map<std::string, SAMSession> m_Sessions;
uint8_t m_DatagramReceiveBuffer[i2p::datagram::MAX_DATAGRAM_SIZE+1];

1007
SSU.cpp

File diff suppressed because it is too large Load Diff

132
SSU.h
View File

@@ -13,137 +13,16 @@
#include "Identity.h"
#include "RouterInfo.h"
#include "I2NPProtocol.h"
#include "TransportSession.h"
#include "SSUData.h"
#include "SSUSession.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
const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds
const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
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 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;
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
{
public:
@@ -152,9 +31,9 @@ namespace transport
~SSUServer ();
void Start ();
void Stop ();
SSUSession * GetSession (const i2p::data::RouterInfo * router, bool peerTest = false);
SSUSession * FindSession (const i2p::data::RouterInfo * router);
SSUSession * FindSession (const boost::asio::ip::udp::endpoint& e);
SSUSession * GetSession (std::shared_ptr<const i2p::data::RouterInfo> router, bool peerTest = false);
SSUSession * FindSession (const i2p::data::RouterInfo * router) const;
SSUSession * FindSession (const boost::asio::ip::udp::endpoint& e) const;
SSUSession * GetRandomEstablishedSession (const SSUSession * excluded);
void DeleteSession (SSUSession * session);
void DeleteAllSessions ();
@@ -192,7 +71,8 @@ namespace transport
boost::asio::ip::udp::endpoint m_SenderEndpoint, m_SenderEndpointV6;
boost::asio::deadline_timer m_IntroducersUpdateTimer;
std::list<boost::asio::ip::udp::endpoint> m_Introducers; // introducers we are connected to
uint8_t m_ReceiveBuffer[2*SSU_MTU_V4], m_ReceiveBufferV6[2*SSU_MTU_V6];
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<uint32_t, boost::asio::ip::udp::endpoint> m_Relays; // we are introducer

View File

@@ -148,6 +148,11 @@ namespace transport
bool isLast = fragmentInfo & 0x010000; // bit 16
uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17
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
I2NPMessage * msg = nullptr;

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,
std::shared_ptr<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

@@ -153,6 +153,8 @@ namespace stream
{
public:
typedef std::function<void (Stream *)> Acceptor;
StreamingDestination (i2p::client::ClientDestination& owner): m_Owner (owner) {};
~StreamingDestination () {};
@@ -161,7 +163,7 @@ namespace stream
Stream * CreateNewOutgoingStream (const i2p::data::LeaseSet& remote, int port = 0);
void DeleteStream (Stream * stream);
void SetAcceptor (const std::function<void (Stream *)>& acceptor) { m_Acceptor = acceptor; };
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; };
@@ -178,7 +180,7 @@ namespace stream
i2p::client::ClientDestination& m_Owner;
std::mutex m_StreamsMutex;
std::map<uint32_t, Stream *> m_Streams;
std::function<void (Stream *)> m_Acceptor;
Acceptor m_Acceptor;
public:

View File

@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <iostream>
#include <memory>
#include "Identity.h"
#include "RouterInfo.h"
@@ -51,7 +52,7 @@ namespace transport
{
public:
TransportSession (const i2p::data::RouterInfo * in_RemoteRouter):
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
m_RemoteRouter (in_RemoteRouter), m_DHKeysPair (nullptr)
{
if (m_RemoteRouter)
@@ -60,12 +61,12 @@ namespace transport
virtual ~TransportSession () { delete m_DHKeysPair; };
const i2p::data::RouterInfo * GetRemoteRouter () { return m_RemoteRouter; };
std::shared_ptr<const i2p::data::RouterInfo> GetRemoteRouter () { return m_RemoteRouter; };
const i2p::data::IdentityEx& GetRemoteIdentity () { return m_RemoteIdentity; };
protected:
const i2p::data::RouterInfo * m_RemoteRouter;
std::shared_ptr<const i2p::data::RouterInfo> m_RemoteRouter;
i2p::data::IdentityEx m_RemoteIdentity;
DHKeysPair * m_DHKeysPair; // X - for client and Y - for server
};

View File

@@ -277,10 +277,10 @@ namespace transport
session->SendI2NPMessage (msg);
else
{
RouterInfo * r = netdb.FindRouter (ident);
auto r = netdb.FindRouter (ident);
if (r)
{
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (r) : nullptr;
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (r.get ()) : nullptr;
if (ssuSession)
ssuSession->SendI2NPMessage (msg);
else
@@ -290,7 +290,7 @@ namespace transport
auto address = r->GetNTCPAddress (!context.SupportsV6 ());
if (address && !r->UsesIntroducer () && !r->IsUnreachable () && msg->GetLength () < NTCP_MAX_MESSAGE_SIZE)
{
auto s = new NTCPClient (m_Service, address->host, address->port, *r);
auto s = new NTCPClient (m_Service, address->host, address->port, r);
AddNTCPSession (s);
s->SendI2NPMessage (msg);
}
@@ -323,7 +323,7 @@ namespace transport
void Transports::HandleResendTimer (const boost::system::error_code& ecode,
boost::asio::deadline_timer * timer, const i2p::data::IdentHash& ident, i2p::I2NPMessage * msg)
{
RouterInfo * r = netdb.FindRouter (ident);
auto r = netdb.FindRouter (ident);
if (r)
{
LogPrint ("Router found. Sending message");

View File

@@ -466,7 +466,7 @@ namespace tunnel
if (!inboundTunnel) return;
LogPrint ("Creating one hop outbound tunnel...");
CreateTunnel<OutboundTunnel> (
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
new TunnelConfig (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >
{
i2p::data::netdb.GetRandomRouter ()
},
@@ -519,7 +519,7 @@ namespace tunnel
// trying to create one more inbound tunnel
LogPrint ("Creating one hop inbound tunnel...");
CreateTunnel<InboundTunnel> (
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
new TunnelConfig (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >
{
i2p::data::netdb.GetRandomRouter ()
}));
@@ -609,9 +609,9 @@ namespace tunnel
void Tunnels::CreateZeroHopsInboundTunnel ()
{
CreateTunnel<InboundTunnel> (
new TunnelConfig (std::vector<const i2p::data::RouterInfo *>
new TunnelConfig (std::vector<std::shared_ptr<const i2p::data::RouterInfo> >
{
&i2p::context.GetRouterInfo ()
i2p::context.GetSharedRouterInfo ()
}));
}
}

View File

@@ -79,7 +79,7 @@ namespace tunnel
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg);
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
const i2p::data::RouterInfo * GetEndpointRouter () const
std::shared_ptr<const i2p::data::RouterInfo> GetEndpointRouter () const
{ return GetTunnelConfig ()->GetLastHop ()->router; };
size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };

View File

@@ -4,6 +4,7 @@
#include <inttypes.h>
#include <sstream>
#include <vector>
#include <memory>
#include "aes.h"
#include "RouterInfo.h"
#include "RouterContext.h"
@@ -14,7 +15,7 @@ namespace tunnel
{
struct TunnelHopConfig
{
const i2p::data::RouterInfo * router, * nextRouter;
std::shared_ptr<const i2p::data::RouterInfo> router, nextRouter;
uint32_t tunnelID, nextTunnelID;
uint8_t layerKey[32];
uint8_t ivKey[32];
@@ -26,7 +27,7 @@ namespace tunnel
i2p::crypto::TunnelDecryption decryption;
int recordIndex; // record # in tunnel build message
TunnelHopConfig (const i2p::data::RouterInfo * r)
TunnelHopConfig (std::shared_ptr<const i2p::data::RouterInfo> r)
{
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
rnd.GenerateBlock (layerKey, 32);
@@ -36,14 +37,14 @@ namespace tunnel
isGateway = true;
isEndpoint = true;
router = r;
nextRouter = 0;
//nextRouter = nullptr;
nextTunnelID = 0;
next = 0;
prev = 0;
next = nullptr;
prev = nullptr;
}
void SetNextRouter (const i2p::data::RouterInfo * r)
void SetNextRouter (std::shared_ptr<const i2p::data::RouterInfo> r)
{
nextRouter = r;
isEndpoint = false;
@@ -88,7 +89,7 @@ namespace tunnel
public:
TunnelConfig (std::vector<const i2p::data::RouterInfo *> peers,
TunnelConfig (std::vector<std::shared_ptr<const i2p::data::RouterInfo> > peers,
const TunnelConfig * replyTunnelConfig = nullptr) // replyTunnelConfig=nullptr means inbound
{
TunnelHopConfig * prev = nullptr;
@@ -109,7 +110,7 @@ namespace tunnel
m_LastHop->SetReplyHop (replyTunnelConfig->GetFirstHop ());
}
else // inbound
m_LastHop->SetNextRouter (&i2p::context.GetRouterInfo ());
m_LastHop->SetNextRouter (i2p::context.GetSharedRouterInfo ());
}
~TunnelConfig ()
@@ -184,7 +185,7 @@ namespace tunnel
if (hop->isGateway) // inbound tunnel
newHop->SetReplyHop (m_FirstHop); // use it as reply tunnel
else
newHop->SetNextRouter (&i2p::context.GetRouterInfo ());
newHop->SetNextRouter (i2p::context.GetSharedRouterInfo ());
}
if (!hop->next) newConfig->m_FirstHop = newHop; // last hop
@@ -195,7 +196,7 @@ namespace tunnel
TunnelConfig * Clone (const TunnelConfig * replyTunnelConfig = nullptr) const
{
std::vector<const i2p::data::RouterInfo *> peers;
std::vector<std::shared_ptr<const i2p::data::RouterInfo> > peers;
TunnelHopConfig * hop = m_FirstHop;
while (hop)
{

View File

@@ -235,7 +235,7 @@ namespace tunnel
m_LocalDestination.ProcessDeliveryStatusMessage (msg);
}
const i2p::data::RouterInfo * TunnelPool::SelectNextHop (const i2p::data::RouterInfo * prevHop) const
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const
{
auto hop = m_NumHops >= 3 ? i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop) :
i2p::data::netdb.GetRandomRouter (prevHop);
@@ -250,8 +250,8 @@ namespace tunnel
if (!outboundTunnel)
outboundTunnel = tunnels.GetNextOutboundTunnel ();
LogPrint ("Creating destination inbound tunnel...");
const i2p::data::RouterInfo * prevHop = &i2p::context.GetRouterInfo ();
std::vector<const i2p::data::RouterInfo *> hops;
auto prevHop = i2p::context.GetSharedRouterInfo ();
std::vector<std::shared_ptr<const i2p::data::RouterInfo> > hops;
int numHops = m_NumHops;
if (outboundTunnel)
{
@@ -294,8 +294,8 @@ namespace tunnel
{
LogPrint ("Creating destination outbound tunnel...");
const i2p::data::RouterInfo * prevHop = &i2p::context.GetRouterInfo ();
std::vector<const i2p::data::RouterInfo *> hops;
auto prevHop = i2p::context.GetSharedRouterInfo ();
std::vector<std::shared_ptr<const i2p::data::RouterInfo> > hops;
for (int i = 0; i < m_NumHops; i++)
{
auto hop = SelectNextHop (prevHop);

View File

@@ -61,7 +61,7 @@ namespace tunnel
template<class TTunnels>
typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels,
typename TTunnels::value_type suggested = nullptr) const;
const i2p::data::RouterInfo * SelectNextHop (const i2p::data::RouterInfo * prevHop) const;
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
private:

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.1
Name PurpleI2P
RequestExecutionLevel highest
SetCompressor /SOLID lzma
ShowInstDetails show
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION 0.3.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.3.0.0-win32-setup.exe
InstallDir $PROGRAMFILES\PurpleI2P
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
VIProductVersion 0.3.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
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "i2pd", "i2pd.vcxproj", "{930568EC-31C9-406A-AD1C-9636DF5D8FAA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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.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.Build.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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal

View File

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

View File

@@ -123,6 +123,18 @@
<ClCompile Include="..\SAM.cpp">
<Filter>Source Files</Filter>
</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>
<ClInclude Include="..\Identity.h">
@@ -245,5 +257,28 @@
<ClInclude Include="..\SAM.h">
<Filter>Source Files</Filter>
</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>
</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_ver "0.1"
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "0.2"
[Setup]
AppName={#I2Pd_AppName}
AppVersion={#I2Pd_ver}
AppName={#I2Pd_AppName}
AppVersion={#I2Pd_ver}
DefaultDirName={pf}\I2Pd
DefaultGroupName=I2Pd
UninstallDisplayIcon={app}\I2Pd.exe
@@ -13,27 +13,50 @@ SolidCompression=yes
OutputDir=.
LicenseFile=.\..\LICENSE
OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver}
ArchitecturesInstallIn64BitMode=x64
[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]
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]
var
DefaultTop,
DefaultLeft,
DefaultTop,
DefaultLeft,
DefaultHeight,
DefaultBackTop,
DefaultNextTop,
DefaultBackTop,
DefaultNextTop,
DefaultCancelTop,
DefaultBevelTop,
DefaultBevelTop,
DefaultOuterHeight: Integer;
const
const
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();
begin
@@ -67,7 +90,7 @@ begin
WizardForm.BackButton.Top := DefaultBackTop + (LicenseHeight - DefaultHeight);
WizardForm.Bevel.Top := DefaultBevelTop + (LicenseHeight - DefaultHeight);
end
else
else
begin
WizardForm.Top := DefaultTop;
WizardForm.Left := DefaultLeft;
@@ -78,4 +101,49 @@ begin
WizardForm.BackButton.Top := DefaultBackTop;
WizardForm.Bevel.Top := DefaultBevelTop;
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
ECBCryptoAESNI::ECBCryptoAESNI ()
{
m_KeySchedule = m_UnalignedBuffer;
uint8_t rem = ((uint64_t)m_KeySchedule) & 0x0f;
if (rem)
m_KeySchedule += (16 - rem);
}
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
@@ -40,7 +32,7 @@ namespace crypto
"pxor %%xmm2, %%xmm3 \n" \
"movaps %%xmm3, "#round1"(%[sched]) \n"
void ECBCryptoAESNI::ExpandKey (const uint8_t * key)
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{
__asm__
(
@@ -73,7 +65,7 @@ namespace crypto
"pxor %%xmm2, %%xmm1 \n"
"movups %%xmm1, 224(%[sched]) \n"
: // output
: [key]"r"(key), [sched]"r"(m_KeySchedule) // input
: [key]"r"((const uint8_t *)key), [sched]"r"(GetKeySchedule ()) // input
: "%xmm1", "%xmm2", "%xmm3", "%xmm4" // clogged
);
}
@@ -102,7 +94,7 @@ namespace crypto
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"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"
DecryptAES256(sched)
"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" \
"movaps %%xmm0, "#offset"(%[shed]) \n"
void ECBDecryptionAESNI::SetKey (const uint8_t * key)
void ECBDecryptionAESNI::SetKey (const AESKey& key)
{
ExpandKey (key); // expand encryption key first
// then invert it using aesimc
@@ -158,7 +150,7 @@ namespace crypto
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
: : [shed]"r"(m_KeySchedule) : "%xmm0"
: : [shed]"r"(GetKeySchedule ()) : "%xmm0"
);
}

73
aes.h
View File

@@ -4,46 +4,83 @@
#include <inttypes.h>
#include <cryptopp/modes.h>
#include <cryptopp/aes.h>
#include "Identity.h"
namespace i2p
{
namespace crypto
{
union ChipherBlock
struct ChipherBlock
{
uint8_t buf[16];
uint64_t ll[2];
void operator^=(const ChipherBlock& other) // XOR
{
ll[0] ^= other.ll[0];
ll[1] ^= other.ll[1];
#if defined(__x86_64__) // for Intel x64
__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
class ECBCryptoAESNI
{
public:
ECBCryptoAESNI ();
uint8_t * GetKeySchedule () { return m_KeySchedule; };
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
uint8_t m_UnalignedBuffer[256]; // 14 rounds for AES-256, 240 + 16 bytes
AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes
};
class ECBEncryptionAESNI: public ECBCryptoAESNI
{
public:
void SetKey (const uint8_t * key) { ExpandKey (key); };
void SetKey (const AESKey& key) { ExpandKey (key); };
void Encrypt (const ChipherBlock * in, ChipherBlock * out);
};
@@ -51,7 +88,7 @@ namespace crypto
{
public:
void SetKey (const uint8_t * key);
void SetKey (const AESKey& key);
void Decrypt (const ChipherBlock * in, ChipherBlock * out);
};
@@ -64,7 +101,7 @@ namespace crypto
{
public:
void SetKey (const uint8_t * key)
void SetKey (const AESKey& key)
{
m_Encryption.SetKey (key, 32);
}
@@ -82,7 +119,7 @@ namespace crypto
{
public:
void SetKey (const uint8_t * key)
void SetKey (const AESKey& key)
{
m_Decryption.SetKey (key, 32);
}
@@ -105,7 +142,7 @@ namespace crypto
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 Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
@@ -125,7 +162,7 @@ namespace crypto
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 Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out);
@@ -142,7 +179,7 @@ namespace crypto
{
public:
void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey)
void SetKeys (const AESKey& layerKey, const AESKey& ivKey)
{
m_LayerEncryption.SetKey (layerKey);
m_IVEncryption.SetKey (ivKey);
@@ -164,7 +201,7 @@ namespace crypto
{
public:
void SetKeys (const uint8_t * layerKey, const uint8_t * ivKey)
void SetKeys (const AESKey& layerKey, const AESKey& ivKey)
{
m_LayerDecryption.SetKey (layerKey);
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

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

View File

@@ -3,17 +3,17 @@
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 HTTPServer.cpp Streaming.cpp \
Destination.cpp Identity.cpp SSU.cpp util.cpp Reseed.cpp DaemonLinux.cpp SSUData.cpp \
aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.cpp AddressBook.cpp Daemon.cpp \
I2PTunnel.cpp SAM.cpp ClientContext.cpp Datagram.cpp i2p.cpp
Destination.cpp Identity.cpp SSU.cpp SSUSession.cpp SSUData.cpp util.cpp Reseed.cpp \
DaemonLinux.cpp SSUData.cpp aes.cpp SOCKS.cpp UPnP.cpp TunnelPool.cpp HTTPProxy.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 \
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 \
Identity.h SSU.h util.h Reseed.h DaemonLinux.h SSUData.h i2p.h aes.h SOCKS.h \
UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h version.h \
Signature.h SAM.h ClientContext.h TransportSession.h Datagram.h
Identity.h SSU.h SSUSession.h SSUData.h util.h Reseed.h DaemonLinux.h SSUData.h \
aes.h SOCKS.h UPnP.h TunnelPool.h HTTPProxy.h AddressBook.h Daemon.h I2PTunnel.h \
version.h Signature.h SAM.h ClientContext.h TransportSession.h Datagram.h
OBJECTS = $(addprefix obj/, $(notdir $(CPP_FILES:.cpp=.o)))

21
hmac.h
View File

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

View File

@@ -15,6 +15,11 @@
#include "util.h"
#include "Log.h"
#if defined(__linux__) || defined(__FreeBSD_kernel__)
#include <sys/types.h>
#include <ifaddrs.h>
#endif
#ifdef WIN32
#include <Windows.h>
#include <shlobj.h>
@@ -96,6 +101,18 @@ namespace config
namespace filesystem
{
std::string appName ("i2pd");
void SetAppName (const std::string& name)
{
appName = name;
}
std::string GetAppName ()
{
return appName;
}
const boost::filesystem::path &GetDataDir()
{
static boost::filesystem::path path;
@@ -173,10 +190,10 @@ namespace filesystem
// Windows
char localAppData[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_APPDATA, 0, NULL, localAppData);
return boost::filesystem::path(std::string(localAppData) + "\\i2pd");
return boost::filesystem::path(std::string(localAppData) + "\\" + appName);
#else
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;
char* pszHome = getenv("HOME");
if (pszHome == NULL || strlen(pszHome) == 0)
@@ -187,10 +204,10 @@ namespace filesystem
// Mac
pathRet /= "Library/Application Support";
boost::filesystem::create_directory(pathRet);
return pathRet / "i2pd";
return pathRet / appName;
#else
// Unix
return pathRet / ".i2pd";
return pathRet / (std::string (".") + appName);
#endif
#endif
}
@@ -389,10 +406,65 @@ namespace http
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
}
}
} // Namespace end
}
} // util
} // i2p

9
util.h
View File

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

View File

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