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},
328 m_numOfPagesReceived{0},
329 m_numOfPacketDrops{0}
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
341 Ipv4Mask("255.0.0.0"),
342 Ipv4Address("0.0.0.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);
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: "
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
611 : m_rxBuffer(0),
612 m_numOfObjectsReceived(0)
613{
614 NS_LOG_FUNCTION(this);
615}
616
617void
619{
620 NS_LOG_FUNCTION(this << size);
621 m_objectsSize.push_back(size);
622}
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;
649 m_numOfObjectsReceived++;
650
651 return true;
652}
653
654bool
656{
657 return (m_objectsSize.empty() && (m_rxBuffer == 0));
658}
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
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 {
914 AddHttpObjectTestCase(run++,
915 channelDelay[i1],
916 bitErrorRate[i2],
917 mtuSize[i3],
918 false);
919 AddHttpObjectTestCase(run++,
920 channelDelay[i1],
921 bitErrorRate[i2],
922 mtuSize[i3],
923 false,
924 8080);
925 AddHttpObjectTestCase(run++,
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.
980 TestCase::Duration testDuration = TestCase::Duration::QUICK;
981 if (rngRun > 20)
982 {
983 testDuration = TestCase::Duration::EXTENSIVE;
984 }
985 if (rngRun > 50)
986 {
987 testDuration = TestCase::Duration::TAKES_FOREVER;
988 }
989
990 AddTestCase(new ThreeGppHttpObjectTestCase(name.str(),
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.
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.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
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.
void SetBase(Ipv6Address network, Ipv6Prefix prefix, Ipv6Address base=Ipv6Address("::1"))
Set the base network number, network prefix, and base interface ID.
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned 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.
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.
encapsulates test code
Definition test.h:1050
Duration
How long the test takes to execute.
Definition test.h:1054
std::string GetName() const
Definition test.cc:367
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
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
AttributeValue implementation for Time.
Definition nstime.h:1432
a unique identifier for an interface.
Definition type-id.h:49
AttributeValue implementation for TypeId.
Definition type-id.h:641
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.