Browse Source

Merge pull request #66 from chertov/master

http status code, load host.txt via proxy
pull/70/head
orignal 11 years ago
parent
commit
4cbc7773ac
  1. 13
      AddressBook.cpp
  2. 49
      HTTPServer.cpp
  3. 4
      HTTPServer.h
  4. 1
      Win32/.gitignore
  5. 6
      Win32/i2pd.vcxproj
  6. 81
      Win32/inno_installer.iss
  7. 67
      util.cpp
  8. 10
      util.h

13
AddressBook.cpp

@ -33,17 +33,12 @@ const IdentHash * AddressBook::FindAddress (const std::string& address)
void AddressBook::LoadHostsFromI2P () void AddressBook::LoadHostsFromI2P ()
{ {
std::string content; std::string content;
std::stringstream url_ss;
// TODO: hosts link in config
// TODO: url download via HTTPProxy
url_ss << "http://127.0.0.1:" << i2p::util::config::GetArg("-httpport", 7070) << "/udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna/hosts.txt";
while (true) while (true)
{ {
content = i2p::util::http::httpRequest(url_ss.str()); // TODO: hosts link in config
int http_code = i2p::util::http::httpRequestViaI2pProxy("http://udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p/hosts.txt", content);
// TODO: check http errors if (http_code ==200)
if (! boost::starts_with(content, "<html>") && content.size() > 0) if (!boost::starts_with(content, "<html>") && !content.empty()) // TODO: test and remove
break; break;
std::this_thread::sleep_for(std::chrono::seconds(5)); std::this_thread::sleep_for(std::chrono::seconds(5));
} }

49
HTTPServer.cpp

@ -118,12 +118,26 @@ namespace util
} // namespace misc_strings } // namespace misc_strings
std::vector<boost::asio::const_buffer> HTTPConnection::reply::to_buffers() std::vector<boost::asio::const_buffer> HTTPConnection::reply::to_buffers(int status)
{ {
std::vector<boost::asio::const_buffer> buffers; std::vector<boost::asio::const_buffer> buffers;
if (headers.size () > 0) if (headers.size () > 0)
{ {
buffers.push_back (boost::asio::buffer ("HTTP/1.0 200 OK\r\n")); // always OK switch (status)
{
case 105: buffers.push_back(boost::asio::buffer("HTTP/1.0 105 Name Not Resolved\r\n")); break;
case 200: buffers.push_back(boost::asio::buffer("HTTP/1.0 200 OK\r\n")); break;
case 400: buffers.push_back(boost::asio::buffer("HTTP/1.0 400 Bad Request\r\n")); break;
case 404: buffers.push_back(boost::asio::buffer("HTTP/1.0 404 Not Found\r\n")); break;
case 408: buffers.push_back(boost::asio::buffer("HTTP/1.0 408 Request Timeout\r\n")); break;
case 500: buffers.push_back(boost::asio::buffer("HTTP/1.0 500 Internal Server Error\r\n")); break;
case 502: buffers.push_back(boost::asio::buffer("HTTP/1.0 502 Bad Gateway\r\n")); break;
case 503: buffers.push_back(boost::asio::buffer("HTTP/1.0 503 Not Implemented\r\n")); break;
case 504: buffers.push_back(boost::asio::buffer("HTTP/1.0 504 Gateway Timeout\r\n")); break;
default:
buffers.push_back(boost::asio::buffer("HTTP/1.0 200 OK\r\n"));
}
for (std::size_t i = 0; i < headers.size(); ++i) for (std::size_t i = 0; i < headers.size(); ++i)
{ {
header& h = headers[i]; header& h = headers[i];
@ -311,13 +325,25 @@ namespace util
{ {
i2p::data::IdentHash destination; i2p::data::IdentHash destination;
std::string fullAddress; std::string fullAddress;
if (address.find (".i2p") != std::string::npos) if (address.find(".b32.i2p") != std::string::npos)
{
if (i2p::data::Base32ToByteStream(address.c_str(), address.length() - strlen(".b32.i2p"), (uint8_t *)destination, 32) != 32)
{
LogPrint ("Invalid Base32 address ", address);
SendReply ("<html>" + itoopieImage + "<br>Invalid Base32 address", 400);
return;
}
fullAddress = address;
}
else
{
if (address.find(".i2p") != std::string::npos)
{ {
auto addr = i2p::data::netdb.FindAddress(address); auto addr = i2p::data::netdb.FindAddress(address);
if (!addr) if (!addr)
{ {
LogPrint ("Unknown address ", address); LogPrint ("Unknown address ", address);
SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>"); SendReply ("<html>" + itoopieImage + "<br>Unknown address " + address + "</html>", 105);
return; return;
} }
destination = *addr; destination = *addr;
@ -325,14 +351,15 @@ namespace util
} }
else else
{ {
if (i2p::data::Base32ToByteStream (address.c_str (), address.length (), (uint8_t *)destination, 32) != 32) if (i2p::data::Base32ToByteStream(address.c_str(), address.length(), (uint8_t *)destination, 32) != 32)
{ {
LogPrint ("Invalid Base32 address ", address); LogPrint("Invalid Base32 address ", address);
SendReply ("<html>" + itoopieImage + "<br>Invalid Base32 address"); SendReply("<html>" + itoopieImage + "<br>Invalid Base32 address", 400);
return; return;
} }
fullAddress = address + ".b32.i2p"; fullAddress = address + ".b32.i2p";
} }
}
auto leaseSet = i2p::data::netdb.FindLeaseSet (destination); auto leaseSet = i2p::data::netdb.FindLeaseSet (destination);
if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) if (!leaseSet || !leaseSet->HasNonExpiredLeases ())
@ -342,7 +369,7 @@ namespace util
leaseSet = i2p::data::netdb.FindLeaseSet (destination); leaseSet = i2p::data::netdb.FindLeaseSet (destination);
if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet if (!leaseSet || !leaseSet->HasNonExpiredLeases ()) // still no LeaseSet
{ {
SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>"); SendReply (leaseSet ? "<html>" + itoopieImage + "<br>Leases expired</html>" : "<html>" + itoopieImage + "LeaseSet not found</html>", 504);
return; return;
} }
} }
@ -375,13 +402,13 @@ namespace util
else else
{ {
if (m_Stream && m_Stream->IsOpen ()) if (m_Stream && m_Stream->IsOpen ())
SendReply ("<html>" + itoopieImage + "<br>Not responding</html>"); SendReply ("<html>" + itoopieImage + "<br>Not responding</html>", 504);
else else
Terminate (); Terminate ();
} }
} }
void HTTPConnection::SendReply (const std::string& content) void HTTPConnection::SendReply (const std::string& content, int status)
{ {
m_Reply.content = content; m_Reply.content = content;
m_Reply.headers.resize(2); m_Reply.headers.resize(2);
@ -390,7 +417,7 @@ namespace util
m_Reply.headers[1].name = "Content-Type"; m_Reply.headers[1].name = "Content-Type";
m_Reply.headers[1].value = "text/html"; m_Reply.headers[1].value = "text/html";
boost::asio::async_write (*m_Socket, m_Reply.to_buffers(), boost::asio::async_write (*m_Socket, m_Reply.to_buffers(status),
boost::bind (&HTTPConnection::HandleWriteReply, this, boost::bind (&HTTPConnection::HandleWriteReply, this,
boost::asio::placeholders::error)); boost::asio::placeholders::error));
} }

4
HTTPServer.h

@ -36,7 +36,7 @@ namespace util
std::vector<header> headers; std::vector<header> headers;
std::string content; std::string content;
std::vector<boost::asio::const_buffer> to_buffers(); std::vector<boost::asio::const_buffer> to_buffers (int status);
}; };
public: public:
@ -53,7 +53,7 @@ namespace util
void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
void HandleWriteReply(const boost::system::error_code& ecode); void HandleWriteReply(const boost::system::error_code& ecode);
void HandleWrite (const boost::system::error_code& ecode); void HandleWrite (const boost::system::error_code& ecode);
void SendReply (const std::string& content); void SendReply (const std::string& content, int status = 200);
void HandleRequest (); void HandleRequest ();
void FillContent (std::stringstream& s); void FillContent (std::stringstream& s);

1
Win32/.gitignore vendored

@ -5,4 +5,5 @@
!*.vcproj !*.vcproj
!*.vcxproj !*.vcxproj
!*.vcxproj.filters !*.vcxproj.filters
!*.iss
!.gitignore !.gitignore

6
Win32/i2pd.vcxproj

@ -106,8 +106,9 @@
<SourcePath>./..;$(VC_SourcePath);</SourcePath> <SourcePath>./..;$(VC_SourcePath);</SourcePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>.\boost;.\cryptopp;$(IncludePath)</IncludePath> <IncludePath>./..;$(BOOST);$(CRYPTOPP);$(IncludePath)</IncludePath>
<LibraryPath>.\stage-x86\lib;$(LibraryPath)</LibraryPath> <LibraryPath>$(BOOST)\stage\lib;$(CRYPTOPP)\cryptopp\Win32\Output\$(Configuration)\;$(LibraryPath)</LibraryPath>
<SourcePath>./..;$(VC_SourcePath);</SourcePath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
@ -134,6 +135,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>cryptlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

81
Win32/inno_installer.iss

@ -0,0 +1,81 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "0.1"
[Setup]
AppName={#I2Pd_AppName}
AppVersion={#I2Pd_ver}
DefaultDirName={pf}\I2Pd
DefaultGroupName=I2Pd
UninstallDisplayIcon={app}\I2Pd.exe
Compression=lzma2
SolidCompression=yes
OutputDir=.
LicenseFile=.\..\LICENSE
OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver}
[Files]
Source: "i2pd.exe"; DestDir: "{app}"
[Icons]
Name: "{group}\I2Pd"; Filename: "{app}\i2pd.exe"
[Code]
var
DefaultTop,
DefaultLeft,
DefaultHeight,
DefaultBackTop,
DefaultNextTop,
DefaultCancelTop,
DefaultBevelTop,
DefaultOuterHeight: Integer;
const
LicenseHeight = 400;
procedure InitializeWizard();
begin
DefaultTop := WizardForm.Top;
DefaultLeft := WizardForm.Left;
DefaultHeight := WizardForm.Height;
DefaultBackTop := WizardForm.BackButton.Top;
DefaultNextTop := WizardForm.NextButton.Top;
DefaultCancelTop := WizardForm.CancelButton.Top;
DefaultBevelTop := WizardForm.Bevel.Top;
DefaultOuterHeight := WizardForm.OuterNotebook.Height;
WizardForm.InnerPage.Height := WizardForm.InnerPage.Height + (LicenseHeight - DefaultHeight);
WizardForm.InnerNotebook.Height := WizardForm.InnerNotebook.Height + (LicenseHeight - DefaultHeight);
WizardForm.LicensePage.Height := WizardForm.LicensePage.Height + (LicenseHeight - DefaultHeight);
WizardForm.LicenseMemo.Height := WizardForm.LicenseMemo.Height + (LicenseHeight - DefaultHeight);
WizardForm.LicenseNotAcceptedRadio.Top := WizardForm.LicenseNotAcceptedRadio.Top + (LicenseHeight - DefaultHeight);
WizardForm.LicenseAcceptedRadio.Top := WizardForm.LicenseAcceptedRadio.Top + (LicenseHeight - DefaultHeight);
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpLicense then
begin
WizardForm.Top := DefaultTop - (LicenseHeight - DefaultHeight) div 2;
WizardForm.Height := LicenseHeight;
WizardForm.OuterNotebook.Height := WizardForm.OuterNotebook.Height + (LicenseHeight - DefaultHeight);
WizardForm.CancelButton.Top := DefaultCancelTop + (LicenseHeight - DefaultHeight);
WizardForm.NextButton.Top := DefaultNextTop + (LicenseHeight - DefaultHeight);
WizardForm.BackButton.Top := DefaultBackTop + (LicenseHeight - DefaultHeight);
WizardForm.Bevel.Top := DefaultBevelTop + (LicenseHeight - DefaultHeight);
end
else
begin
WizardForm.Top := DefaultTop;
WizardForm.Left := DefaultLeft;
WizardForm.Height := DefaultHeight;
WizardForm.OuterNotebook.Height := DefaultOuterHeight;
WizardForm.CancelButton.Top := DefaultCancelTop;
WizardForm.NextButton.Top := DefaultNextTop;
WizardForm.BackButton.Top := DefaultBackTop;
WizardForm.Bevel.Top := DefaultBevelTop;
end;
end;

67
util.cpp

@ -249,13 +249,72 @@ namespace http
} }
} }
std::string url::portstr_ = "80"; int httpRequestViaI2pProxy(const std::string& address, std::string &content)
unsigned int url::port_ = 80; {
std::string url::user_ = ""; content = "";
std::string url::pass_ = ""; try
{
boost::asio::ip::tcp::iostream site;
// please don't uncomment following line because it's not compatible with boost 1.46
// 1.46 is default boost for Ubuntu 12.04 LTS
//site.expires_from_now (boost::posix_time::seconds(30));
{
std::stringstream ss; ss << i2p::util::config::GetArg("-httpproxyport", 4446);
site.connect("127.0.0.1", ss.str());
}
if (site)
{
i2p::util::http::url u(address);
std::stringstream ss;
ss << "GET " << address << " HTTP/1.0" << std::endl;
ss << "Host: " << u.host_ << std::endl;
ss << "Accept: */*" << std::endl;
ss << "User - Agent: Wget / 1.11.4" << std::endl;
ss << "Connection: close" << std::endl;
ss << std::endl;
site << ss.str();
// read response
std::string version, statusMessage;
site >> version; // HTTP version
int status;
site >> status; // status
std::getline(site, statusMessage);
if (status == 200) // OK
{
std::string header;
while (std::getline(site, header) && header != "\r"){}
std::stringstream ss;
ss << site.rdbuf();
content = ss.str();
return status;
}
else
{
LogPrint("HTTP response ", status);
return status;
}
}
else
{
LogPrint("Can't connect to proxy");
return 408;
}
}
catch (std::exception& ex)
{
LogPrint("Failed to download ", address, " : ", ex.what());
return 408;
}
}
url::url(const std::string& url_s) url::url(const std::string& url_s)
{ {
portstr_ = "80";
port_ = 80;
user_ = "";
pass_ = "";
parse(url_s); parse(url_s);
} }

10
util.h

@ -35,16 +35,18 @@ namespace util
namespace http namespace http
{ {
std::string httpRequest(const std::string& address); std::string httpRequest(const std::string& address);
int httpRequestViaI2pProxy(const std::string& address, std::string &content); // return http code
struct url { struct url {
url(const std::string& url_s); // omitted copy, ==, accessors, ... url(const std::string& url_s); // omitted copy, ==, accessors, ...
private: private:
void parse(const std::string& url_s); void parse(const std::string& url_s);
public: public:
std::string protocol_, host_, path_, query_; std::string protocol_, host_, path_, query_;
static std::string portstr_; std::string portstr_;
static unsigned int port_; unsigned int port_;
static std::string user_; std::string user_;
static std::string pass_; std::string pass_;
}; };
} }
} }

Loading…
Cancel
Save