Q3Http Class Reference

#include <q3http.h>

Inheritance diagram for Q3Http:

Inheritance graph
[legend]
Collaboration diagram for Q3Http:

Collaboration graph
[legend]
List of all members.

Detailed Description

The Q3Http class provides an implementation of the HTTP protocol.

This class provides two different interfaces: one is the Q3NetworkProtocol interface that allows you to use HTTP through the QUrlOperator abstraction. The other is a direct interface to HTTP that allows you to have more control over the requests and that allows you to access the response header fields.

Don't mix the two interfaces, since the behavior is not well-defined.

If you want to use Q3Http with the Q3NetworkProtocol interface, you do not use it directly, but rather through a QUrlOperator, for example:

    QUrlOperator op( "http://www.trolltech.com" );
    op.get( "index.html" );

This code will only work if the Q3Http class is registered; to register the class, you must call q3InitNetworkProtocols() before using a QUrlOperator with HTTP.

The Q3NetworkProtocol interface for HTTP only supports the operations operationGet() and operationPut(), i.e. QUrlOperator::get() and QUrlOperator::put(), if you use it with a QUrlOperator.

The rest of this descrption describes the direct interface to HTTP.

The class works asynchronously, so there are no blocking functions. If an operation cannot be executed immediately, the function will still return straight away and the operation will be scheduled for later execution. The results of scheduled operations are reported via signals. This approach depends on the event loop being in operation.

The operations that can be scheduled (they are called "requests" in the rest of the documentation) are the following: setHost(), get(), post(), head() and request().

All of these requests return a unique identifier that allows you to keep track of the request that is currently executed. When the execution of a request starts, the requestStarted() signal with the identifier is emitted and when the request is finished, the requestFinished() signal is emitted with the identifier and a bool that indicates if the request finished with an error.

To make an HTTP request you must set up suitable HTTP headers. The following example demonstrates, how to request the main HTML page from the Trolltech home page (i.e. the URL http://www.trolltech.com/index.html):

    Q3HttpRequestHeader header( "GET", "/index.html" );
    header.setValue( "Host", "www.trolltech.com" );
    http->setHost( "www.trolltech.com" );
    http->request( header );

For the common HTTP requests GET, POST and HEAD, Q3Http provides the convenience functions get(), post() and head(). They already use a reasonable header and if you don't have to set special header fields, they are easier to use. The above example can also be written as:

    http->setHost( "www.trolltech.com" ); // id == 1
    http->get( "/index.html" );           // id == 2

For this example the following sequence of signals is emitted (with small variations, depending on network traffic, etc.):

    requestStarted( 1 )
    requestFinished( 1, false )

    requestStarted( 2 )
    stateChanged( Connecting )
    stateChanged( Sending )
    dataSendProgress( 77, 77 )
    stateChanged( Reading )
    responseHeaderReceived( responseheader )
    dataReadProgress( 5388, 0 )
    readyRead( responseheader )
    dataReadProgress( 18300, 0 )
    readyRead( responseheader )
    stateChanged( Connected )
    requestFinished( 2, false )

    done( false )

    stateChanged( Closing )
    stateChanged( Unconnected )

The dataSendProgress() and dataReadProgress() signals in the above example are useful if you want to show a progressbar to inform the user about the progress of the download. The second argument is the total size of data. In certain cases it is not possible to know the total amount in advance, in which case the second argument is 0. (If you connect to a QProgressBar a total of 0 results in a busy indicator.)

When the response header is read, it is reported with the responseHeaderReceived() signal.

The readyRead() signal tells you that there is data ready to be read. The amount of data can then be queried with the bytesAvailable() function and it can be read with the readBlock() or readAll() functions.

If an error occurs during the execution of one of the commands in a sequence of commands, all the pending commands (i.e. scheduled, but not yet executed commands) are cleared and no signals are emitted for them.

For example, if you have the following sequence of reqeusts

    http->setHost( "www.foo.bar" );       // id == 1
    http->get( "/index.html" );           // id == 2
    http->post( "register.html", data );  // id == 3

and the get() request fails because the host lookup fails, then the post() request is never executed and the signals would look like this:

    requestStarted( 1 )
    requestFinished( 1, false )

    requestStarted( 2 )
    stateChanged( HostLookup )
    requestFinished( 2, true )

    done( true )

    stateChanged( Unconnected )

You can then get details about the error with the error() and errorString() functions. Note that only unexpected behaviour, like network failure is considered as an error. If the server response contains an error status, like a 404 response, this is reported as a normal response case. So you should always check the status code of the response header.

The functions currentId() and currentRequest() provide more information about the currently executing request.

The functions hasPendingRequests() and clearPendingRequests() allow you to query and clear the list of pending requests.

See also:
Q3NetworkProtocol, Q3UrlOperator, Q3Ftp

Definition at line 147 of file q3http.h.

Public Types

enum  State
enum  Error

Public Slots

void abort ()

Signals

void stateChanged (int)
void responseHeaderReceived (const Q3HttpResponseHeader &resp)
void readyRead (const Q3HttpResponseHeader &resp)
void dataSendProgress (int, int)
void dataReadProgress (int, int)
void requestStarted (int)
void requestFinished (int, bool)
void done (bool)

Public Member Functions

 Q3Http ()
 Q3Http (QObject *parent, const char *name=0)
 Q3Http (const QString &hostname, Q_UINT16 port=80, QObject *parent=0, const char *name=0)
virtual ~Q3Http ()
int supportedOperations () const
int setHost (const QString &hostname, Q_UINT16 port=80)
int get (const QString &path, QIODevice *to=0)
int post (const QString &path, QIODevice *data, QIODevice *to=0)
int post (const QString &path, const QByteArray &data, QIODevice *to=0)
int head (const QString &path)
int request (const Q3HttpRequestHeader &header, QIODevice *device=0, QIODevice *to=0)
int request (const Q3HttpRequestHeader &header, const QByteArray &data, QIODevice *to=0)
int closeConnection ()
Q_ULONG bytesAvailable () const
Q_LONG readBlock (char *data, Q_ULONG maxlen)
QByteArray readAll ()
int currentId () const
QIODevicecurrentSourceDevice () const
QIODevicecurrentDestinationDevice () const
Q3HttpRequestHeader currentRequest () const
bool hasPendingRequests () const
void clearPendingRequests ()
State state () const
Error error () const
QString errorString () const

Protected Member Functions

void operationGet (Q3NetworkOperation *op)
void operationPut (Q3NetworkOperation *op)
void timerEvent (QTimerEvent *)

Private Slots

void clientReply (const Q3HttpResponseHeader &rep)
void clientDone (bool)
void clientStateChanged (int)
void startNextRequest ()
void slotReadyRead ()
void slotConnected ()
void slotError (int)
void slotClosed ()
void slotBytesWritten (int)

Private Member Functions

int addRequest (Q3HttpRequest *)
void sendRequest ()
void finishedWithSuccess ()
void finishedWithError (const QString &detail, int errorCode)
void killIdleTimer ()
void init ()
void setState (int)
void close ()

Private Attributes

Q3HttpPrivated
void * unused
int bytesRead

Friends

class Q3HttpNormalRequest
class Q3HttpSetHostRequest
class Q3HttpCloseRequest
class Q3HttpPGHRequest


Member Enumeration Documentation

enum Q3Http::State

This enum is used to specify the state the client is in:

Unconnected There is no connection to the host. HostLookup A host name lookup is in progress. Connecting An attempt to connect to the host is in progress. Sending The client is sending its request to the server. Reading The client's request has been sent and the client is reading the server's response. Connected The connection to the host is open, but the client is neither sending a request, nor waiting for a response. Closing The connection is closing down, but is not yet closed. (The state will be Unconnected when the connection is closed.)

See also:
stateChanged() state()

Reimplemented from Q3NetworkProtocol.

Definition at line 159 of file q3http.h.

enum Q3Http::Error

This enum identifies the error that occurred.

NoError No error occurred. HostNotFound The host name lookup failed. ConnectionRefused The server refused the connection. UnexpectedClose The server closed the connection unexpectedly. InvalidResponseHeader The server sent an invalid response header. WrongContentLength The client could not read the content correctly because an error with respect to the content length occurred. Aborted The request was aborted with abort(). UnknownError An error other than those specified above occurred.

See also:
error()

Reimplemented from Q3NetworkProtocol.

Definition at line 160 of file q3http.h.

00160                {
00161   NoError,
00162   UnknownError,
00163   HostNotFound,
00164   ConnectionRefused,
00165   UnexpectedClose,
00166   InvalidResponseHeader,
00167   WrongContentLength,
00168   Aborted
00169     };


Constructor & Destructor Documentation

Q3Http::Q3Http (  ) 

Constructs a Q3Http object.

Definition at line 1152 of file q3http.cpp.

References init().

01153 {
01154     init();
01155 }

Here is the call graph for this function:

Q3Http::Q3Http ( QObject parent,
const char *  name = 0 
)

Constructs a Q3Http object. The parameters parent and name are passed on to the QObject constructor.

Definition at line 1161 of file q3http.cpp.

References init(), and QObject::parent().

01162 {
01163     if ( parent )
01164   parent->insertChild( this );
01165     setName( name );
01166     init();
01167 }

Here is the call graph for this function:

Q3Http::Q3Http ( const QString hostname,
Q_UINT16  port = 80,
QObject parent = 0,
const char *  name = 0 
)

Constructs a Q3Http object. Subsequent requests are done by connecting to the server hostname on port port. The parameters parent and name are passed on to the QObject constructor.

See also:
setHost()

Definition at line 1177 of file q3http.cpp.

References d, Q3HttpPrivate::hostname, init(), QObject::parent(), and Q3HttpPrivate::port.

01178 {
01179     if ( parent )
01180   parent->insertChild( this );
01181     setName( name );
01182     init();
01183 
01184     d->hostname = hostname;
01185     d->port = port;
01186 }

Here is the call graph for this function:

Q3Http::~Q3Http (  )  [virtual]

Destroys the Q3Http object. If there is an open connection, it is closed.

Definition at line 1214 of file q3http.cpp.

References abort(), and d.

01215 {
01216     abort();
01217     delete d;
01218 }


Member Function Documentation

int Q3Http::supportedOperations (  )  const [virtual]

Reimplemented from Q3NetworkProtocol.

Definition at line 2193 of file q3http.cpp.

References Q3NetworkProtocol::OpGet, and Q3NetworkProtocol::OpPut.

02194 {
02195     return OpGet | OpPut;
02196 }

int Q3Http::setHost ( const QString hostname,
Q_UINT16  port = 80 
)

Sets the HTTP server that is used for requests to hostname on port port.

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

See also:
get() post() head() request() requestStarted() requestFinished() done()

Definition at line 1560 of file q3http.cpp.

References addRequest(), and Q3HttpSetHostRequest.

Referenced by operationGet(), and operationPut().

01561 {
01562     return addRequest( new Q3HttpSetHostRequest( hostname, port ) );
01563 }

Here is the call graph for this function:

int Q3Http::get ( const QString path,
QIODevice to = 0 
)

Sends a get request for path to the server set by setHost() or as specified in the constructor.

path must be an absolute path like /index.html or an absolute URI like http://www.trolltech.com/index.html.

If the IO device to is 0 the readyRead() signal is emitted every time new content data is available to read.

If the IO device to is not 0, the content data of the response is written directly to the device. Make sure that the to pointer is valid for the duration of the operation (it is safe to delete it when the requestFinished() signal is emitted).

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

See also:
setHost() post() head() request() requestStarted() requestFinished() done()

Definition at line 1591 of file q3http.cpp.

References addRequest(), header(), path, and Q3HttpPGHRequest.

01592 {
01593     Q3HttpRequestHeader header( "GET", path );
01594     header.setValue( "Connection", "Keep-Alive" );
01595     return addRequest( new Q3HttpPGHRequest( header, (QIODevice*)0, to ) );
01596 }

Here is the call graph for this function:

int Q3Http::post ( const QString path,
QIODevice data,
QIODevice to = 0 
)

Sends a post request for path to the server set by setHost() or as specified in the constructor.

path must be an absolute path like /index.html or an absolute URI like http://www.trolltech.com/index.html.

The incoming data comes via the data IO device.

If the IO device to is 0 the readyRead() signal is emitted every time new content data is available to read.

If the IO device to is not 0, the content data of the response is written directly to the device. Make sure that the to pointer is valid for the duration of the operation (it is safe to delete it when the requestFinished() signal is emitted).

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

See also:
setHost() get() head() request() requestStarted() requestFinished() done()

Definition at line 1626 of file q3http.cpp.

References addRequest(), Q3NetworkProtocol::data(), header(), path, and Q3HttpPGHRequest.

01627 {
01628     Q3HttpRequestHeader header( "POST", path );
01629     header.setValue( "Connection", "Keep-Alive" );
01630     return addRequest( new Q3HttpPGHRequest( header, data, to ) );
01631 }

Here is the call graph for this function:

int Q3Http::post ( const QString path,
const QByteArray data,
QIODevice to = 0 
)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. data is used as the content data of the HTTP request.

Definition at line 1638 of file q3http.cpp.

References addRequest(), Q3NetworkProtocol::data(), header(), path, and Q3HttpPGHRequest.

01639 {
01640     Q3HttpRequestHeader header( "POST", path );
01641     header.setValue( "Connection", "Keep-Alive" );
01642     return addRequest( new Q3HttpPGHRequest( header, new QByteArray(data), to ) );
01643 }

Here is the call graph for this function:

int Q3Http::head ( const QString path  ) 

Sends a header request for path to the server set by setHost() or as specified in the constructor.

path must be an absolute path like /index.html or an absolute URI like http://www.trolltech.com/index.html.

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

See also:
setHost() get() post() request() requestStarted() requestFinished() done()

Definition at line 1663 of file q3http.cpp.

References addRequest(), header(), path, and Q3HttpPGHRequest.

01664 {
01665     Q3HttpRequestHeader header( "HEAD", path );
01666     header.setValue( "Connection", "Keep-Alive" );
01667     return addRequest( new Q3HttpPGHRequest( header, (QIODevice*)0, 0 ) );
01668 }

Here is the call graph for this function:

int Q3Http::request ( const Q3HttpRequestHeader header,
QIODevice data = 0,
QIODevice to = 0 
)

Sends a request to the server set by setHost() or as specified in the constructor. Uses the header as the HTTP request header. You are responsible for setting up a header that is appropriate for your request.

The incoming data comes via the data IO device.

If the IO device to is 0 the readyRead() signal is emitted every time new content data is available to read.

If the IO device to is not 0, the content data of the response is written directly to the device. Make sure that the to pointer is valid for the duration of the operation (it is safe to delete it when the requestFinished() signal is emitted).

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

See also:
setHost() get() post() head() requestStarted() requestFinished() done()

Definition at line 1697 of file q3http.cpp.

References addRequest(), Q3NetworkProtocol::data(), header(), and Q3HttpNormalRequest.

Referenced by operationGet(), and operationPut().

01698 {
01699     return addRequest( new Q3HttpNormalRequest( header, data, to ) );
01700 }

Here is the call graph for this function:

int Q3Http::request ( const Q3HttpRequestHeader header,
const QByteArray data,
QIODevice to = 0 
)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. data is used as the content data of the HTTP request.

Definition at line 1707 of file q3http.cpp.

References addRequest(), Q3NetworkProtocol::data(), header(), and Q3HttpNormalRequest.

01708 {
01709     return addRequest( new Q3HttpNormalRequest( header, new QByteArray(data), to ) );
01710 }

Here is the call graph for this function:

int Q3Http::closeConnection (  ) 

Closes the connection; this is useful if you have a keep-alive connection and want to close it.

For the requests issued with get(), post() and head(), Q3Http sets the connection to be keep-alive. You can also do this using the header you pass to the request() function. Q3Http only closes the connection to the HTTP server if the response header requires it to do so.

The function does not block and returns immediately. The request is scheduled, and its execution is performed asynchronously. The function returns a unique identifier which is passed by requestStarted() and requestFinished().

When the request is started the requestStarted() signal is emitted. When it is finished the requestFinished() signal is emitted.

If you want to close the connection immediately, you have to use abort() instead.

See also:
stateChanged() abort() requestStarted() requestFinished() done()

Definition at line 1736 of file q3http.cpp.

References addRequest(), and Q3HttpCloseRequest.

01737 {
01738     return addRequest( new Q3HttpCloseRequest() );
01739 }

Here is the call graph for this function:

Q_ULONG Q3Http::bytesAvailable (  )  const

Returns the number of bytes that can be read from the response content at the moment.

See also:
get() post() request() readyRead() readBlock() readAll()

Definition at line 1401 of file q3http.cpp.

References d, qDebug(), Q3HttpPrivate::rba, and Q3Membuf::size().

Referenced by clientReply(), readAll(), slotClosed(), slotReadyRead(), and startNextRequest().

01402 {
01403 #if defined(Q3HTTP_DEBUG)
01404     qDebug( "Q3Http::bytesAvailable(): %d bytes", (int)d->rba.size() );
01405 #endif
01406     return d->rba.size();
01407 }

Here is the call graph for this function:

Q_LONG Q3Http::readBlock ( char *  data,
Q_ULONG  maxlen 
)

Reads maxlen bytes from the response content into data and returns the number of bytes read. Returns -1 if an error occurred.

See also:
get() post() request() readyRead() bytesAvailable() readAll()

Definition at line 1415 of file q3http.cpp.

References Q3HttpPrivate::bytesDone, Q3Membuf::consumeBytes(), d, qDebug(), qWarning(), Q3HttpPrivate::rba, and Q3Membuf::size().

Referenced by readAll().

01416 {
01417     if ( data == 0 && maxlen != 0 ) {
01418 #if defined(QT_CHECK_NULL)
01419   qWarning( "Q3Http::readBlock: Null pointer error" );
01420 #endif
01421   return -1;
01422     }
01423     if ( maxlen >= (Q_ULONG)d->rba.size() )
01424   maxlen = d->rba.size();
01425     d->rba.consumeBytes( maxlen, data );
01426 
01427     d->bytesDone += maxlen;
01428 #if defined(Q3HTTP_DEBUG)
01429     qDebug( "Q3Http::readBlock(): read %d bytes (%d bytes done)", (int)maxlen, d->bytesDone );
01430 #endif
01431     return maxlen;
01432 }

Here is the call graph for this function:

QByteArray Q3Http::readAll (  ) 

Reads all the bytes from the response content and returns them.

See also:
get() post() request() readyRead() bytesAvailable() readBlock()

Definition at line 1439 of file q3http.cpp.

References bytesAvailable(), QByteArray::data(), readBlock(), and QByteArray::resize().

Referenced by clientReply(), and startNextRequest().

01440 {
01441     Q_ULONG avail = bytesAvailable();
01442     QByteArray tmp( avail );
01443     Q_LONG read = readBlock( tmp.data(), avail );
01444     tmp.resize( read );
01445     return tmp;
01446 }

Here is the call graph for this function:

int Q3Http::currentId (  )  const

Returns the identifier of the HTTP request being executed or 0 if there is no request being executed (i.e. they've all finished).

See also:
currentRequest()

Definition at line 1454 of file q3http.cpp.

References d, Q3PtrList< type >::getFirst(), Q3HttpRequest::id, and Q3HttpPrivate::pending.

01455 {
01456     Q3HttpRequest *r = d->pending.getFirst();
01457     if ( r == 0 )
01458   return 0;
01459     return r->id;
01460 }

Here is the call graph for this function:

QIODevice * Q3Http::currentSourceDevice (  )  const

Returns the QIODevice pointer that is used as the data source of the HTTP request being executed. If there is no current request or if the request does not use an IO device as the data source, this function returns 0.

This function can be used to delete the QIODevice in the slot connected to the requestFinished() signal.

See also:
currentDestinationDevice() post() request()

Definition at line 1488 of file q3http.cpp.

References d, Q3PtrList< type >::getFirst(), Q3HttpPrivate::pending, and Q3HttpRequest::sourceDevice().

01489 {
01490     Q3HttpRequest *r = d->pending.getFirst();
01491     if ( !r )
01492   return 0;
01493     return r->sourceDevice();
01494 }

Here is the call graph for this function:

QIODevice * Q3Http::currentDestinationDevice (  )  const

Returns the QIODevice pointer that is used as to store the data of the HTTP request being executed. If there is no current request or if the request does not store the data to an IO device, this function returns 0.

This function can be used to delete the QIODevice in the slot connected to the requestFinished() signal.

See also:
get() post() request()

Definition at line 1506 of file q3http.cpp.

References d, Q3HttpRequest::destinationDevice(), Q3PtrList< type >::getFirst(), and Q3HttpPrivate::pending.

01507 {
01508     Q3HttpRequest *r = d->pending.getFirst();
01509     if ( !r )
01510   return 0;
01511     return r->destinationDevice();
01512 }

Here is the call graph for this function:

Q3HttpRequestHeader Q3Http::currentRequest (  )  const

Returns the request header of the HTTP request being executed. If the request is one issued by setHost() or closeConnection(), it returns an invalid request header, i.e. Q3HttpRequestHeader::isValid() returns false.

See also:
currentId()

Definition at line 1470 of file q3http.cpp.

References d, Q3PtrList< type >::getFirst(), Q3HttpRequest::hasRequestHeader(), Q3HttpPrivate::pending, and Q3HttpRequest::requestHeader().

Referenced by slotReadyRead().

01471 {
01472     Q3HttpRequest *r = d->pending.getFirst();
01473     if ( r != 0 && r->hasRequestHeader() )
01474   return r->requestHeader();
01475     return Q3HttpRequestHeader();
01476 }

Here is the call graph for this function:

bool Q3Http::hasPendingRequests (  )  const

Returns true if there are any requests scheduled that have not yet been executed; otherwise returns false.

The request that is being executed is not considered as a scheduled request.

See also:
clearPendingRequests() currentId() currentRequest()

Definition at line 1523 of file q3http.cpp.

References Q3PtrList< type >::count(), d, and Q3HttpPrivate::pending.

01524 {
01525     return d->pending.count() > 1;
01526 }

Here is the call graph for this function:

void Q3Http::clearPendingRequests (  ) 

Deletes all pending requests from the list of scheduled requests. This does not affect the request that is being executed. If you want to stop this this as well, use abort().

See also:
hasPendingRequests() abort()

Definition at line 1535 of file q3http.cpp.

References Q3PtrList< type >::append(), Q3PtrList< type >::clear(), Q3PtrList< type >::count(), d, Q3HttpPrivate::pending, and Q3PtrList< type >::take().

Referenced by abort().

01536 {
01537     Q3HttpRequest *r = 0;
01538     if ( d->pending.count() > 0 )
01539   r = d->pending.take( 0 );
01540     d->pending.clear();
01541     if ( r )
01542   d->pending.append( r );
01543 }

Here is the call graph for this function:

Q3Http::State Q3Http::state (  )  const

Returns the current state of the object. When the state changes, the stateChanged() signal is emitted.

See also:
State stateChanged()

Definition at line 2099 of file q3http.cpp.

References d, and Q3HttpPrivate::state.

02100 {
02101     return d->state;
02102 }

Q3Http::Error Q3Http::error (  )  const

Returns the last error that occurred. This is useful to find out what happened when receiving a requestFinished() or a done() signal with the error argument true.

If you start a new request, the error status is reset to NoError.

Definition at line 2111 of file q3http.cpp.

References d, and Q3HttpPrivate::error.

Referenced by clientDone(), and init().

02112 {
02113     return d->error;
02114 }

QString Q3Http::errorString (  )  const

Returns a human-readable description of the last error that occurred. This is useful to present a error message to the user when receiving a requestFinished() or a done() signal with the error argument true.

Definition at line 2122 of file q3http.cpp.

References d, and Q3HttpPrivate::errorString.

Referenced by clientDone().

02123 {
02124     return d->errorString;
02125 }

void Q3Http::abort (  )  [slot]

Aborts the current request and deletes all scheduled requests.

For the current request, the requestFinished() signal with the error argument true is emitted. For all other requests that are affected by the abort(), no signals are emitted.

Since this slot also deletes the scheduled requests, there are no requests left and the done() signal is emitted (with the error argument true).

See also:
clearPendingRequests()

Definition at line 1383 of file q3http.cpp.

References Aborted, Q3Socket::clearPendingData(), clearPendingRequests(), close(), d, finishedWithError(), Q3PtrList< type >::getFirst(), Q3HttpPrivate::pending, and Q3HttpPrivate::socket.

Referenced by ~Q3Http().

01384 {
01385     Q3HttpRequest *r = d->pending.getFirst();
01386     if ( r == 0 )
01387   return;
01388 
01389     finishedWithError( QHttp::tr("Request aborted"), Aborted );
01390     clearPendingRequests();
01391     d->socket.clearPendingData();
01392     close();
01393 }

void Q3Http::stateChanged ( int  state  )  [signal]

This signal is emitted when the state of the Q3Http object changes. The argument state is the new state of the connection; it is one of the State values.

This usually happens when a request is started, but it can also happen when the server closes the connection or when a call to closeConnection() succeeded.

See also:
get() post() head() request() closeConnection() state() State

Referenced by clientDone(), operationGet(), operationPut(), and setState().

void Q3Http::responseHeaderReceived ( const Q3HttpResponseHeader resp  )  [signal]

This signal is emitted when the HTTP header of a server response is available. The header is passed in resp.

See also:
get() post() head() request() readyRead()

Referenced by slotReadyRead().

void Q3Http::readyRead ( const Q3HttpResponseHeader resp  )  [signal]

This signal is emitted when there is new response data to read.

If you specified a device in the request where the data should be written to, then this signal is not emitted; instead the data is written directly to the device.

The response header is passed in resp.

You can read the data with the readAll() or readBlock() functions

This signal is useful if you want to process the data in chunks as soon as it becomes available. If you are only interested in the complete data, just connect to the requestFinished() signal and read the data then instead.

See also:
get() post() request() readAll() readBlock() bytesAvailable()

Referenced by clientDone(), init(), operationGet(), operationPut(), and slotReadyRead().

void Q3Http::dataSendProgress ( int  done,
int  total 
) [signal]

This signal is emitted when this object sends data to a HTTP server to inform it about the progress of the upload.

done is the amount of data that has already arrived and total is the total amount of data. It is possible that the total amount of data that should be transferred cannot be determined, in which case total is 0.(If you connect to a QProgressBar, the progress bar shows a busy indicator if the total is 0).

Warning:
done and total are not necessarily the size in bytes, since for large files these values might need to be "scaled" to avoid overflow.
See also:
dataReadProgress() post() request() QProgressBar::setValue()

Referenced by slotBytesWritten().

void Q3Http::dataReadProgress ( int  done,
int  total 
) [signal]

This signal is emitted when this object reads data from a HTTP server to indicate the current progress of the download.

done is the amount of data that has already arrived and total is the total amount of data. It is possible that the total amount of data that should be transferred cannot be determined, in which case total is 0.(If you connect to a QProgressBar, the progress bar shows a busy indicator if the total is 0).

Warning:
done and total are not necessarily the size in bytes, since for large files these values might need to be "scaled" to avoid overflow.
See also:
dataSendProgress() get() post() request() QProgressBar::setValue()

Referenced by slotReadyRead().

void Q3Http::requestStarted ( int  id  )  [signal]

This signal is emitted when processing the request identified by id starts.

See also:
requestFinished() done()

Referenced by startNextRequest().

void Q3Http::requestFinished ( int  id,
bool  error 
) [signal]

This signal is emitted when processing the request identified by id has finished. error is true if an error occurred during the processing; otherwise error is false.

See also:
requestStarted() done() error() errorString()

Referenced by finishedWithError(), and finishedWithSuccess().

void Q3Http::done ( bool  error  )  [signal]

This signal is emitted when the last pending request has finished; (it is emitted after the last request's requestFinished() signal). error is true if an error occurred during the processing; otherwise error is false.

See also:
requestFinished() error() errorString()

Referenced by clientDone(), finishedWithError(), finishedWithSuccess(), operationGet(), and operationPut().

void Q3Http::operationGet ( Q3NetworkOperation op  )  [protected, virtual]

Reimplemented from Q3NetworkProtocol.

Definition at line 2200 of file q3http.cpp.

References bytesRead, clientDone(), clientReply(), clientStateChanged(), QObject::connect(), done(), header(), Q3NetworkProtocol::operationInProgress(), readyRead(), request(), setHost(), Q3NetworkOperation::setState(), SIGNAL, SLOT, stateChanged(), Q3NetworkProtocol::StInProgress, and u.

02201 {
02202     connect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),
02203       this, SLOT(clientReply(Q3HttpResponseHeader)) );
02204     connect( this, SIGNAL(done(bool)),
02205       this, SLOT(clientDone(bool)) );
02206     connect( this, SIGNAL(stateChanged(int)),
02207       this, SLOT(clientStateChanged(int)) );
02208 
02209     bytesRead = 0;
02210     op->setState( StInProgress );
02211     Q3Url u( operationInProgress()->arg( 0 ) );
02212     Q3HttpRequestHeader header( "GET", u.encodedPathAndQuery(), 1, 0 );
02213     header.setValue( "Host", u.host() );
02214     setHost( u.host(), u.port() != -1 ? u.port() : 80 );
02215     request( header );
02216 }

Here is the call graph for this function:

void Q3Http::operationPut ( Q3NetworkOperation op  )  [protected, virtual]

Reimplemented from Q3NetworkProtocol.

Definition at line 2220 of file q3http.cpp.

References bytesRead, clientDone(), clientReply(), clientStateChanged(), QObject::connect(), done(), header(), Q3NetworkProtocol::operationInProgress(), Q3NetworkOperation::rawArg(), readyRead(), request(), setHost(), Q3NetworkOperation::setState(), SIGNAL, SLOT, stateChanged(), Q3NetworkProtocol::StInProgress, and u.

02221 {
02222     connect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),
02223       this, SLOT(clientReply(Q3HttpResponseHeader)) );
02224     connect( this, SIGNAL(done(bool)),
02225       this, SLOT(clientDone(bool)) );
02226     connect( this, SIGNAL(stateChanged(int)),
02227       this, SLOT(clientStateChanged(int)) );
02228 
02229     bytesRead = 0;
02230     op->setState( StInProgress );
02231     Q3Url u( operationInProgress()->arg( 0 ) );
02232     Q3HttpRequestHeader header( "POST", u.encodedPathAndQuery(), 1, 0 );
02233     header.setValue( "Host", u.host() );
02234     setHost( u.host(), u.port() != -1 ? u.port() : 80 );
02235     request( header, op->rawArg(1) );
02236 }

Here is the call graph for this function:

void Q3Http::timerEvent ( QTimerEvent e  )  [protected, virtual]

Reimplemented from QObject.

Definition at line 2129 of file q3http.cpp.

References Connected, d, finishedWithSuccess(), Q3HttpPrivate::idleTimer, QObject::killTimer(), setState(), Q3HttpPrivate::state, QObject::timerEvent(), QTimerEvent::timerId(), and Unconnected.

02130 {
02131     if ( e->timerId() == d->idleTimer ) {
02132   killTimer( d->idleTimer );
02133   d->idleTimer = 0;
02134 
02135   if ( d->state == Connected ) {
02136       finishedWithSuccess();
02137   } else if ( d->state != Unconnected ) {
02138       setState( Unconnected );
02139       finishedWithSuccess();
02140   }
02141     } else {
02142   QObject::timerEvent( e );
02143     }
02144 }

Here is the call graph for this function:

void Q3Http::clientReply ( const Q3HttpResponseHeader rep  )  [private, slot]

Definition at line 2238 of file q3http.cpp.

References bytesAvailable(), bytesRead, Q3HttpHeader::contentLength(), Q3NetworkProtocol::data(), Q3NetworkProtocol::dataTransferProgress(), emit, Q3NetworkProtocol::ErrFileNotExisting, Q3NetworkProtocol::ErrGet, Q3NetworkProtocol::ErrPermissionDenied, Q3NetworkProtocol::ErrPut, Q3HttpHeader::hasContentLength(), Q3NetworkOperation::operation(), Q3NetworkProtocol::operationInProgress(), Q3NetworkProtocol::OpGet, readAll(), Q3HttpResponseHeader::reasonPhrase(), Q3NetworkOperation::setErrorCode(), Q3NetworkOperation::setProtocolDetail(), Q3NetworkOperation::setState(), Q3HttpResponseHeader::statusCode(), and Q3NetworkProtocol::StFailed.

Referenced by clientDone(), operationGet(), and operationPut().

02239 {
02240     Q3NetworkOperation *op = operationInProgress();
02241     if ( op ) {
02242   if ( rep.statusCode() >= 400 && rep.statusCode() < 600 ) {
02243       op->setState( StFailed );
02244       op->setProtocolDetail(
02245         QString("%1 %2").arg(rep.statusCode()).arg(rep.reasonPhrase())
02246                 );
02247       switch ( rep.statusCode() ) {
02248     case 401:
02249     case 403:
02250     case 405:
02251         op->setErrorCode( ErrPermissionDenied );
02252         break;
02253     case 404:
02254         op->setErrorCode(ErrFileNotExisting );
02255         break;
02256     default:
02257         if ( op->operation() == OpGet )
02258       op->setErrorCode( ErrGet );
02259         else
02260       op->setErrorCode( ErrPut );
02261         break;
02262       }
02263   }
02264   // ### In cases of an error, should we still emit the data() signals?
02265   if ( op->operation() == OpGet && bytesAvailable() > 0 ) {
02266       QByteArray ba = readAll();
02267       emit data( ba, op );
02268       bytesRead += ba.size();
02269       if ( rep.hasContentLength() ) {
02270     emit dataTransferProgress( bytesRead, rep.contentLength(), op );
02271       }
02272   }
02273     }
02274 }

void Q3Http::clientDone ( bool   )  [private, slot]

Definition at line 2276 of file q3http.cpp.

References clientReply(), clientStateChanged(), ConnectionRefused, QObject::disconnect(), done(), emit, Q3NetworkProtocol::ErrGet, Q3NetworkProtocol::ErrHostNotFound, error(), errorString(), Q3NetworkProtocol::ErrPut, Q3NetworkProtocol::finished(), HostNotFound, Q3NetworkProtocol::NoError, Q3NetworkOperation::operation(), Q3NetworkProtocol::operationInProgress(), Q3NetworkProtocol::OpGet, readyRead(), Q3NetworkOperation::setErrorCode(), Q3NetworkOperation::setProtocolDetail(), Q3NetworkOperation::setState(), SIGNAL, SLOT, Q3NetworkOperation::state(), stateChanged(), Q3NetworkProtocol::StDone, and Q3NetworkProtocol::StFailed.

Referenced by operationGet(), and operationPut().

02277 {
02278     disconnect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),
02279       this, SLOT(clientReply(Q3HttpResponseHeader)) );
02280     disconnect( this, SIGNAL(done(bool)),
02281       this, SLOT(clientDone(bool)) );
02282     disconnect( this, SIGNAL(stateChanged(int)),
02283       this, SLOT(clientStateChanged(int)) );
02284 
02285     if ( err ) {
02286   Q3NetworkOperation *op = operationInProgress();
02287   if ( op ) {
02288       op->setState( Q3NetworkProtocol::StFailed );
02289       op->setProtocolDetail( errorString() );
02290       switch ( error() ) {
02291     case ConnectionRefused:
02292         op->setErrorCode( ErrHostNotFound );
02293         break;
02294     case HostNotFound:
02295         op->setErrorCode( ErrHostNotFound );
02296         break;
02297     default:
02298         if ( op->operation() == OpGet )
02299       op->setErrorCode( ErrGet );
02300         else
02301       op->setErrorCode( ErrPut );
02302         break;
02303       }
02304       emit finished( op );
02305   }
02306     } else {
02307   Q3NetworkOperation *op = operationInProgress();
02308   if ( op ) {
02309       if ( op->state() != StFailed ) {
02310     op->setState( Q3NetworkProtocol::StDone );
02311     op->setErrorCode( Q3NetworkProtocol::NoError );
02312       }
02313       emit finished( op );
02314   }
02315     }
02316 
02317 }

void Q3Http::clientStateChanged ( int   )  [private, slot]

Definition at line 2319 of file q3http.cpp.

References Q3NetworkProtocol::ConClosed, Q3NetworkProtocol::ConConnected, Q3NetworkProtocol::ConHostFound, Connecting, Q3NetworkProtocol::connectionStateChanged(), emit, Sending, Unconnected, and Q3NetworkProtocol::url().

Referenced by clientDone(), operationGet(), and operationPut().

02320 {
02321     if ( url() ) {
02322   switch ( (State)state ) {
02323       case Connecting:
02324     emit connectionStateChanged( ConHostFound, QHttp::tr( "Host %1 found" ).arg( url()->host() ) );
02325     break;
02326       case Sending:
02327     emit connectionStateChanged( ConConnected, QHttp::tr( "Connected to host %1" ).arg( url()->host() ) );
02328     break;
02329       case Unconnected:
02330     emit connectionStateChanged( ConClosed, QHttp::tr( "Connection to %1 closed" ).arg( url()->host() ) );
02331     break;
02332       default:
02333     break;
02334   }
02335     } else {
02336   switch ( (State)state ) {
02337       case Connecting:
02338     emit connectionStateChanged( ConHostFound, QHttp::tr( "Host found" ) );
02339     break;
02340       case Sending:
02341     emit connectionStateChanged( ConConnected, QHttp::tr( "Connected to host" ) );
02342     break;
02343       case Unconnected:
02344     emit connectionStateChanged( ConClosed, QHttp::tr( "Connection closed" ) );
02345     break;
02346       default:
02347     break;
02348   }
02349     }
02350 }

void Q3Http::startNextRequest (  )  [private, slot]

Definition at line 1752 of file q3http.cpp.

References bytesAvailable(), d, emit, Q3HttpPrivate::error, Q3HttpPrivate::errorString, Q3PtrList< type >::getFirst(), Q3HttpRequest::id, NoError, Q3HttpPrivate::pending, readAll(), requestStarted(), and Q3HttpRequest::start().

Referenced by addRequest(), and finishedWithSuccess().

01753 {
01754     Q3HttpRequest *r = d->pending.getFirst();
01755     if ( r == 0 )
01756   return;
01757 
01758     d->error = NoError;
01759     d->errorString = QHttp::tr( "Unknown error" );
01760 
01761     if ( bytesAvailable() )
01762   readAll(); // clear the data
01763     emit requestStarted( r->id );
01764     r->start( this );
01765 }

void Q3Http::slotReadyRead (  )  [private, slot]

Definition at line 1908 of file q3http.cpp.

References Q3Membuf::append(), Q3HttpPrivate::buffer, bytesAvailable(), Q3Socket::bytesAvailable(), Q3HttpPrivate::bytesDone, Q3Socket::canReadLine(), Q3HttpPrivate::chunkedSize, close(), Connected, QString::contains(), Q3HttpHeader::contentLength(), currentRequest(), d, QByteArray::data(), dataReadProgress(), emit, finishedWithError(), Q3HttpHeader::hasContentLength(), Q3HttpHeader::hasKey(), Q3HttpPrivate::headerStr, Q3HttpPrivate::idleTimer, InvalidResponseHeader, Q3HttpHeader::isValid(), method, n, qDebug(), Q3HttpPrivate::rba, QIODevice::readAll(), Q3HttpPrivate::readHeader, Reading, QIODevice::readLine(), readyRead(), QByteArray::resize(), Q3HttpPrivate::response, responseHeaderReceived(), setState(), QByteArray::size(), Q3HttpPrivate::socket, QObject::startTimer(), Q3HttpPrivate::state, Q3HttpResponseHeader::statusCode(), Q3HttpPrivate::toDevice, QString::toInt(), Q3HttpResponseHeader::toString(), QString::truncate(), Q3HttpHeader::value(), and WrongContentLength.

Referenced by init().

01909 {
01910     if ( d->state != Reading ) {
01911   setState( Reading );
01912   d->buffer = QByteArray();
01913   d->readHeader = true;
01914   d->headerStr = "";
01915   d->bytesDone = 0;
01916   d->chunkedSize = -1;
01917     }
01918 
01919     while ( d->readHeader ) {
01920   bool end = false;
01921   QString tmp;
01922   while ( !end && d->socket.canReadLine() ) {
01923       tmp = d->socket.readLine();
01924       if ( tmp == "\r\n" || tmp == "\n" )
01925     end = true;
01926       else
01927     d->headerStr += tmp;
01928   }
01929 
01930   if ( !end )
01931       return;
01932 
01933 #if defined(Q3HTTP_DEBUG)
01934   qDebug( "Q3Http: read response header:\n---{\n%s}---", d->headerStr.latin1() );
01935 #endif
01936   d->response = Q3HttpResponseHeader( d->headerStr );
01937   d->headerStr = "";
01938 #if defined(Q3HTTP_DEBUG)
01939   qDebug( "Q3Http: read response header:\n---{\n%s}---", d->response.toString().latin1() );
01940 #endif
01941   // Check header
01942   if ( !d->response.isValid() ) {
01943       finishedWithError( QHttp::tr("Invalid HTTP response header"), InvalidResponseHeader );
01944       close();
01945       return;
01946   }
01947 
01948   // The 100-continue header is ignored, because when using the
01949   // POST method, we send both the request header and data in
01950   // one chunk.
01951   if (d->response.statusCode() != 100) {
01952       d->readHeader = false;
01953       if ( d->response.hasKey( "transfer-encoding" ) &&
01954      d->response.value( "transfer-encoding" ).lower().contains( "chunked" ) )
01955     d->chunkedSize = 0;
01956 
01957       emit responseHeaderReceived( d->response );
01958   }
01959     }
01960 
01961     if ( !d->readHeader ) {
01962   bool everythingRead = false;
01963 
01964   if ( currentRequest().method() == "HEAD" ) {
01965       everythingRead = true;
01966   } else {
01967       Q_ULONG n = d->socket.bytesAvailable();
01968       QByteArray *arr = 0;
01969       if ( d->chunkedSize != -1 ) {
01970     // transfer-encoding is chunked
01971     for ( ;; ) {
01972         // get chunk size
01973         if ( d->chunkedSize == 0 ) {
01974       if ( !d->socket.canReadLine() )
01975           break;
01976       QString sizeString = d->socket.readLine();
01977       int tPos = sizeString.find( ';' );
01978       if ( tPos != -1 )
01979           sizeString.truncate( tPos );
01980       bool ok;
01981       d->chunkedSize = sizeString.toInt( &ok, 16 );
01982       if ( !ok ) {
01983           finishedWithError( QHttp::tr("Invalid HTTP chunked body"), WrongContentLength );
01984           close();
01985                             delete arr;
01986           return;
01987       }
01988       if ( d->chunkedSize == 0 ) // last-chunk
01989           d->chunkedSize = -2;
01990         }
01991 
01992         // read trailer
01993         while ( d->chunkedSize == -2 && d->socket.canReadLine() ) {
01994       QString read = d->socket.readLine();
01995       if ( read == "\r\n" || read == "\n" )
01996           d->chunkedSize = -1;
01997         }
01998         if ( d->chunkedSize == -1 ) {
01999       everythingRead = true;
02000       break;
02001         }
02002 
02003         // make sure that you can read the terminating CRLF,
02004         // otherwise wait until next time...
02005         n = d->socket.bytesAvailable();
02006         if ( n == 0 )
02007       break;
02008         if ( (Q_LONG)n == d->chunkedSize || (Q_LONG)n == d->chunkedSize+1 ) {
02009       n = d->chunkedSize - 1;
02010       if ( n == 0 )
02011           break;
02012         }
02013 
02014         // read data
02015         uint toRead = QMIN( (Q_LONG)n, (d->chunkedSize < 0 ? (Q_LONG)n : d->chunkedSize) );
02016         if ( !arr )
02017       arr = new QByteArray( 0 );
02018         uint oldArrSize = arr->size();
02019         arr->resize( oldArrSize + toRead );
02020         Q_LONG read = d->socket.readBlock( arr->data()+oldArrSize, toRead );
02021         arr->resize( oldArrSize + read );
02022 
02023         d->chunkedSize -= read;
02024 
02025         if ( d->chunkedSize == 0 && n - read >= 2 ) {
02026       // read terminating CRLF
02027       char tmp[2];
02028       d->socket.readBlock( tmp, 2 );
02029       if ( tmp[0] != '\r' || tmp[1] != '\n' ) {
02030           finishedWithError( QHttp::tr("Invalid HTTP chunked body"), WrongContentLength );
02031           close();
02032                             delete arr;
02033           return;
02034       }
02035         }
02036     }
02037       } else if ( d->response.hasContentLength() ) {
02038     n = qMin<ulong>( d->response.contentLength() - d->bytesDone, n );
02039     if ( n > 0 ) {
02040         arr = new QByteArray( n );
02041         Q_LONG read = d->socket.readBlock( arr->data(), n );
02042         arr->resize( read );
02043     }
02044     if ( d->bytesDone + bytesAvailable() + n == d->response.contentLength() )
02045         everythingRead = true;
02046       } else if ( n > 0 ) {
02047     // workaround for VC++ bug
02048     QByteArray temp = d->socket.readAll();
02049     arr = new QByteArray( temp );
02050       }
02051 
02052       if ( arr ) {
02053     n = arr->size();
02054     if ( d->toDevice ) {
02055         d->toDevice->writeBlock( arr->data(), n );
02056         delete arr;
02057         d->bytesDone += n;
02058 #if defined(Q3HTTP_DEBUG)
02059         qDebug( "Q3Http::slotReadyRead(): read %ld bytes (%d bytes done)", n, d->bytesDone );
02060 #endif
02061         if ( d->response.hasContentLength() )
02062       emit dataReadProgress( d->bytesDone, d->response.contentLength() );
02063         else
02064       emit dataReadProgress( d->bytesDone, 0 );
02065     } else {
02066         d->rba.append( arr );
02067 #if defined(Q3HTTP_DEBUG)
02068         qDebug( "Q3Http::slotReadyRead(): read %ld bytes (%ld bytes done)", n, d->bytesDone + bytesAvailable() );
02069 #endif
02070         if ( d->response.hasContentLength() )
02071       emit dataReadProgress( d->bytesDone + bytesAvailable(), d->response.contentLength() );
02072         else
02073       emit dataReadProgress( d->bytesDone + bytesAvailable(), 0 );
02074         emit readyRead( d->response );
02075     }
02076       }
02077   }
02078 
02079   if ( everythingRead ) {
02080       // Handle "Connection: close"
02081       if ( d->response.value("connection").lower() == "close" ) {
02082     close();
02083       } else {
02084     setState( Connected );
02085     // Start a timer, so that we emit the keep alive signal
02086     // "after" this method returned.
02087     d->idleTimer = startTimer( 0 );
02088       }
02089   }
02090     }
02091 }

void Q3Http::slotConnected (  )  [private, slot]

Definition at line 1838 of file q3http.cpp.

References Q3HttpPrivate::buffer, Q3HttpPrivate::bytesDone, Q3HttpPrivate::bytesTotal, d, QByteArray::data(), Q3HttpPrivate::header, QString::length(), Q3HttpPrivate::postDevice, qDebug(), Sending, setState(), QByteArray::size(), QIODevice::size(), Q3HttpPrivate::socket, Q3HttpPrivate::state, and Q3HttpRequestHeader::toString().

Referenced by init(), and sendRequest().

01839 {
01840     if ( d->state != Sending ) {
01841   d->bytesDone = 0;
01842   setState( Sending );
01843     }
01844 
01845     QString str = d->header.toString();
01846     d->bytesTotal = str.length();
01847     d->socket.writeBlock( str.latin1(), d->bytesTotal );
01848 #if defined(Q3HTTP_DEBUG)
01849     qDebug( "Q3Http: write request header:\n---{\n%s}---", str.latin1() );
01850 #endif
01851 
01852     if ( d->postDevice ) {
01853   d->bytesTotal += d->postDevice->size();
01854     } else {
01855   d->bytesTotal += d->buffer.size();
01856   d->socket.writeBlock( d->buffer.data(), d->buffer.size() );
01857   d->buffer = QByteArray(); // save memory
01858     }
01859 }

void Q3Http::slotError ( int   )  [private, slot]

Definition at line 1861 of file q3http.cpp.

References close(), Connecting, ConnectionRefused, d, Q3Socket::ErrConnectionRefused, Q3Socket::ErrHostNotFound, finishedWithError(), HostNotFound, Q3Socket::peerName(), Q3HttpPrivate::postDevice, Reading, Sending, Q3HttpPrivate::socket, Q3HttpPrivate::state, and UnknownError.

Referenced by init().

01862 {
01863     d->postDevice = 0;
01864 
01865     if ( d->state == Connecting || d->state == Reading || d->state == Sending ) {
01866   switch ( err ) {
01867       case Q3Socket::ErrConnectionRefused:
01868     finishedWithError( QHttp::tr("Connection refused"), ConnectionRefused );
01869     break;
01870       case Q3Socket::ErrHostNotFound:
01871     finishedWithError( QHttp::tr("Host %1 not found").arg(d->socket.peerName()), HostNotFound );
01872     break;
01873       default:
01874     finishedWithError( QHttp::tr("HTTP request failed"), UnknownError );
01875     break;
01876   }
01877     }
01878 
01879     close();
01880 }

void Q3Http::slotClosed (  )  [private, slot]

Definition at line 1817 of file q3http.cpp.

References bytesAvailable(), Q3HttpPrivate::bytesDone, Closing, Connecting, Q3HttpHeader::contentLength(), d, finishedWithError(), Q3HttpHeader::hasKey(), Q3HttpPrivate::idleTimer, Q3HttpPrivate::postDevice, Reading, Q3HttpPrivate::response, Sending, setState(), QObject::startTimer(), Q3HttpPrivate::state, UnexpectedClose, and WrongContentLength.

Referenced by init().

01818 {
01819     if ( d->state == Closing )
01820   return;
01821 
01822     if ( d->state == Reading ) {
01823   if ( d->response.hasKey( "content-length" ) ) {
01824       // We got Content-Length, so did we get all bytes?
01825       if ( d->bytesDone+bytesAvailable() != d->response.contentLength() ) {
01826     finishedWithError( QHttp::tr("Wrong content length"), WrongContentLength );
01827       }
01828   }
01829     } else if ( d->state == Connecting || d->state == Sending ) {
01830   finishedWithError( QHttp::tr("Server closed connection unexpectedly"), UnexpectedClose );
01831     }
01832 
01833     d->postDevice = 0;
01834     setState( Closing );
01835     d->idleTimer = startTimer( 0 );
01836 }

void Q3Http::slotBytesWritten ( int   )  [private, slot]

Definition at line 1882 of file q3http.cpp.

References QIODevice::atEnd(), Q3HttpPrivate::bytesDone, Q3HttpPrivate::bytesTotal, Q3Socket::bytesToWrite(), close(), d, QByteArray::data(), dataSendProgress(), emit, n, Q3HttpPrivate::postDevice, qWarning(), QIODevice::size(), and Q3HttpPrivate::socket.

Referenced by init().

01883 {
01884     d->bytesDone += written;
01885     emit dataSendProgress( d->bytesDone, d->bytesTotal );
01886 
01887     if ( !d->postDevice )
01888   return;
01889 
01890     if ( d->socket.bytesToWrite() == 0 ) {
01891   int max = qMin<int>( 4096, d->postDevice->size() - d->postDevice->at() );
01892   QByteArray arr( max );
01893 
01894   int n = d->postDevice->readBlock( arr.data(), max );
01895   if ( n != max ) {
01896       qWarning("Could not read enough bytes from the device");
01897       close();
01898       return;
01899   }
01900   if ( d->postDevice->atEnd() ) {
01901       d->postDevice = 0;
01902   }
01903 
01904   d->socket.writeBlock( arr.data(), max );
01905     }
01906 }

int Q3Http::addRequest ( Q3HttpRequest  )  [private]

Definition at line 1741 of file q3http.cpp.

References Q3PtrList< type >::append(), Q3PtrList< type >::count(), d, Q3HttpRequest::id, Q3HttpPrivate::pending, QTimer::singleShot(), SLOT, and startNextRequest().

Referenced by closeConnection(), get(), head(), post(), request(), and setHost().

01742 {
01743     d->pending.append( req );
01744 
01745     if ( d->pending.count() == 1 )
01746   // don't emit the requestStarted() signal before the id is returned
01747   QTimer::singleShot( 0, this, SLOT(startNextRequest()) );
01748 
01749     return req->id;
01750 }

Here is the call graph for this function:

void Q3Http::sendRequest (  )  [private]

Definition at line 1767 of file q3http.cpp.

References Connecting, Q3Socket::Connection, Q3Socket::connectToHost(), d, finishedWithError(), Q3HttpPrivate::hostname, QString::isNull(), killIdleTimer(), Q3Socket::peerName(), Q3Socket::peerPort(), Q3HttpPrivate::port, setState(), slotConnected(), Q3HttpPrivate::socket, Q3Socket::state(), and UnknownError.

Referenced by Q3HttpNormalRequest::start().

01768 {
01769     if ( d->hostname.isNull() ) {
01770   finishedWithError( QHttp::tr("No server set to connect to"), UnknownError );
01771   return;
01772     }
01773 
01774     killIdleTimer();
01775 
01776     // Do we need to setup a new connection or can we reuse an
01777     // existing one ?
01778     if ( d->socket.peerName() != d->hostname || d->socket.peerPort() != d->port
01779         || d->socket.state() != Q3Socket::Connection ) {
01780   setState( Q3Http::Connecting );
01781   d->socket.connectToHost( d->hostname, d->port );
01782     } else {
01783         slotConnected();
01784     }
01785 
01786 }

Here is the call graph for this function:

void Q3Http::finishedWithSuccess (  )  [private]

Definition at line 1788 of file q3http.cpp.

References d, done(), emit, Q3PtrList< type >::getFirst(), Q3HttpRequest::id, Q3PtrList< type >::isEmpty(), Q3HttpPrivate::pending, Q3PtrList< type >::removeFirst(), requestFinished(), and startNextRequest().

Referenced by Q3HttpSetHostRequest::start(), and timerEvent().

01789 {
01790     Q3HttpRequest *r = d->pending.getFirst();
01791     if ( r == 0 )
01792   return;
01793 
01794     emit requestFinished( r->id, false );
01795     d->pending.removeFirst();
01796     if ( d->pending.isEmpty() ) {
01797   emit done( false );
01798     } else {
01799   startNextRequest();
01800     }
01801 }

Here is the call graph for this function:

void Q3Http::finishedWithError ( const QString detail,
int  errorCode 
) [private]

Definition at line 1803 of file q3http.cpp.

References Q3PtrList< type >::clear(), d, done(), emit, Q3HttpPrivate::error, Q3HttpPrivate::errorString, Q3PtrList< type >::getFirst(), Q3HttpRequest::id, Q3HttpPrivate::pending, and requestFinished().

Referenced by abort(), sendRequest(), slotClosed(), slotError(), and slotReadyRead().

01804 {
01805     Q3HttpRequest *r = d->pending.getFirst();
01806     if ( r == 0 )
01807   return;
01808 
01809     d->error = (Error)errorCode;
01810     d->errorString = detail;
01811     emit requestFinished( r->id, true );
01812 
01813     d->pending.clear();
01814     emit done( true );
01815 }

Here is the call graph for this function:

void Q3Http::killIdleTimer (  )  [private]

Definition at line 2146 of file q3http.cpp.

References d, Q3HttpPrivate::idleTimer, and QObject::killTimer().

Referenced by sendRequest().

02147 {
02148     if (d->idleTimer)
02149         killTimer( d->idleTimer );
02150     d->idleTimer = 0;
02151 }

Here is the call graph for this function:

void Q3Http::init (  )  [private]

Definition at line 1188 of file q3http.cpp.

References bytesRead, QObject::connect(), d, error(), Q3HttpPrivate::errorString, Q3HttpPrivate::idleTimer, readyRead(), SIGNAL, SLOT, slotBytesWritten(), slotClosed(), slotConnected(), slotError(), slotReadyRead(), Q3HttpPrivate::socket, and QObject::startTimer().

Referenced by Q3Http().

01189 {
01190     bytesRead = 0;
01191     d = new Q3HttpPrivate;
01192     d->errorString = QHttp::tr( "Unknown error" );
01193 
01194     connect( &d->socket, SIGNAL(connected()),
01195       this, SLOT(slotConnected()) );
01196     connect( &d->socket, SIGNAL(connectionClosed()),
01197       this, SLOT(slotClosed()) );
01198     connect( &d->socket, SIGNAL(delayedCloseFinished()),
01199       this, SLOT(slotClosed()) );
01200     connect( &d->socket, SIGNAL(readyRead()),
01201       this, SLOT(slotReadyRead()) );
01202     connect( &d->socket, SIGNAL(error(int)),
01203       this, SLOT(slotError(int)) );
01204     connect( &d->socket, SIGNAL(bytesWritten(int)),
01205       this, SLOT(slotBytesWritten(int)) );
01206 
01207     d->idleTimer = startTimer( 0 );
01208 }

Here is the call graph for this function:

void Q3Http::setState ( int   )  [private]

Definition at line 2153 of file q3http.cpp.

References d, emit, qDebug(), Q3HttpPrivate::state, and stateChanged().

Referenced by close(), sendRequest(), slotClosed(), slotConnected(), slotReadyRead(), and timerEvent().

02154 {
02155 #if defined(Q3HTTP_DEBUG)
02156     qDebug( "Q3Http state changed %d -> %d", d->state, s );
02157 #endif
02158     d->state = (State)s;
02159     emit stateChanged( s );
02160 }

Here is the call graph for this function:

void Q3Http::close (  )  [private]

Definition at line 2162 of file q3http.cpp.

References Q3Socket::close(), Closing, d, Q3Socket::Idle, Q3HttpPrivate::idleTimer, QIODevice::isOpen(), Q3HttpPrivate::postDevice, setState(), Q3HttpPrivate::socket, QObject::startTimer(), Q3Socket::state(), Q3HttpPrivate::state, and Unconnected.

Referenced by abort(), slotBytesWritten(), slotError(), slotReadyRead(), and Q3HttpCloseRequest::start().

02163 {
02164     // If no connection is open -> ignore
02165     if ( d->state == Closing || d->state == Unconnected )
02166   return;
02167 
02168     d->postDevice = 0;
02169     setState( Closing );
02170 
02171     // Already closed ?
02172     if ( !d->socket.isOpen() ) {
02173   d->idleTimer = startTimer( 0 );
02174     } else {
02175   // Close now.
02176   d->socket.close();
02177 
02178   // Did close succeed immediately ?
02179   if ( d->socket.state() == Q3Socket::Idle ) {
02180       // Prepare to emit the requestFinished() signal.
02181       d->idleTimer = startTimer( 0 );
02182   }
02183     }
02184 }

Here is the call graph for this function:


Friends And Related Function Documentation

friend class Q3HttpNormalRequest [friend]

Definition at line 246 of file q3http.h.

Referenced by request().

friend class Q3HttpSetHostRequest [friend]

Definition at line 247 of file q3http.h.

Referenced by setHost().

friend class Q3HttpCloseRequest [friend]

Definition at line 248 of file q3http.h.

Referenced by closeConnection().

friend class Q3HttpPGHRequest [friend]

Definition at line 249 of file q3http.h.

Referenced by get(), head(), and post().


Member Data Documentation

Q3HttpPrivate* Q3Http::d [private]

Reimplemented from Q3NetworkProtocol.

Definition at line 231 of file q3http.h.

Referenced by abort(), addRequest(), bytesAvailable(), clearPendingRequests(), close(), currentDestinationDevice(), currentId(), currentRequest(), currentSourceDevice(), error(), errorString(), finishedWithError(), finishedWithSuccess(), hasPendingRequests(), init(), killIdleTimer(), Q3Http(), readBlock(), sendRequest(), setState(), slotBytesWritten(), slotClosed(), slotConnected(), slotError(), slotReadyRead(), Q3HttpNormalRequest::start(), Q3HttpSetHostRequest::start(), Q3HttpPGHRequest::start(), startNextRequest(), state(), timerEvent(), and ~Q3Http().

void* Q3Http::unused [private]

Definition at line 232 of file q3http.h.

int Q3Http::bytesRead [private]

Definition at line 233 of file q3http.h.

Referenced by clientReply(), init(), operationGet(), and operationPut().


The documentation for this class was generated from the following files:
Generated on Thu Mar 15 16:01:28 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1