Browse Source

case-insensitive headers

pull/1763/head
orignal 3 years ago
parent
commit
2d4c7729ad
  1. 98
      libi2pd_client/I2PTunnel.cpp
  2. 5
      libi2pd_client/I2PTunnel.h

98
libi2pd_client/I2PTunnel.cpp

@ -7,6 +7,7 @@
*/ */
#include <cassert> #include <cassert>
#include <boost/algorithm/string.hpp>
#include "Base.h" #include "Base.h"
#include "Log.h" #include "Log.h"
#include "Destination.h" #include "Destination.h"
@ -337,38 +338,72 @@ namespace client
I2PTunnelConnection::Write (buf, len); I2PTunnelConnection::Write (buf, len);
else else
{ {
auto headerLen = m_ClientRequest.parse ((const char *)buf, len); m_InHeader.clear ();
if (!headerLen) return; // request is not complete, wait for next portion m_InHeader.write ((const char *)buf, len);
if (headerLen < 0) std::string line;
bool endOfHeader = false, connection = false;
while (!endOfHeader)
{ {
LogPrint (eLogError, "I2PTunnel: Can't parse HTTP request"); std::getline(m_InHeader, line);
Terminate (); if (!m_InHeader.fail ())
return; {
} if (line == "\r") endOfHeader = true;
else
m_ClientRequest.RemoveHeader ("Keep-Alive"); {
auto h = m_ClientRequest.GetHeader ("Connection"); // strip up some headers
if (h.empty ()) static const std::vector<std::string> excluded // list of excluded headers
m_ClientRequest.AddHeader ("Connection", "close"); {
else if (h != "close") "Keep-Alive:", "X-I2P"
{ };
// Upgrade or upgrade ? bool matched = false;
auto x = h.find("pgrade"); for (const auto& it: excluded)
if (x == std::string::npos || !x || std::tolower(h[x - 1]) != 'u') if (boost::iequals (line.substr (0, it.length ()), it))
m_ClientRequest.UpdateHeader("Connection", "close"); {
} matched = true;
if (!m_Host.empty ()) break;
m_ClientRequest.UpdateHeader ("Host", m_Host); }
m_ClientRequest.AddHeader (X_I2P_DEST_B32, context.GetAddressBook ().ToAddress(m_From->GetIdentHash ())); if (matched) break;
m_ClientRequest.AddHeader (X_I2P_DEST_HASH, m_From->GetIdentHash ().ToBase64 ());
m_ClientRequest.AddHeader (X_I2P_DEST_B64, m_From->ToBase64 ()); // replace some headers
if (!m_Host.empty () && boost::iequals (line.substr (0, 5), "Host:"))
m_RequestSendBuffer = m_ClientRequest.to_string (); m_OutHeader << "Host: " << m_Host << "\r\n"; // override host
if ((size_t)headerLen < len) else if (boost::iequals (line.substr (0, 11), "Connection:"))
m_RequestSendBuffer.append ((const char *)(buf + headerLen), len - headerLen); // data right after header {
m_From = nullptr; auto x = line.find("pgrade");
m_HeaderSent = true; if (x != std::string::npos && x && std::tolower(line[x - 1]) != 'u') // upgrade or Upgrade
I2PTunnelConnection::Write ((uint8_t *)m_RequestSendBuffer.c_str (), m_RequestSendBuffer.length ()); m_OutHeader << line << "\n";
else
m_OutHeader << "Connection: close\r\n";
connection = true;
}
else // forward as is
m_OutHeader << line << "\n";
}
}
else
break;
}
if (endOfHeader)
{
// add Connection if not presented
if (!connection)
m_OutHeader << "Connection: close\r\n";
// add X-I2P fields
if (m_From)
{
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
}
m_OutHeader << "\r\n"; // end of header
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
m_InHeader.str ("");
m_From = nullptr;
m_HeaderSent = true;
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
}
} }
} }
@ -1134,3 +1169,4 @@ namespace client
} }
} }
} }

5
libi2pd_client/I2PTunnel.h

@ -20,7 +20,6 @@
#include "Destination.h" #include "Destination.h"
#include "Datagram.h" #include "Datagram.h"
#include "Streaming.h" #include "Streaming.h"
#include "HTTP.h"
#include "I2PService.h" #include "I2PService.h"
#include "AddressBook.h" #include "AddressBook.h"
@ -111,9 +110,7 @@ namespace client
private: private:
std::string m_Host; std::string m_Host;
i2p::http::HTTPReq m_ClientRequest; std::stringstream m_InHeader, m_OutHeader;
std::string m_RequestSendBuffer;
std::stringstream m_InHeader, m_OutHeader; // for responses
bool m_HeaderSent, m_ResponseHeaderSent; bool m_HeaderSent, m_ResponseHeaderSent;
std::shared_ptr<const i2p::data::IdentityEx> m_From; std::shared_ptr<const i2p::data::IdentityEx> m_From;
}; };

Loading…
Cancel
Save