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:"
583 << " average=" << m_delayCalculator->getMean() << " min="
584 << m_delayCalculator->getMin() << " max=" << m_delayCalculator->getMax());
585 NS_LOG_INFO(this << " Round-trip delays:"
586 << " average=" << m_rttCalculator->getMean() << " min="
587 << m_rttCalculator->getMin() << " max=" << m_rttCalculator->getMax());
588 NS_LOG_INFO(this << " Number of packets dropped by the devices: " << m_numOfPacketDrops
589 << " packet(s).");
590
591 // Some post-simulation tests.
592 NS_TEST_EXPECT_MSG_EQ(m_numOfPagesReceived, 3, "Unexpected number of web pages processed.");
594 true,
595 "Tracker of request objects detected irrelevant packet(s).");
597 true,
598 "Tracker of main objects detected irrelevant packet(s).");
600 true,
601 "Tracker of embedded objects detected irrelevant packet(s).");
602
604
605} // end of `void HttpClientServerTestCase::DoRun ()`
606
607void
612
614 : m_rxBuffer(0),
615 m_numOfObjectsReceived(0)
616{
617 NS_LOG_FUNCTION(this);
618}
619
620void
622{
623 NS_LOG_FUNCTION(this << size);
624 m_objectsSize.push_back(size);
625}
626
627void
633
634bool
636 uint32_t& rxSize)
637{
638 NS_LOG_FUNCTION(this);
639
640 if (m_objectsSize.empty())
641 {
642 return false;
643 }
644
645 // Set output values.
646 txSize = m_objectsSize.front();
647 rxSize = m_rxBuffer;
648
649 // Reset counters.
650 m_objectsSize.pop_front();
651 m_rxBuffer = 0;
652 m_numOfObjectsReceived++;
653
654 return true;
655}
656
657bool
659{
660 return (m_objectsSize.empty() && (m_rxBuffer == 0));
661}
662
663uint16_t
668
669void
671{
672 NS_LOG_FUNCTION(this << packet << packet->GetSize());
673 m_requestObjectTracker.ObjectSent(packet->GetSize());
674}
675
676void
678{
679 NS_LOG_FUNCTION(this << packet << packet->GetSize());
680 m_requestObjectTracker.ObjectSent(packet->GetSize());
681}
682
683void
685 const Address& from,
686 const Address& to)
687{
688 NS_LOG_INFO(this << packet << packet->GetSize() << from << to);
689
690 uint16_t port{};
692 {
694 }
696 {
698 }
701 "Incorrect port");
702
703 // Check the header in packet
704 Ptr<Packet> copy = packet->Copy();
705 ThreeGppHttpHeader httpHeader;
706 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
707 22,
708 "Error finding ThreeGppHttpHeader in a packet received by the server");
710 Seconds(0),
711 "Request object's client TS is unexpectedly non-positive");
712
713 m_requestObjectTracker.PartReceived(packet->GetSize());
714
715 /*
716 * Request objects are assumed to be small and to not typically split. So we
717 * immediately follow by concluding the receive of a whole request object.
718 */
719 uint32_t txSize = 0;
720 uint32_t rxSize = 0;
721 bool isSent = m_requestObjectTracker.ObjectReceived(txSize, rxSize);
722 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Server receives one too many request object");
724 rxSize,
725 "Transmitted size and received size of request object differ");
726}
727
728void
734
735void
737{
738 NS_LOG_FUNCTION(this << packet << packet->GetSize());
739 m_mainObjectTracker.PartReceived(packet->GetSize());
740}
741
742void
744 Ptr<const Packet> packet)
745{
746 NS_LOG_FUNCTION(this << httpClient << httpClient->GetNode()->GetId());
747
748 // Verify the header in the packet.
749 Ptr<Packet> copy = packet->Copy();
750 ThreeGppHttpHeader httpHeader;
751 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
752 22,
753 "Error finding ThreeGppHttpHeader in a packet received by the server");
756 "Invalid content type in the received packet");
758 Seconds(0),
759 "Main object's client TS is unexpectedly non-positive");
761 Seconds(0),
762 "Main object's server TS is unexpectedly non-positive");
763
764 uint32_t txSize = 0;
765 uint32_t rxSize = 0;
766 bool isSent = m_mainObjectTracker.ObjectReceived(txSize, rxSize);
767 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Client receives one too many main object");
769 rxSize,
770 "Transmitted size and received size of main object differ");
772 rxSize,
773 "Actual main object packet size and received size of main object differ");
774}
775
776void
782
783void
789
790void
792 Ptr<const Packet> packet)
793{
794 NS_LOG_FUNCTION(this << httpClient << httpClient->GetNode()->GetId());
795
796 // Verify the header in the packet.
797 Ptr<Packet> copy = packet->Copy();
798 ThreeGppHttpHeader httpHeader;
799 NS_TEST_ASSERT_MSG_EQ(copy->RemoveHeader(httpHeader),
800 22,
801 "Error finding ThreeGppHttpHeader in a packet received by the server");
804 "Invalid content type in the received packet");
806 Seconds(0),
807 "Embedded object's client TS is unexpectedly non-positive");
809 Seconds(0),
810 "Embedded object's server TS is unexpectedly non-positive");
811
812 uint32_t txSize = 0;
813 uint32_t rxSize = 0;
814 bool isSent = m_embeddedObjectTracker.ObjectReceived(txSize, rxSize);
815 NS_TEST_ASSERT_MSG_EQ(isSent, true, "Client receives one too many embedded object");
817 rxSize,
818 "Transmitted size and received size of embedded object differ");
820 httpHeader.GetContentLength(),
821 rxSize,
822 "Actual embedded object packet size and received size of embedded object differ");
823}
824
825void
827 const std::string& newState)
828{
829 NS_LOG_FUNCTION(this << oldState << newState);
830
831 if (newState == "READING")
832 {
834
835 if (m_numOfPagesReceived >= 3)
836 {
837 // We have processed 3 web pages and that should be enough for this test.
838 NS_LOG_LOGIC(this << " Test is stopping now.");
840 }
841 }
842}
843
844void
850
851void
853{
854 NS_LOG_FUNCTION(this << delay.As(Time::S) << from);
855 m_delayCalculator->Update(delay.GetSeconds());
856}
857
858void
860{
861 NS_LOG_FUNCTION(this << rtt.As(Time::S) << from);
862 m_rttCalculator->Update(rtt.GetSeconds());
863}
864
865void
867{
868 NS_LOG_FUNCTION(this << packet << packet->GetSize());
870}
871
872// TEST SUITE /////////////////////////////////////////////////////////////////
873
874/**
875 * @ingroup http
876 * @ingroup applications-test
877 * @ingroup tests
878 * A test class for running several system tests which validate the web
879 * browsing traffic model.
880 *
881 * The tests cover the combinations of the following parameters:
882 * - the use of NewReno (ns-3's default)
883 * - various lengths of channel delay: 3 ms, 30 ms, and 300 ms;
884 * - the existence of transmission error;
885 * - different MTU (maximum transmission unit) sizes;
886 * - IPv4 and IPv6; and
887 * - the use of different set of random numbers.
888 *
889 * The _fullness_ parameter specified when running the test framework will
890 * determine the number of test cases created by this test suite.
891 */
893{
894 public:
895 /// Instantiate the test suite.
897 : TestSuite("applications-three-gpp-http-client-server", Type::SYSTEM)
898 {
899 // LogComponentEnable ("ThreeGppHttpClientServerTest", LOG_INFO);
900 // LogComponentEnable ("ThreeGppHttpClient", LOG_INFO);
901 // LogComponentEnable ("ThreeGppHttpServer", LOG_INFO);
902 // LogComponentEnableAll (LOG_PREFIX_ALL);
903
904 Time channelDelay[] = {MilliSeconds(3), MilliSeconds(30), MilliSeconds(300)};
905 double bitErrorRate[] = {0.0, 5.0e-6};
906 uint32_t mtuSize[] = {536, 1460};
907
908 uint32_t run = 1;
909 while (run <= 100)
910 {
911 for (uint32_t i1 = 0; i1 < 3; i1++)
912 {
913 for (uint32_t i2 = 0; i2 < 2; i2++)
914 {
915 for (uint32_t i3 = 0; i3 < 2; i3++)
916 {
917 AddHttpObjectTestCase(run++,
918 channelDelay[i1],
919 bitErrorRate[i2],
920 mtuSize[i3],
921 false);
922 AddHttpObjectTestCase(run++,
923 channelDelay[i1],
924 bitErrorRate[i2],
925 mtuSize[i3],
926 false,
927 8080);
928 AddHttpObjectTestCase(run++,
929 channelDelay[i1],
930 bitErrorRate[i2],
931 mtuSize[i3],
932 true);
933 }
934 }
935 }
936 }
937 }
938
939 private:
940 /**
941 * Creates a test case with the given parameters.
942 *
943 * @param rngRun Run index to be used, intended to affect the values produced
944 * by random number generators throughout the test.
945 * @param channelDelay Transmission delay between the client and the server
946 * (and vice versa) which is due to the channel.
947 * @param bitErrorRate The probability of transmission error between the
948 * client and the server (and vice versa) in the unit of
949 * bits.
950 * @param mtuSize Maximum transmission unit (in bytes) to be used by the
951 * server model.
952 * @param useIpv6 If true, IPv6 will be used to address both client and
953 * server. Otherwise, IPv4 will be used.
954 * @param port The port to use if provided, otherwise the default port is used.
955 */
957 const Time& channelDelay,
958 double bitErrorRate,
959 uint32_t mtuSize,
960 bool useIpv6,
961 std::optional<uint16_t> port = std::nullopt)
962 {
963 std::ostringstream name;
964 name << "Run #" << rngRun;
965 name << " delay=" << channelDelay.As(Time::MS);
966 name << " ber=" << bitErrorRate;
967 name << " mtu=" << mtuSize;
968
969 if (useIpv6)
970 {
971 name << " IPv6";
972 }
973 else
974 {
975 name << " IPv4";
976 }
977 if (port)
978 {
979 name << "(" << *port << ")";
980 }
981
982 // Assign higher fullness for tests with higher RngRun.
983 TestCase::Duration testDuration = TestCase::Duration::QUICK;
984 if (rngRun > 20)
985 {
986 testDuration = TestCase::Duration::EXTENSIVE;
987 }
988 if (rngRun > 50)
989 {
990 testDuration = TestCase::Duration::TAKES_FOREVER;
991 }
992
993 AddTestCase(new ThreeGppHttpObjectTestCase(name.str(),
994 rngRun,
996 channelDelay,
997 bitErrorRate,
998 mtuSize,
999 useIpv6,
1000 port),
1001 testDuration);
1002 }
1003
1004}; // end of class `ThreeGppHttpClientServerTestSuite`
1005
1006/// 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:560
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:404
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:1431
a unique identifier for an interface.
Definition type-id.h:48
AttributeValue implementation for TypeId.
Definition type-id.h:617
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:929
#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:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
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.