• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

kopete/protocols/messenger/libpapillon

httpcoreprotocol.cpp

Go to the documentation of this file.
00001 /*
00002    messengercoreprotocol.cpp - Messenger core protocol for Papillon 
00003 
00004    Copyright (c) 2006 by Michaƫl Larouche <larouche@kde.org>
00005 
00006    Based on code copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
00007    Based on Iris, Copyright (C) 2003  Justin Karneges
00008 
00009    *************************************************************************
00010    *                                                                       *
00011    * This library is free software; you can redistribute it and/or         *
00012    * modify it under the terms of the GNU Lesser General Public            *
00013    * License as published by the Free Software Foundation; either          *
00014    * version 2 of the License, or (at your option) any later version.      *
00015    *                                                                       *
00016    *************************************************************************
00017 */
00018 #include "Papillon/Http/CoreProtocol"
00019 
00020 // Qt includes
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 // Papillon includes
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     // buffer containing unprocessed bytes we received
00042     QByteArray in;
00043     // the transfer that is being received
00044     HttpTransfer *inTransfer;
00045     // represents the protocol's overall state
00046     HttpCoreProtocol::State state;
00047     // Represend the length of payload data to read.
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     // Append incoming bytes to incoming buffer
00067     d->in += incomingBytes;
00068 
00069     // convert every event in the chunk to a Transfer, signalling it back to the clientstream
00070     int parsedBytes = 0;
00071     int transferCount = 0;
00072     // while there is data left in the input buffer, and we are able to parse something out of it
00073     while ( d->in.size() && ( parsedBytes = rawToTransfer( d->in ) ) )
00074     {
00075         transferCount++;
00076         int size =  d->in.size();
00077         if ( parsedBytes < size )
00078         {
00079             // Remove the parsed bytes and keep the old ones.
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     // Clear the transfer.
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     // look at first four bytes and decide what to do with the chunk
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                 // lastIndexOf return the index before the 2 \r\n\r\n, so we add their size manually.
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             // Strip to get only the raw header.
00142             QByteArray rawHttpHeader = tempRaw.left(endHeaderPos);
00143             QString httpHeader(rawHttpHeader);
00144 //          qDebug() << Q_FUNC_INFO << "HTTP header: " << httpHeader;
00145             
00146             // Parse HTTP header
00147             QHttpResponseHeader responseHeader(httpHeader);
00148             d->inTransfer = new HttpTransfer(HttpTransfer::HttpResponse);
00149             d->inTransfer->setHttpHeader(responseHeader);
00150             
00151             // The transfer has a body, get the body.
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             // This transfer has no body, so we are available.
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             // Retrieve the full content data from raw data (do a shared copy)
00179             QByteArray bodyData = tempRaw.left(d->contentLength);
00180             
00181             d->inTransfer->setBody(bodyData);
00182             qDebug() << Q_FUNC_INFO << "Byte data length:" << bodyData.size();
00183 //          qDebug() << Q_FUNC_INFO << "Payload data read(from Transfer):" << d->inTransfer->payloadLength();
00184             // Show full payload command to output
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 //kate: indent-mode csands; tab-width 4;

kopete/protocols/messenger/libpapillon

Skip menu "kopete/protocols/messenger/libpapillon"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal