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
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
39NS_LOG_COMPONENT_DEFINE ("ThreeGppHttpServer");
40
41
42namespace ns3 {
43
44
45// HTTP SERVER ////////////////////////////////////////////////////////////////
46
47
48NS_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
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 (),
82 MakeAddressAccessor (&ThreeGppHttpServer::m_localAddress),
83 MakeAddressChecker ())
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.",
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
132void
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
154std::string
156{
157 return GetStateString (m_state);
158}
159
160
161// static
162std::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
184void
186{
187 NS_LOG_FUNCTION (this);
188
189 if (!Simulator::IsFinished ())
190 {
192 }
193
194 Application::DoDispose (); // Chain up.
195}
196
197
198void
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,
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,
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
287void
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
311bool
313 const Address &address)
314{
315 NS_LOG_FUNCTION (this << socket << address);
316 return true; // Unconditionally accept the connection request.
317}
318
319
320void
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
352void
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
389void
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
409void
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 }
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
485void
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
536void
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
561void
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
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
668void
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
689bool
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
697void
699{
700 NS_LOG_FUNCTION (this << socket);
701
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
715void
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
742void
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
777void
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
804bool
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
815Time
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
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
848bool
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
859void
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
884void
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
900void
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
928void
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.
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.
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.
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.
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:432
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 > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
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
Pcket size generated at the AP.