OLD | NEW |
(Empty) | |
| 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 descripti
on |
| 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 receivin
g |
| 100 * all objects. |
| 101 * |
| 102 * Each request by default has a constant size of 350 bytes. A ThreeGppHttpHeade
r |
| 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 ac
cept it. |
| 138 CONNECTING, |
| 139 /// Sent the server a request for a main object and waiting to receive the p
ackets. |
| 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 th
e |
| 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 pac
ket 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 p
acket 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 and containing single ThreeGpp
HttpHeader. |
| 356 Ptr<Packet> m_constructedPacket; |
| 357 /// The client time stamp of the ThreeGppHttpHeader from the last received pac
ket. |
| 358 Time m_objectClientTs; |
| 359 /// The server time stamp of the ThreeGppHttpHeader from the last received pac
ket. |
| 360 Time m_objectServerTs; |
| 361 /// Determined after parsing the main object. |
| 362 uint32_t m_embeddedObjectsToBeRequested; |
| 363 |
| 364 // ATTRIBUTES |
| 365 |
| 366 /// The `Variables` attribute. A random number generator. |
| 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_connectionEstablishedTra
ce; |
| 377 /// The `ConnectionClosed` trace source. |
| 378 ns3::TracedCallback<Ptr<const ThreeGppHttpClient> > m_connectionClosedTrace; |
| 379 /// The `TxMainObjectRequest` trace source. |
| 380 ns3::TracedCallback<Ptr<const Packet> > m_txMainObjectRequestTrace; |
| 381 /// The `TxEmbeddedObjectRequest` trace source. |
| 382 ns3::TracedCallback<Ptr<const Packet> > m_txEmbeddedObjectRequestTrace; |
| 383 /// The `TxMainObjectPacket` trace source. |
| 384 ns3::TracedCallback<Ptr<const Packet> > m_rxMainObjectPacketTrace; |
| 385 /// The `TxMainObject` trace source. |
| 386 ns3::TracedCallback<Ptr<const ThreeGppHttpClient>, Ptr<const Packet> > m_rxMa
inObjectTrace; |
| 387 /// The `TxEmbeddedObjectPacket` trace source. |
| 388 ns3::TracedCallback<Ptr<const Packet> > m_rxEmbeddedObjectPacketTrace; |
| 389 /// The `TxEmbeddedObject` trace source. |
| 390 ns3::TracedCallback<Ptr<const ThreeGppHttpClient>, Ptr<const Packet> > m_rxEmb
eddedObjectTrace; |
| 391 /// The `Rx` trace source. |
| 392 ns3::TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace; |
| 393 /// The `RxDelay` trace source. |
| 394 ns3::TracedCallback<const Time &, const Address &> m_rxDelayTrace; |
| 395 /// The `RxRtt` trace source. |
| 396 ns3::TracedCallback<const Time &, const Address &> m_rxRttTrace; |
| 397 /// The `StateTransition` trace source. |
| 398 ns3::TracedCallback<const std::string &, const std::string &> m_stateTransitio
nTrace; |
| 399 |
| 400 // EVENTS |
| 401 |
| 402 /** |
| 403 * An event of either RequestMainObject() or OpenConnection(), scheduled to |
| 404 * trigger after a connection has been established or reading time has |
| 405 * elapsed. |
| 406 */ |
| 407 EventId m_eventRequestMainObject; |
| 408 /** |
| 409 * An event of either RequestEmbeddedObject() or OpenConnection(). |
| 410 */ |
| 411 EventId m_eventRequestEmbeddedObject; |
| 412 /** |
| 413 * An event of ParseMainObject(), scheduled to trigger after parsing time has |
| 414 * elapsed. |
| 415 */ |
| 416 EventId m_eventParseMainObject; |
| 417 |
| 418 }; // end of `class ThreeGppHttpClient` |
| 419 |
| 420 |
| 421 } // end of `namespace ns3` |
| 422 |
| 423 |
| 424 #endif /* THREE_GPP_HTTP_CLIENT_H */ |
OLD | NEW |