Browse Source

Merge pull request #431 from PurpleI2P/openssl

recent changes
pull/464/head
orignal 9 years ago
parent
commit
40cdcf8b06
  1. 113
      AddressBook.cpp
  2. 12
      AddressBook.h
  3. 4
      Base.cpp
  4. 1
      Config.cpp
  5. 7
      FS.cpp
  6. 17
      FS.h
  7. 2
      HTTPProxy.cpp
  8. 2
      NTCPSession.cpp
  9. 5
      Reseed.cpp
  10. 1
      SSUSession.cpp
  11. 12
      Transports.cpp
  12. BIN
      Win32/Anke_2200px.jpg
  13. BIN
      Win32/Anke_700px.bmp
  14. 6
      Win32/Resource.rc
  15. 45
      Win32/Win32App.cpp
  16. BIN
      Win32/anke.ico
  17. 1
      Win32/resource.h
  18. 75
      docs/build_notes_cross.md
  19. 17
      docs/configuration.md
  20. 111
      docs/i2pd.conf

113
AddressBook.cpp

@ -24,7 +24,7 @@ namespace client
{ {
private: private:
i2p::fs::HashedStorage storage; i2p::fs::HashedStorage storage;
std::string indexPath; std::string etagsPath, indexPath, localPath;
public: public:
AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") {}; AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") {};
@ -34,14 +34,34 @@ namespace client
bool Init (); bool Init ();
int Load (std::map<std::string, i2p::data::IdentHash>& addresses); int Load (std::map<std::string, i2p::data::IdentHash>& addresses);
int LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses);
int Save (const std::map<std::string, i2p::data::IdentHash>& addresses); int Save (const std::map<std::string, i2p::data::IdentHash>& addresses);
void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified);
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
private:
int LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses); // returns -1 if can't open file, otherwise number of records
}; };
bool AddressBookFilesystemStorage::Init() bool AddressBookFilesystemStorage::Init()
{ {
storage.SetPlace(i2p::fs::GetDataDir()); storage.SetPlace(i2p::fs::GetDataDir());
indexPath = storage.GetRoot() + i2p::fs::dirSep + "addresses.csv"; // init storage
return storage.Init(i2p::data::GetBase32SubstitutionTable(), 32); if (storage.Init(i2p::data::GetBase32SubstitutionTable(), 32))
{
// init ETags
etagsPath = i2p::fs::StorageRootPath (storage, "etags");
if (!i2p::fs::Exists (etagsPath))
i2p::fs::CreateDirectory (etagsPath);
// init address files
indexPath = i2p::fs::StorageRootPath (storage, "addresses.csv");
localPath = i2p::fs::StorageRootPath (storage, "local.csv");
return true;
}
return false;
} }
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const
@ -87,24 +107,18 @@ namespace client
storage.Remove( ident.ToBase32() ); storage.Remove( ident.ToBase32() );
} }
int AddressBookFilesystemStorage::Load (std::map<std::string, i2p::data::IdentHash>& addresses) int AddressBookFilesystemStorage::LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses)
{ {
int num = 0; int num = 0;
std::string s; std::ifstream f (filename, std::ifstream::in); // in text mode
std::ifstream f (indexPath, std::ifstream::in); // in text mode if (!f) return -1;
if (f.is_open ()) {
LogPrint(eLogInfo, "Addressbook: using index file ", indexPath);
} else {
LogPrint(eLogWarning, "Addressbook: Can't open ", indexPath);
return 0;
}
addresses.clear (); addresses.clear ();
while (!f.eof ()) { while (!f.eof ())
{
std::string s;
getline(f, s); getline(f, s);
if (!s.length()) if (!s.length()) continue; // skip empty line
continue; // skip empty line
std::size_t pos = s.find(','); std::size_t pos = s.find(',');
if (pos != std::string::npos) if (pos != std::string::npos)
@ -118,8 +132,28 @@ namespace client
num++; num++;
} }
} }
return num;
}
int AddressBookFilesystemStorage::Load (std::map<std::string, i2p::data::IdentHash>& addresses)
{
int num = LoadFromFile (indexPath, addresses);
if (num < 0)
{
LogPrint(eLogWarning, "Addressbook: Can't open ", indexPath);
return 0;
}
LogPrint(eLogInfo, "Addressbook: using index file ", indexPath);
LogPrint (eLogInfo, "Addressbook: ", num, " addresses loaded from storage"); LogPrint (eLogInfo, "Addressbook: ", num, " addresses loaded from storage");
return num;
}
int AddressBookFilesystemStorage::LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses)
{
int num = LoadFromFile (localPath, addresses);
if (num < 0) return 0;
LogPrint (eLogInfo, "Addressbook: ", num, " local addresses loaded");
return num; return num;
} }
@ -146,6 +180,28 @@ namespace client
return num; return num;
} }
void AddressBookFilesystemStorage::SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified)
{
std::string fname = etagsPath + i2p::fs::dirSep + subscription.ToBase32 () + ".txt";
std::ofstream f (fname, std::ofstream::out | std::ofstream::trunc);
if (f)
{
f << etag << std::endl;
f<< lastModified << std::endl;
}
}
bool AddressBookFilesystemStorage::GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified)
{
std::string fname = etagsPath + i2p::fs::dirSep + subscription.ToBase32 () + ".txt";
std::ifstream f (fname, std::ofstream::in);
if (!f || f.eof ()) return false;
std::getline (f, etag);
if (f.eof ()) return false;
std::getline (f, lastModified);
return true;
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
AddressBook::AddressBook (): m_Storage(new AddressBookFilesystemStorage), m_IsLoaded (false), m_IsDownloading (false), AddressBook::AddressBook (): m_Storage(new AddressBookFilesystemStorage), m_IsLoaded (false), m_IsDownloading (false),
m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
@ -274,6 +330,8 @@ namespace client
LoadHostsFromStream (f); LoadHostsFromStream (f);
m_IsLoaded = true; m_IsLoaded = true;
} }
// load local
m_Storage->LoadLocal (m_Addresses);
} }
void AddressBook::LoadHostsFromStream (std::istream& f) void AddressBook::LoadHostsFromStream (std::istream& f)
@ -337,7 +395,15 @@ namespace client
LogPrint (eLogError, "Addressbook: subscriptions already loaded"); LogPrint (eLogError, "Addressbook: subscriptions already loaded");
} }
void AddressBook::DownloadComplete (bool success) bool AddressBook::GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified)
{
if (m_Storage)
return m_Storage->GetEtag (subscription, etag, lastModified);
else
return false;
}
void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified)
{ {
m_IsDownloading = false; m_IsDownloading = false;
int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT;
@ -348,6 +414,7 @@ namespace client
nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT;
else else
m_IsLoaded = true; m_IsLoaded = true;
if (m_Storage) m_Storage->SaveEtag (subscription, etag, lastModified);
} }
if (m_SubscriptionsUpdateTimer) if (m_SubscriptionsUpdateTimer)
{ {
@ -438,6 +505,12 @@ namespace client
i2p::data::IdentHash ident; i2p::data::IdentHash ident;
if (m_Book.GetIdentHash (u.host_, ident)) if (m_Book.GetIdentHash (u.host_, ident))
{ {
if (!m_Etag.length ())
{
// load ETag
m_Book.GetEtag (ident, m_Etag, m_LastModified);
LogPrint (eLogInfo, "Addressbook: set ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
}
std::condition_variable newDataReceived; std::condition_variable newDataReceived;
std::mutex newDataReceivedMutex; std::mutex newDataReceivedMutex;
auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident); auto leaseSet = i2p::client::context.GetSharedLocalDestination ()->FindLeaseSet (ident);
@ -468,7 +541,7 @@ namespace client
<< "X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n" << "X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n"
<< "Connection: close\r\n"; << "Connection: close\r\n";
if (m_Etag.length () > 0) // etag if (m_Etag.length () > 0) // etag
request << i2p::util::http::IF_NONE_MATCH << ": \"" << m_Etag << "\"\r\n"; request << i2p::util::http::IF_NONE_MATCH << ": " << m_Etag << "\r\n";
if (m_LastModified.length () > 0) // if-modfief-since if (m_LastModified.length () > 0) // if-modfief-since
request << i2p::util::http::IF_MODIFIED_SINCE << ": " << m_LastModified << "\r\n"; request << i2p::util::http::IF_MODIFIED_SINCE << ": " << m_LastModified << "\r\n";
request << "\r\n"; // end of header request << "\r\n"; // end of header
@ -529,7 +602,7 @@ namespace client
!header.compare (colon + 1, std::string::npos, "x-i2p-gzip"); !header.compare (colon + 1, std::string::npos, "x-i2p-gzip");
} }
} }
LogPrint (eLogInfo, "Addressbook: ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified); LogPrint (eLogInfo, "Addressbook: received ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
if (!response.eof ()) if (!response.eof ())
{ {
success = true; success = true;
@ -561,7 +634,7 @@ namespace client
if (!success) if (!success)
LogPrint (eLogError, "Addressbook: download hosts.txt from ", m_Link, " failed"); LogPrint (eLogError, "Addressbook: download hosts.txt from ", m_Link, " failed");
m_Book.DownloadComplete (success); m_Book.DownloadComplete (success, ident, m_Etag, m_LastModified);
} }
bool AddressBookSubscription::ProcessResponse (std::stringstream& s, bool isGzip) bool AddressBookSubscription::ProcessResponse (std::stringstream& s, bool isGzip)

12
AddressBook.h

@ -37,7 +37,11 @@ namespace client
virtual bool Init () = 0; virtual bool Init () = 0;
virtual int Load (std::map<std::string, i2p::data::IdentHash>& addresses) = 0; virtual int Load (std::map<std::string, i2p::data::IdentHash>& addresses) = 0;
virtual int LoadLocal (std::map<std::string, i2p::data::IdentHash>& addresses) = 0;
virtual int Save (const std::map<std::string, i2p::data::IdentHash>& addresses) = 0; virtual int Save (const std::map<std::string, i2p::data::IdentHash>& addresses) = 0;
virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
}; };
class AddressBookSubscription; class AddressBookSubscription;
@ -56,10 +60,13 @@ namespace client
void InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address); void InsertAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
void LoadHostsFromStream (std::istream& f); void LoadHostsFromStream (std::istream& f);
void DownloadComplete (bool success); void DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified);
//This method returns the ".b32.i2p" address //This method returns the ".b32.i2p" address
std::string ToAddress(const i2p::data::IdentHash& ident) { return GetB32Address(ident); } std::string ToAddress(const i2p::data::IdentHash& ident) { return GetB32Address(ident); }
std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) { return ToAddress(ident->GetIdentHash ()); } std::string ToAddress(std::shared_ptr<const i2p::data::IdentityEx> ident) { return ToAddress(ident->GetIdentHash ()); }
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
private: private:
void StartSubscriptions (); void StartSubscriptions ();
@ -73,7 +80,7 @@ namespace client
private: private:
std::mutex m_AddressBookMutex; std::mutex m_AddressBookMutex;
std::map<std::string, i2p::data::IdentHash> m_Addresses; std::map<std::string, i2p::data::IdentHash> m_Addresses, m_LocalAddresses;
AddressBookStorage * m_Storage; AddressBookStorage * m_Storage;
volatile bool m_IsLoaded, m_IsDownloading; volatile bool m_IsLoaded, m_IsDownloading;
std::vector<AddressBookSubscription *> m_Subscriptions; std::vector<AddressBookSubscription *> m_Subscriptions;
@ -97,6 +104,7 @@ namespace client
AddressBook& m_Book; AddressBook& m_Book;
std::string m_Link, m_Etag, m_LastModified; std::string m_Link, m_Etag, m_LastModified;
// m_Etag must be surrounded by ""
}; };
} }
} }

4
Base.cpp

@ -8,8 +8,8 @@ namespace data
{ {
static const char T32[32] = { static const char T32[32] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'k', 'k', 'l', 'm', 'n', 'o', 'p', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 't', 't', 'u', 'v', 'w', 'x', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '2', '3', '4', '5', '6', '7', 'y', 'z', '2', '3', '4', '5', '6', '7',
}; };

1
Config.cpp

@ -126,6 +126,7 @@ namespace config {
#ifdef _WIN32 #ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')") ("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping") ("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
("close", value<std::string>()->default_value("ask"), "On close action") // minimize, exit, ask TODO: add custom validator or something
#endif #endif
; ;

7
FS.cpp

@ -102,6 +102,13 @@ namespace fs {
return boost::filesystem::remove(path); return boost::filesystem::remove(path);
} }
bool CreateDirectory (const std::string& path)
{
if (boost::filesystem::exists(path) &&
boost::filesystem::is_directory (boost::filesystem::status (path))) return true;
return boost::filesystem::create_directory(path);
}
void HashedStorage::SetPlace(const std::string &path) { void HashedStorage::SetPlace(const std::string &path) {
root = path + i2p::fs::dirSep + name; root = path + i2p::fs::dirSep + name;
} }

17
FS.h

@ -48,8 +48,8 @@ namespace fs {
/** create subdirs in storage */ /** create subdirs in storage */
bool Init(const char* chars, size_t cnt); bool Init(const char* chars, size_t cnt);
const std::string & GetRoot() const { return this->root; } const std::string & GetRoot() const { return root; }
const std::string & GetName() const { return this->name; } const std::string & GetName() const { return name; }
/** set directory where to place storage directory */ /** set directory where to place storage directory */
void SetPlace(const std::string & path); void SetPlace(const std::string & path);
/** path to file with given ident */ /** path to file with given ident */
@ -109,6 +109,8 @@ namespace fs {
*/ */
bool Exists(const std::string & path); bool Exists(const std::string & path);
bool CreateDirectory (const std::string& path);
template<typename T> template<typename T>
void _ExpandPath(std::stringstream & path, T c) { void _ExpandPath(std::stringstream & path, T c) {
path << i2p::fs::dirSep << c; path << i2p::fs::dirSep << c;
@ -136,6 +138,17 @@ namespace fs {
return s.str(); return s.str();
} }
template<typename Storage, typename... Filename>
std::string StorageRootPath (const Storage& storage, Filename... filenames)
{
std::stringstream s("");
s << storage.GetRoot ();
_ExpandPath(s, filenames...);
return s.str();
}
} // fs } // fs
} // i2p } // i2p

2
HTTPProxy.cpp

@ -204,7 +204,7 @@ namespace proxy
if (eol) if (eol)
{ {
*eol = 0; eol++; *eol = 0; eol++;
if (strncmp ((const char *)http_buff, "Referer", 7)) // strip out referer if (strncmp ((const char *)http_buff, "Referer", 7) && strncmp ((const char *)http_buff, "Connection", 10)) // strip out referer and connection
{ {
if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent
m_request.append("User-Agent: MYOB/6.66 (AN/ON)"); m_request.append("User-Agent: MYOB/6.66 (AN/ON)");

2
NTCPSession.cpp

@ -94,8 +94,6 @@ namespace transport
m_DHKeysPair = nullptr; m_DHKeysPair = nullptr;
SendTimeSyncMessage (); SendTimeSyncMessage ();
m_SendQueue.push_back (CreateDatabaseStoreMsg ()); // we tell immediately who we are
transports.PeerConnected (shared_from_this ()); transports.PeerConnected (shared_from_this ());
} }

5
Reseed.cpp

@ -26,13 +26,12 @@ namespace data
static std::vector<std::string> httpsReseedHostList = static std::vector<std::string> httpsReseedHostList =
{ {
"https://reseed.i2p-projekt.de/", // Only HTTPS "https://reseed.i2p-projekt.de/", // Only HTTPS
//"https://i2pseed.zarrenspry.info/", // Only HTTPS and SU3 (v3) support
"https://i2p.mooo.com/netDb/", "https://i2p.mooo.com/netDb/",
"https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required "https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required
"https://us.reseed.i2p2.no:444/", "https://us.reseed.i2p2.no:444/",
"https://uk.reseed.i2p2.no:444/", "https://uk.reseed.i2p2.no:444/",
"https://www.torontocrypto.org:8443/", "https://i2p.manas.ca:8443/",
"https://i2p-0.manas.ca:8443/" "https://i2p-0.manas.ca:8443/",
"https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support "https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support
"https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support "https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support
"https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support "https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support

1
SSUSession.cpp

@ -855,7 +855,6 @@ namespace transport
m_DHKeysPair = nullptr; m_DHKeysPair = nullptr;
m_SignedData = nullptr; m_SignedData = nullptr;
m_Data.Start (); m_Data.Start ();
m_Data.Send (CreateDatabaseStoreMsg ());
transports.PeerConnected (shared_from_this ()); transports.PeerConnected (shared_from_this ());
if (m_IsPeerTest) if (m_IsPeerTest)
SendPeerTest (); SendPeerTest ();

12
Transports.cpp

@ -505,12 +505,24 @@ namespace transport
auto it = m_Peers.find (ident); auto it = m_Peers.find (ident);
if (it != m_Peers.end ()) if (it != m_Peers.end ())
{ {
bool sendDatabaseStore = true;
if (it->second.delayedMessages.size () > 0)
{
// check if first message is our DatabaseStore (publishing)
auto firstMsg = it->second.delayedMessages[0];
if (firstMsg && firstMsg->GetTypeID () == eI2NPDatabaseStore &&
i2p::data::IdentHash(firstMsg->GetPayload () + DATABASE_STORE_KEY_OFFSET) == i2p::context.GetIdentHash ())
sendDatabaseStore = false; // we have it in the list already
}
if (sendDatabaseStore)
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () });
it->second.sessions.push_back (session); it->second.sessions.push_back (session);
session->SendI2NPMessages (it->second.delayedMessages); session->SendI2NPMessages (it->second.delayedMessages);
it->second.delayedMessages.clear (); it->second.delayedMessages.clear ();
} }
else // incoming connection else // incoming connection
{ {
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
std::unique_lock<std::mutex> l(m_PeersMutex); std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} })); m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} }));
} }

BIN
Win32/Anke_2200px.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
Win32/Anke_700px.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

6
Win32/Resource.rc

@ -52,7 +52,11 @@ END
// Icon with lowest ID value placed first to ensure application icon // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems. // remains consistent on all systems.
MAINICON ICON "ictoopie.ico" //MAINICON ICON "ictoopie.ico"
MAINICON ICON "anke.ico"
MASCOT BITMAP "Anke_700px.bmp"
#endif // English (United States) resources #endif // English (United States) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

45
Win32/Win32App.cpp

@ -4,6 +4,11 @@
#include "../Config.h" #include "../Config.h"
#include "resource.h" #include "resource.h"
#include "Win32App.h" #include "Win32App.h"
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
#define ID_ABOUT 2000 #define ID_ABOUT 2000
#define ID_EXIT 2001 #define ID_EXIT 2001
@ -98,7 +103,7 @@ namespace win32
char buf[30]; char buf[30];
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
std::snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort); snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL); ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
return 0; return 0;
} }
@ -119,6 +124,29 @@ namespace win32
ShowWindow(hWnd, SW_HIDE); ShowWindow(hWnd, SW_HIDE);
return 0; return 0;
} }
case SC_CLOSE:
{
std::string close; i2p::config::GetOption("close", close);
if (0 == close.compare("ask"))
switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
" You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
"Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
{
case IDYES: close = "minimize"; break;
case IDNO: close = "exit"; break;
default: return 0;
}
if (0 == close.compare("minimize"))
{
ShowWindow(hWnd, SW_HIDE);
return 0;
}
if (0 != close.compare("exit"))
{
::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
return 0;
}
}
} }
} }
case WM_TRAYICON: case WM_TRAYICON:
@ -136,6 +164,19 @@ namespace win32
} }
break; break;
} }
case WM_PAINT:
{
PAINTSTRUCT ps;
auto hDC = BeginPaint (hWnd, &ps);
auto mascot = LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE (MASCOT));
auto mascotDC = CreateCompatibleDC (hDC);
SelectObject (mascotDC, mascot);
BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
DeleteDC (mascotDC);
DeleteObject (mascot);
EndPaint (hWnd, &ps);
break;
}
} }
return DefWindowProc( hWnd, uMsg, wParam, lParam); return DefWindowProc( hWnd, uMsg, wParam, lParam);
} }
@ -164,7 +205,7 @@ namespace win32
wclx.lpszClassName = I2PD_WIN32_CLASSNAME; wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
RegisterClassEx (&wclx); RegisterClassEx (&wclx);
// create new window // create new window
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 250, 150, NULL, NULL, hInst, NULL)) if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 533, 700, NULL, NULL, hInst, NULL))
{ {
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false; return false;

BIN
Win32/anke.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

1
Win32/resource.h

@ -3,6 +3,7 @@
// Used by Resource.rc // Used by Resource.rc
// //
#define MAINICON 101 #define MAINICON 101
#define MASCOT 201
// Next default values for new objects // Next default values for new objects
// //

75
docs/build_notes_cross.md

@ -0,0 +1,75 @@
Cross compilation notes
=======================
Static 64 bit windows binary on Ubuntu 15.10 (Wily Werewolf)
---------------------------------------------------------------------
Install cross compiler and friends
```sh
sudo apt-get install g++-mingw-w64-x86-64
```
Default is to use Win32 threading model which lacks std::mutex and such. So we change defaults
```sh
sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
```
From now on we assume we have everything in `~/dev/`. Get Boost sources unpacked into `~/dev/boost_1_60_0/`
and change directory to it.
Now add out cross compiler configuration. Warning: the following will wipe out whatever you had in there.
```sh
echo "using gcc : mingw : x86_64-w64-mingw32-g++ ;" > ~/user-config.jam
```
Proceed with building Boost normal way, but let's define dedicated staging directory
```sh
./bootstrap.sh
./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \
--build-type=minimal --with-filesystem --with-program_options --with-regex --with-date_time \
--stagedir=stage-mingw-64
cd ..
```
Now we get & build OpenSSL
```sh
git clone https://github.com/openssl/openssl
cd openssl
git checkout OpenSSL_1_0_2g
./Configure mingw64 no-rc2 no-rc4 no-rc5 no-idea no-bf no-cast no-whirlpool no-md2 no-md4 no-ripemd no-mdc2 \
no-camellia no-seed no-comp no-krb5 no-gmp no-rfc3779 no-ec2m no-ssl2 no-jpake no-srp no-sctp no-srtp \
--prefix=~/dev/stage --cross-compile-prefix=x86_64-w64-mingw32-
make depend
make
make install
cd ..
```
and Zlib
```sh
git clone https://github.com/madler/zlib
cd zlib
git checkout v1.2.8
CC=x86_64-w64-mingw32-gcc CFLAGS=-O3 ./configure --static --64 --prefix=~/dev/stage
make
make install
cd ..
```
Now we prepare cross toolchain hint file for CMake, let's name it `~/dev/toolchain-mingw.cmake`
```cmake
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
```
Download miniupnpc, unpack, and symlink it into `~/dev/miniupnpc/`.
Finally, we can build i2pd with all that goodness
```sh
git clone https://github.com/PurpleI2P/i2pd
mkdir i2pd-mingw-64-build
cd i2pd-mingw-64-build
BOOST_ROOT=~/dev/boost_1_60_0 cmake -G 'Unix Makefiles' ~/dev/i2pd/build -DBUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=~/dev/toolchain-mingw.cmake -DWITH_AESNI=ON -DWITH_UPNP=ON -DWITH_STATIC=ON \
-DWITH_HARDENING=ON -DCMAKE_INSTALL_PREFIX:PATH=~/dev/i2pd-mingw-64-static \
-DZLIB_ROOT=~/dev/stage -DBOOST_LIBRARYDIR:PATH=~/dev/boost_1_60_0/stage-mingw-64/lib \
-DOPENSSL_ROOT_DIR:PATH=~/dev/stage
make
x86_64-w64-mingw32-strip i2pd.exe
```
By now, you should have a release build with stripped symbols.

17
docs/configuration.md

@ -17,9 +17,9 @@ Command line options
* --port= - The port to listen on * --port= - The port to listen on
* --daemon - Router will go to background after start * --daemon - Router will go to background after start
* --service - Router will use system folders like '/var/lib/i2pd' * --service - Router will use system folders like '/var/lib/i2pd'
* --ipv6 - Enable communication through ipv6 * --ipv6 - Enable communication through ipv6. false by default
* --notransit - Router will not accept transit tunnels at startup * --notransit - Router will not accept transit tunnels at startup. false by default
* --floodfill - Router will be floodfill * --floodfill - Router will be floodfill. false by default
* --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited * --bandwidth= - L if bandwidth is limited to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited
* --family= - Name of a family, router belongs to * --family= - Name of a family, router belongs to
* --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove") * --svcctl= - Windows service management (--svcctl="install" or --svcctl="remove")
@ -30,21 +30,26 @@ Command line options
* --httpproxy.address= - The address to listen on (HTTP Proxy) * --httpproxy.address= - The address to listen on (HTTP Proxy)
* --httpproxy.port= - The port to listen on (HTTP Proxy) 4446 by default * --httpproxy.port= - The port to listen on (HTTP Proxy) 4446 by default
* --httpproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS) * --httpproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS)
* --httpproxy.enabled= - If HTTP proxy is enabled. true by default
* --socksproxy.address= - The address to listen on (SOCKS Proxy) * --socksproxy.address= - The address to listen on (SOCKS Proxy)
* --socksproxy.port= - The port to listen on (SOCKS Proxy). 4447 by default * --socksproxy.port= - The port to listen on (SOCKS Proxy). 4447 by default
* --socksproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS) * --socksproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS)
* --socksproxy.enabled= - If SOCKS proxy is enabled. true by default
* --socksproxy.outproxy= - Address of outproxy. requests outside i2p will go there * --socksproxy.outproxy= - Address of outproxy. requests outside i2p will go there
* --socksproxy.outproxyport= - Outproxy remote port * --socksproxy.outproxyport= - Outproxy remote port
* --sam.address= - The address to listen on (SAM bridge) * --sam.address= - The address to listen on (SAM bridge)
* --sam.port= - Port of SAM bridge. Usually 7656. SAM is off if not specified * --sam.port= - Port of SAM bridge. Usually 7656. SAM is off if not specified
* --sam.enabled= - If SAM is enabled. false by default
* --bob.address= - The address to listen on (BOB command channel) * --bob.address= - The address to listen on (BOB command channel)
* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified * --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified
* --sam.enabled= - If BOB is enabled. false by default
* --i2pcontrol.address= - The address to listen on (I2P control service) * --i2pcontrol.address= - The address to listen on (I2P control service)
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified * --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
* --i2pcontrol.enabled= - If I2P control is enabled. false by default
Config files Config files
------------ ------------
@ -58,15 +63,15 @@ For example:
i2p.conf: i2p.conf:
# comment # comment
log = yes log = true
ipv6 = yes ipv6 = true
# settings for specific module # settings for specific module
[httpproxy] [httpproxy]
port = 4444 port = 4444
# ^^ this will be --httproxy.port= in cmdline # ^^ this will be --httproxy.port= in cmdline
# another one # another one
[sam] [sam]
enabled = yes enabled = true
tunnels.cfg (filename of this config is subject of change): tunnels.cfg (filename of this config is subject of change):

111
docs/i2pd.conf

@ -0,0 +1,111 @@
## Configuration file for a typical i2pd user
## See https://i2pd.readthedocs.org/en/latest/configuration.html
## for more options you can use in this file.
## Lines that begin with "## " try to explain what's going on. Lines
## that begin with just "#" are disabled commands: you can enable them
## by removing the "#" symbol.
## Tunnels config file
## Default: ~/.i2pd/tunnels.cfg or /var/lib/i2pd/tunnels.cfg
#tunconf = /var/lib/i2pd/tunnels.cfg
## Where to write pidfile (don't write by default)
#pidfile = /var/run/i2pd.pid
## Logging configuration section
## By default logs go to stdout with level info
##
## Logs destination (stdout, file)
#log = file
## Path to logfile (default - autodetect)
#logfile = /var/log/i2pd.log
## Log messages above this level (debug, *info, warn, error)
#loglevel = info
## Path to storage of i2pd data (RI, keys, peer profiles, ...)
## Default: ~/.i2pd or /var/lib/i2pd
#datadir = /var/lib/i2pd
## Daemon mode. Router will go to background after start
#daemon
## Run as a service. Router will use system folders like ‘/var/lib/i2pd’
#service
## External IP address to listen for connections
## By default i2pd sets IP automatically
#host = 1.2.3.4
## Port to listen for connections
## By default i2pd picks random port. You MUST pick a random number too,
## don't just uncomment this
#port = 4321
##Enable communication through ipv6
ipv6
## Bandwidth configuration
## L limit bandwidth to 32Kbs/sec, O - to 256Kbs/sec, P - unlimited
## Default is P for floodfill, L for regular node
#bandwidth = L
## Router will not accept transit tunnels at startup
#notransit
## Router will be floodfill
#floodfill
## Section for Web Console
## By default it's available at 127.0.0.1:7070 even if it's not configured
[http]
## The address to listen on
address = 127.0.0.1
## The port to listen on
port = 7070
## Section for HTTP proxy
## By default it's available at 127.0.0.1:4444 even if it's not configured
[httpproxy]
## The address to listen on
address = 127.0.0.1
## The port to listen on
port = 4444
## Optional keys file for proxy local destination
#keys = http-proxy-keys.dat
## Uncomment if you want to disable HTTP proxy
#enabled=false
## Section for Socks proxy
## By default it's available at 127.0.0.1:4447 even if it's not configured
#[socksproxy]
## The address to listen on
#address = 127.0.0.1
## The port to listen on
#port = 4447
## Optional keys file for proxy local destination
#keys = socks-proxy-keys.dat
## Uncomment if you want to disable Socks proxy
#enabled=false
## Socks outproxy. Example below is set to use Tor for all connections except i2p
## Address of outproxy
#outproxy = 127.0.0.1
## Outproxy remote port
#outproxyport = 9050
## Section for SAM bridge
#[sam]
## The address to listen on
#address = 127.0.0.1
## Port of SAM bridge
#port = 7656
## Section for BOB command channel
#[bob]
## The address to listen on
#address = 127.0.0.1
## Port of BOB command channel. Usually 2827. BOB is off if not specified
#port = 2827
## Section for I2PControl protocol
#[i2pcontrol]
## The address to listen on
#address = 127.0.0.1
## Port of I2P control service
#port = 7650
Loading…
Cancel
Save