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