/*************************************************************************** msnsockethttp.h - description ------------------- begin : Thu Apr 4 2008 copyright : (C) 2008 by Valerio Pilo email : valerio@kmess.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef MSNSOCKETHTTP_H #define MSNSOCKETHTTP_H #include "msnsocketbase.h" #include <QHash> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QStringList> #include <QTime> #include <QTimer> // Forward declarations class CurrentAccount; class QNetworkReply; class QSslError; /** * @brief Basic I/O functionality for the MSN server protocol over a HTTP connection. * * This is a low-level class used used by MsnConnection. * The class provides the following facilities: * - HTTP-only connection to the MSN servers, with exclusive usage of ports 80 and 443. * - sending/receiving raw protocol data. * * With HTTP the server has no way of contacting the client by itself. Everytime we * send a request to the server (the "MSN HTTP Gateway"), it will send along with the answer * a full list of messages which we didn't receive yet. So if we've got nothing to send, * we're forced to periodically send 'poll' requests. These are bogus calls which exist only * to allow the gateway to send any new message back. * * In any given moment, there may only be one active message. This means that if we send two * subsequent requests, we will be disconnected immediately with a '400 Bad Request' response. * Therefore, this class implements a 1-item-wide sending window. It's not necessary to apply * it to receiving also, since the server just responds in order. * * Data from the server (the "HTTP Gateway") is handled by the slotDataReceived() slot. * This method receives responses to HTTP requests made by the class; they contain a list of * new undelivered messages. The slotDataReceived() method splits it up to individual commands * and forwards the received commands to MsnConnection individually. * * Simple scheme of requests/responses: * - Got a request to send. Send it immediately. * - Received a response with messages. Have queued requests? * - Yes. Send the next now. * - No. Send a polling request now. * - Received an empty response (without messages). Have queued requests? * - Yes. Send the next now. * - No. What kind of message was last sent? * - A command. Send a poll in 5 seconds. * - A poll. Send another poll in 10 seconds. * * @author Valerio Pilo <valerio@kmess.org> * @ingroup NetworkCore */ 00075 class MsnSocketHttp : public MsnSocketBase { Q_OBJECT public: // Public methods // The constructor MsnSocketHttp( ServerType serverType ); // The destructor ~MsnSocketHttp(); // Connect to the given server void connectToServer( const QString& server = QString(), const quint16 port = 0 ); // Disconnect from the server void disconnectFromServer( bool isTransfer = false ); // Return the local IP address QString getLocalIp() const; // Set whether to send pings or not void setSendPings( bool sendPings ); // Write data to the socket without conversions qint64 writeBinaryData( const QByteArray& data ); // Write data to the socket qint64 writeData( const QString& data ); private: // Private methods // Clean up the connection void cleanUp(); // Dump the content of requests and replies void dump( void *obj, QByteArray data, bool isRequest ); // Sends the next queued request void sendNextRequest(); // Change the server connection gateway void setGateway( QString host ); private slots: // Private slots // Send a polling message to the server, to retrieve pending commands void slotQueryServer(); // Read received data and pass along the contained commands void slotReplyReceived( QNetworkReply *reply ); private: // Private structures // Structure to hold all the useful data about an HTTP request struct RequestInfo { // Special request parameters to be sent along with the data QString requestQueryString; // The actual contents of the request QByteArray data; }; private: // Private attributes // URL to specify in the queries QString baseServerPath_; // State variable to detect whether it's possible or not to send another request bool canSendRequests_; // Time at which the last request has been sent QTime lastRequestTime_; // Saved gateway address QString gatewayAddress_; // The HTTP interface QNetworkAccessManager *http_; // true if the last sent request was a polling message bool lastRequestWasPolling_; // true if the last received response didn't carry any new commands bool lastResponseWasEmpty_; // Time counter to regularly report pings to the application QDateTime lastPing_; // Next request's ID QString nextRequestId_; // Next request's parameters QString nextRequestParameters_; // A timer to regularly query the server for new commands QTimer pollingTimer_; // List of requests waiting to be sent QList<RequestInfo> queuedRequests_; // Container for never-changing request information QNetworkRequest requestHeader_; // Are we sending pings? bool sendPings_; // Hashmap of non answered requests QList<QNetworkReply*> unansweredRequests_; }; #endif