defuze.me  Client
webframe.cpp
00001 /**************************************************************************
00002 ** defuze.me Epitech Innovative Project
00003 **
00004 ** Copyright 2010-2011
00005 **   Athena Calmettes - Jocelyn De La Rosa - Francois Gaillard
00006 **   Adrien Jarthon - Alexandre Moore - Luc Peres - Arnaud Sellier
00007 **
00008 ** All rights reserved.
00009 **************************************************************************/
00010 
00011 #include "webframe.hpp"
00012 #include <QDebug>
00013 #include <QtGlobal>
00014 
00015 using namespace Network;
00016 
00017 WebFrame::WebFrame()
00018 {
00019 }
00020 
00021 WebFrame::WebFrame(const QByteArray &binary)
00022 {
00023     opcode = BINARY;
00024     init(binary);
00025 }
00026 
00027 WebFrame::WebFrame(const QString &text)
00028 {
00029     opcode = TEXT;
00030     init(text.toUtf8());
00031 }
00032 
00033 void    WebFrame::init(const QByteArray& data, bool masked)
00034 {
00035     payload = data;
00036     fin = (remainingFrames() <= 1);
00037     rsv1 = rsv2 = rsv3 = false;
00038     this->masked = masked;
00039     length = payload.length();
00040     if (this->masked)
00041         generateMask();
00042 }
00043 
00044 bool    WebFrame::isMultiFrame() const
00045 {
00046     return remainingFrames() > 1;
00047 }
00048 
00049 int     WebFrame::remainingFrames() const
00050 {
00051     if (payload.length() > 0)
00052         return ((payload.length() - 1) / MaxFrameSize + 1);
00053     else
00054         return 0;
00055 }
00056 
00057 void    WebFrame::generateMask()
00058 {
00059     mask.resize(4);
00060     for(int i = 0; i < 4; i++)
00061         mask[i] = qrand() % 0xFF;
00062 }
00063 
00064 void    WebFrame::applyMask(int until)
00065 {
00066     if (until == -1)
00067         until = payload.length();
00068     for(int i = 0; i < until; i++)
00069         payload[i] = payload[i] ^ mask[i % 4];
00070 }
00071 
00072 bool    WebFrame::complete() const
00073 {
00074     return (payload.length() == length);
00075 }
00076 
00077 const QByteArray&   WebFrame::content() const
00078 {
00079     return payload;
00080 }
00081 
00082 void        WebFrame::append(QIODevice* device)
00083 {
00084     qint64  toRead = qMin(length - payload.length(), MaxRead);
00085     payload += device->read(toRead);
00086 }
00087 
00088 QByteArray  WebFrame::encoded()
00089 {
00090     QByteArray  data;
00091     uint        length = qMin(payload.length(), MaxFrameSize);
00092     char        c = 0;
00093 
00094     fin = (remainingFrames() <= 1);
00095     c |= fin << 7;
00096     c |= rsv1 << 6;
00097     c |= rsv2 << 5;
00098     c |= rsv3 << 4;
00099     c |= opcode & 0xF;
00100     data += c;
00101     c = masked << 7;
00102     if (length > 65535)
00103     {
00104         c |= 127;
00105         data += c;
00106         for (int i = 0; i < 8; i++)
00107             data += static_cast<char>((length >> (8 * (7 - i)) & 0xFF));
00108     }
00109     else if (length > 125)
00110     {
00111         c |= 126;
00112         data += c;
00113         data += length >> 8;
00114         data += length & 0xFF;
00115     }
00116     else
00117     {
00118         c |= length;
00119         data += c;
00120     }
00121     if (masked)
00122     {
00123         data += mask;
00124         applyMask(length);
00125     }
00126     data += payload.left(length);
00127     payload.remove(0, length);
00128     opcode = CONTINUATION;
00129     return data;
00130 }
00131 
00132 WebFrame*   WebFrame::fromStream(QIODevice* device)
00133 {
00134     WebFrame    *frame = new WebFrame();
00135     QByteArray  head = device->read(2);
00136 
00137     if (head.size() == 2)
00138     {
00139         frame->fin = head[0] & (1 << 7);
00140         if (!frame->fin)
00141             qDebug() << "WebSocket: Multipart frame received!";
00142         frame->rsv1 = head[0] & (1 << 6);
00143         frame->rsv2 = head[0] & (1 << 5);
00144         frame->rsv3 = head[0] & (1 << 4);
00145         frame->opcode = static_cast<OpCode>(head[0] & 0x0F);
00146         frame->masked = head[1] & (1 << 7);
00147         frame->length = head[1] & 0x7F;
00148         if (frame->length == 126)
00149         {
00150             head = device->read(2);
00151             frame->length = (uchar)head[0] << 8 | (uchar)head[1];
00152         }
00153         else if (frame->length == 127)
00154         {
00155             head = device->read(8);
00156             frame->length = 0;
00157             for (int i = 0; i < 8; i++)
00158             {
00159                 frame->length <<= 8;
00160                 frame->length |= (uchar)head[i];
00161             }
00162         }
00163         if (frame->masked)
00164             frame->mask = device->read(4);
00165         frame->append(device);
00166         return frame;
00167     }
00168     delete frame;
00169     return 0;
00170 }