defuze.me
Client
|
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 }