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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Budiarto Herman <budiarto.herman@magister.fi>
18 *
19 */
20
22
24
25#include <ns3/callback.h>
26#include <ns3/config.h>
27#include <ns3/inet-socket-address.h>
28#include <ns3/inet6-socket-address.h>
29#include <ns3/log.h>
30#include <ns3/packet.h>
31#include <ns3/pointer.h>
32#include <ns3/simulator.h>
33#include <ns3/socket.h>
34#include <ns3/tcp-socket-factory.h>
35#include <ns3/tcp-socket.h>
36#include <ns3/uinteger.h>
37
38NS_LOG_COMPONENT_DEFINE("ThreeGppHttpServer");
39
40namespace ns3
41{
42
43// HTTP SERVER ////////////////////////////////////////////////////////////////
44
45NS_OBJECT_ENSURE_REGISTERED(ThreeGppHttpServer);
46
48 : m_state(NOT_STARTED),
49 m_initialSocket(nullptr),
51 m_httpVariables(CreateObject<ThreeGppHttpVariables>())
52{
53 NS_LOG_FUNCTION(this);
54
55 m_mtuSize = m_httpVariables->GetMtuSize();
56 NS_LOG_INFO(this << " MTU size for this server application is " << m_mtuSize << " bytes.");
57}
58
59// static
62{
63 static TypeId tid =
64 TypeId("ns3::ThreeGppHttpServer")
66 .AddConstructor<ThreeGppHttpServer>()
67 .AddAttribute("Variables",
68 "Variable collection, which is used to control e.g. processing and "
69 "object generation delays.",
72 MakePointerChecker<ThreeGppHttpVariables>())
73 .AddAttribute("LocalAddress",
74 "The local address of the server, "
75 "i.e., the address on which to bind the Rx socket.",
77 MakeAddressAccessor(&ThreeGppHttpServer::m_localAddress),
78 MakeAddressChecker())
79 .AddAttribute("LocalPort",
80 "Port on which the application listen for incoming packets.",
81 UintegerValue(80), // the default HTTP port
83 MakeUintegerChecker<uint16_t>())
84 .AddAttribute("Mtu",
85 "Maximum transmission unit (in bytes) of the TCP sockets "
86 "used in this application, excluding the compulsory 40 "
87 "bytes TCP header. Typical values are 1460 and 536 bytes. "
88 "The attribute is read-only because the value is randomly "
89 "determined.",
93 MakeUintegerChecker<uint32_t>())
94 .AddTraceSource(
95 "ConnectionEstablished",
96 "Connection to a remote web client has been established.",
98 "ns3::HttpServer::ConnectionEstablishedCallback")
99 .AddTraceSource("MainObject",
100 "A main object has been generated.",
102 "ns3::HttpServer::HttpObjectCallback")
103 .AddTraceSource("EmbeddedObject",
104 "An embedded object has been generated.",
106 "ns3::HttpServer::HttpObjectCallback")
107 .AddTraceSource("Tx",
108 "A packet has been sent.",
110 "ns3::Packet::TracedCallback")
111 .AddTraceSource("Rx",
112 "A packet has been received.",
114 "ns3::Packet::PacketAddressTracedCallback")
115 .AddTraceSource("RxDelay",
116 "A packet has been received with delay information.",
118 "ns3::Application::DelayAddressCallback")
119 .AddTraceSource("StateTransition",
120 "Trace fired upon every HTTP client state transition.",
122 "ns3::Application::StateTransitionCallback");
123 return tid;
124}
125
126void
128{
129 NS_LOG_FUNCTION(this << mtuSize);
130 m_mtuSize = mtuSize;
131}
132
135{
136 return m_initialSocket;
137}
138
141{
142 return m_state;
143}
144
145std::string
147{
148 return GetStateString(m_state);
149}
150
151// static
152std::string
154{
155 switch (state)
156 {
157 case NOT_STARTED:
158 return "NOT_STARTED";
159 case STARTED:
160 return "STARTED";
161 case STOPPED:
162 return "STOPPED";
163 default:
164 NS_FATAL_ERROR("Unknown state");
165 return "FATAL_ERROR";
166 }
167}
168
169void
171{
172 NS_LOG_FUNCTION(this);
173
175 {
177 }
178
179 Application::DoDispose(); // Chain up.
180}
181
182void
184{
185 NS_LOG_FUNCTION(this);
186
187 if (m_state == NOT_STARTED)
188 {
189 m_httpVariables->Initialize();
190 if (!m_initialSocket)
191 {
192 // Find the current default MTU value of TCP sockets.
193 Ptr<const ns3::AttributeValue> previousSocketMtu;
194 const TypeId tcpSocketTid = TcpSocket::GetTypeId();
195 for (uint32_t i = 0; i < tcpSocketTid.GetAttributeN(); i++)
196 {
197 TypeId::AttributeInformation attrInfo = tcpSocketTid.GetAttribute(i);
198 if (attrInfo.name == "SegmentSize")
199 {
200 previousSocketMtu = attrInfo.initialValue;
201 }
202 }
203
204 // Creating a TCP socket to connect to the server.
207
209 {
211 const InetSocketAddress inetSocket = InetSocketAddress(ipv4, m_localPort);
212 NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_localPort << " / "
213 << inetSocket << ".");
214 int ret [[maybe_unused]] = m_initialSocket->Bind(inetSocket);
215 NS_LOG_DEBUG(this << " Bind() return value= " << ret
216 << " GetErrNo= " << m_initialSocket->GetErrno() << ".");
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
229 int ret [[maybe_unused]] = m_initialSocket->Listen();
230 NS_LOG_DEBUG(this << " Listen () return value= " << ret
231 << " GetErrNo= " << m_initialSocket->GetErrno() << ".");
232
233 } // end of `if (m_initialSocket == 0)`
234
235 NS_ASSERT_MSG(m_initialSocket, "Failed creating socket.");
246
247 } // end of `if (m_state == NOT_STARTED)`
248 else
249 {
250 NS_FATAL_ERROR("Invalid state " << GetStateString() << " for StartApplication().");
251 }
252
253} // end of `void StartApplication ()`
254
255void
257{
258 NS_LOG_FUNCTION(this);
259
261
262 // Close all accepted sockets.
263 m_txBuffer->CloseAllSockets();
264
265 // Stop listening.
266 if (m_initialSocket)
267 {
270 MakeNullCallback<void, Ptr<Socket>, const Address&>());
275 }
276}
277
278bool
280{
281 NS_LOG_FUNCTION(this << socket << address);
282 return true; // Unconditionally accept the connection request.
283}
284
285void
287{
288 NS_LOG_FUNCTION(this << socket << address);
289
290 socket->SetCloseCallbacks(MakeCallback(&ThreeGppHttpServer::NormalCloseCallback, this),
292 socket->SetRecvCallback(MakeCallback(&ThreeGppHttpServer::ReceivedDataCallback, this));
293 socket->SetSendCallback(MakeCallback(&ThreeGppHttpServer::SendCallback, this));
294
295 m_connectionEstablishedTrace(this, socket);
296 m_txBuffer->AddSocket(socket);
297
298 /*
299 * A typical connection is established after receiving an empty (i.e., no
300 * data) TCP packet with ACK flag. The actual data will follow in a separate
301 * packet after that and will be received by ReceivedDataCallback().
302 *
303 * However, that empty ACK packet might get lost. In this case, we may
304 * receive the first data packet right here already, because it also counts
305 * as a new connection. The statement below attempts to fetch the data from
306 * that packet, if any.
307 */
308 ReceivedDataCallback(socket);
309}
310
311void
313{
314 NS_LOG_FUNCTION(this << socket);
315
316 if (socket == m_initialSocket)
317 {
318 if (m_state == STARTED)
319 {
320 NS_FATAL_ERROR("Initial listener socket shall not be closed"
321 << " when the server instance is still running.");
322 }
323 }
324 else if (m_txBuffer->IsSocketAvailable(socket))
325 {
326 // The application should now prepare to close the socket.
327 if (m_txBuffer->IsBufferEmpty(socket))
328 {
329 /*
330 * Here we declare that we have nothing more to send and the socket
331 * may be closed immediately.
332 */
333 socket->ShutdownSend();
334 m_txBuffer->RemoveSocket(socket);
335 }
336 else
337 {
338 /*
339 * Remember to close the socket later, whenever the buffer becomes
340 * empty.
341 */
342 m_txBuffer->PrepareClose(socket);
343 }
344 }
345}
346
347void
349{
350 NS_LOG_FUNCTION(this << socket);
351
352 if (socket == m_initialSocket)
353 {
354 if (m_state == STARTED)
355 {
356 NS_FATAL_ERROR("Initial listener socket shall not be closed"
357 << " when the server instance is still running.");
358 }
359 }
360 else if (m_txBuffer->IsSocketAvailable(socket))
361 {
362 m_txBuffer->CloseSocket(socket);
363 }
364}
365
366void
368{
369 NS_LOG_FUNCTION(this << socket);
370
371 Ptr<Packet> packet;
372 Address from;
373
374 while ((packet = socket->RecvFrom(from)))
375 {
376 if (packet->GetSize() == 0)
377 {
378 break; // EOF
379 }
380
381#ifdef NS3_LOG_ENABLE
382 // Some log messages.
384 {
385 NS_LOG_INFO(this << " A packet of " << packet->GetSize() << " bytes"
386 << " received from " << InetSocketAddress::ConvertFrom(from).GetIpv4()
387 << " port " << InetSocketAddress::ConvertFrom(from).GetPort() << " / "
389 }
391 {
392 NS_LOG_INFO(this << " A packet of " << packet->GetSize() << " bytes"
393 << " received from " << Inet6SocketAddress::ConvertFrom(from).GetIpv6()
394 << " port " << Inet6SocketAddress::ConvertFrom(from).GetPort() << " / "
396 }
397#endif /* NS3_LOG_ENABLE */
398
399 // Check the header. No need to remove it, since it is not a "real" header.
400 ThreeGppHttpHeader httpHeader;
401 packet->PeekHeader(httpHeader);
402
403 // Fire trace sources.
404 m_rxTrace(packet, from);
405 m_rxDelayTrace(Simulator::Now() - httpHeader.GetClientTs(), from);
406
407 Time processingDelay;
408 switch (httpHeader.GetContentType())
409 {
411 processingDelay = m_httpVariables->GetMainObjectGenerationDelay();
412 NS_LOG_INFO(this << " Will finish generating a main object"
413 << " in " << processingDelay.As(Time::S) << ".");
414 m_txBuffer->RecordNextServe(socket,
415 Simulator::Schedule(processingDelay,
417 this,
418 socket),
419 httpHeader.GetClientTs());
420 break;
421
423 processingDelay = m_httpVariables->GetEmbeddedObjectGenerationDelay();
424 NS_LOG_INFO(this << " Will finish generating an embedded object"
425 << " in " << processingDelay.As(Time::S) << ".");
426 m_txBuffer->RecordNextServe(
427 socket,
428 Simulator::Schedule(processingDelay,
430 this,
431 socket),
432 httpHeader.GetClientTs());
433 break;
434
435 default:
436 NS_FATAL_ERROR("Invalid packet.");
437 break;
438 }
439
440 } // end of `while ((packet = socket->RecvFrom (from)))`
441
442} // end of `void ReceivedDataCallback (Ptr<Socket> socket)`
443
444void
446{
447 NS_LOG_FUNCTION(this << socket << availableBufferSize);
448
449 if (!m_txBuffer->IsBufferEmpty(socket))
450 {
451 const uint32_t txBufferSize [[maybe_unused]] = m_txBuffer->GetBufferSize(socket);
452 const uint32_t actualSent [[maybe_unused]] = ServeFromTxBuffer(socket);
453
454#ifdef NS3_LOG_ENABLE
455 // Some log messages.
456 if (actualSent < txBufferSize)
457 {
458 switch (m_txBuffer->GetBufferContentType(socket))
459 {
461 NS_LOG_INFO(this << " Transmission of main object is suspended"
462 << " after " << actualSent << " bytes.");
463 break;
465 NS_LOG_INFO(this << " Transmission of embedded object is suspended"
466 << " after " << actualSent << " bytes.");
467 break;
468 default:
469 NS_FATAL_ERROR("Invalid Tx buffer content type.");
470 break;
471 }
472 }
473 else
474 {
475 switch (m_txBuffer->GetBufferContentType(socket))
476 {
478 NS_LOG_INFO(this << " Finished sending a whole main object.");
479 break;
481 NS_LOG_INFO(this << " Finished sending a whole embedded object.");
482 break;
483 default:
484 NS_FATAL_ERROR("Invalid Tx buffer content type.");
485 break;
486 }
487 }
488#endif /* NS3_LOG_ENABLE */
489
490 } // end of `if (m_txBuffer->IsBufferEmpty (socket))`
491
492} // end of `void SendCallback (Ptr<Socket> socket, uint32_t availableBufferSize)`
493
494void
496{
497 NS_LOG_FUNCTION(this << socket);
498
499 const uint32_t objectSize = m_httpVariables->GetMainObjectSize();
500 NS_LOG_INFO(this << " Main object to be served is " << objectSize << " bytes.");
501 m_mainObjectTrace(objectSize);
502 m_txBuffer->WriteNewObject(socket, ThreeGppHttpHeader::MAIN_OBJECT, objectSize);
503 const uint32_t actualSent = ServeFromTxBuffer(socket);
504
505 if (actualSent < objectSize)
506 {
507 NS_LOG_INFO(this << " Transmission of main object is suspended"
508 << " after " << actualSent << " bytes.");
509 }
510 else
511 {
512 NS_LOG_INFO(this << " Finished sending a whole main object.");
513 }
514}
515
516void
518{
519 NS_LOG_FUNCTION(this << socket);
520
521 const uint32_t objectSize = m_httpVariables->GetEmbeddedObjectSize();
522 NS_LOG_INFO(this << " Embedded object to be served is " << objectSize << " bytes.");
523 m_embeddedObjectTrace(objectSize);
524 m_txBuffer->WriteNewObject(socket, ThreeGppHttpHeader::EMBEDDED_OBJECT, objectSize);
525 const uint32_t actualSent = ServeFromTxBuffer(socket);
526
527 if (actualSent < objectSize)
528 {
529 NS_LOG_INFO(this << " Transmission of embedded object is suspended"
530 << " after " << actualSent << " bytes.");
531 }
532 else
533 {
534 NS_LOG_INFO(this << " Finished sending a whole embedded object.");
535 }
536}
537
540{
541 NS_LOG_FUNCTION(this << socket);
542
543 if (m_txBuffer->IsBufferEmpty(socket))
544 {
545 NS_LOG_LOGIC(this << " Tx buffer is empty. Not sending anything.");
546 return 0;
547 }
548 bool firstPartOfObject = !m_txBuffer->HasTxedPartOfObject(socket);
549
550 const uint32_t socketSize = socket->GetTxAvailable();
551 NS_LOG_DEBUG(this << " Socket has " << socketSize << " bytes available for Tx.");
552
553 // Get the number of bytes remaining to be sent.
554 const uint32_t txBufferSize = m_txBuffer->GetBufferSize(socket);
555
556 // Compute the size of actual content to be sent; has to fit into the socket.
557 // Note that header size is NOT counted as TxBuffer content. Header size is overhead.
558 uint32_t contentSize = std::min(txBufferSize, socketSize - 22);
559 Ptr<Packet> packet = Create<Packet>(contentSize);
560 uint32_t packetSize = contentSize;
561 if (packetSize == 0)
562 {
563 NS_LOG_LOGIC(this << " Socket size leads to packet size of zero; not sending anything.");
564 return 0;
565 }
566
567 // If this is the first packet of an object, attach a header.
568 if (firstPartOfObject)
569 {
570 // Create header.
571 ThreeGppHttpHeader httpHeader;
572 httpHeader.SetContentLength(txBufferSize);
573 httpHeader.SetContentType(m_txBuffer->GetBufferContentType(socket));
574 // Using the client TS value as per the corresponding request packet.
575 httpHeader.SetClientTs(m_txBuffer->GetClientTs(socket));
576 httpHeader.SetServerTs(Simulator::Now());
577 packet->AddHeader(httpHeader);
578 packetSize += httpHeader.GetSerializedSize();
579
580 NS_LOG_INFO(this << " Created packet " << packet << " of " << packetSize << " bytes."
581 << " The corresponding request came "
582 << (Simulator::Now() - httpHeader.GetClientTs()).As(Time::S) << " ago.");
583 }
584 else
585 {
586 NS_LOG_INFO(this << " Created packet " << packet << " of " << packetSize
587 << " bytes to be appended to a previous packet.");
588 }
589
590 // Send.
591 const int actualBytes = socket->Send(packet);
592 NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packetSize << " bytes,"
593 << " return value= " << actualBytes << ".");
594 m_txTrace(packet);
595
596 if (actualBytes == static_cast<int>(packetSize))
597 {
598 // The packet goes through successfully.
599 m_txBuffer->DepleteBufferSize(socket, contentSize);
600 NS_LOG_INFO(this << " Remaining object to be sent " << m_txBuffer->GetBufferSize(socket)
601 << " bytes.");
602 return packetSize;
603 }
604 else
605 {
606 NS_LOG_INFO(this << " Failed to send object,"
607 << " GetErrNo= " << socket->GetErrno() << ","
608 << " suspending transmission"
609 << " and waiting for another Tx opportunity.");
610 return 0;
611 }
612
613} // end of `uint32_t ServeFromTxBuffer (Ptr<Socket> socket)`
614
615void
617{
618 const std::string oldState = GetStateString();
619 const std::string newState = GetStateString(state);
620 NS_LOG_FUNCTION(this << oldState << newState);
621 m_state = state;
622 NS_LOG_INFO(this << " ThreeGppHttpServer " << oldState << " --> " << newState << ".");
623 m_stateTransitionTrace(oldState, newState);
624}
625
626// HTTP SERVER TX BUFFER //////////////////////////////////////////////////////
627
629{
630 NS_LOG_FUNCTION(this);
631}
632
633bool
635{
636 auto it = m_txBuffer.find(socket);
637 return (it != m_txBuffer.end());
638}
639
640void
642{
643 NS_LOG_FUNCTION(this << socket);
644
646 this << " Cannot add socket " << socket
647 << " because it has already been added before.");
648
649 TxBuffer_t txBuffer;
651 txBuffer.txBufferSize = 0;
652 txBuffer.isClosing = false;
653 txBuffer.hasTxedPartOfObject = false;
654 m_txBuffer.insert(std::pair<Ptr<Socket>, TxBuffer_t>(socket, txBuffer));
655}
656
657void
659{
660 NS_LOG_FUNCTION(this << socket);
661
662 auto it = m_txBuffer.find(socket);
663 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
664
665 if (!Simulator::IsExpired(it->second.nextServe))
666 {
667 NS_LOG_INFO(this << " Canceling a serving event which is due in "
668 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
669 Simulator::Cancel(it->second.nextServe);
670 }
671
672 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
674 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
675 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
676
677 m_txBuffer.erase(it);
678}
679
680void
682{
683 NS_LOG_FUNCTION(this << socket);
684
685 auto it = m_txBuffer.find(socket);
686 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
687
688 if (!Simulator::IsExpired(it->second.nextServe))
689 {
690 NS_LOG_INFO(this << " Canceling a serving event which is due in "
691 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
692 Simulator::Cancel(it->second.nextServe);
693 }
694
695 if (it->second.txBufferSize > 0)
696 {
697 NS_LOG_WARN(this << " Closing a socket where " << it->second.txBufferSize
698 << " bytes of transmission"
699 << " is still pending in the corresponding Tx buffer.");
700 }
701
702 it->first->Close();
703 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
705 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
706 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
707
708 m_txBuffer.erase(it);
709}
710
711void
713{
714 NS_LOG_FUNCTION(this);
715
716 for (auto it = m_txBuffer.begin(); it != m_txBuffer.end(); ++it)
717 {
718 if (!Simulator::IsExpired(it->second.nextServe))
719 {
720 NS_LOG_INFO(this << " Canceling a serving event which is due in "
721 << Simulator::GetDelayLeft(it->second.nextServe).As(Time::S) << ".");
722 Simulator::Cancel(it->second.nextServe);
723 }
724
725 it->first->Close();
726 it->first->SetCloseCallbacks(MakeNullCallback<void, Ptr<Socket>>(),
728 it->first->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
729 it->first->SetSendCallback(MakeNullCallback<void, Ptr<Socket>, uint32_t>());
730 }
731
732 m_txBuffer.clear();
733}
734
735bool
737{
738 auto it = m_txBuffer.find(socket);
739 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
740 return (it->second.txBufferSize == 0);
741}
742
743Time
745{
746 auto it = m_txBuffer.find(socket);
747 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
748 return it->second.clientTs;
749}
750
753{
754 auto it = m_txBuffer.find(socket);
755 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
756 return it->second.txBufferContentType;
757}
758
761{
762 auto it = m_txBuffer.find(socket);
763 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
764 return it->second.txBufferSize;
765}
766
767bool
769{
770 auto it = m_txBuffer.find(socket);
771 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found");
772 return it->second.hasTxedPartOfObject;
773}
774
775void
778 uint32_t objectSize)
779{
780 NS_LOG_FUNCTION(this << socket << contentType << objectSize);
781
783 "Unable to write an object without a proper Content-Type.");
784 NS_ASSERT_MSG(objectSize > 0, "Unable to write a zero-sized object.");
785
786 auto it = m_txBuffer.find(socket);
787 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
788 NS_ASSERT_MSG(it->second.txBufferSize == 0,
789 "Cannot write to Tx buffer of socket "
790 << socket << " until the previous content has been completely sent.");
791 it->second.txBufferContentType = contentType;
792 it->second.txBufferSize = objectSize;
793 it->second.hasTxedPartOfObject = false;
794}
795
796void
798 const EventId& eventId,
799 const Time& clientTs)
800{
801 NS_LOG_FUNCTION(this << socket << clientTs.As(Time::S));
802
803 auto it = m_txBuffer.find(socket);
804 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
805 it->second.nextServe = eventId;
806 it->second.clientTs = clientTs;
807}
808
809void
811{
812 NS_LOG_FUNCTION(this << socket << amount);
813
814 NS_ASSERT_MSG(amount > 0, "Unable to consume zero bytes.");
815
816 auto it = m_txBuffer.find(socket);
817 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
818 NS_ASSERT_MSG(it->second.txBufferSize >= amount,
819 "The requested amount is larger than the current buffer size.");
820 it->second.txBufferSize -= amount;
821 it->second.hasTxedPartOfObject = true;
822
823 if (it->second.isClosing && (it->second.txBufferSize == 0))
824 {
825 /*
826 * The peer has earlier issued a close request and we have now waited
827 * until all the existing data are pushed into the socket. Now we close
828 * the socket explicitly.
829 */
830 CloseSocket(socket);
831 }
832}
833
834void
836{
837 NS_LOG_FUNCTION(this << socket);
838 auto it = m_txBuffer.find(socket);
839 NS_ASSERT_MSG(it != m_txBuffer.end(), "Socket " << socket << " cannot be found.");
840 it->second.isClosing = true;
841}
842
843} // namespace ns3
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Address.
The base class for all ns3 applications.
Definition: application.h:62
void DoDispose() override
Destructor implementation.
Definition: application.cc:86
Ptr< Node > GetNode() const
Definition: application.cc:108
An identifier for simulation events.
Definition: event-id.h:55
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.
Definition: ipv4-address.h:42
static Ipv4Address ConvertFrom(const Address &address)
static bool IsMatchingType(const Address &address)
Describes an IPv6 address.
Definition: ipv6-address.h:49
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:204
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
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:285
static bool IsFinished()
Check if the simulation should finish.
Definition: simulator.cc:171
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static bool IsExpired(const EventId &id)
Check if an event has already run or been cancelled.
Definition: simulator.cc:295
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:217
virtual Socket::SocketErrno GetErrno() const =0
Get last error number.
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:105
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
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:96
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:72
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:54
Header used by web browsing applications to transmit information about content type,...
void SetClientTs(Time clientTs)
void SetServerTs(Time serverTs)
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.
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:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
@ S
second
Definition: nstime.h:116
a unique identifier for an interface.
Definition: type-id.h:59
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1100
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1108
Hold an unsigned integer type.
Definition: uinteger.h:45
#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:86
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:747
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:579
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition: ptr.h:442
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.
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:704
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:81
std::string name
Attribute name.
Definition: type-id.h:83
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition: type-id.h:91
static const uint32_t packetSize
Packet size generated at the AP.