diff --git a/src/applications/examples/three-gpp-http-example.cc b/src/applications/examples/three-gpp-http-example.cc index 2fe725cb4..991d0f37d 100644 --- a/src/applications/examples/three-gpp-http-example.cc +++ b/src/applications/examples/three-gpp-http-example.cc @@ -93,6 +93,17 @@ ClientEmbeddedObjectReceived(Ptr, Ptr pa } } +void +ClientPageReceived(Ptr client, + const Time& time, + uint32_t numObjects, + uint32_t numBytes) +{ + NS_LOG_INFO("Client " << client << " has received a page that took " << time.As(Time::MS) + << " ms to load with " << numObjects << " objects and " << numBytes + << " bytes."); +} + int main(int argc, char* argv[]) { @@ -163,6 +174,7 @@ main(int argc, char* argv[]) httpClient->TraceConnectWithoutContext("RxEmbeddedObject", MakeCallback(&ClientEmbeddedObjectReceived)); httpClient->TraceConnectWithoutContext("Rx", MakeCallback(&ClientRx)); + httpClient->TraceConnectWithoutContext("RxPage", MakeCallback(&ClientPageReceived)); // Stop browsing after 30 minutes clientApps.Stop(Seconds(simTimeSec)); diff --git a/src/applications/model/three-gpp-http-client.cc b/src/applications/model/three-gpp-http-client.cc index 8cfec42f2..53a6ee297 100644 --- a/src/applications/model/three-gpp-http-client.cc +++ b/src/applications/model/three-gpp-http-client.cc @@ -47,6 +47,9 @@ ThreeGppHttpClient::ThreeGppHttpClient() m_objectClientTs(MilliSeconds(0)), m_objectServerTs(MilliSeconds(0)), m_embeddedObjectsToBeRequested(0), + m_pageLoadStartTs(MilliSeconds(0)), + m_numberEmbeddedObjectsRequested(0), + m_numberBytesPage(0), m_httpVariables(CreateObject()) { NS_LOG_FUNCTION(this); @@ -76,6 +79,10 @@ ThreeGppHttpClient::GetTypeId() UintegerValue(80), // the default HTTP port MakeUintegerAccessor(&ThreeGppHttpClient::m_remoteServerPort), MakeUintegerChecker()) + .AddTraceSource("RxPage", + "A page has been received.", + MakeTraceSourceAccessor(&ThreeGppHttpClient::m_rxPageTrace), + "ns3::ThreeGppHttpClient::RxPageTracedCallback") .AddTraceSource( "ConnectionEstablished", "Connection to the destination web server has been established.", @@ -447,6 +454,7 @@ ThreeGppHttpClient::RequestMainObject() else { SwitchToState(EXPECTING_MAIN_OBJECT); + m_pageLoadStartTs = Simulator::Now(); // start counting page loading time } } else @@ -628,6 +636,7 @@ ThreeGppHttpClient::ReceiveEmbeddedObject(Ptr packet, const Address& fro * downloaded completely. Now is the time to read it. */ NS_LOG_INFO(this << " Finished receiving a web page."); + FinishReceivingPage(); // trigger callback for page loading time EnterReadingTime(); } @@ -669,6 +678,7 @@ ThreeGppHttpClient::Receive(Ptr packet) m_constructedPacket->AddHeader(httpHeader); } uint32_t contentSize = packet->GetSize(); + m_numberBytesPage += contentSize; // increment counter of page size /* Note that the packet does not contain header at this point. * The content is purely raw data, which was the only intended data to be received. @@ -724,6 +734,8 @@ ThreeGppHttpClient::ParseMainObject() if (m_state == PARSING_MAIN_OBJECT) { m_embeddedObjectsToBeRequested = m_httpVariables->GetNumOfEmbeddedObjects(); + // saving total number of embedded objects + m_numberEmbeddedObjectsRequested = m_embeddedObjectsToBeRequested; NS_LOG_INFO(this << " Parsing has determined " << m_embeddedObjectsToBeRequested << " embedded object(s) in the main object."); @@ -743,6 +755,7 @@ ThreeGppHttpClient::ParseMainObject() * enjoy the plain web page. */ NS_LOG_INFO(this << " Finished receiving a web page."); + FinishReceivingPage(); // trigger callback for page loading time EnterReadingTime(); } } @@ -826,4 +839,16 @@ ThreeGppHttpClient::SwitchToState(ThreeGppHttpClient::State_t state) m_stateTransitionTrace(oldState, newState); } +void +ThreeGppHttpClient::FinishReceivingPage() +{ + m_rxPageTrace(this, + Simulator::Now() - m_pageLoadStartTs, + m_numberEmbeddedObjectsRequested, + m_numberBytesPage); + // Reset counter variables. + m_numberEmbeddedObjectsRequested = 0; + m_numberBytesPage = 0; +} + } // namespace ns3 diff --git a/src/applications/model/three-gpp-http-client.h b/src/applications/model/three-gpp-http-client.h index a149ce878..d0ad86ce7 100644 --- a/src/applications/model/three-gpp-http-client.h +++ b/src/applications/model/three-gpp-http-client.h @@ -172,6 +172,20 @@ class ThreeGppHttpClient : public Application */ typedef void (*TracedCallback)(Ptr httpClient); + /** + * Callback signature for `RxPage` trace sources. + * \param httpClient Pointer to this instance of ThreeGppHttpClient, + * which is where the trace originated. + * \param time Elapsed time from the start to the end of the request. + * \param numObjects Number of objects downloaded, including main and + * embedded objects. + * \param numBytes Total number of bytes included in the page. + */ + typedef void (*RxPageTracedCallback)(Ptr httpClient, + const Time& time, + uint32_t numObjects, + uint32_t numBytes); + protected: // Inherited from Object base class. void DoDispose() override; @@ -343,6 +357,12 @@ class ThreeGppHttpClient : public Application */ void SwitchToState(State_t state); + /** + * Finish receiving a page. This function should be called when a full-page + * finishes loading, including the main object and all embedded objects. + */ + void FinishReceivingPage(); + /// The current state of the client application. Begins with NOT_STARTED. State_t m_state; /// The socket for sending and receiving packets to/from the web server. @@ -357,6 +377,12 @@ class ThreeGppHttpClient : public Application Time m_objectServerTs; /// Determined after parsing the main object. uint32_t m_embeddedObjectsToBeRequested; + /// The time stamp when the page started loading. + Time m_pageLoadStartTs; + /// Number of embedded objects to requested in the current page. + uint32_t m_numberEmbeddedObjectsRequested; + /// Number of bytes received for the current page. + uint32_t m_numberBytesPage; // ATTRIBUTES @@ -369,6 +395,9 @@ class ThreeGppHttpClient : public Application // TRACE SOURCES + /// The `RxPage` trace source. + ns3::TracedCallback, const Time&, uint32_t, uint32_t> + m_rxPageTrace; /// The `ConnectionEstablished` trace source. ns3::TracedCallback> m_connectionEstablishedTrace; /// The `ConnectionClosed` trace source.