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