A Discrete-Event Network Simulator
API
three-gpp-http-server.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 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: Budiarto Herman <budiarto.herman@magister.fi>
19  *
20  */
21 
22 #include "three-gpp-http-server.h"
23 
24 #include <ns3/log.h>
25 #include <ns3/simulator.h>
26 #include <ns3/callback.h>
27 #include <ns3/config.h>
28 #include <ns3/pointer.h>
29 #include <ns3/uinteger.h>
30 #include <ns3/three-gpp-http-variables.h>
31 #include <ns3/packet.h>
32 #include <ns3/socket.h>
33 #include <ns3/tcp-socket.h>
34 #include <ns3/tcp-socket-factory.h>
35 #include <ns3/inet-socket-address.h>
36 #include <ns3/inet6-socket-address.h>
37 
38 
39 NS_LOG_COMPONENT_DEFINE ("ThreeGppHttpServer");
40 
41 
42 namespace ns3 {
43 
44 
45 // HTTP SERVER ////////////////////////////////////////////////////////////////
46 
47 
48 NS_OBJECT_ENSURE_REGISTERED (ThreeGppHttpServer);
49 
50 
52  : m_state (NOT_STARTED),
53  m_initialSocket (0),
54  m_txBuffer (Create<ThreeGppHttpServerTxBuffer> ()),
55  m_httpVariables (CreateObject<ThreeGppHttpVariables> ())
56 {
57  NS_LOG_FUNCTION (this);
58 
59  m_mtuSize = m_httpVariables->GetMtuSize ();
60  NS_LOG_INFO (this << " MTU size for this server application is "
61  << m_mtuSize << " bytes.");
62 }
63 
64 
65 // static
66 TypeId
68 {
69  static TypeId tid = TypeId ("ns3::ThreeGppHttpServer")
71  .AddConstructor<ThreeGppHttpServer> ()
72  .AddAttribute ("Variables",
73  "Variable collection, which is used to control e.g. processing and "
74  "object generation delays.",
75  PointerValue (),
77  MakePointerChecker<ThreeGppHttpVariables> ())
78  .AddAttribute ("LocalAddress",
79  "The local address of the server, "
80  "i.e., the address on which to bind the Rx socket.",
81  AddressValue (),
84  .AddAttribute ("LocalPort",
85  "Port on which the application listen for incoming packets.",
86  UintegerValue (80), // the default HTTP port
88  MakeUintegerChecker<uint16_t> ())
89  .AddAttribute ("Mtu",
90  "Maximum transmission unit (in bytes) of the TCP sockets "
91  "used in this application, excluding the compulsory 40 "
92  "bytes TCP header. Typical values are 1460 and 536 bytes. "
93  "The attribute is read-only because the value is randomly "
94  "determined.",
96  UintegerValue (),
98  MakeUintegerChecker<uint32_t> ())
99  .AddTraceSource ("ConnectionEstablished",
100  "Connection to a remote web client has been established.",
102  "ns3::HttpServer::ConnectionEstablishedCallback")
103  .AddTraceSource ("MainObject",
104  "A main object has been generated.",
106  "ns3::HttpServer::HttpObjectCallback")
107  .AddTraceSource ("EmbeddedObject",
108  "An embedded object has been generated.",
110  "ns3::HttpServer::HttpObjectCallback")
111  .AddTraceSource ("Tx",
112  "A packet has been sent.",
114  "ns3::Packet::TracedCallback")
115  .AddTraceSource ("Rx",
116  "A packet has been received.",
118  "ns3::Packet::PacketAddressTracedCallback")
119  .AddTraceSource ("RxDelay",
120  "A packet has been received with delay information.",
122  "ns3::Application::DelayAddressCallback")
123  .AddTraceSource ("StateTransition",
124  "Trace fired upon every HTTP client state transition.",
126  "ns3::Application::StateTransitionCallback")
127  ;
128  return tid;
129 }
130 
131 
132 void
134 {
135  NS_LOG_FUNCTION (this << mtuSize);
136  m_mtuSize = mtuSize;
137 }
138 
139 
142 {
143  return m_initialSocket;
144 }
145 
146 
149 {
150  return m_state;
151 }
152 
153 
154 std::string
156 {
157  return GetStateString (m_state);
158 }
159 
160 
161 // static
162 std::string
164 {
165  switch (state)
166  {
167  case NOT_STARTED:
168  return "NOT_STARTED";
169  break;
170  case STARTED:
171  return "STARTED";
172  break;
173  case STOPPED:
174  return "STOPPED";
175  break;
176  default:
177  NS_FATAL_ERROR ("Unknown state");
178  return "FATAL_ERROR";
179  break;
180  }
181 }
182 
183 
184 void
186 {
187  NS_LOG_FUNCTION (this);
188 
189  if (!Simulator::IsFinished ())
190  {
191  StopApplication ();
192  }
193 
194  Application::DoDispose (); // Chain up.
195 }
196 
197 
198 void
200 {
201  NS_LOG_FUNCTION (this);
202 
203  if (m_state == NOT_STARTED)
204  {
205  m_httpVariables->Initialize ();
206  if (m_initialSocket == 0)
207  {
208  // Find the current default MTU value of TCP sockets.
209  Ptr<const ns3::AttributeValue> previousSocketMtu;
210  const TypeId tcpSocketTid = TcpSocket::GetTypeId ();
211  for (uint32_t i = 0; i < tcpSocketTid.GetAttributeN (); i++)
212  {
213  struct TypeId::AttributeInformation attrInfo = tcpSocketTid.GetAttribute (i);
214  if (attrInfo.name == "SegmentSize")
215  {
216  previousSocketMtu = attrInfo.initialValue;
217  }
218  }
219 
220  // Creating a TCP socket to connect to the server.
224 
225  [[maybe_unused]] int ret;
226 
228  {
230  const InetSocketAddress inetSocket = InetSocketAddress (ipv4,
231  m_localPort);
232  NS_LOG_INFO (this << " Binding on " << ipv4
233  << " port " << m_localPort
234  << " / " << inetSocket << ".");
235  ret = m_initialSocket->Bind (inetSocket);
236  NS_LOG_DEBUG (this << " Bind() return value= " << ret
237  << " GetErrNo= "
238  << m_initialSocket->GetErrno () << ".");
239  }
241  {
243  const Inet6SocketAddress inet6Socket = Inet6SocketAddress (ipv6,
244  m_localPort);
245  NS_LOG_INFO (this << " Binding on " << ipv6
246  << " port " << m_localPort
247  << " / " << inet6Socket << ".");
248  ret = m_initialSocket->Bind (inet6Socket);
249  NS_LOG_DEBUG (this << " Bind() return value= " << ret
250  << " GetErrNo= "
251  << m_initialSocket->GetErrno () << ".");
252  }
253 
254  ret = m_initialSocket->Listen ();
255  NS_LOG_DEBUG (this << " Listen () return value= " << ret
256  << " GetErrNo= " << m_initialSocket->GetErrno ()
257  << ".");
258 
259 
260  } // end of `if (m_initialSocket == 0)`
261 
262  NS_ASSERT_MSG (m_initialSocket != 0, "Failed creating socket.");
264  this),
266  this));
268  this),
270  this));
272  this));
274  this));
276 
277  } // end of `if (m_state == NOT_STARTED)`
278  else
279  {
280  NS_FATAL_ERROR ("Invalid state " << GetStateString ()
281  << " for StartApplication().");
282  }
283 
284 } // end of `void StartApplication ()`
285 
286 
287 void
289 {
290  NS_LOG_FUNCTION (this);
291 
293 
294  // Close all accepted sockets.
295  m_txBuffer->CloseAllSockets ();
296 
297  // Stop listening.
298  if (m_initialSocket != 0)
299  {
302  MakeNullCallback<void, Ptr<Socket>, const Address &> ());
304  MakeNullCallback<void, Ptr<Socket> > ());
307  }
308 }
309 
310 
311 bool
313  const Address &address)
314 {
315  NS_LOG_FUNCTION (this << socket << address);
316  return true; // Unconditionally accept the connection request.
317 }
318 
319 
320 void
322  const Address &address)
323 {
324  NS_LOG_FUNCTION (this << socket << address);
325 
327  this),
329  this));
331  this));
333  this));
334 
335  m_connectionEstablishedTrace (this, socket);
336  m_txBuffer->AddSocket (socket);
337 
338  /*
339  * A typical connection is established after receiving an empty (i.e., no
340  * data) TCP packet with ACK flag. The actual data will follow in a separate
341  * packet after that and will be received by ReceivedDataCallback().
342  *
343  * However, that empty ACK packet might get lost. In this case, we may
344  * receive the first data packet right here already, because it also counts
345  * as a new connection. The statement below attempts to fetch the data from
346  * that packet, if any.
347  */
348  ReceivedDataCallback (socket);
349 }
350 
351 
352 void
354 {
355  NS_LOG_FUNCTION (this << socket);
356 
357  if (socket == m_initialSocket)
358  {
359  if (m_state == STARTED)
360  {
361  NS_FATAL_ERROR ("Initial listener socket shall not be closed"
362  << " when the server instance is still running.");
363  }
364  }
365  else if (m_txBuffer->IsSocketAvailable (socket))
366  {
367  // The application should now prepare to close the socket.
368  if (m_txBuffer->IsBufferEmpty (socket))
369  {
370  /*
371  * Here we declare that we have nothing more to send and the socket
372  * may be closed immediately.
373  */
374  socket->ShutdownSend ();
375  m_txBuffer->RemoveSocket (socket);
376  }
377  else
378  {
379  /*
380  * Remember to close the socket later, whenever the buffer becomes
381  * empty.
382  */
383  m_txBuffer->PrepareClose (socket);
384  }
385  }
386 }
387 
388 
389 void
391 {
392  NS_LOG_FUNCTION (this << socket);
393 
394  if (socket == m_initialSocket)
395  {
396  if (m_state == STARTED)
397  {
398  NS_FATAL_ERROR ("Initial listener socket shall not be closed"
399  << " when the server instance is still running.");
400  }
401  }
402  else if (m_txBuffer->IsSocketAvailable (socket))
403  {
404  m_txBuffer->CloseSocket (socket);
405  }
406 }
407 
408 
409 void
411 {
412  NS_LOG_FUNCTION (this << socket);
413 
414  Ptr<Packet> packet;
415  Address from;
416 
417  while ((packet = socket->RecvFrom (from)))
418  {
419  if (packet->GetSize () == 0)
420  {
421  break; // EOF
422  }
423 
424 #ifdef NS3_LOG_ENABLE
425  // Some log messages.
427  {
428  NS_LOG_INFO (this << " A packet of " << packet->GetSize () << " bytes"
429  << " received from " << InetSocketAddress::ConvertFrom (from).GetIpv4 ()
430  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
431  << " / " << InetSocketAddress::ConvertFrom (from));
432  }
433  else if (Inet6SocketAddress::IsMatchingType (from))
434  {
435  NS_LOG_INFO (this << " A packet of " << packet->GetSize () << " bytes"
436  << " received from " << Inet6SocketAddress::ConvertFrom (from).GetIpv6 ()
437  << " port " << Inet6SocketAddress::ConvertFrom (from).GetPort ()
438  << " / " << Inet6SocketAddress::ConvertFrom (from));
439  }
440 #endif /* NS3_LOG_ENABLE */
441 
442  // Check the header. No need to remove it, since it is not a "real" header.
443  ThreeGppHttpHeader httpHeader;
444  packet->PeekHeader (httpHeader);
445 
446  // Fire trace sources.
447  m_rxTrace (packet, from);
448  m_rxDelayTrace (Simulator::Now () - httpHeader.GetClientTs (), from);
449 
450  Time processingDelay;
451  switch (httpHeader.GetContentType ())
452  {
454  processingDelay = m_httpVariables->GetMainObjectGenerationDelay ();
455  NS_LOG_INFO (this << " Will finish generating a main object"
456  << " in " << processingDelay.As (Time::S) << ".");
457  m_txBuffer->RecordNextServe (socket,
458  Simulator::Schedule (processingDelay,
460  this, socket),
461  httpHeader.GetClientTs ());
462  break;
463 
465  processingDelay = m_httpVariables->GetEmbeddedObjectGenerationDelay ();
466  NS_LOG_INFO (this << " Will finish generating an embedded object"
467  << " in " << processingDelay.As (Time::S) << ".");
468  m_txBuffer->RecordNextServe (socket,
469  Simulator::Schedule (processingDelay,
471  this, socket),
472  httpHeader.GetClientTs ());
473  break;
474 
475  default:
476  NS_FATAL_ERROR ("Invalid packet.");
477  break;
478  }
479 
480  } // end of `while ((packet = socket->RecvFrom (from)))`
481 
482 } // end of `void ReceivedDataCallback (Ptr<Socket> socket)`
483 
484 
485 void
486 ThreeGppHttpServer::SendCallback (Ptr<Socket> socket, uint32_t availableBufferSize)
487 {
488  NS_LOG_FUNCTION (this << socket << availableBufferSize);
489 
490  if (!m_txBuffer->IsBufferEmpty (socket))
491  {
492  [[maybe_unused]] const uint32_t txBufferSize = m_txBuffer->GetBufferSize (socket);
493  [[maybe_unused]] const uint32_t actualSent = ServeFromTxBuffer (socket);
494 
495 #ifdef NS3_LOG_ENABLE
496  // Some log messages.
497  if (actualSent < txBufferSize)
498  {
499  switch (m_txBuffer->GetBufferContentType (socket))
500  {
502  NS_LOG_INFO (this << " Transmission of main object is suspended"
503  << " after " << actualSent << " bytes.");
504  break;
506  NS_LOG_INFO (this << " Transmission of embedded object is suspended"
507  << " after " << actualSent << " bytes.");
508  break;
509  default:
510  NS_FATAL_ERROR ("Invalid Tx buffer content type.");
511  break;
512  }
513  }
514  else
515  {
516  switch (m_txBuffer->GetBufferContentType (socket))
517  {
519  NS_LOG_INFO (this << " Finished sending a whole main object.");
520  break;
522  NS_LOG_INFO (this << " Finished sending a whole embedded object.");
523  break;
524  default:
525  NS_FATAL_ERROR ("Invalid Tx buffer content type.");
526  break;
527  }
528  }
529 #endif /* NS3_LOG_ENABLE */
530 
531  } // end of `if (m_txBuffer->IsBufferEmpty (socket))`
532 
533 } // end of `void SendCallback (Ptr<Socket> socket, uint32_t availableBufferSize)`
534 
535 
536 void
538 {
539  NS_LOG_FUNCTION (this << socket);
540 
541  const uint32_t objectSize = m_httpVariables->GetMainObjectSize ();
542  NS_LOG_INFO (this << " Main object to be served is "
543  << objectSize << " bytes.");
544  m_mainObjectTrace (objectSize);
545  m_txBuffer->WriteNewObject (socket, ThreeGppHttpHeader::MAIN_OBJECT,
546  objectSize);
547  const uint32_t actualSent = ServeFromTxBuffer (socket);
548 
549  if (actualSent < objectSize)
550  {
551  NS_LOG_INFO (this << " Transmission of main object is suspended"
552  << " after " << actualSent << " bytes.");
553  }
554  else
555  {
556  NS_LOG_INFO (this << " Finished sending a whole main object.");
557  }
558 }
559 
560 
561 void
563 {
564  NS_LOG_FUNCTION (this << socket);
565 
566  const uint32_t objectSize = m_httpVariables->GetEmbeddedObjectSize ();
567  NS_LOG_INFO (this << " Embedded object to be served is "
568  << objectSize << " bytes.");
569  m_embeddedObjectTrace (objectSize);
570  m_txBuffer->WriteNewObject (socket, ThreeGppHttpHeader::EMBEDDED_OBJECT,
571  objectSize);
572  const uint32_t actualSent = ServeFromTxBuffer (socket);
573 
574  if (actualSent < objectSize)
575  {
576  NS_LOG_INFO (this << " Transmission of embedded object is suspended"
577  << " after " << actualSent << " bytes.");
578  }
579  else
580  {
581  NS_LOG_INFO (this << " Finished sending a whole embedded object.");
582  }
583 }
584 
585 
586 uint32_t
588 {
589  NS_LOG_FUNCTION (this << socket);
590 
591  if (m_txBuffer->IsBufferEmpty (socket))
592  {
593  NS_LOG_LOGIC (this << " Tx buffer is empty. Not sending anything.");
594  return 0;
595  }
596  bool firstPartOfObject = !m_txBuffer->HasTxedPartOfObject (socket);
597 
598  const uint32_t socketSize = socket->GetTxAvailable ();
599  NS_LOG_DEBUG (this << " Socket has " << socketSize
600  << " bytes available for Tx.");
601 
602  // Get the number of bytes remaining to be sent.
603  const uint32_t txBufferSize = m_txBuffer->GetBufferSize (socket);
604 
605  // Compute the size of actual content to be sent; has to fit into the socket.
606  // Note that header size is NOT counted as TxBuffer content. Header size is overhead.
607  uint32_t contentSize = std::min (txBufferSize, socketSize - 22);
608  Ptr<Packet> packet = Create<Packet> (contentSize);
609  uint32_t packetSize = contentSize;
610  if (packetSize == 0)
611  {
612  NS_LOG_LOGIC (this << " Socket size leads to packet size of zero; not sending anything.");
613  return 0;
614  }
615 
616  // If this is the first packet of an object, attach a header.
617  if (firstPartOfObject)
618  {
619  // Create header.
620  ThreeGppHttpHeader httpHeader;
621  httpHeader.SetContentLength (txBufferSize);
622  httpHeader.SetContentType (m_txBuffer->GetBufferContentType (socket));
623  // Using the client TS value as per the corresponding request packet.
624  httpHeader.SetClientTs (m_txBuffer->GetClientTs (socket));
625  httpHeader.SetServerTs (Simulator::Now ());
626  packet->AddHeader (httpHeader);
627  packetSize += httpHeader.GetSerializedSize ();
628 
629  NS_LOG_INFO (this << " Created packet " << packet << " of "
630  << packetSize << " bytes."
631  << " The corresponding request came "
632  << (Simulator::Now () - httpHeader.GetClientTs ()).As (Time::S)
633  << " ago.");
634  }
635  else
636  {
637  NS_LOG_INFO (this << " Created packet " << packet << " of "
638  << packetSize << " bytes to be appended to a previous packet.");
639  }
640 
641  // Send.
642  const int actualBytes = socket->Send (packet);
643  NS_LOG_DEBUG (this << " Send() packet " << packet
644  << " of " << packetSize << " bytes,"
645  << " return value= " << actualBytes << ".");
646  m_txTrace (packet);
647 
648  if (actualBytes == static_cast<int> (packetSize))
649  {
650  // The packet goes through successfully.
651  m_txBuffer->DepleteBufferSize (socket, contentSize);
652  NS_LOG_INFO (this << " Remaining object to be sent "
653  << m_txBuffer->GetBufferSize (socket) << " bytes.");
654  return packetSize;
655  }
656  else
657  {
658  NS_LOG_INFO (this << " Failed to send object,"
659  << " GetErrNo= " << socket->GetErrno () << ","
660  << " suspending transmission"
661  << " and waiting for another Tx opportunity.");
662  return 0;
663  }
664 
665 } // end of `uint32_t ServeFromTxBuffer (Ptr<Socket> socket)`
666 
667 
668 void
670 {
671  const std::string oldState = GetStateString ();
672  const std::string newState = GetStateString (state);
673  NS_LOG_FUNCTION (this << oldState << newState);
674  m_state = state;
675  NS_LOG_INFO (this << " ThreeGppHttpServer " << oldState
676  << " --> " << newState << ".");
677  m_stateTransitionTrace (oldState, newState);
678 }
679 
680 
681 // HTTP SERVER TX BUFFER //////////////////////////////////////////////////////
682 
683 
685 {
686  NS_LOG_FUNCTION (this);
687 }
688 
689 bool
691 {
692  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
693  it = m_txBuffer.find (socket);
694  return (it != m_txBuffer.end ());
695 }
696 
697 void
699 {
700  NS_LOG_FUNCTION (this << socket);
701 
702  NS_ASSERT_MSG (!IsSocketAvailable (socket),
703  this << " Cannot add socket " << socket
704  << " because it has already been added before.");
705 
706  TxBuffer_t txBuffer;
708  txBuffer.txBufferSize = 0;
709  txBuffer.isClosing = false;
710  txBuffer.hasTxedPartOfObject = false;
711  m_txBuffer.insert (std::pair<Ptr<Socket>, TxBuffer_t> (socket, txBuffer));
712 }
713 
714 
715 void
717 {
718  NS_LOG_FUNCTION (this << socket);
719 
720  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
721  it = m_txBuffer.find (socket);
722  NS_ASSERT_MSG (it != m_txBuffer.end (),
723  "Socket " << socket << " cannot be found.");
724 
725  if (!Simulator::IsExpired (it->second.nextServe))
726  {
727  NS_LOG_INFO (this << " Canceling a serving event which is due in "
728  << Simulator::GetDelayLeft (it->second.nextServe).As (Time::S)
729  << ".");
730  Simulator::Cancel (it->second.nextServe);
731  }
732 
733  it->first->SetCloseCallbacks (MakeNullCallback<void, Ptr<Socket> > (),
734  MakeNullCallback<void, Ptr<Socket> > ());
735  it->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
736  it->first->SetSendCallback (MakeNullCallback<void, Ptr<Socket>, uint32_t > ());
737 
738  m_txBuffer.erase (it);
739 }
740 
741 
742 void
744 {
745  NS_LOG_FUNCTION (this << socket);
746 
747  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
748  it = m_txBuffer.find (socket);
749  NS_ASSERT_MSG (it != m_txBuffer.end (),
750  "Socket " << socket << " cannot be found.");
751 
752  if (!Simulator::IsExpired (it->second.nextServe))
753  {
754  NS_LOG_INFO (this << " Canceling a serving event which is due in "
755  << Simulator::GetDelayLeft (it->second.nextServe).As (Time::S)
756  << ".");
757  Simulator::Cancel (it->second.nextServe);
758  }
759 
760  if (it->second.txBufferSize > 0)
761  {
762  NS_LOG_WARN (this << " Closing a socket where "
763  << it->second.txBufferSize << " bytes of transmission"
764  << " is still pending in the corresponding Tx buffer.");
765  }
766 
767  it->first->Close ();
768  it->first->SetCloseCallbacks (MakeNullCallback<void, Ptr<Socket> > (),
769  MakeNullCallback<void, Ptr<Socket> > ());
770  it->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
771  it->first->SetSendCallback (MakeNullCallback<void, Ptr<Socket>, uint32_t > ());
772 
773  m_txBuffer.erase (it);
774 }
775 
776 
777 void
779 {
780  NS_LOG_FUNCTION (this);
781 
782  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
783  for (it = m_txBuffer.begin (); it != m_txBuffer.end (); ++it)
784  {
785  if (!Simulator::IsExpired (it->second.nextServe))
786  {
787  NS_LOG_INFO (this << " Canceling a serving event which is due in "
788  << Simulator::GetDelayLeft (it->second.nextServe).As (Time::S)
789  << ".");
790  Simulator::Cancel (it->second.nextServe);
791  }
792 
793  it->first->Close ();
794  it->first->SetCloseCallbacks (MakeNullCallback<void, Ptr<Socket> > (),
795  MakeNullCallback<void, Ptr<Socket> > ());
796  it->first->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
797  it->first->SetSendCallback (MakeNullCallback<void, Ptr<Socket>, uint32_t > ());
798  }
799 
800  m_txBuffer.clear ();
801 }
802 
803 
804 bool
806 {
807  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
808  it = m_txBuffer.find (socket);
809  NS_ASSERT_MSG (it != m_txBuffer.end (),
810  "Socket " << socket << " cannot be found.");
811  return (it->second.txBufferSize == 0);
812 }
813 
814 
815 Time
817 {
818  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
819  it = m_txBuffer.find (socket);
820  NS_ASSERT_MSG (it != m_txBuffer.end (),
821  "Socket " << socket << " cannot be found.");
822  return it->second.clientTs;
823 }
824 
825 
828 {
829  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
830  it = m_txBuffer.find (socket);
831  NS_ASSERT_MSG (it != m_txBuffer.end (),
832  "Socket " << socket << " cannot be found.");
833  return it->second.txBufferContentType;
834 }
835 
836 
837 uint32_t
839 {
840  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
841  it = m_txBuffer.find (socket);
842  NS_ASSERT_MSG (it != m_txBuffer.end (),
843  "Socket " << socket << " cannot be found.");
844  return it->second.txBufferSize;
845 }
846 
847 
848 bool
850 {
851  std::map<Ptr<Socket>, TxBuffer_t>::const_iterator it;
852  it = m_txBuffer.find (socket);
853  NS_ASSERT_MSG (it != m_txBuffer.end (),
854  "Socket " << socket << " cannot be found");
855  return it->second.hasTxedPartOfObject;
856 }
857 
858 
859 void
862  uint32_t objectSize)
863 {
864  NS_LOG_FUNCTION (this << socket << contentType << objectSize);
865 
867  "Unable to write an object without a proper Content-Type.");
868  NS_ASSERT_MSG (objectSize > 0,
869  "Unable to write a zero-sized object.");
870 
871  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
872  it = m_txBuffer.find (socket);
873  NS_ASSERT_MSG (it != m_txBuffer.end (),
874  "Socket " << socket << " cannot be found.");
875  NS_ASSERT_MSG (it->second.txBufferSize == 0,
876  "Cannot write to Tx buffer of socket " << socket
877  << " until the previous content has been completely sent.");
878  it->second.txBufferContentType = contentType;
879  it->second.txBufferSize = objectSize;
880  it->second.hasTxedPartOfObject = false;
881 }
882 
883 
884 void
886  const EventId &eventId,
887  const Time &clientTs)
888 {
889  NS_LOG_FUNCTION (this << socket << clientTs.As (Time::S));
890 
891  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
892  it = m_txBuffer.find (socket);
893  NS_ASSERT_MSG (it != m_txBuffer.end (),
894  "Socket " << socket << " cannot be found.");
895  it->second.nextServe = eventId;
896  it->second.clientTs = clientTs;
897 }
898 
899 
900 void
902 {
903  NS_LOG_FUNCTION (this << socket << amount);
904 
905  NS_ASSERT_MSG (amount > 0, "Unable to consume zero bytes.");
906 
907  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
908  it = m_txBuffer.find (socket);
909  NS_ASSERT_MSG (it != m_txBuffer.end (),
910  "Socket " << socket << " cannot be found.");
911  NS_ASSERT_MSG (it->second.txBufferSize >= amount,
912  "The requested amount is larger than the current buffer size.");
913  it->second.txBufferSize -= amount;
914  it->second.hasTxedPartOfObject = true;
915 
916  if (it->second.isClosing && (it->second.txBufferSize == 0))
917  {
918  /*
919  * The peer has earlier issued a close request and we have now waited
920  * until all the existing data are pushed into the socket. Now we close
921  * the socket explicitly.
922  */
923  CloseSocket (socket);
924  }
925 }
926 
927 
928 void
930 {
931  NS_LOG_FUNCTION (this << socket);
932  std::map<Ptr<Socket>, TxBuffer_t>::iterator it;
933  it = m_txBuffer.find (socket);
934  NS_ASSERT_MSG (it != m_txBuffer.end (),
935  "Socket " << socket << " cannot be found.");
936  it->second.isClosing = true;
937 }
938 
939 
940 } // end of `namespace ns3`
#define min(a, b)
Definition: 80211b.c:42
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Address.
Definition: address.h:278
The base class for all ns3 applications.
Definition: application.h:61
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
Ptr< Node > GetNode() const
Definition: application.cc:104
An identifier for simulation events.
Definition: event-id.h:54
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
uint16_t GetPort(void) const
Get the port.
an Inet address class
uint16_t GetPort(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address ConvertFrom(const Address &address)
static bool IsMatchingType(const Address &address)
Describes an IPv6 address.
Definition: ipv6-address.h:50
static Ipv6Address ConvertFrom(const Address &address)
Convert the Address object into an Ipv6Address ones.
static bool IsMatchingType(const Address &address)
If the Address matches the type.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Hold objects of type Ptr<T>.
Definition: pointer.h:37
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:268
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static bool IsExpired(const EventId &id)
Check if an event has already run or been cancelled.
Definition: simulator.cc:278
static bool IsFinished(void)
Check if the simulation should finish.
Definition: simulator.cc:165
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:204
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition: socket.cc:104
virtual int Listen(void)=0
Listen for incoming connections.
virtual int ShutdownSend(void)=0
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
virtual int Close(void)=0
Close a socket.
void SetCloseCallbacks(Callback< void, Ptr< Socket > > normalClose, Callback< void, Ptr< Socket > > errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:94
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual enum Socket::SocketErrno GetErrno(void) const =0
Get last error number.
virtual uint32_t GetTxAvailable(void) const =0
Returns the number of bytes which can be sent in a single call to Send.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
static TypeId GetTypeId(void)
Get the type ID.
static TypeId GetTypeId(void)
Get the type ID.
Definition: tcp-socket.cc:45
Header used by web browsing applications to transmit information about content type,...
void SetClientTs(Time clientTs)
void SetServerTs(Time serverTs)
void SetContentLength(uint32_t contentLength)
void SetContentType(ContentType_t contentType)
ContentType_t
The possible types of content (default = NOT_SET).
@ NOT_SET
Integer equivalent = 0.
@ EMBEDDED_OBJECT
Integer equivalent = 2.
@ MAIN_OBJECT
Integer equivalent = 1.
virtual uint32_t GetSerializedSize() const
ContentType_t GetContentType() const
State_t
The possible states of the application.
@ NOT_STARTED
Before StartApplication() is invoked.
@ STOPPED
After StopApplication() is invoked.
@ STARTED
Passively listening and responding to requests.
virtual void DoDispose()
Destructor implementation.
uint32_t ServeFromTxBuffer(Ptr< Socket > socket)
Creates a packet out of a pending object in the Tx buffer send it over the given socket.
State_t m_state
The current state of the client application. Begins with NOT_STARTED.
Ptr< ThreeGppHttpVariables > m_httpVariables
The Variables attribute.
uint16_t m_localPort
The LocalPort attribute.
TracedCallback< uint32_t > m_embeddedObjectTrace
The EmbeddedObject trace source.
Address m_localAddress
The LocalAddress attribute.
void ReceivedDataCallback(Ptr< Socket > socket)
Invoked when m_initialSocket receives some packet data.
void ServeNewMainObject(Ptr< Socket > socket)
Generates a new main object and push it into the Tx buffer.
virtual void StartApplication()
Application specific startup code.
virtual void StopApplication()
Application specific shutdown code.
TracedCallback< uint32_t > m_mainObjectTrace
The MainObject trace source.
uint32_t m_mtuSize
The Mtu attribute.
State_t GetState() const
Returns the current state of the application.
Ptr< ThreeGppHttpServerTxBuffer > m_txBuffer
Pointer to the transmission buffer.
bool ConnectionRequestCallback(Ptr< Socket > socket, const Address &address)
Invoked when m_initialSocket receives a connection request.
void ServeNewEmbeddedObject(Ptr< Socket > socket)
Generates a new embedded object and push it into the Tx buffer.
void ErrorCloseCallback(Ptr< Socket > socket)
Invoked when a connection with a web client is terminated.
void SendCallback(Ptr< Socket > socket, uint32_t availableBufferSize)
Invoked when more buffer space for transmission is added to a socket.
Ptr< Socket > GetSocket() const
Returns a pointer to the listening socket.
TracedCallback< Ptr< const ThreeGppHttpServer >, Ptr< Socket > > m_connectionEstablishedTrace
The ConnectionEstablished trace source.
Ptr< Socket > m_initialSocket
The listening socket, for receiving connection requests from clients.
static TypeId GetTypeId()
Returns the object TypeId.
TracedCallback< const Time &, const Address & > m_rxDelayTrace
The RxDelay trace source.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
The Rx trace source.
std::string GetStateString() const
Returns the current state of the application in string format.
ThreeGppHttpServer()
Creates a new instance of HTTP server application.
TracedCallback< Ptr< const Packet > > m_txTrace
The Tx trace source.
void NormalCloseCallback(Ptr< Socket > socket)
Invoked when a connection with a web client is terminated.
void NewConnectionCreatedCallback(Ptr< Socket > socket, const Address &address)
Invoked when a new connection has been established.
void SetMtuSize(uint32_t mtuSize)
Sets the maximum transmission unit (MTU) size used by the application.
TracedCallback< const std::string &, const std::string & > m_stateTransitionTrace
The StateTransition trace source.
void SwitchToState(State_t state)
Change the state of the server.
void DepleteBufferSize(Ptr< Socket > socket, uint32_t amount)
Decrements a buffer size by a given amount.
ThreeGppHttpHeader::ContentType_t GetBufferContentType(Ptr< Socket > socket) const
Returns ThreeGppHttpHeader::NOT_SET when the buffer is new and never been filled with any data before...
uint32_t GetBufferSize(Ptr< Socket > socket) const
void CloseAllSockets()
Close and remove all stored sockets, hence clearing the buffer.
bool HasTxedPartOfObject(Ptr< Socket > socket) const
void PrepareClose(Ptr< Socket > socket)
Tell the buffer to close the associated socket once the buffer becomes empty.
Time GetClientTs(Ptr< Socket > socket) const
void CloseSocket(Ptr< Socket > socket)
Close and remove a socket and its associated transmission buffer, and then unset the socket's callbac...
ThreeGppHttpServerTxBuffer()
Create an empty instance of transmission buffer.
void RecordNextServe(Ptr< Socket > socket, const EventId &eventId, const Time &clientTs)
Informs about a pending transmission event associated with the socket, so that it would be automatica...
std::map< Ptr< Socket >, TxBuffer_t > m_txBuffer
Collection of accepted sockets and its individual transmission buffer.
void WriteNewObject(Ptr< Socket > socket, ThreeGppHttpHeader::ContentType_t contentType, uint32_t objectSize)
Writes a data representing a new main object or embedded object to the transmission buffer.
bool IsBufferEmpty(Ptr< Socket > socket) const
bool IsSocketAvailable(Ptr< Socket > socket) const
This method is typically used before calling other methods.
void AddSocket(Ptr< Socket > socket)
Add a new socket and create an empty transmission buffer for it.
void RemoveSocket(Ptr< Socket > socket)
Remove a socket and its associated transmission buffer, and then unset the socket's callbacks to prev...
Container of various random variables to assist in generating web browsing traffic pattern.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
@ S
second
Definition: nstime.h:114
TimeWithUnit As(const enum Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:418
a unique identifier for an interface.
Definition: type-id.h:59
std::size_t GetAttributeN(void) const
Get the number of attributes.
Definition: type-id.cc:1076
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
struct TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1083
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeAccessor > MakeAddressAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: address.h:278
Ptr< const AttributeChecker > MakeAddressChecker(void)
Definition: address.cc:172
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
Callback< R, Ts... > MakeNullCallback(void)
Definition: callback.h:1688
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:576
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:409
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
Set of fields representing a single transmission buffer, which will be associated with a socket.
ThreeGppHttpHeader::ContentType_t txBufferContentType
The content type of the current data inside the transmission buffer.
uint32_t txBufferSize
The length (in bytes) of the current data inside the transmission buffer.
bool isClosing
True if the remote end has issued a request to close, which means that this socket will immediately c...
bool hasTxedPartOfObject
True if the buffer content has been read since it is written.
Attribute implementation.
Definition: type-id.h:78
std::string name
Attribute name.
Definition: type-id.h:80
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:88
static const uint32_t packetSize