23 #include <ns3/packet.h>
25 #include "ns3/http-header.h"
45 const std::string& url,
46 const std::string& method,
47 const std::map<std::string, std::string>& parameters,
48 const std::vector<std::string>& headers)
55 for (
const auto& parameter : parameters)
57 if (!
first) body +=
"&";
68 const std::string& url,
69 const std::string& method,
70 const std::string& body,
71 const std::vector<std::string>& headers)
78 std::vector<uint8_t>(body.begin(), body.end()),
85 const std::string& url,
86 const std::string& method,
87 const std::vector<uint8_t>& body,
88 const std::vector<std::string>& headers
96 std::string headerData = method +
" " +
m_path +
" HTTP/1.1\r\n";
98 for (
const std::string& header : headers){
99 headerData += header +
"\r\n";
102 headerData +=
"Host: " +
m_domain +
"\r\n"
107 headerData +=
"Accept-Language: en-us,en;q=0.5\r\n";
108 headerData +=
"Accept-Encoding: gzip,deflate\r\n";
109 headerData +=
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
110 headerData +=
"Keep-Alive: 300\r\n";
111 headerData +=
"Connection: keep-alive\r\n";
112 headerData +=
"Cookie: PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120\r\n";
113 headerData +=
"Pragma: no-cache\r\n";
114 headerData +=
"Cache-Control: no-cache\r\n" "\r\n";
122 std::vector<uint8_t> requestData(headerData.begin(), headerData.end());
143 const std::string& body,
144 const std::vector<std::string>& headers)
148 std::vector<uint8_t>(body.begin(), body.end()),
156 const std::vector<uint8_t>& body,
157 const std::vector<std::string>& headers
160 std::string bodyString = std::string{body.begin(), body.end()};
169 for (
const std::string& header : headers){
170 headerData += header +
"\r\n";
173 headerData +=
"Server: nginx/1.17.0 (Ubuntu)\r\n"
178 headerData +=
"Date: Sat, 28 Nov 2021 04:36:25 GMT\r\n";
179 headerData +=
"Connection: close\r\n";
180 headerData +=
"Pragma: public\r\n";
181 headerData +=
"Etag: pub1259380237;gz\r\n";
182 headerData +=
"Cache-Control: max-age=3600, public\r\n";
183 headerData +=
"Content-Encoding: gzip\r\n";
184 headerData +=
"Vary: Accept-Encoding, Cookie\r\n" "\r\n";
191 std::vector<uint8_t> requestData(headerData.begin(), headerData.end());
206 constexpr std::uint8_t crlf[] = {
'\r',
'\n'};
207 std::vector<std::uint8_t> responseData =
m_allData;
208 bool firstLine =
true;
209 bool parsedHeaders =
false;
210 bool contentLengthReceived =
false;
211 bool chunkedResponse =
false;
212 std::size_t expectedChunkSize = 0;
213 bool removeCrlfAfterChunk =
false;
220 const auto i = std::search(responseData.begin(), responseData.end(), std::begin(crlf), std::end(crlf));
223 if (i == responseData.end())
break;
225 const std::string line(responseData.begin(), i);
226 responseData.erase(responseData.begin(), i + 2);
234 parsedHeaders =
true;
242 std::string::size_type lastPos = 0;
243 const auto length = line.length();
244 std::vector<std::string> parts;
247 while (lastPos < length + 1)
249 auto pos = line.find(
' ', lastPos);
250 if (pos == std::string::npos) pos = length;
253 parts.emplace_back(line.data() + lastPos,
254 static_cast<std::vector<std::string>::size_type
>(pos) - lastPos);
261 if (parts.size() >= 2){
262 if(parts[0] ==
"HTTP/1.1"){
275 const auto pos = line.find(
':');
277 if (pos != std::string::npos)
279 std::string headerName = line.substr(0, pos);
280 std::string headerValue = line.substr(pos + 1);
283 headerValue.erase(headerValue.begin(),
284 std::find_if(headerValue.begin(), headerValue.end(),
285 [](
int c) {return !std::isspace(c);}));
288 headerValue.erase(std::find_if(headerValue.rbegin(), headerValue.rend(),
289 [](
int c) {return !std::isspace(c);}).base(),
292 if (headerName ==
"Content-Length")
295 contentLengthReceived =
true;
298 else if (headerName ==
"Request URI")
302 else if (headerName ==
"Transfer-Encoding")
304 if (headerValue ==
"chunked")
305 chunkedResponse =
true;
309 else if (headerName ==
"Host")
324 bool dataReceived =
false;
330 if (expectedChunkSize > 0)
332 const auto toWrite =
std::min(expectedChunkSize, responseData.size());
333 m_payload.insert(
m_payload.end(), responseData.begin(), responseData.begin() +
static_cast<ptrdiff_t
>(toWrite));
334 m_allData.insert(
m_allData.end(), responseData.begin(), responseData.begin() +
static_cast<ptrdiff_t
>(toWrite));
335 responseData.erase(responseData.begin(), responseData.begin() +
static_cast<ptrdiff_t
>(toWrite));
336 expectedChunkSize -= toWrite;
339 if (expectedChunkSize == 0) removeCrlfAfterChunk =
true;
340 if (responseData.empty())
break;
344 if (removeCrlfAfterChunk)
346 if (responseData.size() >= 2)
348 removeCrlfAfterChunk =
false;
349 responseData.erase(responseData.begin(), responseData.begin() + 2);
354 const auto i = std::search(responseData.begin(), responseData.end(), std::begin(crlf), std::end(crlf));
356 if (i == responseData.end())
break;
358 const std::string line(responseData.begin(), i);
359 responseData.erase(responseData.begin(), i + 2);
361 expectedChunkSize = std::stoul(line,
nullptr, 16);
363 if (expectedChunkSize == 0)
378 responseData.clear();
387 NS_LOG_FUNCTION(
this <<
"Extract header data from the rest of the payload!");
396 NS_LOG_FUNCTION(
this <<
"287!!!!!!!" << chunkedResponse << contentLengthReceived << payload);
424 std::vector<uint8_t> vec(input.begin(), input.end());
430 "input.size(): " << input.size() <<
"\n" <<
433 "Headers.size():" <<
m_headers.size() <<
"\n"
483 .AddConstructor<HttpHeader> ()
543 std::vector<uint8_t> receivedData(tmpBuffer, tmpBuffer +
m_contentLength /
sizeof(
char));
570 std::ostringstream oss;
1007 return "SwitchingProtocol";
1009 return "Processing";
1011 return "EarlyHints";
1020 return "NonAuthoritativeInformation";
1024 return "ResetContent";
1026 return "PartialContent";
1028 return "MultiStatus";
1030 return "AlreadyReported";
1035 return "MultipleChoice";
1037 return "MovedPermanently";
1043 return "NotModified";
1047 return "TemporaryRedirect";
1049 return "PermanentRedirect";
1052 return "BadRequest";
1054 return "Unauthorized";
1056 return "PaymentRequired";
1062 return "MethodNotAllowed";
1064 return "NotAcceptable";
1066 return "ProxyAuthenticationRequired";
1068 return "RequestTimeout";
1074 return "LengthRequired";
1076 return "PreconditionFailed";
1078 return "PayloadTooLarge";
1080 return "UriTooLong";
1082 return "UnsupportedMediaType";
1084 return "RangeNotSatisfiable";
1086 return "ExpectationFailed";
1090 return "MisdirectedRequest";
1092 return "UnprocessableEntity";
1096 return "FailedDependency";
1100 return "UpgradeRequired";
1102 return "PreconditionRequired";
1104 return "TooManyRequests";
1106 return "RequestHeaderFieldsTooLarge";
1108 return "UnavailableForLegalReasons";
1111 return "InternalServerError";
1113 return "NotImplemented";
1115 return "BadGateway";
1117 return "ServiceUnavailable";
1119 return "GatewayTimeout";
1121 return "HttpVersionNotSupported";
1123 return "VariantAlsoNegotiates";
1125 return "InsufficientStorage";
1127 return "LoopDetected";
1129 return "NotExtended";
1131 return "NetworkAuthenticationRequired";
1148 else if (m ==
"GET")
1150 else if (m ==
"HEAD")
1152 else if (m ==
"PATCH")
1154 else if (m ==
"POST")
1156 else if (m ==
"PUT")
1231 constexpr
char hexChars[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
1235 for (
auto i = str.begin(); i != str.end(); ++i)
1237 const std::uint8_t cp = *i & 0xFF;
1239 if ((cp >= 0x30 && cp <= 0x39) ||
1240 (cp >= 0x41 && cp <= 0x5A) ||
1241 (cp >= 0x61 && cp <= 0x7A) ||
1242 cp == 0x2D || cp == 0x2E || cp == 0x5F)
1243 result +=
static_cast<char>(cp);
1244 else if (cp <= 0x7F)
1245 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1246 else if ((cp >> 5) == 0x06)
1248 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1249 if (++i == str.end())
break;
1250 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1252 else if ((cp >> 4) == 0x0E)
1254 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1255 if (++i == str.end())
break;
1256 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1257 if (++i == str.end())
break;
1258 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1260 else if ((cp >> 3) == 0x1E)
1262 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1263 if (++i == str.end())
break;
1264 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1265 if (++i == str.end())
break;
1266 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1267 if (++i == str.end())
break;
1268 result += std::string(
"%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1293 const auto schemeEndPosition = url.find(
"://");
1295 if (schemeEndPosition != std::string::npos)
1297 m_scheme = url.substr(0, schemeEndPosition);
1298 m_path = url.substr(schemeEndPosition + 3);
1306 const auto fragmentPosition =
m_path.find(
'#');
1309 if (fragmentPosition != std::string::npos)
1310 m_path.resize(fragmentPosition);
1312 const auto pathPosition =
m_path.find(
'/');
1314 if (pathPosition == std::string::npos)
1325 const auto portPosition =
m_domain.find(
':');
1327 if (portPosition != std::string::npos)
iterator in a Buffer instance
void Read(uint8_t *buffer, uint32_t size)
uint32_t GetDistanceFrom(Iterator const &o) const
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Every class exported by the ns3 library is enclosed in the ns3 namespace.