kopete/protocols/messenger/libpapillon
httpcoreprotocol.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "Papillon/Http/CoreProtocol"
00019
00020
00021 #include <QtDebug>
00022 #include <QtCore/QDataStream>
00023 #include <QtCore/QTextStream>
00024 #include <QtCore/QLatin1String>
00025 #include <QtCore/QStringList>
00026 #include <QtNetwork/QHttpResponseHeader>
00027
00028
00029 #include "Papillon/Http/Transfer"
00030
00031 namespace Papillon
00032 {
00033
00034 class HttpCoreProtocol::Private
00035 {
00036 public:
00037 Private()
00038 : inTransfer(0), state(HttpCoreProtocol::NoData)
00039 {}
00040
00041
00042 QByteArray in;
00043
00044 HttpTransfer *inTransfer;
00045
00046 HttpCoreProtocol::State state;
00047
00048 int contentLength;
00049 };
00050
00051 HttpCoreProtocol::HttpCoreProtocol() : QObject(), d(new Private)
00052 {}
00053
00054 HttpCoreProtocol::~HttpCoreProtocol()
00055 {
00056 delete d;
00057 }
00058
00059 int HttpCoreProtocol::state()
00060 {
00061 return (int)d->state;
00062 }
00063
00064 void HttpCoreProtocol::addIncomingData(const QByteArray &incomingBytes )
00065 {
00066
00067 d->in += incomingBytes;
00068
00069
00070 int parsedBytes = 0;
00071 int transferCount = 0;
00072
00073 while ( d->in.size() && ( parsedBytes = rawToTransfer( d->in ) ) )
00074 {
00075 transferCount++;
00076 int size = d->in.size();
00077 if ( parsedBytes < size )
00078 {
00079
00080 d->in = d->in.right( size - parsedBytes );
00081 }
00082 else
00083 {
00084 d->in.clear();
00085 }
00086 }
00087
00088 }
00089
00090 HttpTransfer *HttpCoreProtocol::incomingTransfer()
00091 {
00092 if ( d->state == Available )
00093 {
00094 d->state = NoData;
00095 return d->inTransfer;
00096 }
00097 else
00098 {
00099 return 0;
00100 }
00101 }
00102
00103 void HttpCoreProtocol::outgoingTransfer(HttpTransfer *outgoing)
00104 {
00105 emit outgoingData( outgoing->toRawCommand() );
00106
00107 delete outgoing;
00108 }
00109
00110 int HttpCoreProtocol::rawToTransfer(const QByteArray &raw)
00111 {
00112 uint bytesParsed = 0;
00113
00114 if ( raw.size() < 4 )
00115 {
00116 d->state = NeedMore;
00117 return bytesParsed;
00118 }
00119
00120 QByteArray tempRaw = raw;
00121 QDataStream din( &tempRaw, QIODevice::ReadOnly );
00122
00123
00124 if ( okToProceed( din ) )
00125 {
00126 if(d->state == NoData)
00127 {
00128 int endHeaderPos = tempRaw.lastIndexOf("\r\n\r\n");
00129 if(endHeaderPos != -1)
00130 {
00131
00132 endHeaderPos += 4;
00133 }
00134 else
00135 {
00136 qDebug() << Q_FUNC_INFO << "End of HTTP header wasn't found.";
00137 d->state = NeedMore;
00138 return bytesParsed;
00139 }
00140
00141
00142 QByteArray rawHttpHeader = tempRaw.left(endHeaderPos);
00143 QString httpHeader(rawHttpHeader);
00144
00145
00146
00147 QHttpResponseHeader responseHeader(httpHeader);
00148 d->inTransfer = new HttpTransfer(HttpTransfer::HttpResponse);
00149 d->inTransfer->setHttpHeader(responseHeader);
00150
00151
00152 if( responseHeader.hasContentLength() )
00153 {
00154 d->state = WaitForContent;
00155 d->contentLength = responseHeader.contentLength();
00156
00157 qDebug() << Q_FUNC_INFO << "Begin content transfer. Length:" << d->contentLength << "State:" << (int)d->state;
00158 }
00159
00160 else
00161 {
00162 d->state = Available;
00163 qDebug() << Q_FUNC_INFO << d->inTransfer->toRawCommand();
00164 emit incomingData();
00165 }
00166
00167 bytesParsed = rawHttpHeader.size();
00168 }
00169 else if(d->state == WaitForContent || d->state == NeedMore)
00170 {
00171 if(raw.size() < d->contentLength)
00172 {
00173 qDebug() << Q_FUNC_INFO << "Raw size:" << raw.size() << "Content length:" << d->contentLength;
00174 d->state = NeedMore;
00175 return bytesParsed;
00176 }
00177
00178
00179 QByteArray bodyData = tempRaw.left(d->contentLength);
00180
00181 d->inTransfer->setBody(bodyData);
00182 qDebug() << Q_FUNC_INFO << "Byte data length:" << bodyData.size();
00183
00184
00185 qDebug() << Q_FUNC_INFO << d->inTransfer->toRawCommand();
00186 d->state = Available;
00187 emit incomingData();
00188
00189 bytesParsed = bodyData.length();
00190 }
00191 }
00192 return bytesParsed;
00193 }
00194
00195 void HttpCoreProtocol::reset()
00196 {
00197 d->in.clear();
00198 }
00199
00200 bool HttpCoreProtocol::okToProceed(const QDataStream &din)
00201 {
00202 if( din.atEnd() )
00203 {
00204 d->state = NeedMore;
00205 return false;
00206 }
00207 else
00208 return true;
00209 }
00210
00211 }
00212
00213 #include "httpcoreprotocol.moc"
00214