A Discrete-Event Network Simulator
API
http-header.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015 Magister Solutions
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Miralem Mehic <miralem.mehic@ieee.org>
19  *
20  */
21 
22 #include <ns3/log.h>
23 #include <ns3/packet.h>
24 #include <sstream>
25 #include "ns3/http-header.h"
26 
27 NS_LOG_COMPONENT_DEFINE ("HttpHeader");
28 
29 namespace ns3 {
30 
31 NS_OBJECT_ENSURE_REGISTERED (HttpHeader);
32 
34  : Header (),
35  m_status(0),
36  m_contentLength (0),
37  m_headerSize (0)
38 {
39  NS_LOG_FUNCTION (this);
40  m_fragmented = false;
41 }
42 
43 void
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)
49 {
50  NS_LOG_FUNCTION(this << "48");
51 
52  std::string body;
53  bool first = true;
54 
55  for (const auto& parameter : parameters)
56  {
57  if (!first) body += "&";
58  first = false;
59 
60  body += urlEncode(parameter.first) + "=" + urlEncode(parameter.second);
61  }
62 
63  CreateRequest(url, method, body, headers);
64 }
65 
66 void
68  const std::string& url,
69  const std::string& method,
70  const std::string& body,
71  const std::vector<std::string>& headers)
72 {
73  NS_LOG_FUNCTION(this << "71");
74 
76  url,
77  method,
78  std::vector<uint8_t>(body.begin(), body.end()),
79  headers
80  );
81 }
82 
83 void
85  const std::string& url,
86  const std::string& method,
87  const std::vector<uint8_t>& body,
88  const std::vector<std::string>& headers
89 ) {
90 
91  NS_LOG_FUNCTION(this << "89" << url << method);
92  SetUri(url);
93  SetMethod(method);
94  m_headers = headers;
95 
96  std::string headerData = method + " " + m_path + " HTTP/1.1\r\n";
97 
98  for (const std::string& header : headers){
99  headerData += header + "\r\n";
100  }
101 
102  headerData += "Host: " + m_domain + "\r\n"
103  "Content-Length: " + std::to_string(body.size()) + "\r\n";
104 
105  //if(body.size()>300) headerData += "Transfer-Encoding: chunked\r\n";
106 
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";
115 
116 
117 
118  m_allData.clear();
119  m_payload.clear();
120 
121  //add headers
122  std::vector<uint8_t> requestData(headerData.begin(), headerData.end());
123  m_allData = requestData;
124 
125  //add payload
126  m_allData.insert(m_allData.end(), body.begin(), body.end());
127  m_payload.insert(m_payload.end(), body.begin(), body.end());
128 
129  NS_LOG_FUNCTION(this << "headerData: " << headerData);
130  NS_LOG_FUNCTION(this << "headerData.size(): " << headerData.size());
131  NS_LOG_FUNCTION(this << "m_payload.size(): " << m_payload.size());
132  NS_LOG_FUNCTION(this << "m_allData.size(): " << m_allData.size());
133 
134  m_headerSize = headerData.size();
135  m_contentLength = m_payload.size();
136 
137 }
138 
139 
140 void
142  const HttpHeader::HttpStatus status,
143  const std::string& body,
144  const std::vector<std::string>& headers)
145 {
147  status,
148  std::vector<uint8_t>(body.begin(), body.end()),
149  headers
150  );
151 }
152 
153 void
155  const HttpHeader::HttpStatus status,
156  const std::vector<uint8_t>& body,
157  const std::vector<std::string>& headers
158 ) {
159 
160  std::string bodyString = std::string{body.begin(), body.end()};
161 
162  NS_LOG_FUNCTION( this << bodyString << std::to_string(body.size()) );
163 
164  SetStatus(status);
165  m_headers = headers;
166 
167  std::string headerData = "HTTP/1.1 " + std::to_string(m_status) + " " + GetStatusString() + "\r\n";
168 
169  for (const std::string& header : headers){
170  headerData += header + "\r\n";
171  }
172 
173  headerData += "Server: nginx/1.17.0 (Ubuntu)\r\n"
174  "Content-Length: " + std::to_string(body.size()) + "\r\n";
175 
176  //if(body.size()>300) headerData += "Transfer-Encoding: chunked\r\n";
177 
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";
185 
186 
187  m_allData.clear();
188  m_payload.clear();
189 
190  //add headers
191  std::vector<uint8_t> requestData(headerData.begin(), headerData.end());
192  m_allData = requestData;
193 
194  //add payload
195  m_allData.insert(m_allData.end(), body.begin(), body.end());
196  m_payload.insert(m_payload.end(), body.begin(), body.end());
197 
198  NS_LOG_FUNCTION( this << "m_allData.size(): " << m_allData.size() << GetPayloadString() );
199  m_contentLength = m_allData.size();
200 
201 }
202 
203 void
205 {
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;
214  m_headerSize = 0;
215 
216  // read the response
217  if (!parsedHeaders)
218  for (;;)
219  {
220  const auto i = std::search(responseData.begin(), responseData.end(), std::begin(crlf), std::end(crlf));
221 
222  // didn't find a newline
223  if (i == responseData.end()) break;
224 
225  const std::string line(responseData.begin(), i);
226  responseData.erase(responseData.begin(), i + 2);
227 
228 
229  NS_LOG_FUNCTION(this << "221: " << "\t" << line << line.size() << m_headerSize );
230 
231  // empty line indicates the end of the header section
232  if (line.empty())
233  {
234  parsedHeaders = true;
235  break;
236  }
237  else if (firstLine) // first line
238  {
239  firstLine = false;
240  m_headerSize += line.size();
241 
242  std::string::size_type lastPos = 0;
243  const auto length = line.length();
244  std::vector<std::string> parts;
245 
246  // tokenize first line
247  while (lastPos < length + 1)
248  {
249  auto pos = line.find(' ', lastPos);
250  if (pos == std::string::npos) pos = length;
251 
252  if (pos != lastPos)
253  parts.emplace_back(line.data() + lastPos,
254  static_cast<std::vector<std::string>::size_type>(pos) - lastPos);
255 
256  lastPos = pos + 1;
257  }
258 
259  NS_LOG_FUNCTION(this << parts[0] << parts[1] << parts[2]);
260 
261  if (parts.size() >= 2){
262  if(parts[0] == "HTTP/1.1"){
263  m_status = std::stoi(parts[1]);
264  }else{
265  SetMethod( parts[0] );
266  m_uri = parts[1];
267  }
268  }
269  }
270  else // headers
271  {
272  m_headers.push_back(line);
273  m_headerSize += line.size() + 1;
274 
275  const auto pos = line.find(':');
276 
277  if (pos != std::string::npos)
278  {
279  std::string headerName = line.substr(0, pos);
280  std::string headerValue = line.substr(pos + 1);
281 
282  // ltrim
283  headerValue.erase(headerValue.begin(),
284  std::find_if(headerValue.begin(), headerValue.end(),
285  [](int c) {return !std::isspace(c);}));
286 
287  // rtrim
288  headerValue.erase(std::find_if(headerValue.rbegin(), headerValue.rend(),
289  [](int c) {return !std::isspace(c);}).base(),
290  headerValue.end());
291 
292  if (headerName == "Content-Length")
293  {
294  m_contentLength = std::stoul(headerValue);
295  contentLengthReceived = true;
296  m_allData.reserve(m_contentLength);
297  }
298  else if (headerName == "Request URI")
299  {
300  m_request_uri = headerValue;
301  }
302  else if (headerName == "Transfer-Encoding")
303  {
304  if (headerValue == "chunked")
305  chunkedResponse = true;
306  else
307  NS_FATAL_ERROR ("Unsupported transfer encoding: " + headerValue);
308  }
309  else if (headerName == "Host")
310  {
311  m_uri = headerValue + m_uri;
312  NS_LOG_FUNCTION(this << headerValue);
313  }
314  }
315  }
316  }
317 
318  if (parsedHeaders)
319  {
320 
321  // Content-Length must be ignored if Transfer-Encoding is received
322  if (chunkedResponse)
323  {
324  bool dataReceived = false;
325  for (;;)
326  {
327 
328  NS_LOG_FUNCTION(this <<"expectedChunkSize:" << expectedChunkSize);
329 
330  if (expectedChunkSize > 0)
331  {
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;
337 
338 
339  if (expectedChunkSize == 0) removeCrlfAfterChunk = true;
340  if (responseData.empty()) break;
341  }
342  else
343  {
344  if (removeCrlfAfterChunk)
345  {
346  if (responseData.size() >= 2)
347  {
348  removeCrlfAfterChunk = false;
349  responseData.erase(responseData.begin(), responseData.begin() + 2);
350  }
351  else break;
352  }
353 
354  const auto i = std::search(responseData.begin(), responseData.end(), std::begin(crlf), std::end(crlf));
355 
356  if (i == responseData.end()) break;
357 
358  const std::string line(responseData.begin(), i);
359  responseData.erase(responseData.begin(), i + 2);
360 
361  expectedChunkSize = std::stoul(line, nullptr, 16);
362 
363  if (expectedChunkSize == 0)
364  {
365  dataReceived = true;
366  break;
367  }
368  }
369  }
370  NS_LOG_FUNCTION(dataReceived);
371 
372  // if (dataReceived) break;
373  }
374  else
375  {
376 
377  m_payload.insert(m_payload.end(), responseData.begin(), responseData.end());
378  responseData.clear();
379 
380  NS_LOG_FUNCTION(this << "m_contentLength:" << m_contentLength);
381  NS_LOG_FUNCTION(this << "payload.size(): " << m_payload.size());
382 
383  if(m_contentLength > m_payload.size()){
384  m_fragmented = true;
385  NS_LOG_FUNCTION(this <<"Fragmented header received!");
386  }else if(m_contentLength < m_payload.size()){
387  NS_LOG_FUNCTION(this << "Extract header data from the rest of the payload!");
388  std::vector<uint8_t> vec2(m_payload.begin(), m_payload.begin()+m_contentLength);
389  m_payload = vec2;
390  }else{
391  NS_LOG_FUNCTION(this << "Exact header size received!)");
392  }
393 
394 
395  std::string payload = std::string{m_payload.begin(), m_payload.end()};
396  NS_LOG_FUNCTION(this << "287!!!!!!!" << chunkedResponse << contentLengthReceived << payload);
397 
398  // got the whole content
399  //if (contentLengthReceived && m_allData.size() >= contentLength) break;
400  NS_LOG_FUNCTION(contentLengthReceived);
401  }
402  }
403 
404  std::string payload = std::string{m_payload.begin(), m_payload.end()};
405  NS_LOG_FUNCTION(this << parsedHeaders << payload << "374m_headerSize:" << m_headerSize << "m_contentLength:" << m_contentLength );
406 
407 }
408 
409 std::string
411 
413  std::string output;
414  output.assign(m_allData.begin(), m_allData.end());
415 
416  NS_LOG_FUNCTION(this << output << output.size() << m_allData.size());
417  return output;
418 }
419 
420 void
421 HttpHeader::SetHeaderString(std::string input){
422 
423  NS_LOG_FUNCTION(this << input << input.size());
424  std::vector<uint8_t> vec(input.begin(), input.end());
425  m_allData = vec;
426 
427  if(m_headers.size() == 0 && m_payload.size() == 0) ParseResponse();
428 
429  NS_LOG_FUNCTION(this << "\n" <<
430  "input.size(): " << input.size() << "\n" <<
431  "Header-Length: " << m_headerSize << "\n" <<
432  "Content-Length: " << m_contentLength << "\n"
433  "Headers.size():" << m_headers.size() << "\n"
434  );
435 
436  /*
437  if(input.size() < (m_headerSize + m_contentLength+m_headers.size()+4)){
438  m_fragmented = true;
439  NS_LOG_FUNCTION(this << "Fragment received!" << input.size() << m_headerSize + m_contentLength);
440  }else if(input.size() > (m_headerSize + m_contentLength)){
441  NS_LOG_FUNCTION(this << "Larger header received!");
442 
443  std::vector<uint8_t> vec1(m_allData.begin(), m_allData.begin()+m_headerSize);
444  NS_LOG_FUNCTION(this << "headers vec1.size(): " << vec1.size() );
445 
446  std::vector<uint8_t> vec2(m_payload.begin(), m_payload.begin()+m_contentLength);
447  m_payload = vec2;
448  NS_LOG_FUNCTION(this << "payload vec2.size(): " << vec2.size() );
449 
450  std::vector<uint8_t> vec3(m_allData.begin(), m_allData.begin()+m_headerSize+m_headers.size()+4+m_contentLength);
451  m_allData = vec3;
452  NS_LOG_FUNCTION(this << "all vec3.size(): " << vec3.size() );
453 
454 
455 
456  std::string headers = std::string{vec1.begin(), vec1.end()};
457  NS_LOG_FUNCTION(this << ":::423:::\n" << headers);
458 
459  std::string payload = std::string{vec2.begin(), vec2.end()};
460  NS_LOG_FUNCTION(this << ":::424:::\n" << payload);
461 
462  std::string ALL = std::string{vec3.begin(), vec3.end()};
463  NS_LOG_FUNCTION(this << ":::425:::\n" << ALL);
464 
465  m_fragmented = false;
466 
467 
468 
469 
470  }else{
471  NS_LOG_FUNCTION(this << "Exact size header received!");
472  }*/
473 
474 }
475 
476 
477 // static
478 TypeId
480 {
481  static TypeId tid = TypeId ("ns3::HttpHeader")
482  .SetParent<Header> ()
483  .AddConstructor<HttpHeader> ()
484  ;
485  return tid;
486 }
487 
488 TypeId
490 {
491  return GetTypeId ();
492 }
493 
494 uint32_t
496 {
497  return (m_headerSize + m_contentLength) * sizeof(uint8_t);
498 }
499 
500 void
502 {
503  NS_LOG_FUNCTION (this << &start);
504 
505  NS_LOG_FUNCTION( this
506  << "m_contentLength: " << m_contentLength
507  );
508 
509  start.WriteU32 (m_contentLength);
510 
511  char tmpBuffer [ m_contentLength ];
512  std::copy(m_allData.begin(), m_allData.end(), tmpBuffer);
513  start.Write ((uint8_t *)tmpBuffer, m_contentLength);
514 
515 }
516 
517 uint32_t
519 {
520  NS_LOG_FUNCTION ( this << &start << start.GetSize() );
521  Buffer::Iterator i = start;
522 
523  m_contentLength = i.ReadU32 ();
524  NS_LOG_FUNCTION(this << "m_contentLength: " << m_contentLength);
525  NS_LOG_FUNCTION(this << "start.GetSize(): " << start.GetSize());
526  NS_LOG_FUNCTION(this << "i.GetDistanceFrom (start) " << i.GetDistanceFrom (start) );
527 
528  if(m_contentLength > start.GetSize()){
529  return i.GetDistanceFrom (start);
530  }
531 
532  //if we have not received the full header
533  //i.e start.GetSize() = 1339
534  //but we received 4 bytes (i.ReadU32 ()) + m_contentLength (1337)
535  //we need two more bytes to receive!
536  if(start.GetSize() < i.GetDistanceFrom (start) + m_contentLength){
537  return i.GetDistanceFrom (start);
538  }
539 
540  char tmpBuffer [ m_contentLength ];
541  i.Read ((uint8_t*)tmpBuffer, m_contentLength);
542 
543  std::vector<uint8_t> receivedData(tmpBuffer, tmpBuffer + m_contentLength / sizeof(char));
544  m_allData = receivedData;
545 
546  uint32_t dist = i.GetDistanceFrom (start);
547  NS_LOG_FUNCTION( this << dist << GetSerializedSize() );
548  NS_ASSERT (dist == GetSerializedSize ());
549 
550  if(m_headers.size() == 0 && m_payload.size() == 0){
551  ParseResponse();
552  }
553  return dist;
554 }
555 
556 void
557 HttpHeader::Print (std::ostream &os) const
558 {
559  NS_LOG_FUNCTION (this << &os);
560  os <<
561  "Header-Length: " << m_headerSize << "\n" <<
562  "Content-Length: " << m_contentLength << "\n" <<
563  std::string{m_allData.begin(), m_allData.end()} << "\n";
564 }
565 
566 std::string
568 {
569  NS_LOG_FUNCTION (this);
570  std::ostringstream oss;
571  Print (oss);
572  return oss.str ();
573 }
574 
575 uint32_t
577  return m_headerSize;
578 }
579 
580 uint32_t
582  NS_LOG_FUNCTION(this);
583  return m_contentLength;
584 }
585 
586 uint32_t
588 {
589  return m_headerSize + m_contentLength;
590 }
591 
592 void
594 {
595  NS_LOG_FUNCTION (this << status);
596  switch (status)
597  {
598  case Continue:
599  m_status = 100;
600  break;
601  case SwitchingProtocol:
602  m_status = 101;
603  break;
604  case Processing:
605  m_status = 102;
606  break;
607  case EarlyHints:
608  m_status = 103;
609  break;
610 
611  case Ok:
612  m_status = 200;
613  break;
614  case Created:
615  m_status = 201;
616  break;
617  case Accepted:
618  m_status = 202;
619  break;
621  m_status = 203;
622  break;
623  case NoContent:
624  m_status = 204;
625  break;
626  case ResetContent:
627  m_status = 205;
628  break;
629  case PartialContent:
630  m_status = 206;
631  break;
632  case MultiStatus:
633  m_status = 207;
634  break;
635  case AlreadyReported:
636  m_status = 208;
637  break;
638  case ImUsed:
639  m_status = 226;
640  break;
641 
642  case MultipleChoice:
643  m_status = 300;
644  break;
645  case MovedPermanently:
646  m_status = 301;
647  break;
648  case Found:
649  m_status = 302;
650  break;
651  case SeeOther:
652  m_status = 303;
653  break;
654  case NotModified:
655  m_status = 304;
656  break;
657  case UseProxy:
658  m_status = 305;
659  break;
660  case TemporaryRedirect:
661  m_status = 307;
662  break;
663  case PermanentRedirect:
664  m_status = 308;
665  break;
666 
667  case BadRequest:
668  m_status = 400;
669  break;
670  case Unauthorized:
671  m_status = 401;
672  break;
673  case PaymentRequired:
674  m_status = 402;
675  break;
676  case Forbidden:
677  m_status = 403;
678  break;
679  case NotFound:
680  m_status = 404;
681  break;
682  case MethodNotAllowed:
683  m_status = 405;
684  break;
685  case NotAcceptable:
686  m_status = 406;
687  break;
689  m_status = 407;
690  break;
691  case RequestTimeout:
692  m_status = 408;
693  break;
694  case Conflict:
695  m_status = 409;
696  break;
697  case Gone:
698  m_status = 410;
699  break;
700  case LengthRequired:
701  m_status = 411;
702  break;
703  case PreconditionFailed:
704  m_status = 412;
705  break;
706  case PayloadTooLarge:
707  m_status = 413;
708  break;
709  case UriTooLong:
710  m_status = 414;
711  break;
712  case UnsupportedMediaType:
713  m_status = 415;
714  break;
715  case RangeNotSatisfiable:
716  m_status = 416;
717  break;
718  case ExpectationFailed:
719  m_status = 417;
720  break;
721  case ImaTeapot:
722  m_status = 418;
723  break;
724  case MisdirectedRequest:
725  m_status = 421;
726  break;
727  case UnprocessableEntity:
728  m_status = 422;
729  break;
730  case Locked:
731  m_status = 423;
732  break;
733  case FailedDependency:
734  m_status = 424;
735  break;
736  case TooEarly:
737  m_status = 425;
738  break;
739  case UpgradeRequired:
740  m_status = 426;
741  break;
742  case PreconditionRequired:
743  m_status = 428;
744  break;
745  case TooManyRequests:
746  m_status = 429;
747  break;
749  m_status = 431;
750  break;
752  m_status = 451;
753  break;
754 
755  case InternalServerError:
756  m_status = 500;
757  break;
758  case NotImplemented:
759  m_status = 501;
760  break;
761  case BadGateway:
762  m_status = 502;
763  break;
764  case ServiceUnavailable:
765  m_status = 503;
766  break;
767  case GatewayTimeout:
768  m_status = 504;
769  break;
771  m_status = 505;
772  break;
773  case VariantAlsoNegotiates:
774  m_status = 506;
775  break;
776  case InsufficientStorage:
777  m_status = 507;
778  break;
779  case LoopDetected:
780  m_status = 508;
781  break;
782  case NotExtended:
783  m_status = 510;
784  break;
786  m_status = 511;
787  break;
788  default:
789  NS_FATAL_ERROR ("Unknown status: " << m_status);
790  break;
791  }
792 }
793 
796 {
797  HttpStatus ret;
798  switch (m_status)
799  {
800  case 100:
801  ret = Continue;
802  break;
803  case 101:
804  ret = SwitchingProtocol;
805  break;
806  case 102:
807  ret = Processing;
808  break;
809  case 103:
810  ret = EarlyHints;
811  break;
812 
813  case 200:
814  ret = Ok;
815  break;
816  case 201:
817  ret = Created;
818  break;
819  case 202:
820  ret = Accepted;
821  break;
822  case 203:
824  break;
825  case 204:
826  ret = NoContent;
827  break;
828  case 205:
829  ret = ResetContent;
830  break;
831  case 206:
832  ret = PartialContent;
833  break;
834  case 207:
835  ret = MultiStatus;
836  break;
837  case 208:
838  ret = AlreadyReported;
839  break;
840  case 226:
841  ret = ImUsed;
842  break;
843 
844  case 300:
845  ret = MultipleChoice;
846  break;
847  case 301:
848  ret = MovedPermanently;
849  break;
850  case 302:
851  ret = Found;
852  break;
853  case 303:
854  ret = SeeOther;
855  break;
856  case 304:
857  ret = NotModified;
858  break;
859  case 305:
860  ret = UseProxy;
861  break;
862  case 307:
863  ret = TemporaryRedirect;
864  break;
865  case 308:
866  ret = PermanentRedirect;
867  break;
868 
869  case 400:
870  ret = BadRequest;
871  break;
872  case 401:
873  ret = Unauthorized;
874  break;
875  case 402:
876  ret = PaymentRequired;
877  break;
878  case 403:
879  ret = Forbidden;
880  break;
881  case 404:
882  ret = NotFound;
883  break;
884  case 405:
885  ret = MethodNotAllowed;
886  break;
887  case 406:
888  ret = NotAcceptable;
889  break;
890  case 407:
892  break;
893  case 408:
894  ret = RequestTimeout;
895  break;
896  case 409:
897  ret = Conflict;
898  break;
899  case 410:
900  ret = Gone;
901  break;
902  case 411:
903  ret = LengthRequired;
904  break;
905  case 412:
906  ret = PreconditionFailed;
907  break;
908  case 413:
909  ret = PayloadTooLarge;
910  break;
911  case 414:
912  ret = UriTooLong;
913  break;
914  case 415:
915  ret = UnsupportedMediaType;
916  break;
917  case 416:
918  ret = RangeNotSatisfiable;
919  break;
920  case 417:
921  ret = ExpectationFailed;
922  break;
923  case 418:
924  ret = ImaTeapot;
925  break;
926  case 421:
927  ret = MisdirectedRequest;
928  break;
929  case 422:
930  ret = UnprocessableEntity;
931  break;
932  case 423:
933  ret = Locked;
934  break;
935  case 424:
936  ret = FailedDependency;
937  break;
938  case 425:
939  ret = TooEarly;
940  break;
941  case 426:
942  ret = UpgradeRequired;
943  break;
944  case 428:
945  ret = PreconditionRequired;
946  break;
947  case 429:
948  ret = TooManyRequests;
949  break;
950  case 431:
952  break;
953  case 451:
955  break;
956 
957  case 500:
958  ret = InternalServerError;
959  break;
960  case 501:
961  ret = NotImplemented;
962  break;
963  case 502:
964  ret = BadGateway;
965  break;
966  case 503:
967  ret = ServiceUnavailable;
968  break;
969  case 504:
970  ret = GatewayTimeout;
971  break;
972  case 505:
974  break;
975  case 506:
976  ret = VariantAlsoNegotiates;
977  break;
978  case 507:
979  ret = InsufficientStorage;
980  break;
981  case 508:
982  ret = LoopDetected;
983  break;
984  case 510:
985  ret = NotExtended;
986  break;
987  case 511:
989  break;
990  default:
991  NS_FATAL_ERROR ("Unknown status: " << m_status);
992  break;
993  }
994  return ret;
995 }
996 
997 
998 std::string
1000 {
1001  std::string output;
1002  switch (m_status)
1003  {
1004  case 100:
1005  return "Continue";
1006  case 101:
1007  return "SwitchingProtocol";
1008  case 102:
1009  return "Processing";
1010  case 103:
1011  return "EarlyHints";
1012 
1013  case 200:
1014  return "Ok";
1015  case 201:
1016  return "Created";
1017  case 202:
1018  return "Accepted";
1019  case 203:
1020  return "NonAuthoritativeInformation";
1021  case 204:
1022  return "NoContent";
1023  case 205:
1024  return "ResetContent";
1025  case 206:
1026  return "PartialContent";
1027  case 207:
1028  return "MultiStatus";
1029  case 208:
1030  return "AlreadyReported";
1031  case 226:
1032  return "ImUsed";
1033 
1034  case 300:
1035  return "MultipleChoice";
1036  case 301:
1037  return "MovedPermanently";
1038  case 302:
1039  return "Found";
1040  case 303:
1041  return "SeeOther";
1042  case 304:
1043  return "NotModified";
1044  case 305:
1045  return "UseProxy";
1046  case 307:
1047  return "TemporaryRedirect";
1048  case 308:
1049  return "PermanentRedirect";
1050 
1051  case 400:
1052  return "BadRequest";
1053  case 401:
1054  return "Unauthorized";
1055  case 402:
1056  return "PaymentRequired";
1057  case 403:
1058  return "Forbidden";
1059  case 404:
1060  return "NotFound";
1061  case 405:
1062  return "MethodNotAllowed";
1063  case 406:
1064  return "NotAcceptable";
1065  case 407:
1066  return "ProxyAuthenticationRequired";
1067  case 408:
1068  return "RequestTimeout";
1069  case 409:
1070  return "Conflict";
1071  case 410:
1072  return "Gone";
1073  case 411:
1074  return "LengthRequired";
1075  case 412:
1076  return "PreconditionFailed";
1077  case 413:
1078  return "PayloadTooLarge";
1079  case 414:
1080  return "UriTooLong";
1081  case 415:
1082  return "UnsupportedMediaType";
1083  case 416:
1084  return "RangeNotSatisfiable";
1085  case 417:
1086  return "ExpectationFailed";
1087  case 418:
1088  return "ImaTeapot";
1089  case 421:
1090  return "MisdirectedRequest";
1091  case 422:
1092  return "UnprocessableEntity";
1093  case 423:
1094  return "Locked";
1095  case 424:
1096  return "FailedDependency";
1097  case 425:
1098  return "TooEarly";
1099  case 426:
1100  return "UpgradeRequired";
1101  case 428:
1102  return "PreconditionRequired";
1103  case 429:
1104  return "TooManyRequests";
1105  case 431:
1106  return "RequestHeaderFieldsTooLarge";
1107  case 451:
1108  return "UnavailableForLegalReasons";
1109 
1110  case 500:
1111  return "InternalServerError";
1112  case 501:
1113  return "NotImplemented";
1114  case 502:
1115  return "BadGateway";
1116  case 503:
1117  return "ServiceUnavailable";
1118  case 504:
1119  return "GatewayTimeout";
1120  case 505:
1121  return "HttpVersionNotSupported";
1122  case 506:
1123  return "VariantAlsoNegotiates";
1124  case 507:
1125  return "InsufficientStorage";
1126  case 508:
1127  return "LoopDetected";
1128  case 510:
1129  return "NotExtended";
1130  case 511:
1131  return "NetworkAuthenticationRequired";
1132  default:
1133  NS_FATAL_ERROR ("Unknown status: " << m_status);
1134  break;
1135  }
1136  return output;
1137 }
1138 
1139 
1140 void
1141 HttpHeader::SetMethod (const std::string& m){
1142 
1143  NS_LOG_FUNCTION (this << m);
1144  HttpHeader::HttpMethod method;
1145 
1146  if (m == "DELETE")
1147  method = HttpHeader::DELETE;
1148  else if (m == "GET")
1149  method = HttpHeader::GET;
1150  else if (m == "HEAD")
1151  method = HttpHeader::HEAD;
1152  else if (m == "PATCH")
1153  method = HttpHeader::PATCH;
1154  else if (m == "POST")
1155  method = HttpHeader::POST;
1156  else if (m == "PUT")
1157  method = HttpHeader::PUT;
1158  else
1159  NS_FATAL_ERROR ("Unknown Content-Type: " << m);
1160 
1161  SetMethod(method);
1162 }
1163 
1164 
1165 void
1167 
1168  NS_LOG_FUNCTION (this << static_cast<uint16_t> (m_method));
1169 
1170  switch (method)
1171  {
1172  case DELETE:
1173  m_method = 0;
1174  break;
1175  case GET:
1176  m_method = 1;
1177  break;
1178  case HEAD:
1179  m_method = 2;
1180  break;
1181  case PATCH:
1182  m_method = 3;
1183  break;
1184  case POST:
1185  m_method = 4;
1186  break;
1187  case PUT:
1188  m_method = 5;
1189  break;
1190  default:
1191  NS_FATAL_ERROR ("Unknown Content-Type: " << m_method);
1192  break;
1193  }
1194 }
1195 
1198 {
1199 
1200  HttpMethod ret;
1201  switch (m_method)
1202  {
1203  case 0:
1204  ret = DELETE;
1205  break;
1206  case 1:
1207  ret = GET;
1208  break;
1209  case 2:
1210  ret = HEAD;
1211  break;
1212  case 3:
1213  ret = PATCH;
1214  break;
1215  case 4:
1216  ret = POST;
1217  break;
1218  case 5:
1219  ret = PUT;
1220  break;
1221  NS_FATAL_ERROR ("Unknown Method: " << m_method);
1222  break;
1223  }
1224  return ret;
1225 
1226 }
1227 
1228 std::string
1229 HttpHeader::urlEncode(const std::string& str)
1230 {
1231  constexpr char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
1232 
1233  std::string result;
1234 
1235  for (auto i = str.begin(); i != str.end(); ++i)
1236  {
1237  const std::uint8_t cp = *i & 0xFF;
1238 
1239  if ((cp >= 0x30 && cp <= 0x39) || // 0-9
1240  (cp >= 0x41 && cp <= 0x5A) || // A-Z
1241  (cp >= 0x61 && cp <= 0x7A) || // a-z
1242  cp == 0x2D || cp == 0x2E || cp == 0x5F) // - . _
1243  result += static_cast<char>(cp);
1244  else if (cp <= 0x7F) // length = 1
1245  result += std::string("%") + hexChars[(*i & 0xF0) >> 4] + hexChars[*i & 0x0F];
1246  else if ((cp >> 5) == 0x06) // length = 2
1247  {
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];
1251  }
1252  else if ((cp >> 4) == 0x0E) // length = 3
1253  {
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];
1259  }
1260  else if ((cp >> 3) == 0x1E) // length = 4
1261  {
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];
1269  }
1270  }
1271 
1272  return result;
1273 }
1274 
1275 std::string
1277 {
1278  return m_uri;
1279 }
1280 
1281 std::string
1283  return m_request_uri;
1284 }
1285 
1286 void
1287 HttpHeader::SetUri(const std::string& url)
1288 {
1289  NS_LOG_FUNCTION (this << url << url.length() );
1290 
1291  m_uri = url;
1292 
1293  const auto schemeEndPosition = url.find("://");
1294 
1295  if (schemeEndPosition != std::string::npos)
1296  {
1297  m_scheme = url.substr(0, schemeEndPosition);
1298  m_path = url.substr(schemeEndPosition + 3);
1299  }
1300  else
1301  {
1302  m_scheme = "http";
1303  m_path = url;
1304  }
1305 
1306  const auto fragmentPosition = m_path.find('#');
1307 
1308  // remove the fragment part
1309  if (fragmentPosition != std::string::npos)
1310  m_path.resize(fragmentPosition);
1311 
1312  const auto pathPosition = m_path.find('/');
1313 
1314  if (pathPosition == std::string::npos)
1315  {
1316  m_domain = m_path;
1317  m_path = "/";
1318  }
1319  else
1320  {
1321  m_domain = m_path.substr(0, pathPosition);
1322  m_path = m_path.substr(pathPosition);
1323  }
1324 
1325  const auto portPosition = m_domain.find(':');
1326 
1327  if (portPosition != std::string::npos)
1328  {
1329  m_domain.resize(portPosition);
1330  }
1331 
1332  NS_LOG_FUNCTION(this << m_domain << m_path << m_scheme);
1333 
1334 }
1335 
1336 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
iterator in a Buffer instance
Definition: buffer.h:99
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1124
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:788
uint32_t ReadU32(void)
Definition: buffer.cc:973
Protocol header serialization and deserialization.
Definition: header.h:43
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
uint16_t m_method
" Connection method field in integer format.
Definition: http-header.h:289
std::string m_uri
Definition: http-header.h:297
std::vector< uint8_t > m_payload
Definition: http-header.h:286
virtual void Serialize(Buffer::Iterator start) const
Definition: http-header.cc:501
uint32_t GetSize() const
Definition: http-header.cc:587
HttpHeader()
Creates an empty instance .
Definition: http-header.cc:33
std::vector< std::string > m_headers
Definition: http-header.h:285
virtual void Print(std::ostream &os) const
Definition: http-header.cc:557
HttpStatus GetStatus() const
Definition: http-header.cc:795
std::vector< uint8_t > m_allData
Definition: http-header.h:287
std::string m_domain
Definition: http-header.h:282
uint32_t GetHeaderSize()
Definition: http-header.cc:576
virtual TypeId GetInstanceTypeId() const
Get the most derived TypeId for this Object.
Definition: http-header.cc:489
virtual uint32_t GetSerializedSize() const
Definition: http-header.cc:495
uint32_t m_headerSize
Definition: http-header.h:293
std::string GetHeaderString()
Definition: http-header.cc:410
std::string GetRequestUri() const
uint32_t GetContentSize()
Definition: http-header.cc:581
std::string GetUri() const
std::string m_path
Definition: http-header.h:283
static TypeId GetTypeId()
Returns the object TypeId.
Definition: http-header.cc:479
void CreateResponse(const HttpHeader::HttpStatus status, const std::map< std::string, std::string > &body, const std::vector< std::string > &headers={})
void SetStatus(HttpStatus status)
Definition: http-header.cc:593
uint16_t m_status
" Connection status field in integer format.
Definition: http-header.h:290
std::string GetPayloadString()
Definition: http-header.h:214
@ NetworkAuthenticationRequired
Definition: http-header.h:145
@ RequestHeaderFieldsTooLarge
Definition: http-header.h:132
@ ProxyAuthenticationRequired
Definition: http-header.h:112
@ UnavailableForLegalReasons
Definition: http-header.h:133
@ NonAuthoritativeInformation
Definition: http-header.h:88
std::string GetStatusString() const
Definition: http-header.cc:999
HttpMethod GetMethod() const
void SetHeaderString(std::string input)
Definition: http-header.cc:421
@ POST
Http Method Post.
Definition: http-header.h:74
@ HEAD
Http Method Head.
Definition: http-header.h:72
@ PUT
Http Method Put.
Definition: http-header.h:75
@ PATCH
Http Method Patch.
Definition: http-header.h:73
@ GET
Http Method GET.
Definition: http-header.h:71
@ DELETE
Http Method Delete.
Definition: http-header.h:70
uint32_t m_contentLength
" Content length field (in bytes unit).
Definition: http-header.h:292
void CreateRequest(const std::string &url, const std::string &method, const std::map< std::string, std::string > &parameters, const std::vector< std::string > &headers={})
Definition: http-header.cc:44
std::string m_scheme
Definition: http-header.h:281
std::string m_request_uri
Definition: http-header.h:298
std::string ToString() const
Definition: http-header.cc:567
void SetUri(const std::string &url)
void SetMethod(HttpMethod method)
void ParseResponse()
Definition: http-header.cc:204
std::string urlEncode(const std::string &str)
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#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.
Definition: object-base.h:45
Definition: first.py:1
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1853