Merge pull request #370 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2016-02-08 14:41:40 -05:00
commit bfff125cc5
22 changed files with 215 additions and 111 deletions

View File

@ -190,6 +190,13 @@ namespace data
return outCount;
}
size_t Base64EncodingBufferSize (const size_t input_size)
{
auto d = div (input_size, 3);
if (d.rem) d.quot++;
return 4*d.quot;
}
/*
*
* iT64
@ -327,7 +334,7 @@ namespace data
LogPrint (eLogError, "Compression error ", err);
return 0;
}
}
}
}
}

5
Base.h
View File

@ -17,6 +17,11 @@ namespace data
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
/**
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
size_t Base64EncodingBufferSize(const size_t input_size);
template<int sz>
class Tag
{

View File

@ -70,7 +70,7 @@ namespace crypto
void operator^=(const ChipherBlock& other) // XOR
{
#if defined(__x86_64__) // for Intel x64
#if defined(__x86_64__) || defined(__SSE__) // for Intel x84 or with SSE
__asm__
(
"movups (%[buf]), %%xmm0 \n"

View File

@ -17,9 +17,9 @@ void handle_signal(int sig)
switch (sig)
{
case SIGHUP:
LogPrint(eLogInfo, "Daemon: Got SIGHUP, doing nothing");
// TODO:
break;
LogPrint(eLogInfo, "Daemon: Got SIGHUP, reopening log...");
ReopenLogFile ();
break;
case SIGABRT:
case SIGTERM:
case SIGINT:

View File

@ -187,16 +187,17 @@ namespace client
auto it = m_RemoteLeaseSets.find (ident);
if (it != m_RemoteLeaseSets.end ())
{
if (it->second->HasNonExpiredLeases ())
if (!it->second->IsExpired ())
return it->second;
else
LogPrint (eLogWarning, "Destination: All leases of remote LeaseSet expired");
LogPrint (eLogWarning, "Destination: remote LeaseSet expired");
}
else
{
auto ls = i2p::data::netdb.FindLeaseSet (ident);
if (ls)
{
ls->PopulateLeases (); // since we don't store them in netdb
m_RemoteLeaseSets[ident] = ls;
return ls;
}
@ -664,7 +665,7 @@ namespace client
{
if (ecode != boost::asio::error::operation_aborted)
{
CleanupRoutingSessions ();
CleanupExpiredTags ();
CleanupRemoteLeaseSets ();
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer,
@ -674,9 +675,10 @@ namespace client
void ClientDestination::CleanupRemoteLeaseSets ()
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();)
{
if (!it->second->HasNonExpiredLeases ()) // all leases expired
if (ts > it->second->GetExpirationTime ()) // leaseset expired
{
LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
it = m_RemoteLeaseSets.erase (it);

View File

@ -72,7 +72,7 @@ namespace client
bool IsRunning () const { return m_IsRunning; };
boost::asio::io_service& GetService () { return m_Service; };
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
bool IsReady () const { return m_LeaseSet && m_LeaseSet->HasNonExpiredLeases () && m_Pool->GetOutboundTunnels ().size () > 0; };
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
void CancelDestinationRequest (const i2p::data::IdentHash& dest);

View File

@ -409,28 +409,6 @@ namespace garlic
else
LogPrint (eLogError, "Garlic: Failed to decrypt message");
}
// cleanup expired tags
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts > m_LastTagsCleanupTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
if (m_LastTagsCleanupTime)
{
int numExpiredTags = 0;
for (auto it = m_Tags.begin (); it != m_Tags.end ();)
{
if (ts > it->first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
numExpiredTags++;
it = m_Tags.erase (it);
}
else
it++;
}
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ());
}
m_LastTagsCleanupTime = ts;
}
}
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
@ -570,8 +548,25 @@ namespace garlic
return session;
}
void GarlicDestination::CleanupRoutingSessions ()
void GarlicDestination::CleanupExpiredTags ()
{
// incoming
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
int numExpiredTags = 0;
for (auto it = m_Tags.begin (); it != m_Tags.end ();)
{
if (ts > it->first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
numExpiredTags++;
it = m_Tags.erase (it);
}
else
it++;
}
if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " tags expired for ", GetIdentHash().ToBase64 ());
// outgoing
std::unique_lock<std::mutex> l(m_SessionsMutex);
for (auto it = m_Sessions.begin (); it != m_Sessions.end ();)
{

View File

@ -119,18 +119,19 @@ namespace garlic
// for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
};
using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
class GarlicDestination: public i2p::data::LocalDestination
{
public:
GarlicDestination (): m_NumTags (32), m_LastTagsCleanupTime (0) {}; // 32 tags by default
GarlicDestination (): m_NumTags (32) {}; // 32 tags by default
~GarlicDestination ();
void SetNumTags (int numTags) { m_NumTags = numTags; };
std::shared_ptr<GarlicRoutingSession> GetRoutingSession (std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet);
void CleanupRoutingSessions ();
void CleanupExpiredTags ();
void RemoveDeliveryStatusSession (uint32_t msgID);
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
@ -166,7 +167,6 @@ namespace garlic
std::map<i2p::data::IdentHash, GarlicRoutingSessionPtr> m_Sessions;
// incoming
std::map<SessionTag, std::shared_ptr<i2p::crypto::CBCDecryption>> m_Tags;
uint32_t m_LastTagsCleanupTime;
// DeliveryStatus
std::map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session

View File

@ -793,7 +793,7 @@ namespace util
}
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
if (leaseSet && leaseSet->HasNonExpiredLeases ())
if (leaseSet && !leaseSet->IsExpired ())
SendToDestination (leaseSet, port, buf, len);
else
{
@ -812,7 +812,7 @@ namespace util
if (ecode != boost::asio::error::operation_aborted)
{
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (destination);
if (leaseSet && leaseSet->HasNonExpiredLeases ())
if (leaseSet && !leaseSet->IsExpired ())
SendToDestination (leaseSet, port, buf, len);
else
// still no LeaseSet

View File

@ -22,6 +22,10 @@ namespace data
size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
{
if ( len < DEFAULT_IDENTITY_SIZE ) {
// buffer too small, don't overflow
return 0;
}
memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE);
return DEFAULT_IDENTITY_SIZE;
}
@ -228,26 +232,35 @@ namespace data
}
size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const
{
{
const size_t fullLen = GetFullLen();
if (fullLen > len) {
// buffer is too small and may overflow somewhere else
return 0;
}
memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
if (m_ExtendedLen > 0 && m_ExtendedBuffer)
memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen);
return GetFullLen ();
return fullLen;
}
size_t IdentityEx::FromBase64(const std::string& s)
{
uint8_t buf[1024];
auto len = Base64ToByteStream (s.c_str(), s.length(), buf, 1024);
const size_t slen = s.length();
const size_t bufLen = Base64EncodingBufferSize(slen);
uint8_t buf[bufLen];
const size_t len = Base64ToByteStream (s.c_str(), slen, buf, bufLen);
return FromBuffer (buf, len);
}
std::string IdentityEx::ToBase64 () const
{
uint8_t buf[1024];
char str[1536];
size_t l = ToBuffer (buf, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, 1536);
const size_t bufLen = GetFullLen();
const size_t strLen = Base64EncodingBufferSize(bufLen);
uint8_t buf[bufLen];
char str[strLen];
size_t l = ToBuffer (buf, bufLen);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, strLen);
str[l1] = 0;
return std::string (str);
}

View File

@ -12,8 +12,8 @@ namespace i2p
namespace data
{
LeaseSet::LeaseSet (const uint8_t * buf, size_t len):
m_IsValid (true)
LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases):
m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0)
{
m_Buffer = new uint8_t[len];
memcpy (m_Buffer, buf, len);
@ -22,7 +22,7 @@ namespace data
}
LeaseSet::LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool):
m_IsValid (true)
m_IsValid (true), m_StoreLeases (true), m_ExpirationTime (0)
{
if (!pool) return;
// header
@ -55,6 +55,7 @@ namespace data
uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
ts *= 1000; // in milliseconds
ts += rand () % 6; // + random milliseconds 0-5
if (ts > m_ExpirationTime) m_ExpirationTime = ts;
htobe64buf (m_Buffer + m_BufferLen, ts);
m_BufferLen += 8; // end date
}
@ -79,7 +80,14 @@ namespace data
m_BufferLen = len;
ReadFromBuffer (false);
}
void LeaseSet::PopulateLeases ()
{
m_StoreLeases = true;
m_Leases.clear ();
ReadFromBuffer (false);
}
void LeaseSet::ReadFromBuffer (bool readIdentity)
{
if (readIdentity || !m_Identity)
@ -105,6 +113,7 @@ namespace data
}
// process leases
m_ExpirationTime = 0;
const uint8_t * leases = m_Buffer + size;
for (int i = 0; i < num; i++)
{
@ -113,16 +122,20 @@ namespace data
leases += 32; // gateway
lease.tunnelID = bufbe32toh (leases);
leases += 4; // tunnel ID
lease.endDate = bufbe64toh (leases);
lease.endDate = bufbe64toh (leases);
leases += 8; // end date
m_Leases.push_back (lease);
// check if lease's gateway is in our netDb
if (!netdb.FindRouter (lease.tunnelGateway))
{
// if not found request it
LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting");
netdb.RequestDestination (lease.tunnelGateway);
if (lease.endDate > m_ExpirationTime)
m_ExpirationTime = lease.endDate;
if (m_StoreLeases)
{
m_Leases.push_back (lease);
// check if lease's gateway is in our netDb
if (!netdb.FindRouter (lease.tunnelGateway))
{
// if not found request it
LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting");
netdb.RequestDestination (lease.tunnelGateway);
}
}
}
@ -150,19 +163,17 @@ namespace data
}
bool LeaseSet::HasExpiredLeases () const
{
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto& it: m_Leases)
if (ts >= it.endDate) return true;
return false;
}
}
bool LeaseSet::HasNonExpiredLeases () const
bool LeaseSet::IsExpired () const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto& it: m_Leases)
if (ts < it.endDate) return true;
return false;
return ts > m_ExpirationTime;
}
}
}

View File

@ -37,10 +37,11 @@ namespace data
{
public:
LeaseSet (const uint8_t * buf, size_t len);
LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true);
LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool);
~LeaseSet () { delete[] m_Buffer; };
void Update (const uint8_t * buf, size_t len);
void PopulateLeases (); /// from buffer
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
const uint8_t * GetBuffer () const { return m_Buffer; };
@ -52,7 +53,8 @@ namespace data
const std::vector<Lease>& GetLeases () const { return m_Leases; };
const std::vector<Lease> GetNonExpiredLeases (bool withThreshold = true) const;
bool HasExpiredLeases () const;
bool HasNonExpiredLeases () const;
bool IsExpired () const;
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; };
bool IsDestination () const { return true; };
@ -62,8 +64,9 @@ namespace data
private:
bool m_IsValid;
bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill
std::vector<Lease> m_Leases;
uint64_t m_ExpirationTime; // in milliseconds
std::shared_ptr<const IdentityEx> m_Identity;
uint8_t m_EncryptionKey[256];
uint8_t * m_Buffer;

23
Log.cpp
View File

@ -13,7 +13,8 @@ static const char * g_LogLevelStr[eNumLogLevels] =
void LogMsg::Process()
{
auto& output = (log && log->GetLogStream ()) ? *log->GetLogStream () : std::cerr;
auto stream = log ? log->GetLogStream () : nullptr;
auto& output = stream ? *stream : std::cout;
if (log)
output << log->GetTimestamp ();
else
@ -45,16 +46,25 @@ void Log::Flush ()
void Log::SetLogFile (const std::string& fullFilePath)
{
auto logFile = new std::ofstream (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
m_FullFilePath = fullFilePath;
auto logFile = std::make_shared<std::ofstream> (fullFilePath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc);
if (logFile->is_open ())
{
SetLogStream (logFile);
LogPrint(eLogInfo, "Log: will send messages to ", fullFilePath);
}
else
delete logFile;
}
void Log::ReopenLogFile ()
{
if (m_FullFilePath.length () > 0)
{
SetLogFile (m_FullFilePath);
LogPrint(eLogInfo, "Log: file ", m_FullFilePath, " reopen");
}
}
void Log::SetLogLevel (const std::string& level)
{
if (level == "error") { m_MinLevel = eLogError; }
@ -65,11 +75,10 @@ void Log::SetLogLevel (const std::string& level)
LogPrint(eLogError, "Log: Unknown loglevel: ", level);
return;
}
LogPrint(eLogInfo, "Log: min messages level set to ", level);
LogPrint(eLogInfo, "Log: min msg level set to ", level);
}
void Log::SetLogStream (std::ostream * logStream)
void Log::SetLogStream (std::shared_ptr<std::ostream> logStream)
{
if (m_LogStream) delete m_LogStream;
m_LogStream = logStream;
}

21
Log.h
View File

@ -7,6 +7,7 @@
#include <fstream>
#include <functional>
#include <chrono>
#include <memory>
#include "Queue.h"
enum LogLevel
@ -34,13 +35,14 @@ class Log: public i2p::util::MsgQueue<LogMsg>
{
public:
Log (): m_LogStream (nullptr) { SetOnEmpty (std::bind (&Log::Flush, this)); };
~Log () { delete m_LogStream; };
Log () { SetOnEmpty (std::bind (&Log::Flush, this)); };
~Log () {};
void SetLogFile (const std::string& fullFilePath);
void ReopenLogFile ();
void SetLogLevel (const std::string& level);
void SetLogStream (std::ostream * logStream);
std::ostream * GetLogStream () const { return m_LogStream; };
void SetLogStream (std::shared_ptr<std::ostream> logStream);
std::shared_ptr<std::ostream> GetLogStream () const { return m_LogStream; };
const std::string& GetTimestamp ();
LogLevel GetLogLevel () { return m_MinLevel; };
@ -50,7 +52,8 @@ class Log: public i2p::util::MsgQueue<LogMsg>
private:
std::ostream * m_LogStream;
std::string m_FullFilePath; // empty if stream
std::shared_ptr<std::ostream> m_LogStream;
enum LogLevel m_MinLevel;
std::string m_Timestamp;
#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 6) && !defined(__clang__) // gcc 4.6
@ -73,7 +76,7 @@ inline void StartLog (const std::string& fullFilePath)
}
}
inline void StartLog (std::ostream * s)
inline void StartLog (std::shared_ptr<std::ostream> s)
{
if (!g_Log)
{
@ -101,6 +104,12 @@ inline void SetLogLevel (const std::string& level)
g_Log->SetLogLevel(level);
}
inline void ReopenLogFile ()
{
if (g_Log)
g_Log->ReopenLogFile ();
}
template<typename TValue>
void LogPrint (std::stringstream& s, TValue arg)
{

View File

@ -8,4 +8,6 @@ LDLIBS = -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) -Wl,-Bstatic -lboost_date_ti
ifeq ($(USE_AESNI),1)
CPU_FLAGS = -maes -DAESNI
else
CPU_FLAGS = -msse
endif

View File

@ -134,6 +134,7 @@ namespace transport
void NTCPSession::HandlePhase1Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogInfo, "NTCP: couldn't send Phase 1 message: ", ecode.message ());
@ -150,6 +151,7 @@ namespace transport
void NTCPSession::HandlePhase1Received (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogInfo, "NTCP: phase 1 read error: ", ecode.message ());
@ -205,6 +207,7 @@ namespace transport
void NTCPSession::HandlePhase2Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsB)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 2 message: ", ecode.message ());
@ -221,6 +224,7 @@ namespace transport
void NTCPSession::HandlePhase2Received (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogInfo, "NTCP: Phase 2 read error: ", ecode.message (), ". Wrong ident assumed");
@ -277,7 +281,8 @@ namespace transport
if (paddingSize > 0)
{
paddingSize = 16 - paddingSize;
// TODO: fill padding with random data
// fill padding with random data
RAND_bytes(buf, paddingSize);
buf += paddingSize;
len += paddingSize;
}
@ -297,6 +302,7 @@ namespace transport
void NTCPSession::HandlePhase3Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred, uint32_t tsA)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogInfo, "NTCP: Couldn't send Phase 3 message: ", ecode.message ());
@ -420,6 +426,7 @@ namespace transport
void NTCPSession::HandlePhase4Sent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogWarning, "NTCP: Couldn't send Phase 4 message: ", ecode.message ());
@ -645,8 +652,11 @@ namespace transport
}
int rem = (len + 6) & 0x0F; // %16
int padding = 0;
if (rem > 0) padding = 16 - rem;
// TODO: fill padding
if (rem > 0) {
padding = 16 - rem;
// fill with random padding
RAND_bytes(sendBuffer + len + 2, padding);
}
htobe32buf (sendBuffer + len + 2 + padding, adler32 (adler32 (0, Z_NULL, 0), sendBuffer, len + 2+ padding));
int l = len + padding + 6;
@ -667,6 +677,7 @@ namespace transport
void NTCPSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs)
{
(void) msgs;
m_IsSending = false;
if (ecode)
{

View File

@ -206,7 +206,7 @@ namespace data
}
else
{
auto leaseSet = std::make_shared<LeaseSet> (buf, len);
auto leaseSet = std::make_shared<LeaseSet> (buf, len, false); // we don't need leases in netdb
if (leaseSet->IsValid ())
{
LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64());
@ -316,7 +316,8 @@ namespace data
const std::string& fullPath = it1->path();
#endif
auto r = std::make_shared<RouterInfo>(fullPath);
if (!r->IsUnreachable () && (!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour
if (r->GetRouterIdentity () && !r->IsUnreachable () &&
(!r->UsesIntroducer () || ts < r->GetTimestamp () + 3600*1000LL)) // 1 hour
{
r->DeleteBuffer ();
r->ClearProperties (); // properties are not used for regular routers
@ -980,9 +981,10 @@ namespace data
void NetDb::ManageLeaseSets ()
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();)
{
if (!it->second->HasNonExpiredLeases ()) // all leases expired
if (ts > it->second->GetExpirationTime ())
{
LogPrint (eLogWarning, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
it = m_LeaseSets.erase (it);

View File

@ -208,6 +208,11 @@ namespace data
uint16_t fileNameLength, extraFieldLength;
s.read ((char *)&fileNameLength, 2);
fileNameLength = le16toh (fileNameLength);
if ( fileNameLength > 255 ) {
// too big
LogPrint(eLogError, "Reseed: SU3 fileNameLength too large: ", fileNameLength);
return numFiles;
}
s.read ((char *)&extraFieldLength, 2);
extraFieldLength = le16toh (extraFieldLength);
char localFileName[255];

13
SAM.cpp
View File

@ -631,10 +631,15 @@ namespace client
m_SocketType = eSAMSocketTypeStream;
if (!m_IsSilent)
{
// send remote peer address
uint8_t ident[1024];
size_t l = stream->GetRemoteIdentity ()->ToBuffer (ident, 1024);
size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE);
// get remote peer address
auto ident_ptr = stream->GetRemoteIdentity();
const size_t ident_len = ident_ptr->GetFullLen();
uint8_t* ident = new uint8_t[ident_len];
// send remote peer address as base64
const size_t l = ident_ptr->ToBuffer (ident, ident_len);
const size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE);
delete[] ident;
m_StreamBuffer[l1] = '\n';
HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream
}

View File

@ -31,7 +31,7 @@ namespace api
i2p::crypto::TerminateCrypto ();
}
void StartI2P (std::ostream * logStream)
void StartI2P (std::shared_ptr<std::ostream> logStream)
{
if (logStream)
StartLog (logStream);

2
api.h
View File

@ -14,7 +14,7 @@ namespace api
// initialization start and stop
void InitI2P (int argc, char* argv[], const char * appName);
void TerminateI2P ();
void StartI2P (std::ostream * logStream = nullptr);
void StartI2P (std::shared_ptr<std::ostream> logStream = nullptr);
// write system log to logStream, if not specified to <appName>.log in application's folder
void StopI2P ();
void RunPeerTest (); // should be called after UPnP

View File

@ -20,11 +20,15 @@ development location for the sake of convenience. Adjust paths
accordingly if it is not the case. Note that msys uses unix-alike
paths like /c/dev/ for C:\dev\.
msys2
-----
### x86 (32-bit architecture)
Get install file msys2-i686-20150916.exe from https://msys2.github.io.
open MSys2Shell (from Start menu).
open MSYS2 Shell (from Start menu).
Install all prerequisites and download i2pd source:
```bash
@ -37,14 +41,23 @@ export PATH=/mingw32/bin:/usr/bin # we need compiler on PATH which is usually he
make
```
If your processor has
[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set),
you use `make USE_AESNI=1`. No check is done however, it
will compile, but it might crash with `Illegal instruction` if not supported.
You should be able to run ./i2pd . If you need to start from the new
shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as
it adds`/minw32/bin` to the PATH.
### x64 (64-bit architecture)
Get install file msys2-x86_64-20150916.exe from https://msys2.github.io.
open MSYS2 Shell (from Start menu).
Install all prerequisites and download i2pd source:
```bash
pacman -S mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc git make
mkdir -p /c/dev/i2pd
cd /c/dev/i2pd
git clone https://github.com/PurpleI2P/i2pd.git
cd i2pd
export PATH=/mingw64/bin:/usr/bin # we need compiler on PATH which is usually heavily cluttered on Windows
make
```
### Caveats
@ -63,6 +76,19 @@ home page, otherwise you might end up with DLLs incompatibility
problems.
### AES-NI
If your processor has
[AES instruction set](https://en.wikipedia.org/wiki/AES_instruction_set),
you use `make USE_AESNI=1`. No check is done however, it
will compile, but it might crash with `Illegal instruction` if not supported.
You should be able to run ./i2pd . If you need to start from the new
shell, consider starting *MinGW-w64 Win32 Shell* instead of *MSYS2 Shell* as
it adds`/minw32/bin` to the PATH.
Using Visual Studio
-------------------
@ -77,7 +103,7 @@ Requirements for building:
* Strawberry Perl or ActiveState Perl, do NOT try msys2 perl, it won't work
## Building Boost
### Building Boost
Open a Command Prompt (there is no need to start Visual Studio command
prompt to build Boost) and run the following:
@ -98,8 +124,8 @@ only and static linking, and/or you are out of space/time, you might
consider `--build-type=minimal`. Take a look at
[appveyor.yml](../appveyor.yml) for details on how test builds are done.
Building OpenSSL
-----------------
### Building OpenSSL
Download OpenSSL, e.g. with git
@ -123,8 +149,8 @@ maintaining multiple versions, e.g. 64 bit and/or
static/shared. Consult `C:\Program Files
(x86)\CMake\share\cmake-3.3\Modules\FindOpenSSL.cmake` for details.
Get miniupnpc
-------------
### Get miniupnpc
If you are behind a UPnP enabled router and don't feel like manually
configuring port forwarding, you should consider using
@ -139,8 +165,7 @@ Note that you might need to build DLL yourself for 64-bit systems
using msys2 as 64-bit DLLs are not provided by the project.
Creating Visual Studio project
------------------------------
### Creating Visual Studio project
Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options.
@ -155,8 +180,8 @@ cmake ..\build -G "Visual Studio 12 2013" -DWITH_UPNP=ON -DWITH_PCH=ON -DCMAKE_I
WITH_UPNP will stay off, if necessary files are not found.
Building i2pd
-------------
### Building i2pd
You can open generated solution/project with Visual Studio and build
from there, alternatively you can use `cmake --build . --config Release --target install` or