1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 2 /* 3 * Copyright (c) 2013 Magister Solutions 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation; 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * 18 * Author: Budiarto Herman <budiarto.herman@magister.fi> 19 * 20 */ 21 22 #ifndef THREE_GPP_HTTP_CLIENT_H 23 #define THREE_GPP_HTTP_CLIENT_H 24 25 #include <ns3/application.h> 26 #include <ns3/address.h> 27 #include <ns3/traced-callback.h> 28 #include <ns3/three-gpp-http-header.h> 29 30 31 namespace ns3 { 32 33 34 class Socket; 35 class Packet; 36 class ThreeGppHttpVariables; 37 38 39 /** 40 * \ingroup applications 41 * \defgroup http ThreeGppHttpClientServer 42 * 43 * This traffic generator simulates web browsing traffic using the Hypertext 44 * Transfer Protocol (HTTP). It consists of one or more ThreeGppHttpClient 45 * applications which connect to an ThreeGppHttpServer application. The client 46 * models a web browser which requests web pages to the server. The server 47 * is then responsible to serve the web pages as requested. Please refer to 48 * ThreeGppHttpClientHelper and ThreeGppHttpServerHelper for usage instructions. 49 * 50 * Technically speaking, the client transmits *request objects* to demand a 51 * service from the server. Depending on the type of request received, the 52 * server transmits either: 53 * - a *main object*, i.e., the HTML file of the web page; or 54 * - an *embedded object*, e.g., an image referenced by the HTML file. 55 * 56 * A major portion of the traffic pattern is *reading time*, which does not 57 * generate any traffic. Because of this, one may need to simulate a good 58 * number of clients and/or sufficiently long simulation duration in order to 59 * generate any significant traffic in the system. 60 * 61 * Many aspects of the traffic are randomly determined by ThreeGppHttpVariables. 62 * These characteristics are based on a legacy 3GPP specification. The description 63 * can be found in the following references: 64 * - 3GPP TR 25.892, "Feasibility Study for Orthogonal Frequency Division 65 * Multiplexing (OFDM) for UTRAN enhancement" 66 * - IEEE 802.16m, "Evaluation Methodology Document (EMD)", 67 * IEEE 802.16m-08/004r5, July 2008. 68 * - NGMN Alliance, "NGMN Radio Access Performance Evaluation Methodology", 69 * v1.0, January 2008. 70 * - 3GPP2-TSGC5, "HTTP, FTP and TCP models for 1xEV-DV simulations", 2001. 71 */ 72 73 /** 74 * \ingroup http 75 * Model application which simulates the traffic of a web browser. This 76 * application works in conjunction with an ThreeGppHttpServer application. 77 * 78 * In summary, the application works as follows. 79 * 1. Upon start, it opens a connection to the destination web server 80 * (ThreeGppHttpServer). 81 * 2. After the connection is established, the application immediately requests 82 * a *main object* from the server by sending a request packet. 83 * 3. After receiving a main object (which can take some time if it consists of 84 * several packets), the application "parses" the main object. 85 * 4. The parsing takes a short time (randomly determined) to determine the 86 * number of *embedded objects* (also randomly determined) in the web page. 87 * - If at least one embedded object is determined, the application requests 88 * the first embedded object from the server. The request for the next 89 * embedded object follows after the previous embedded object has been 90 * completely received. 91 * - If there is no more embedded object to request, the application enters 92 * the *reading time*. 93 * 5. Reading time is a long delay (again, randomly determined) where the 94 * application does not induce any network traffic, thus simulating the user 95 * reading the downloaded web page. 96 * 6. After the reading time is finished, the process repeats to step #2. 97 * 98 * The client models HTTP *persistent connection*, i.e., HTTP 1.1, where the 99 * connection to the server is maintained and used for transmitting and receiving 100 * all objects. 101 * 102 * Each request by default has a constant size of 350 bytes. A ThreeGppHttpHeader 103 * is attached to each request packet. The header contains information 104 * such as the content type requested (either main object or embedded object) 105 * and the timestamp when the packet is transmitted (which will be used to 106 * compute the delay and RTT of the packet). 107 */ 108 class ThreeGppHttpClient : public Application 109 { 110 public: 111 /** 112 * Creates a new instance of HTTP client application. 113 * 114 * After creation, the application must be further configured through 115 * attributes. To avoid having to do this process manually, please use 116 * ThreeGppHttpClientHelper. 117 */ 118 ThreeGppHttpClient (); 119 120 /** 121 * Returns the object TypeId. 122 * \return The object TypeId. 123 */ 124 static TypeId GetTypeId (); 125 126 /** 127 * Returns a pointer to the associated socket. 128 * \return Pointer to the associated socket. 129 */ 130 Ptr<Socket> GetSocket () const; 131 132 /// The possible states of the application. 133 enum State_t 134 { 135 /// Before StartApplication() is invoked. 136 NOT_STARTED = 0, 137 /// Sent the server a connection request and waiting for the server to be accept it. 138 CONNECTING, 139 /// Sent the server a request for a main object and waiting to receive the packets. 140 EXPECTING_MAIN_OBJECT, 141 /// Parsing a main object that has just been received. 142 PARSING_MAIN_OBJECT, 143 /// Sent the server a request for an embedded object and waiting to receive the packets. 144 EXPECTING_EMBEDDED_OBJECT, 145 /// User reading a web page that has just been received. 146 READING, 147 /// After StopApplication() is invoked. 148 STOPPED 149 }; 150 151 /** 152 * Returns the current state of the application. 153 * \return The current state of the application. 154 */ 155 State_t GetState () const; 156 157 /** 158 * Returns the current state of the application in string format. 159 * \return The current state of the application in string format. 160 */ 161 std::string GetStateString () const; 162 163 /** 164 * Returns the given state in string format. 165 * \param state An arbitrary state of an application. 166 * \return The given state equivalently expressed in string format. 167 */ 168 static std::string GetStateString (State_t state); 169 170 /** 171 * Common callback signature for `ConnectionEstablished`, `RxMainObject`, and 172 * `RxEmbeddedObject` trace sources. 173 * \param httpClient Pointer to this instance of ThreeGppHttpClient, 174 * which is where the trace originated. 175 */ 176 typedef void (*TracedCallback)(Ptr<const ThreeGppHttpClient> httpClient); 177 178 protected: 179 // Inherited from Object base class. 180 virtual void DoDispose (); 181 182 // Inherited from Application base class. 183 virtual void StartApplication (); 184 virtual void StopApplication (); 185 186 private: 187 // SOCKET CALLBACK METHODS 188 189 /** 190 * Invoked when a connection is established successfully on #m_socket. This 191 * triggers a request for a main object. 192 * \param socket Pointer to the socket where the event originates from. 193 */ 194 void ConnectionSucceededCallback (Ptr<Socket> socket); 195 /** 196 * Invoked when #m_socket cannot establish a connection with the web server. 197 * Simulation will stop and error will be raised. 198 * \param socket Pointer to the socket where the event originates from. 199 */ 200 void ConnectionFailedCallback (Ptr<Socket> socket); 201 /** 202 * Invoked when connection between #m_socket and the web sever is terminated. 203 * Error will be logged, but simulation continues. 204 * \param socket Pointer to the socket where the event originates from. 205 */ 206 void NormalCloseCallback (Ptr<Socket> socket); 207 /** 208 * Invoked when connection between #m_socket and the web sever is terminated. 209 * Error will be logged, but simulation continues. 210 * \param socket Pointer to the socket where the event originates from. 211 */ 212 void ErrorCloseCallback (Ptr<Socket> socket); 213 /** 214 * Invoked when #m_socket receives some packet data. Fires the `Rx` trace 215 * source and triggers ReceiveMainObject() or ReceiveEmbeddedObject(). 216 * \param socket Pointer to the socket where the event originates from. 217 */ 218 void ReceivedDataCallback (Ptr<Socket> socket); 219 220 // CONNECTION-RELATED METHOD 221 222 /** 223 * Initialize #m_socket to connect to the destination web server at 224 * #m_remoteServerAddress and #m_remoteServerPort and set up callbacks to 225 * listen to its event. Invoked upon the start of the application. 226 */ 227 void OpenConnection (); 228 229 // TX-RELATED METHODS 230 231 /** 232 * Send a request object for a main object to the destination web server. 233 * The size of the request packet is randomly determined by HttpVariables and 234 * is assumed to be smaller than 536 bytes. Fires the `TxMainObjectRequest` 235 * trace source. 236 * 237 * The method is invoked after a connection is established or after a 238 * reading time has elapsed. 239 */ 240 void RequestMainObject (); 241 /** 242 * Send a request object for an embedded object to the destination web 243 * server. The size of the request packet is randomly determined by 244 * ThreeGppHttpVariables and is assumed to be smaller than 536 bytes. Fires the 245 * `TxEmbeddedObjectRequest` trace source. 246 */ 247 void RequestEmbeddedObject (); 248 249 // RX-RELATED METHODS 250 251 /** 252 * Receive a packet of main object from the destination web server. Fires the 253 * `RxMainObjectPacket` trace source. 254 * 255 * A main object may come from more than one packets. This is determined by 256 * comparing the content length specified in the ThreeGppHttpHeader of the packet and 257 * the actual packet size. #m_objectBytesToBeReceived keeps track of the 258 * number of bytes that has been received. 259 * 260 * If the received packet is not the last packet of the object, then the 261 * method simply quits, expecting it to be invoked again when the next packet 262 * comes. 263 * 264 * If the received packet is the last packet of the object, then the method 265 * fires the `RxMainObject`, `RxDelay`, and `RxRtt` trace sources. The client 266 * then triggers EnterParsingTime(). 267 * 268 * \param packet The received packet. 269 * \param from Address of the sender. 270 */ 271 void ReceiveMainObject (Ptr<Packet> packet, const Address &from); 272 /** 273 * Receive a packet of embedded object from the destination web server. Fires 274 * the `RxEmbeddedObjectPacket` trace source. 275 * 276 * An embedded object may come from more than one packets. This is determined 277 * by comparing the content length specified in the TheeGppHttpHeader of the packet and 278 * the actual packet size. #m_objectBytesToBeReceived keeps track of the 279 * number of bytes that has been received. 280 * 281 * If the received packet is not the last packet of the object, then the 282 * method simply quits, expecting it to be invoked again when the next packet 283 * comes. 284 * 285 * If the received packet is the last packet of the object, then the method 286 * fires the `RxEmbeddedObject`, `RxDelay`, and `RxRtt` trace sources. 287 * Depending on the number of embedded objects remaining 288 * (#m_embeddedObjectsToBeRequested) the client can either trigger 289 * RequestEmbeddedObject() or EnterReadingTime(). 290 * 291 * \param packet The received packet. 292 * \param from Address of the sender. 293 */ 294 void ReceiveEmbeddedObject (Ptr<Packet> packet, const Address &from); 295 /** 296 * Simulate a consumption of the received packet by subtracting the packet 297 * size from the internal counter at #m_objectBytesToBeReceived. Also updates 298 * #m_objectClientTs and #m_objectServerTs according to the ThreeGppHttpHeader 299 * found in the packet. 300 * 301 * This method is invoked as a sub-procedure of ReceiveMainObject() and 302 * ReceiveEmbeddedObject(). 303 * 304 * \param packet The received packet. If it is the first packet of the object, 305 * then it must have a ThreeGppHttpHeader attached to it. 306 */ 307 void Receive (Ptr<Packet> packet); 308 309 // OFF-TIME-RELATED METHODS 310 311 /** 312 * Becomes idle for a randomly determined amount of time, and then triggers 313 * ParseMainObject(). The length of idle time is determined by 314 * TheeGppHttpVariables. 315 * 316 * The method is invoked after a complete main object has been received. 317 */ 318 void EnterParsingTime (); 319 /** 320 * Randomly determines the number of embedded objects in the main object. 321 * ThreeGppHttpVariables is utilized for this purpose. Then proceeds with 322 * RequestEmbeddedObject(). If the number of embedded objects has been 323 * determined as zero, then EnterReadingTime() is triggered. 324 * 325 * The method is invoked after parsing time has elapsed. 326 */ 327 void ParseMainObject (); 328 /** 329 * Becomes idle for a randomly determined amount of time, and then triggers 330 * RequestMainObject(). The length of idle time is determined by 331 * ThreeGppHttpVariables. 332 * 333 * The method is invoked after a complete web page has been received. 334 */ 335 void EnterReadingTime (); 336 /** 337 * Cancels #m_eventRequestMainObject, #m_eventRequestEmbeddedObject, and 338 * #m_eventParseMainObject. Invoked by StopApplication() and when connection 339 * has been terminated. 340 */ 341 void CancelAllPendingEvents (); 342 343 /** 344 * Change the state of the client. Fires the `StateTransition` trace source. 345 * \param state The new state. 346 */ 347 void SwitchToState (State_t state); 348 349 /// The current state of the client application. Begins with NOT_STARTED. 350 State_t m_state; 351 /// The socket for sending and receiving packets to/from the web server. 352 Ptr<Socket> m_socket; 353 /// According to the content length specified by the ThreeGppHttpHeader. 354 uint32_t m_objectBytesToBeReceived; 355 /// The packet constructed of one or more parts with ThreeGppHttpHeader. 356 Ptr<Packet> m_constructedPacket; 357 /// The client time stamp of the ThreeGppHttpHeader from the last received packet. 358 Time m_objectClientTs; 359 /// The server time stamp of the ThreeGppHttpHeader from the last received packet. 360 Time m_objectServerTs; 361 /// Determined after parsing the main object. 362 uint32_t m_embeddedObjectsToBeRequested; 363 364 // ATTRIBUTES 365 366 /// The `Variables` attribute. 367 Ptr<ThreeGppHttpVariables> m_httpVariables; 368 /// The `RemoteServerAddress` attribute. The address of the web server. 369 Address m_remoteServerAddress; 370 /// The `RemoteServerPort` attribute. 371 uint16_t m_remoteServerPort; 372 373 // TRACE SOURCES 374 375 /// The `ConnectionEstablished` trace source. 376 ns3::TracedCallback<Ptr<const ThreeGppHttpClient> > m_connectionEstablishedTrace; 377 /// The `ConnectionClosed` trace source. 378 ns3::TracedCallback<Ptr<const ThreeGppHttpClient> > m_connectionClosedTrace; 379 /// The `Tx` trace source. 380 ns3::TracedCallback<Ptr<const Packet> > m_txTrace; 381 /// The `TxMainObjectRequest` trace source. 382 ns3::TracedCallback<Ptr<const Packet> > m_txMainObjectRequestTrace; 383 /// The `TxEmbeddedObjectRequest` trace source. 384 ns3::TracedCallback<Ptr<const Packet> > m_txEmbeddedObjectRequestTrace; 385 /// The `TxMainObjectPacket` trace source. 386 ns3::TracedCallback<Ptr<const Packet> > m_rxMainObjectPacketTrace; 387 /// The `TxMainObject` trace source. 388 ns3::TracedCallback<Ptr<const ThreeGppHttpClient>, Ptr<const Packet> > m_rxMainObjectTrace; 389 /// The `TxEmbeddedObjectPacket` trace source. 390 ns3::TracedCallback<Ptr<const Packet> > m_rxEmbeddedObjectPacketTrace; 391 /// The `TxEmbeddedObject` trace source. 392 ns3::TracedCallback<Ptr<const ThreeGppHttpClient>, Ptr<const Packet> > m_rxEmbeddedObjectTrace; 393 /// The `Rx` trace source. 394 ns3::TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace; 395 /// The `RxDelay` trace source. 396 ns3::TracedCallback<const Time &, const Address &> m_rxDelayTrace; 397 /// The `RxRtt` trace source. 398 ns3::TracedCallback<const Time &, const Address &> m_rxRttTrace; 399 /// The `StateTransition` trace source. 400 ns3::TracedCallback<const std::string &, const std::string &> m_stateTransitionTrace; 401 402 // EVENTS 403 404 /** 405 * An event of either RequestMainObject() or OpenConnection(), scheduled to 406 * trigger after a connection has been established or reading time has 407 * elapsed. 408 */ 409 EventId m_eventRequestMainObject; 410 /** 411 * An event of either RequestEmbeddedObject() or OpenConnection(). 412 */ 413 EventId m_eventRequestEmbeddedObject; 414 /** 415 * An event of ParseMainObject(), scheduled to trigger after parsing time has 416 * elapsed. 417 */ 418 EventId m_eventParseMainObject; 419 420 }; // end of `class ThreeGppHttpClient` 421 422 423 } // end of `namespace ns3` 424 425 426 #endif /* THREE_GPP_HTTP_CLIENT_H */ 427