A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-http-client-server-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Magister Solutions
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Budiarto Herman <budiarto.herman@magister.fi>
7 *
8 */
9
10#include "ns3/basic-data-calculators.h"
11#include "ns3/config.h"
12#include "ns3/error-model.h"
13#include "ns3/integer.h"
14#include "ns3/internet-stack-helper.h"
15#include "ns3/ipv4-address-helper.h"
16#include "ns3/ipv6-address-helper.h"
17#include "ns3/log.h"
18#include "ns3/mac48-address.h"
19#include "ns3/node.h"
20#include "ns3/nstime.h"
21#include "ns3/packet.h"
22#include "ns3/ptr.h"
23#include "ns3/simple-channel.h"
24#include "ns3/simple-net-device.h"
25#include "ns3/tcp-congestion-ops.h"
26#include "ns3/tcp-l4-protocol.h"
27#include "ns3/test.h"
28#include "ns3/three-gpp-http-client.h"
29#include "ns3/three-gpp-http-header.h"
30#include "ns3/three-gpp-http-helper.h"
31#include "ns3/three-gpp-http-server.h"
32
33#include <list>
34#include <optional>
35#include <sstream>
36
37NS_LOG_COMPONENT_DEFINE("ThreeGppHttpClientServerTest");
38
39using namespace ns3;
40
41// HTTP OBJECT TEST CASE //////////////////////////////////////////////////////
42
43/**
44 * @ingroup http
45 * @ingroup applications-test
46 * @ingroup tests
47 * A test class which verifies that each HTTP object sent is also received the
48 * same size.
49 *
50 * The test uses a minimalist scenario of one HTTP server and one HTTP client,
51 * connected through a SimpleChannel. The simulation runs until 3 web pages
52 * have been successfully downloaded by the client.
53 *
54 * The test also collects some statistical information from the simulation for
55 * informational or debugging purpose. This can be seen by enabling LOG_INFO.
56 */
58{
59 public:
60 /**
61 * @param name A textual label to briefly describe the test.
62 * @param rngRun Run index to be used, intended to affect the values produced
63 * by random number generators throughout the test.
64 * @param tcpType Type of TCP algorithm to be used by the connection between
65 * the client and the server. Must be a child type of
66 * ns3::TcpSocketFactory.
67 * @param channelDelay Transmission delay between the client and the server
68 * (and vice versa) which is due to the channel.
69 * @param bitErrorRate The probability of transmission error between the
70 * client and the server (and vice versa) in the unit of
71 * bits.
72 * @param mtuSize Maximum transmission unit (in bytes) to be used by the
73 * server model.
74 * @param useIpv6 If true, IPv6 will be used to address both client and
75 * server. Otherwise, IPv4 will be used.
76 * @param port The port to use if provided, otherwise the default port is used.
77 */
78 ThreeGppHttpObjectTestCase(const std::string& name,
79 uint32_t rngRun,
80 const TypeId& tcpType,
81 const Time& channelDelay,
82 double bitErrorRate,
83 uint32_t mtuSize,
84 bool useIpv6,
85 std::optional<uint16_t> port);
86
87 private:
88 /**
89 * Creates a Node, complete with a TCP/IP stack.
90 * #m_tcpType determines the TCP algorithm installed at the TCP stack.
91 *
92 * \param[in] channel Pointer to a channel which the node's device will be
93 * attached to.
94 * @return Pointer to the newly created node.
95 */
97
98 /**
99 * Assign a socket address for a device.
100 * #m_useIpv6 determines whether to use IPv4 addressing or IPv6 addressing.
101 *
102 * \param[in] dev Pointer to the device.
103 * \param[in] port the port to use for the socket address.
104 * @return The resulting socket address.
105 */
107
108 /**
109 * Assign an IPv4 address to a device.
110 *
111 * \param[in] dev Pointer to the device to assign an address to.
112 * \param[in] logging flag to indicate whether to log the assigned address.
113 * @return The resulting IPv4 address of the device.
114 */
115 Ipv4Address AssignIpv4Address(Ptr<NetDevice> dev, bool logging = true);
116
117 /**
118 * Assign an IPv6 address to a device.
119 *
120 * \param[in] dev Pointer to the device to assign an address to.
121 * \param[in] logging flag to indicate whether to log the assigned address.
122 * @return The resulting IPv6 address of the device.
123 */
124 Ipv6Address AssignIpv6Address(Ptr<NetDevice> dev, bool logging = true);
125
126 // Inherited from TestCase base class.
127 void DoRun() override;
128 void DoTeardown() override;
129
130 /**
131 * @internal
132 * Internal class used by ThreeGppHttpObjectTestCase. Keep track of the number
133 * of object and bytes that have been sent and received in the simulation by
134 * listening to the relevant trace sources.
135 */
137 {
138 public:
139 /// Creates a new instance with all counters begin at zero.
141 /**
142 * Shall be invoked when a whole object has been transmitted.
143 * @param size Size of the whole object (in bytes).
144 */
145 void ObjectSent(uint32_t size);
146 /**
147 * Shall be invoked when an object part has been received.
148 * @param size Size of the object part (in bytes). This amount will be
149 * accumulated until ObjectReceived() is invoked.
150 */
151 void PartReceived(uint32_t size);
152 /**
153 * Shall be invoked after all parts of a complete object have been
154 * received.
155 * \param[out] txSize Size of the whole object (in bytes) when it was
156 * transmitted.
157 * \param[out] rxSize Size of the whole object (in bytes) received.
158 * @return True if this receive operation has a matching transmission
159 * operation (ObjectSent()), otherwise false. Both arguments are
160 * guaranteed to be replaced with initialized values if the return
161 * value is true.
162 */
163 bool ObjectReceived(uint32_t& txSize, uint32_t& rxSize);
164 /// @return True if zero object is currently tracked.
165 bool IsEmpty() const;
166 /// @return Number of whole objects that have been received so far.
167 uint16_t GetNumOfObjectsReceived() const;
168
169 private:
170 /**
171 * Each entry is the size (in bytes) of object transmitted. A new entry is
172 * pushed to the back when a new object is transmitted. The frontmost entry
173 * is then removed when a whole object is received, i.e., it's logically a
174 * first-in-first-out queue data structure.
175 */
176 std::list<uint32_t> m_objectsSize;
177 /// The accumulated size (in bytes) of parts of a whole object.
179 /// Number of whole objects that have been received so far.
181 };
182
183 // The following defines one tracker for each HTTP object type.
184 ThreeGppHttpObjectTracker m_requestObjectTracker; ///< Tracker of request objects.
185 ThreeGppHttpObjectTracker m_mainObjectTracker; ///< Tracker of main objects.
186 ThreeGppHttpObjectTracker m_embeddedObjectTracker; ///< Tracker of embedded objects.
187
188 // CALLBACK TO TRACE SOURCES.
189
190 /**
191 * Connected with `TxMainObjectRequest` trace source of the client.
192 * Updates #m_requestObjectTracker.
193 * @param packet The packet of main object sent.
194 */
196 /**
197 * Connected with `TxEmbeddedObjectRequest` trace source of the client.
198 * Updates #m_requestObjectTracker.
199 * @param packet The packet of embedded object sent.
200 */
202 /**
203 * Connected with `Rx` trace source of the server.
204 * Updates #m_requestObjectTracker and perform some tests on the packet and
205 * the size of the object.
206 * @param packet The packet received.
207 * @param from The address where the packet originates from.
208 * @param to The local address on which the server binds to.
209 */
210 void ServerRxCallback(Ptr<const Packet> packet, const Address& from, const Address& to);
211 /**
212 * Connected with `MainObject` trace source of the server.
213 * Updates #m_mainObjectTracker.
214 * @param size Size of the generated main object (in bytes).
215 */
217 /**
218 * Connected with `RxMainObjectPacket` trace source of the client.
219 * Updates #m_mainObjectTracker and perform some tests on the packet.
220 * @param packet The packet received.
221 */
223 /**
224 * Connected with `RxMainObject` trace source of the client. Updates
225 * #m_mainObjectTracker and perform some tests on the size of the object.
226 * @param httpClient Pointer to the application.
227 * @param packet Full packet received by application.
228 */
230 Ptr<const Packet> packet);
231 /**
232 * Connected with `EmbeddedObject` trace source of the server.
233 * Updates #m_embeddedObjectTracker.
234 * @param size Size of the generated embedded object (in bytes).
235 */
237 /**
238 * Connected with `RxEmbeddedObjectPacket` trace source of the client.
239 * Updates #m_embeddedObjectTracker and perform some tests on the packet.
240 * @param packet The packet received.
241 */
243 /**
244 * Connected with `RxEmbeddedObject` trace source of the client. Updates
245 * #m_embeddedObjectTracker and perform some tests on the size of the object.
246 * @param httpClient Pointer to the application.
247 * @param packet Full packet received by application.
248 */
250 Ptr<const Packet> packet);
251 /**
252 * Connected with `StateTransition` trace source of the client.
253 * Increments #m_numOfPagesReceived when the client enters READING state.
254 * @param oldState The name of the previous state.
255 * @param newState The name of the current state.
256 */
257 void ClientStateTransitionCallback(const std::string& oldState, const std::string& newState);
258 /**
259 * Connected with `RxDelay` trace source of the client.
260 * Updates the statistics in #m_delayCalculator.
261 * @param delay The packet one-trip delay time.
262 * @param from The address of the device where the packet originates from.
263 */
264 void ClientRxDelayCallback(const Time& delay, const Address& from);
265 /**
266 * Connected with `RxRtt` trace source of the client.
267 * Updates the statistics in #m_rttCalculator.
268 * @param rtt The packet round trip delay time.
269 * @param from The address of the device where the packet originates from.
270 */
271 void ClientRxRttCallback(const Time& rtt, const Address& from);
272 /**
273 * Connected with `PhyRxDrop` trace source of both the client's and server's
274 * devices. Increments #m_numOfPacketDrops.
275 * @param packet Pointer to the packet being dropped.
276 */
278 /**
279 * Dummy event
280 */
281 void ProgressCallback();
282
283 // THE PARAMETERS OF THE TEST CASE.
284
285 uint32_t m_rngRun; ///< Determines the set of random values generated.
286 TypeId m_tcpType; ///< TCP algorithm used.
287 Time m_channelDelay; ///< %Time needed by a packet to propagate.
288 uint32_t m_mtuSize; ///< Maximum transmission unit (in bytes).
289 bool m_useIpv6; ///< Whether to use IPv6 or IPv4.
290 std::optional<uint16_t> m_port; ///< port to use if provided, otherwise the default port is used
291
292 // OTHER MEMBER VARIABLES.
293
294 /// Receive error model to be attached to the devices of both directions.
296 /// Begins with 0. Simulation stops if this reaches 3.
298 /// Number of packets dropped because of #m_errorModel.
300 /// Installs TCP/IP stack on the nodes.
302 /// Assigns IPv4 addresses to the nodes.
304 /// Assigns IPv6 addresses to the nodes.
306 /// Keeps statistical information of one-trip delays (in seconds).
308 /// Keeps statistical information of round-trip delays (in seconds).
310
311}; // end of `class HttpClientServerTestCase`
312
314 uint32_t rngRun,
315 const TypeId& tcpType,
316 const Time& channelDelay,
317 double bitErrorRate,
318 uint32_t mtuSize,
319 bool useIpv6,
320 std::optional<uint16_t> port)
321 : TestCase(name),
322 m_rngRun{rngRun},
323 m_tcpType{tcpType},
324 m_channelDelay{channelDelay},
325 m_mtuSize{mtuSize},
326 m_useIpv6{useIpv6},
327 m_port{port},
330{
331 NS_LOG_FUNCTION(this << GetName());
332
333 // NS_ASSERT (tcpType.IsChildOf (TypeId::LookupByName ("ns3::TcpSocketBase")));
334 NS_ASSERT(channelDelay.IsPositive());
335
337 m_errorModel->SetRate(bitErrorRate);
339
340 m_ipv4AddressHelper.SetBase(Ipv4Address("10.0.0.0"),
341 Ipv4Mask("255.0.0.0"),
342 Ipv4Address("0.0.0.1"));
343 m_ipv6AddressHelper.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64), Ipv6Address("::1"));
344
347}
348
351{
352 NS_LOG_FUNCTION(this << channel);
353
355 dev->SetAddress(Mac48Address::Allocate());
356 dev->SetChannel(channel);
357 dev->SetReceiveErrorModel(m_errorModel);
358
360 node->AddDevice(dev);
361 m_internetStackHelper.Install(node);
362
363 // Set the TCP algorithm.
364 Ptr<TcpL4Protocol> tcp = node->GetObject<TcpL4Protocol>();
365 tcp->SetAttribute("SocketType", TypeIdValue(m_tcpType));
366
367 // Connect with the trace source that informs about packet drop due to error.
368 dev->TraceConnectWithoutContext(
369 "PhyRxDrop",
371
372 return node;
373}
374
377{
378 NS_LOG_FUNCTION(this);
380 NS_ASSERT(ipv4Ifs.GetN() == 1);
381 const auto assignedAddress = ipv4Ifs.GetAddress(0, 0);
382 if (logging)
383 {
384 NS_LOG_DEBUG(this << " node is assigned to " << assignedAddress << ".");
385 }
386 return assignedAddress;
387}
388
391{
392 NS_LOG_FUNCTION(this);
394 NS_ASSERT(ipv6Ifs.GetN() == 1);
395 const auto assignedAddress = ipv6Ifs.GetAddress(0, 0);
396 if (logging)
397 {
398 NS_LOG_DEBUG(this << " node is assigned to " << assignedAddress << ".");
399 }
400 return assignedAddress;
401}
402
405{
406 NS_LOG_FUNCTION(this);
407 Address assignedAddress;
408
409 // Assign IP address according to the selected Ip version.
410 if (m_useIpv6)
411 {
412 assignedAddress = Inet6SocketAddress(AssignIpv6Address(dev, false), port);
413 }
414 else
415 {
416 assignedAddress = InetSocketAddress(AssignIpv4Address(dev, false), port);
417 }
418
419 NS_LOG_DEBUG(this << " node is assigned to " << assignedAddress << ".");
420
421 return assignedAddress;
422}
423
424void
426{
427 NS_LOG_FUNCTION(this << GetName());
429 NS_LOG_INFO(this << " Running test case " << GetName());
430
431 /*
432 * Create topology:
433 *
434 * Server Node Client Node
435 * +-----------------+ +-----------------+
436 * | HTTP Server | | HTTP Client |
437 * | Application | | Application |
438 * +-----------------+ +-----------------+
439 * | TCP | | TCP |
440 * +-----------------+ +-----------------+
441 * | IPv4/v6 | | IPv4/v6 |
442 * +-----------------+ +-----------------+
443 * | Simple NetDev | | Simple NetDev |
444 * +-----------------+ +-----------------+
445 * | |
446 * | |
447 * +----------------------------+
448 * Simple Channel
449 */
450
451 // Channel.
452 auto channel = CreateObject<SimpleChannel>();
453 channel->SetAttribute("Delay", TimeValue(m_channelDelay));
454
455 // Server and client nodes.
456 ApplicationContainer serverApplications{};
457 ApplicationContainer clientApplications{};
458 auto serverNode = CreateSimpleInternetNode(channel);
459 auto clientNode = CreateSimpleInternetNode(channel);
460
461 // applications.
462 if (m_port)
463 {
464 const auto serverAddress = AssignSocketAddress(serverNode->GetDevice(0), *m_port);
465 ThreeGppHttpServerHelper serverHelper(serverAddress);
466 serverApplications = serverHelper.Install(serverNode);
467 AssignSocketAddress(clientNode->GetDevice(0), *m_port);
468 ThreeGppHttpClientHelper clientHelper(serverAddress);
469 clientApplications = clientHelper.Install(clientNode);
470 }
471 else
472 {
473 if (m_useIpv6)
474 {
475 const auto serverAddress = AssignIpv6Address(serverNode->GetDevice(0));
476 ThreeGppHttpServerHelper serverHelper(serverAddress);
477 serverApplications = serverHelper.Install(serverNode);
478 AssignIpv6Address(clientNode->GetDevice(0));
479 ThreeGppHttpClientHelper clientHelper(serverAddress);
480 clientApplications = clientHelper.Install(clientNode);
481 }
482 else
483 {
484 const auto serverAddress = AssignIpv4Address(serverNode->GetDevice(0));
485 ThreeGppHttpServerHelper serverHelper(serverAddress);
486 serverApplications = serverHelper.Install(serverNode);
487 AssignIpv4Address(clientNode->GetDevice(0));
488 ThreeGppHttpClientHelper clientHelper(serverAddress);
489 clientApplications = clientHelper.Install(clientNode);
490 }
491 }
492 NS_TEST_ASSERT_MSG_EQ(serverApplications.GetN(),
493 1,
494 "Invalid number of HTTP servers has been installed");
495 auto httpServer = serverApplications.Get(0)->GetObject<ThreeGppHttpServer>();
496 NS_TEST_ASSERT_MSG_NE(httpServer,
497 nullptr,
498 "HTTP server installation fails to produce a proper type");
499 httpServer->SetMtuSize(m_mtuSize);
500 NS_TEST_ASSERT_MSG_EQ(clientApplications.GetN(),
501 1,
502 "Invalid number of HTTP clients has been installed");
503 auto httpClient = clientApplications.Get(0)->GetObject<ThreeGppHttpClient>();
504 NS_TEST_ASSERT_MSG_NE(httpClient,
505 nullptr,
506 "HTTP client installation fails to produce a proper type");
507
508 // Uplink (requests) trace sources.
509 bool traceSourceConnected = httpClient->TraceConnectWithoutContext(
510 "TxMainObjectRequest",
512 NS_ASSERT(traceSourceConnected);
513 traceSourceConnected = httpClient->TraceConnectWithoutContext(
514 "TxEmbeddedObjectRequest",
516 NS_ASSERT(traceSourceConnected);
517 traceSourceConnected = httpServer->TraceConnectWithoutContext(
518 "RxWithAddresses",
520 NS_ASSERT(traceSourceConnected);
521
522 // Downlink (main objects) trace sources.
523 traceSourceConnected = httpServer->TraceConnectWithoutContext(
524 "MainObject",
526 NS_ASSERT(traceSourceConnected);
527 traceSourceConnected = httpClient->TraceConnectWithoutContext(
528 "RxMainObjectPacket",
530 NS_ASSERT(traceSourceConnected);
531 traceSourceConnected = httpClient->TraceConnectWithoutContext(
532 "RxMainObject",
534 NS_ASSERT(traceSourceConnected);
535
536 // Downlink (embedded objects) trace sources.
537 traceSourceConnected = httpServer->TraceConnectWithoutContext(
538 "EmbeddedObject",
540 NS_ASSERT(traceSourceConnected);
541
542 traceSourceConnected = httpClient->TraceConnectWithoutContext(
543 "RxEmbeddedObjectPacket",
545 NS_ASSERT(traceSourceConnected);
546
547 traceSourceConnected = httpClient->TraceConnectWithoutContext(
548 "RxEmbeddedObject",
550 NS_ASSERT(traceSourceConnected);
551
552 // Other trace sources.
553 traceSourceConnected = httpClient->TraceConnectWithoutContext(
554 "StateTransition",
556 NS_ASSERT(traceSourceConnected);
557 traceSourceConnected = httpClient->TraceConnectWithoutContext(
558 "RxDelay",
560 NS_ASSERT(traceSourceConnected);
561 traceSourceConnected = httpClient->TraceConnectWithoutContext(
562 "RxRtt",
564 NS_ASSERT(traceSourceConnected);
565
567
568 /*
569 * Here we don't set the simulation stop time. During the run, the simulation
570 * will stop immediately after the client has completely received the third
571 * web page.
572 */
574
575 // Dump some statistical information about the simulation.
576 NS_LOG_INFO(this << " Total request objects received: "
577 << m_requestObjectTracker.GetNumOfObjectsReceived() << " object(s).");
578 NS_LOG_INFO(this << " Total main objects received: "
579 << m_mainObjectTracker.GetNumOfObjectsReceived() << " object(s).");
580 NS_LOG_INFO(this << " Total embedded objects received: "
581 << m_embeddedObjectTracker.GetNumOfObjectsReceived() << " object(s).");
582 NS_LOG_INFO(this << " One-trip delays: average=" << m_delayCalculator->getMean() << " min="
583 << m_delayCalculator->getMin() << " max=" << m_delayCalculator->getMax());
584 NS_LOG_INFO(this << " Round-trip delays: average=" << m_rttCalculator->getMean() << " min="
585 << m_rttCalculator->getMin() << " max=" << m_rttCalculator->getMax());
586 NS_LOG_INFO(this << " Number of packets dropped by the devices: " << m_numOfPacketDrops
587 << " packet(s).");
588
589 // Some post-simulation tests.
590 NS_TEST_EXPECT_MSG_EQ(m_numOfPagesReceived, 3, "Unexpected number of web pages processed.");
592 true,
593 "Tracker of request objects detected irrelevant packet(s).");
595 true,
596 "Tracker of main objects detected irrelevant packet(s).");
598 true,
599 "Tracker of embedded objects detected irrelevant packet(s).");
600
602}
603
604void
609
616
617void
623
624void
630
631bool
633 uint32_t& rxSize)
634{
635 NS_LOG_FUNCTION(this);
636
637 if (m_objectsSize.empty())
638 {
639 return false;
640 }
641
642 // Set output values.
643 txSize = m_objectsSize.front();
644 rxSize = m_rxBuffer;
645
646 // Reset counters.
647 m_objectsSize.pop_front();
648 m_rxBuffer = 0;
650
651 return true;
652}
653
654bool
659
660uint16_t
665
666void
668{
669 NS_LOG_FUNCTION(this << packet << packet->GetSize());
670 m_requestObjectTracker.ObjectSent(packet->GetSize());
671}
672
673void
675{
676 NS_LOG_FUNCTION(this << packet << packet->GetSize());
677 m_requestObjectTracker.ObjectSent(packet->GetSize());
678}
679
680void
682 const Address& from,
683 const Address& to)
684{
685 NS_LOG_INFO(this << packet << packet->GetSize() << from << to);
686
687 uint16_t port{};
689 {
691 }
693 {
695 }
698 "Incorrect port");
699
700 // Check the header in packet
701 Ptr<Packet> copy = packet->Copy();
702 ThreeGppHttpHeader httpHeader;
703 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
704 22,
705 "Error finding ThreeGppHttpHeader in a packet received by the server");
707 Seconds(0),
708 "Request object's client TS is unexpectedly non-positive");
709
710 m_requestObjectTracker.PartReceived(packet->GetSize());
711
712 /*
713 * Request objects are assumed to be small and to not typically split. So we
714 * immediately follow by concluding the receive of a whole request object.
715 */
716 uint32_t txSize = 0;
717 uint32_t rxSize = 0;
718 bool isSent = m_requestObjectTracker.ObjectReceived(txSize, rxSize);
719 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Server receives one too many request object");
721 rxSize,
722 "Transmitted size and received size of request object differ");
723}
724
725void
731
732void
734{
735 NS_LOG_FUNCTION(this << packet << packet->GetSize());
736 m_mainObjectTracker.PartReceived(packet->GetSize());
737}
738
739void
741 Ptr<const Packet> packet)
742{
743 NS_LOG_FUNCTION(this << httpClient << httpClient->GetNode()->GetId());
744
745 // Verify the header in the packet.
746 Ptr<Packet> copy = packet->Copy();
747 ThreeGppHttpHeader httpHeader;
748 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
749 22,
750 "Error finding ThreeGppHttpHeader in a packet received by the server");
753 "Invalid content type in the received packet");
755 Seconds(0),
756 "Main object's client TS is unexpectedly non-positive");
758 Seconds(0),
759 "Main object's server TS is unexpectedly non-positive");
760
761 uint32_t txSize = 0;
762 uint32_t rxSize = 0;
763 bool isSent = m_mainObjectTracker.ObjectReceived(txSize, rxSize);
764 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Client receives one too many main object");
766 rxSize,
767 "Transmitted size and received size of main object differ");
769 rxSize,
770 "Actual main object packet size and received size of main object differ");
771}
772
773void
779
780void
782{
783 NS_LOG_FUNCTION(this << packet << packet->GetSize());
784 m_embeddedObjectTracker.PartReceived(packet->GetSize());
785}
786
787void
789 Ptr<const Packet> packet)
790{
791 NS_LOG_FUNCTION(this << httpClient << httpClient->GetNode()->GetId());
792
793 // Verify the header in the packet.
794 Ptr<Packet> copy = packet->Copy();
795 ThreeGppHttpHeader httpHeader;
796 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
797 22,
798 "Error finding ThreeGppHttpHeader in a packet received by the server");
801 "Invalid content type in the received packet");
803 Seconds(0),
804 "Embedded object's client TS is unexpectedly non-positive");
806 Seconds(0),
807 "Embedded object's server TS is unexpectedly non-positive");
808
809 uint32_t txSize = 0;
810 uint32_t rxSize = 0;
811 bool isSent = m_embeddedObjectTracker.ObjectReceived(txSize, rxSize);
812 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Client receives one too many embedded object");
814 rxSize,
815 "Transmitted size and received size of embedded object differ");
817 httpHeader.GetContentLength(),
818 rxSize,
819 "Actual embedded object packet size and received size of embedded object differ");
820}
821
822void
824 const std::string& newState)
825{
826 NS_LOG_FUNCTION(this << oldState << newState);
827
828 if (newState == "READING")
829 {
831
832 if (m_numOfPagesReceived >= 3)
833 {
834 // We have processed 3 web pages and that should be enough for this test.
835 NS_LOG_LOGIC(this << " Test is stopping now.");
837 }
838 }
839}
840
841void
847
848void
850{
851 NS_LOG_FUNCTION(this << delay.As(Time::S) << from);
852 m_delayCalculator->Update(delay.GetSeconds());
853}
854
855void
857{
858 NS_LOG_FUNCTION(this << rtt.As(Time::S) << from);
859 m_rttCalculator->Update(rtt.GetSeconds());
860}
861
862void
864{
865 NS_LOG_FUNCTION(this << packet << packet->GetSize());
867}
868
869// TEST SUITE /////////////////////////////////////////////////////////////////
870
871/**
872 * @ingroup http
873 * @ingroup applications-test
874 * @ingroup tests
875 * A test class for running several system tests which validate the web
876 * browsing traffic model.
877 *
878 * The tests cover the combinations of the following parameters:
879 * - the use of NewReno (ns-3's default)
880 * - various lengths of channel delay: 3 ms, 30 ms, and 300 ms;
881 * - the existence of transmission error;
882 * - different MTU (maximum transmission unit) sizes;
883 * - IPv4 and IPv6; and
884 * - the use of different set of random numbers.
885 *
886 * The _fullness_ parameter specified when running the test framework will
887 * determine the number of test cases created by this test suite.
888 */
890{
891 public:
892 /// Instantiate the test suite.
894 : TestSuite("applications-three-gpp-http-client-server", Type::SYSTEM)
895 {
896 // LogComponentEnable ("ThreeGppHttpClientServerTest", LOG_INFO);
897 // LogComponentEnable ("ThreeGppHttpClient", LOG_INFO);
898 // LogComponentEnable ("ThreeGppHttpServer", LOG_INFO);
899 // LogComponentEnableAll (LOG_PREFIX_ALL);
900
901 Time channelDelay[] = {MilliSeconds(3), MilliSeconds(30), MilliSeconds(300)};
902 double bitErrorRate[] = {0.0, 5.0e-6};
903 uint32_t mtuSize[] = {536, 1460};
904
905 uint32_t run = 1;
906 while (run <= 100)
907 {
908 for (uint32_t i1 = 0; i1 < 3; i1++)
909 {
910 for (uint32_t i2 = 0; i2 < 2; i2++)
911 {
912 for (uint32_t i3 = 0; i3 < 2; i3++)
913 {
915 channelDelay[i1],
916 bitErrorRate[i2],
917 mtuSize[i3],
918 false);
920 channelDelay[i1],
921 bitErrorRate[i2],
922 mtuSize[i3],
923 false,
924 8080);
926 channelDelay[i1],
927 bitErrorRate[i2],
928 mtuSize[i3],
929 true);
930 }
931 }
932 }
933 }
934 }
935
936 private:
937 /**
938 * Creates a test case with the given parameters.
939 *
940 * @param rngRun Run index to be used, intended to affect the values produced
941 * by random number generators throughout the test.
942 * @param channelDelay Transmission delay between the client and the server
943 * (and vice versa) which is due to the channel.
944 * @param bitErrorRate The probability of transmission error between the
945 * client and the server (and vice versa) in the unit of
946 * bits.
947 * @param mtuSize Maximum transmission unit (in bytes) to be used by the
948 * server model.
949 * @param useIpv6 If true, IPv6 will be used to address both client and
950 * server. Otherwise, IPv4 will be used.
951 * @param port The port to use if provided, otherwise the default port is used.
952 */
954 const Time& channelDelay,
955 double bitErrorRate,
956 uint32_t mtuSize,
957 bool useIpv6,
958 std::optional<uint16_t> port = std::nullopt)
959 {
960 std::ostringstream name;
961 name << "Run #" << rngRun;
962 name << " delay=" << channelDelay.As(Time::MS);
963 name << " ber=" << bitErrorRate;
964 name << " mtu=" << mtuSize;
965
966 if (useIpv6)
967 {
968 name << " IPv6";
969 }
970 else
971 {
972 name << " IPv4";
973 }
974 if (port)
975 {
976 name << "(" << *port << ")";
977 }
978
979 // Assign higher fullness for tests with higher RngRun.
981 if (rngRun > 20)
982 {
983 testDuration = TestCase::Duration::EXTENSIVE;
984 }
985 if (rngRun > 50)
986 {
988 }
989
991 rngRun,
993 channelDelay,
994 bitErrorRate,
995 mtuSize,
996 useIpv6,
997 port),
998 testDuration);
999 }
1000
1001}; // end of class `ThreeGppHttpClientServerTestSuite`
1002
1003/// The global instance of the `three-gpp-http-client-server` system test.
A test class for running several system tests which validate the web browsing traffic model.
void AddHttpObjectTestCase(uint32_t rngRun, const Time &channelDelay, double bitErrorRate, uint32_t mtuSize, bool useIpv6, std::optional< uint16_t > port=std::nullopt)
Creates a test case with the given parameters.
ThreeGppHttpClientServerTestSuite()
Instantiate the test suite.
ThreeGppHttpObjectTracker()
Creates a new instance with all counters begin at zero.
void PartReceived(uint32_t size)
Shall be invoked when an object part has been received.
void ObjectSent(uint32_t size)
Shall be invoked when a whole object has been transmitted.
bool ObjectReceived(uint32_t &txSize, uint32_t &rxSize)
Shall be invoked after all parts of a complete object have been received.
uint32_t m_rxBuffer
The accumulated size (in bytes) of parts of a whole object.
uint16_t m_numOfObjectsReceived
Number of whole objects that have been received so far.
std::list< uint32_t > m_objectsSize
Each entry is the size (in bytes) of object transmitted.
A test class which verifies that each HTTP object sent is also received the same size.
ThreeGppHttpObjectTracker m_embeddedObjectTracker
Tracker of embedded objects.
void DeviceDropCallback(Ptr< const Packet > packet)
Connected with PhyRxDrop trace source of both the client's and server's devices.
InternetStackHelper m_internetStackHelper
Installs TCP/IP stack on the nodes.
void ClientRxDelayCallback(const Time &delay, const Address &from)
Connected with RxDelay trace source of the client.
void ClientTxEmbeddedObjectRequestCallback(Ptr< const Packet > packet)
Connected with TxEmbeddedObjectRequest trace source of the client.
void ClientTxMainObjectRequestCallback(Ptr< const Packet > packet)
Connected with TxMainObjectRequest trace source of the client.
void ClientRxEmbeddedObjectCallback(Ptr< const ThreeGppHttpClient > httpClient, Ptr< const Packet > packet)
Connected with RxEmbeddedObject trace source of the client.
uint16_t m_numOfPagesReceived
Begins with 0. Simulation stops if this reaches 3.
void DoRun() override
Implementation to actually run this TestCase.
Ipv4AddressHelper m_ipv4AddressHelper
Assigns IPv4 addresses to the nodes.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_mtuSize
Maximum transmission unit (in bytes).
void ClientRxMainObjectPacketCallback(Ptr< const Packet > packet)
Connected with RxMainObjectPacket trace source of the client.
std::optional< uint16_t > m_port
port to use if provided, otherwise the default port is used
void ClientRxMainObjectCallback(Ptr< const ThreeGppHttpClient > httpClient, Ptr< const Packet > packet)
Connected with RxMainObject trace source of the client.
void ClientRxEmbeddedObjectPacketCallback(Ptr< const Packet > packet)
Connected with RxEmbeddedObjectPacket trace source of the client.
Ptr< MinMaxAvgTotalCalculator< double > > m_rttCalculator
Keeps statistical information of round-trip delays (in seconds).
void ClientStateTransitionCallback(const std::string &oldState, const std::string &newState)
Connected with StateTransition trace source of the client.
ThreeGppHttpObjectTracker m_requestObjectTracker
Tracker of request objects.
Time m_channelDelay
Time needed by a packet to propagate.
Address AssignSocketAddress(Ptr< NetDevice > dev, uint16_t port)
Assign a socket address for a device.
uint32_t m_rngRun
Determines the set of random values generated.
void ServerEmbeddedObjectCallback(uint32_t size)
Connected with EmbeddedObject trace source of the server.
uint16_t m_numOfPacketDrops
Number of packets dropped because of m_errorModel.
Ipv6AddressHelper m_ipv6AddressHelper
Assigns IPv6 addresses to the nodes.
ThreeGppHttpObjectTestCase(const std::string &name, uint32_t rngRun, const TypeId &tcpType, const Time &channelDelay, double bitErrorRate, uint32_t mtuSize, bool useIpv6, std::optional< uint16_t > port)
Ptr< MinMaxAvgTotalCalculator< double > > m_delayCalculator
Keeps statistical information of one-trip delays (in seconds).
void ClientRxRttCallback(const Time &rtt, const Address &from)
Connected with RxRtt trace source of the client.
Ipv6Address AssignIpv6Address(Ptr< NetDevice > dev, bool logging=true)
Assign an IPv6 address to a device.
bool m_useIpv6
Whether to use IPv6 or IPv4.
Ptr< Node > CreateSimpleInternetNode(Ptr< SimpleChannel > channel)
Creates a Node, complete with a TCP/IP stack.
void ServerRxCallback(Ptr< const Packet > packet, const Address &from, const Address &to)
Connected with Rx trace source of the server.
Ipv4Address AssignIpv4Address(Ptr< NetDevice > dev, bool logging=true)
Assign an IPv4 address to a device.
Ptr< RateErrorModel > m_errorModel
Receive error model to be attached to the devices of both directions.
void ServerMainObjectCallback(uint32_t size)
Connected with MainObject trace source of the server.
ThreeGppHttpObjectTracker m_mainObjectTracker
Tracker of main objects.
a polymophic address class
Definition address.h:90
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
uint32_t GetN() const
Get the number of Ptr<Application> stored in this container.
ApplicationContainer Install(NodeContainer c)
Install an application on each node of the input container configured with all the attributes set wit...
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.
an Inet address class
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
Ipv4 addresses are stored in host order in this class.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
a class to represent an Ipv4 address mask
Helper class to auto-assign global IPv6 unicast addresses.
Describes an IPv6 address.
Keep track of a set of IPv6 interfaces.
Ipv6Address GetAddress(uint32_t i, uint32_t j) const
Get the address for the specified index.
Describes an IPv6 prefix.
static Mac48Address Allocate()
Allocate a new Mac48Address.
holds a vector of ns3::NetDevice pointers
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
TCP socket creation and multiplexing/demultiplexing.
static TypeId GetTypeId()
Get the type ID.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
Duration
How long the test takes to execute.
Definition test.h:1054
@ EXTENSIVE
Medium length test.
Definition test.h:1056
@ QUICK
Fast test.
Definition test.h:1055
@ TAKES_FOREVER
Very long running test.
Definition test.h:1057
TestCase(const TestCase &)=delete
std::string GetName() const
Definition test.cc:367
Type
Type of test.
Definition test.h:1274
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:490
static constexpr auto SYSTEM
Definition test.h:1293
Helper to make it easier to instantiate an ThreeGppHttpClient on a set of nodes.
Model application which simulates the traffic of a web browser.
Header used by web browsing applications to transmit information about content type,...
@ EMBEDDED_OBJECT
Integer equivalent = 2.
@ MAIN_OBJECT
Integer equivalent = 1.
ContentType_t GetContentType() const
Helper to make it easier to instantiate an ThreeGppHttpServer on a set of nodes.
Model application which simulates the traffic of a web server.
static constexpr uint16_t HTTP_DEFAULT_PORT
default HTTP port
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
bool IsPositive() const
Exactly equivalent to t >= 0.
Definition nstime.h:322
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ MS
millisecond
Definition nstime.h:106
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:49
Hold an unsigned integer type.
Definition uinteger.h:34
uint16_t port
Definition dsdv-manet.cc:33
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
void SetGlobal(std::string name, const AttributeValue &value)
Definition config.cc:932
#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_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_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:554
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition test.h:864
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
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:684
static ThreeGppHttpClientServerTestSuite g_httpClientServerTestSuiteInstance
The global instance of the three-gpp-http-client-server system test.