A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-http-server.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Magister Solutions
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Budiarto Herman <budiarto.herman@magister.fi>
7 *
8 */
9
11
13
14#include <ns3/callback.h>
15#include <ns3/config.h>
16#include <ns3/inet-socket-address.h>
17#include <ns3/inet6-socket-address.h>
18#include <ns3/log.h>
19#include <ns3/packet.h>
20#include <ns3/pointer.h>
21#include <ns3/simulator.h>
22#include <ns3/socket.h>
23#include <ns3/tcp-socket-factory.h>
24#include <ns3/tcp-socket.h>
25#include <ns3/uinteger.h>
26
27NS_LOG_COMPONENT_DEFINE("ThreeGppHttpServer");
28
29namespace ns3
30{
31
32// HTTP SERVER ////////////////////////////////////////////////////////////////
33
34NS_OBJECT_ENSURE_REGISTERED(ThreeGppHttpServer);
35
37 : m_state(NOT_STARTED),
38 m_initialSocket(nullptr),
40 m_httpVariables(CreateObject<ThreeGppHttpVariables>())
41{
42 NS_LOG_FUNCTION(this);
43
44 m_mtuSize = m_httpVariables->GetMtuSize();
45 NS_LOG_INFO(this << " MTU size for this server application is " << m_mtuSize << " bytes.");
46}
47
48// static
51{
52 static TypeId tid =
53 TypeId("ns3::ThreeGppHttpServer")
55 .AddConstructor<ThreeGppHttpServer>()
56 .AddAttribute("Variables",
57 "Variable collection, which is used to control e.g. processing and "
58 "object generation delays.",
62 .AddAttribute("LocalAddress",
63 "The local address of the server, "
64 "i.e., the address on which to bind the Rx socket.",
68 .AddAttribute("LocalPort",
69 "Port on which the application listen for incoming packets.",
70 UintegerValue(80), // the default HTTP port
73 .AddAttribute("Tos",
74 "The Type of Service used to send packets. "
75 "All 8 bits of the TOS byte are set (including ECN bits).",
79 .AddAttribute("Mtu",
80 "Maximum transmission unit (in bytes) of the TCP sockets "
81 "used in this application, excluding the compulsory 40 "
82 "bytes TCP header. Typical values are 1460 and 536 bytes. "
83 "The attribute is read-only because the value is randomly "
84 "determined.",
89 .AddTraceSource(
90 "ConnectionEstablished",
91 "Connection to a remote web client has been established.",
93 "ns3::HttpServer::ConnectionEstablishedCallback")
94 .AddTraceSource("MainObject",
95 "A main object has been generated.",
97 "ns3::HttpServer::HttpObjectCallback")
98 .AddTraceSource("EmbeddedObject",
99 "An embedded object has been generated.",
101 "ns3::HttpServer::HttpObjectCallback")
102 .AddTraceSource("Tx",
103 "A packet has been sent.",
105 "ns3::Packet::TracedCallback")
106 .AddTraceSource("Rx",
107 "A packet has been received.",
109 "ns3::Packet::PacketAddressTracedCallback")
110 .AddTraceSource("RxDelay",
111 "A packet has been received with delay information.",
113 "ns3::Application::DelayAddressCallback")
114 .AddTraceSource("StateTransition",
115 "Trace fired upon every HTTP client state transition.",
117 "ns3::Application::StateTransitionCallback");
118 return tid;
119}
120
121void
123{
124 NS_LOG_FUNCTION(this << mtuSize);
125 m_mtuSize = mtuSize;
126}
127
130{
131 return m_initialSocket;
132}
133
136{
137 return m_state;
138}
139
140std::string
145
146// static
147std::string
149{
150 switch (state)
151 {
152 case NOT_STARTED:
153 return "NOT_STARTED";
154 case STARTED:
155 return "STARTED";
156 case STOPPED:
157 return "STOPPED";
158 default:
159 NS_FATAL_ERROR("Unknown state");
160 return "FATAL_ERROR";
161 }
162}
163
164void
166{
167 NS_LOG_FUNCTION(this);
168
170 {
172 }
173
174 Application::DoDispose(); // Chain up.
175}
176
177void
179{
180 NS_LOG_FUNCTION(this);
181
182 if (m_state == NOT_STARTED)
183 {
184 m_httpVariables->Initialize();
185 if (!m_initialSocket)
186 {
187 // Find the current default MTU value of TCP sockets.
188 Ptr<const ns3::AttributeValue> previousSocketMtu;
189 const TypeId tcpSocketTid = TcpSocket::GetTypeId();
190 for (uint32_t i = 0; i < tcpSocketTid.GetAttributeN(); i++)
191 {
192 TypeId::AttributeInformation attrInfo = tcpSocketTid.GetAttribute(i);
193 if (attrInfo.name == "SegmentSize")
194 {
195 previousSocketMtu = attrInfo.initialValue;
196 }
197 }
198
199 // Creating a TCP socket to connect to the server.
202
204 "'LocalAddress' attribute not properly set");
205
207 {
209 const InetSocketAddress inetSocket = InetSocketAddress(ipv4, m_localPort);
210 NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_localPort << " / "
211 << inetSocket << ".");
212 int ret [[maybe_unused]] = m_initialSocket->Bind(inetSocket);
213 NS_LOG_DEBUG(this << " Bind() return value= " << ret
214 << " GetErrNo= " << m_initialSocket->GetErrno() << ".");
215
216 m_initialSocket->SetIpTos(m_tos); // Affects only IPv4 sockets.
217 }
219 {
221 const Inet6SocketAddress inet6Socket = Inet6SocketAddress(ipv6, m_localPort);
222 NS_LOG_INFO(this << " Binding on " << ipv6 << " port " << m_localPort << " / "
223 << inet6Socket << ".");
224 int ret [[maybe_unused]] = m_initialSocket->Bind(inet6Socket);
225 NS_LOG_DEBUG(this << " Bind() return value= " << ret
226 << " GetErrNo= " << m_initialSocket->GetErrno() << ".");
227 }
228 else
229 {
230 NS_ABORT_MSG("Incompatible local address");
231 }
232
233 int ret [[maybe_unused]] = m_initialSocket->Listen();
234 NS_LOG_DEBUG(this << " Listen () return value= " << ret
235 << " GetErrNo= " << m_initialSocket->GetErrno() << ".");
236
237 } // end of `if (m_initialSocket == 0)`
238
239 NS_ASSERT_MSG(m_initialSocket, "Failed creating socket.");
250
251 } // end of `if (m_state == NOT_STARTED)`
252 else
253 {
254 NS_FATAL_ERROR("Invalid state " << GetStateString() << " for StartApplication().");
255 }
256
257} // end of `void StartApplication ()`
258
259void
261{
262 NS_LOG_FUNCTION(this);
263
265
266 // Close all accepted sockets.
267 m_txBuffer->CloseAllSockets();
268
269 // Stop listening.
270 if (m_initialSocket)
271 {
274 MakeNullCallback<void, Ptr<Socket>, const Address&>());
279 }
280}
281
282bool
284{
285 NS_LOG_FUNCTION(this << socket << address);
286 return true; // Unconditionally accept the connection request.
287}
288
289void
291{
292 NS_LOG_FUNCTION(this << socket << address);
293
294 socket->SetCloseCallbacks(MakeCallback(&ThreeGppHttpServer::NormalCloseCallback, this),
296 socket->SetRecvCallback(MakeCallback(&ThreeGppHttpServer::ReceivedDataCallback, this));
297 socket->SetSendCallback(MakeCallback(&ThreeGppHttpServer::SendCallback, this));
298
299 m_connectionEstablishedTrace(this, socket);
300 m_txBuffer->AddSocket(socket);
301
302 /*
303 * A typical connection is established after receiving an empty (i.e., no
304 * data) TCP packet with ACK flag. The actual data will follow in a separate
305 * packet after that and will be received by ReceivedDataCallback().
306 *
307 * However, that empty ACK packet might get lost. In this case, we may
308 * receive the first data packet right here already, because it also counts
309 * as a new connection. The statement below attempts to fetch the data from
310 * that packet, if any.
311 */
312 ReceivedDataCallback(socket);
313}
314
315void
317{
318 NS_LOG_FUNCTION(this << socket);
319
320 if (socket == m_initialSocket)
321 {
322 if (m_state == STARTED)
323 {
324 NS_FATAL_ERROR("Initial listener socket shall not be closed"
325 << " when the server instance is still running.");
326 }
327 }
328 else if (m_txBuffer->IsSocketAvailable(socket))
329 {
330 // The application should now prepare to close the socket.
331 if (m_txBuffer->IsBufferEmpty(socket))
332 {
333 /*
334 * Here we declare that we have nothing more to send and the socket
335 * may be closed immediately.
336 */
337 socket->ShutdownSend();
338 m_txBuffer->RemoveSocket(socket);
339 }
340 else
341 {
342 /*
343 * Remember to close the socket later, whenever the buffer becomes
344 * empty.
345 */
346 m_txBuffer->PrepareClose(socket);
347 }
348 }
349}
350
351void
353{
354 NS_LOG_FUNCTION(this << socket);
355
356 if (socket == m_initialSocket)
357 {
358 if (m_state == STARTED)
359 {
360 NS_FATAL_ERROR("Initial listener socket shall not be closed"
361 << " when the server instance is still running.");
362 }
363 }
364 else if (m_txBuffer->IsSocketAvailable(socket))
365 {
366 m_txBuffer->CloseSocket(socket);
367 }
368}
369
370void
372{
373 NS_LOG_FUNCTION(this << socket);
374
375 Ptr<Packet> packet;
376 Address from;
377
378 while ((packet = socket->RecvFrom(from)))
379 {
380 if (packet->GetSize() == 0)
381 {
382 break; // EOF
383 }
384
385#ifdef NS3_LOG_ENABLE
386 // Some log messages.
388 {
389 NS_LOG_INFO(this << " A packet of " << packet->GetSize() << " bytes"
390 << " received from " << InetSocketAddress::ConvertFrom(from).GetIpv4()
391 << " port " << InetSocketAddress::ConvertFrom(from).GetPort() << " / "
393 }
395 {
396 NS_LOG_INFO(this << " A packet of " << packet->GetSize() << " bytes"
397 << " received from " << Inet6SocketAddress::ConvertFrom(from).GetIpv6()
398 << " port " << Inet6SocketAddress::ConvertFrom(from).GetPort() << " / "
400 }
401#endif /* NS3_LOG_ENABLE */
402
403 // Check the header. No need to remove it, since it is not a "real" header.
404 ThreeGppHttpHeader httpHeader;
405 packet->PeekHeader(httpHeader);
406
407 // Fire trace sources.
408 m_rxTrace(packet, from);
409 m_rxDelayTrace(Simulator::Now() - httpHeader.GetClientTs(), from);
410
411 Time processingDelay;
412 switch (httpHeader.GetContentType())
413 {
415 processingDelay = m_httpVariables->GetMainObjectGenerationDelay();
416 NS_LOG_INFO(this << " Will finish generating a main object"
417 << " in " << processingDelay.As(Time::S) << ".");
418 m_txBuffer->RecordNextServe(socket,
419 Simulator::Schedule(processingDelay,
421 this,
422 socket),
423 httpHeader.GetClientTs());
424 break;
425
427 processingDelay = m_httpVariables->GetEmbeddedObjectGenerationDelay();
428 NS_LOG_INFO(this << " Will finish generating an embedded object"
429 << " in " << processingDelay.As(Time::S) << ".");
430 m_txBuffer->RecordNextServe(
431 socket,
432 Simulator::Schedule(processingDelay,
434 this,
435 socket),
436 httpHeader.GetClientTs());
437 break;
438
439 default:
440 NS_FATAL_ERROR("Invalid packet.");
441 break;
442 }
443
444 } // end of `while ((packet = socket->RecvFrom (from)))`
445
446} // end of `void ReceivedDataCallback (Ptr<Socket> socket)`
447
448void
450{
451 NS_LOG_FUNCTION(this << socket << availableBufferSize);
452
453 if (!m_txBuffer->IsBufferEmpty(socket))
454 {
455 const uint32_t txBufferSize [[maybe_unused]] = m_txBuffer->GetBufferSize(socket);
456 const uint32_t actualSent [[maybe_unused]] = ServeFromTxBuffer(socket);
457
458#ifdef NS3_LOG_ENABLE
459 // Some log messages.
460 if (actualSent < txBufferSize)
461 {
462 switch (m_txBuffer->GetBufferContentType(socket))
463 {
465 NS_LOG_INFO(this << " Transmission of main object is suspended"
466 << " after " << actualSent << " bytes.");
467 break;
469 NS_LOG_INFO(this << " Transmission of embedded object is suspended"
470 << " after " << actualSent << " bytes.");
471 break;
472 default:
473 NS_FATAL_ERROR("Invalid Tx buffer content type.");
474 break;
475 }
476 }
477 else
478 {
479 switch (m_txBuffer->GetBufferContentType(socket))
480 {
482 NS_LOG_INFO(this << " Finished sending a whole main object.");
483 break;
485 NS_LOG_INFO(this << " Finished sending a whole embedded object.");
486 break;
487 default:
488 NS_FATAL_ERROR("Invalid Tx buffer content type.");
489 break;
490 }
491 }
492#endif /* NS3_LOG_ENABLE */
493
494 } // end of `if (m_txBuffer->IsBufferEmpty (socket))`
495
496} // end of `void SendCallback (Ptr<Socket> socket, uint32_t availableBufferSize)`
497
498void
500{
501 NS_LOG_FUNCTION(this << socket);
502
503 const uint32_t objectSize = m_httpVariables->GetMainObjectSize();
504 NS_LOG_INFO(this << " Main object to be served is " << objectSize << " bytes.");
505 m_mainObjectTrace(objectSize);
506 m_txBuffer->WriteNewObject(socket, ThreeGppHttpHeader::MAIN_OBJECT, objectSize);
507 const uint32_t actualSent = ServeFromTxBuffer(socket);
508
509 if (actualSent < objectSize)
510 {
511 NS_LOG_INFO(this << " Transmission of main object is suspended"
512 << " after " << actualSent << " bytes.");
513 }
514 else
515 {
516 NS_LOG_INFO(this << " Finished sending a whole main object.");
517 }
518}
519
520void
522{
523 NS_LOG_FUNCTION(this << socket);
524
525 const uint32_t objectSize = m_httpVariables->GetEmbeddedObjectSize();
526 NS_LOG_INFO(this << " Embedded object to be served is " << objectSize << " bytes.");
527 m_embeddedObjectTrace(objectSize);
528 m_txBuffer->WriteNewObject(socket, ThreeGppHttpHeader::EMBEDDED_OBJECT, objectSize);
529 const uint32_t actualSent = ServeFromTxBuffer(socket);
530
531 if (actualSent < objectSize)
532 {
533 NS_LOG_INFO(this << " Transmission of embedded object is suspended"
534 << " after " << actualSent << " bytes.");
535 }
536 else
537 {
538 NS_LOG_INFO(this << " Finished sending a whole embedded object.");
539 }
540}
541
544{
545 NS_LOG_FUNCTION(this << socket);
546
547 if (m_txBuffer->IsBufferEmpty(socket))
548 {
549 NS_LOG_LOGIC(this << " Tx buffer is empty. Not sending anything.");
550 return 0;
551 }
552 bool firstPartOfObject = !m_txBuffer->HasTxedPartOfObject(socket);
553
554 const uint32_t socketSize = socket->GetTxAvailable();
555 NS_LOG_DEBUG(this << " Socket has " << socketSize << " bytes available for Tx.");
556
557 // Get the number of bytes remaining to be sent.
558 const uint32_t txBufferSize = m_txBuffer->GetBufferSize(socket);
559
560 // Compute the size of actual content to be sent; has to fit into the socket.
561 // Note that header size is NOT counted as TxBuffer content. Header size is overhead.
562 uint32_t contentSize = std::min(txBufferSize, socketSize - 22);
563 Ptr<Packet> packet = Create<Packet>(contentSize);
564 uint32_t packetSize = contentSize;
565 if (packetSize == 0)
566 {
567 NS_LOG_LOGIC(this << " Socket size leads to packet size of zero; not sending anything.");
568 return 0;
569 }
570
571 // If this is the first packet of an object, attach a header.
572 if (firstPartOfObject)
573 {
574 // Create header.
575 ThreeGppHttpHeader httpHeader;
576 httpHeader.SetContentLength(txBufferSize);
577 httpHeader.SetContentType(m_txBuffer->GetBufferContentType(socket));
578 // Using the client TS value as per the corresponding request packet.
579 httpHeader.SetClientTs(m_txBuffer->GetClientTs(socket));
580 httpHeader.SetServerTs(Simulator::Now());
581 packet->AddHeader(httpHeader);
582 packetSize += httpHeader.GetSerializedSize();
583
584 NS_LOG_INFO(this << " Created packet " << packet << " of " << packetSize << " bytes."
585 << " The corresponding request came "
586 << (Simulator::Now() - httpHeader.GetClientTs()).As(Time::S) << " ago.");
587 }
588 else
589 {
590 NS_LOG_INFO(this << " Created packet " << packet << " of " << packetSize
591 << " bytes to be appended to a previous packet.");
592 }
593
594 // Send.
595 const int actualBytes = socket->Send(packet);
596 NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packetSize << " bytes,"
597 << " return value= " << actualBytes << ".");
598 m_txTrace(packet);
599
600 if (actualBytes == static_cast<int>(packetSize))
601 {
602 // The packet goes through successfully.
603 m_txBuffer->DepleteBufferSize(socket, contentSize);
604 NS_LOG_INFO(this << " Remaining object to be sent " << m_txBuffer->GetBufferSize(socket)
605 << " bytes.");
606 return packetSize;
607 }
608 else
609 {
610 NS_LOG_INFO(this << " Failed to send object,"
611 << " GetErrNo= " << socket->GetErrno() << ","
612 << " suspending transmission"
613 << " and waiting for another Tx opportunity.");
614 return 0;
615 }
616
617} // end of `uint32_t ServeFromTxBuffer (Ptr<Socket> socket)`
618
619void
621{
622 const std::string oldState = GetStateString();
623 const std::string newState = GetStateString(state);
624 NS_LOG_FUNCTION(this << oldState << newState);
625 m_state = state;
626 NS_LOG_INFO(this << " ThreeGppHttpServer " << oldState << " --> " << newState << ".");
627 m_stateTransitionTrace(oldState, newState);
628}
629
630// HTTP SERVER TX BUFFER //////////////////////////////////////////////////////
631
636
637bool
639{
640 auto it = m_txBuffer.find(socket);
641 return (it != m_txBuffer.end());
642}
643
644void
646{
647 NS_LOG_FUNCTION(this << socket);
648
650 this << " Cannot add socket " << socket
651 << " because it has already been added before.");
652
653 TxBuffer_t txBuffer;
655 txBuffer.txBufferSize = 0;
656 txBuffer.isClosing = false;
657 txBuffer.hasTxedPartOfObject = false;
658 m_txBuffer.insert(std::pair<Ptr<Socket>, TxBuffer_t>(socket, txBuffer));
659}
660
661void
663{
664 NS_LOG_FUNCTION(this << socket);
665
666 auto it = m_txBuffer.find(socket);
667 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
668
669 if (!Simulator::IsExpired(it->second.nextServe))
670 {
671 NS_LOG_INFO(this << " Canceling a serving event which is due in "
672 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
673 Simulator::Cancel(it->second.nextServe);
674 }
675
676 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
678 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
679 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
680
681 m_txBuffer.erase(it);
682}
683
684void
686{
687 NS_LOG_FUNCTION(this << socket);
688
689 auto it = m_txBuffer.find(socket);
690 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
691
692 if (!Simulator::IsExpired(it->second.nextServe))
693 {
694 NS_LOG_INFO(this << " Canceling a serving event which is due in "
695 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
696 Simulator::Cancel(it->second.nextServe);
697 }
698
699 if (it->second.txBufferSize > 0)
700 {
701 NS_LOG_WARN(this << " Closing a socket where " << it->second.txBufferSize
702 << " bytes of transmission"
703 << " is still pending in the corresponding Tx buffer.");
704 }
705
706 it->first->Close();
707 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
709 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
710 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
711
712 m_txBuffer.erase(it);
713}
714
715void
717{
718 NS_LOG_FUNCTION(this);
719
720 for (auto it = m_txBuffer.begin(); it != m_txBuffer.end(); ++it)
721 {
722 if (!Simulator::IsExpired(it->second.nextServe))
723 {
724 NS_LOG_INFO(this << " Canceling a serving event which is due in "
725 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
726 Simulator::Cancel(it->second.nextServe);
727 }
728
729 it->first->Close();
730 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
732 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
733 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
734 }
735
736 m_txBuffer.clear();
737}
738
739bool
741{
742 auto it = m_txBuffer.find(socket);
743 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
744 return (it->second.txBufferSize == 0);
745}
746
747Time
749{
750 auto it = m_txBuffer.find(socket);
751 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
752 return it->second.clientTs;
753}
754
757{
758 auto it = m_txBuffer.find(socket);
759 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
760 return it->second.txBufferContentType;
761}
762
765{
766 auto it = m_txBuffer.find(socket);
767 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
768 return it->second.txBufferSize;
769}
770
771bool
773{
774 auto it = m_txBuffer.find(socket);
775 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found");
776 return it->second.hasTxedPartOfObject;
777}
778
779void
782 uint32_t objectSize)
783{
784 NS_LOG_FUNCTION(this << socket << contentType << objectSize);
785
787 "Unable to write an object without a proper Content-Type.");
788 NS_ASSERT_MSG(objectSize > 0, "Unable to write a zero-sized object.");
789
790 auto it = m_txBuffer.find(socket);
791 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
792 NS_ASSERT_MSG(it->second.txBufferSize == 0,
793 "Cannot write to Tx buffer of socket "
794 << socket << " until the previous content has been completely sent.");
795 it->second.txBufferContentType = contentType;
796 it->second.txBufferSize = objectSize;
797 it->second.hasTxedPartOfObject = false;
798}
799
800void
802 const EventId& eventId,
803 const Time& clientTs)
804{
805 NS_LOG_FUNCTION(this << socket << clientTs.As(Time::S));
806
807 auto it = m_txBuffer.find(socket);
808 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
809 it->second.nextServe = eventId;
810 it->second.clientTs = clientTs;
811}
812
813void
815{
816 NS_LOG_FUNCTION(this << socket << amount);
817
818 NS_ASSERT_MSG(amount > 0, "Unable to consume zero bytes.");
819
820 auto it = m_txBuffer.find(socket);
821 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
822 NS_ASSERT_MSG(it->second.txBufferSize >= amount,
823 "The requested amount is larger than the current buffer size.");
824 it->second.txBufferSize -= amount;
825 it->second.hasTxedPartOfObject = true;
826
827 if (it->second.isClosing && (it->second.txBufferSize == 0))
828 {
829 /*
830 * The peer has earlier issued a close request and we have now waited
831 * until all the existing data are pushed into the socket. Now we close
832 * the socket explicitly.
833 */
834 CloseSocket(socket);
835 }
836}
837
838void
840{
841 NS_LOG_FUNCTION(this << socket);
842 auto it = m_txBuffer.find(socket);
843 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
844 it->second.isClosing = true;
845}
846
847} // namespace ns3
a polymophic address class
Definition address.h:90
bool IsInvalid() const
Definition address.cc:60
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
An identifier for simulation events.
Definition event-id.h:45
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint16_t GetPort() const
Get the port.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
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.
static Ipv4Address ConvertFrom(const Address &address)
static bool IsMatchingType(const Address &address)
Describes an IPv6 address.
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.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
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:274
static bool IsFinished()
Check if the simulation should finish.
Definition simulator.cc:160
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static bool IsExpired(const EventId &id)
Check if an event has already run or been cancelled.
Definition simulator.cc:284
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:206
virtual Socket::SocketErrno GetErrno() const =0
Get last error number.
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition socket.cc:423
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:94
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition socket.cc:110
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:85
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
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:61
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
static TypeId GetTypeId()
Get the type ID.
static TypeId GetTypeId()
Get the type ID.
Definition tcp-socket.cc:43
Header used by web browsing applications to transmit information about content type,...
uint32_t GetSerializedSize() const override
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.
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.
void StartApplication() override
Application specific startup code.
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.
TracedCallback< uint32_t > m_mainObjectTrace
The MainObject trace source.
uint32_t m_mtuSize
The Mtu attribute.
TracedCallback< const Time &, const Address & > m_rxDelayTrace
The RxDelay trace source.
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.
TracedCallback< const std::string &, const std::string & > m_stateTransitionTrace
The StateTransition trace source.
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.
TracedCallback< Ptr< const Packet >, const Address & > m_rxTrace
The Rx trace source.
uint8_t m_tos
The Tos attribute.
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.
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 DoDispose() override
Destructor implementation.
void StopApplication() override
Application specific shutdown code.
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.
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:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:48
@ ATTR_GET
The attribute can be read.
Definition type-id.h:53
std::size_t GetAttributeN() const
Get the number of attributes.
Definition type-id.cc:1170
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition type-id.cc:1178
Hold an unsigned integer type.
Definition uinteger.h:34
#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:75
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:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeAddressChecker()
Definition address.cc:169
Ptr< const AttributeAccessor > MakeAddressAccessor(T1 a1)
Definition address.h:275
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:70
std::string name
Attribute name.
Definition type-id.h:72
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition type-id.h:80
static const uint32_t packetSize
Packet size generated at the AP.