websocket_message.cpp
Go to the documentation of this file.
00001 #include "async_web_server_cpp/websocket_message.hpp"
00002 
00003 namespace async_web_server_cpp
00004 {
00005 
00006 bool WebsocketFrame::fromMessage(const WebsocketMessage& message)
00007 {
00008   switch (message.type)
00009   {
00010   case WebsocketMessage::type_text:
00011     header.opcode = WebsocketFrame::Header::opcode_text;
00012     break;
00013   case WebsocketMessage::type_binary:
00014     header.opcode = WebsocketFrame::Header::opcode_binary;
00015     break;
00016   case WebsocketMessage::type_close:
00017     header.opcode = WebsocketFrame::Header::opcode_close;
00018     break;
00019   case WebsocketMessage::type_ping:
00020     header.opcode = WebsocketFrame::Header::opcode_ping;
00021     break;
00022   case WebsocketMessage::type_pong:
00023     header.opcode = WebsocketFrame::Header::opcode_pong;
00024     break;
00025   default:
00026     return false;
00027   }
00028   header.fin = true;
00029   header.rsv1 = false;
00030   header.rsv2 = false;
00031   header.rsv3 = false;
00032   content = message.content;
00033   length = message.content.size();
00034   return true;
00035 }
00036 
00037 bool WebsocketFrame::serialize(std::vector<unsigned char>& buffer)
00038 {
00039   int header_size = 2; // first two bytes of header
00040   if (length < 126)
00041   {
00042     header.len = length;
00043   }
00044   else if (length <= std::numeric_limits<uint16_t>::max())
00045   {
00046     header.len = 126;
00047     header_size += 2;
00048   }
00049   else if (length <= std::numeric_limits<uint64_t>::max())
00050   {
00051     header.len = 127;
00052     header_size += 8;
00053   }
00054   else
00055     return false; // Message too big
00056   header.mask = false; // sending from server
00057 
00058   buffer.resize(header_size + content.size());
00059   buffer[0] = header_bytes[0];
00060   buffer[1] = header_bytes[1];
00061 
00062   if (length < 126)
00063   {
00064     // already copied in header bytes
00065   }
00066   else if (length <= std::numeric_limits<uint16_t>::max())
00067   {
00068     buffer[2] = (length >> 8) & 0xFF;
00069     buffer[3] = (length >> 0) & 0xFF;
00070   }
00071   else if (length <= std::numeric_limits<uint64_t>::max())
00072   {
00073     buffer[2] = (length >> 56) & 0xFF;
00074     buffer[3] = (length >> 48) & 0xFF;
00075     buffer[4] = (length >> 40) & 0xFF;
00076     buffer[5] = (length >> 32) & 0xFF;
00077     buffer[6] = (length >> 24) & 0xFF;
00078     buffer[7] = (length >> 16) & 0xFF;
00079     buffer[8] = (length >> 8) & 0xFF;
00080     buffer[9] = (length >> 0) & 0xFF;
00081   }
00082   content.copy((char*)&buffer[header_size], content.size());
00083   return true;
00084 }
00085 
00086 
00087 WebsocketFrameParser::WebsocketFrameParser()
00088 {
00089   reset();
00090 }
00091 
00092 void WebsocketFrameParser::reset()
00093 {
00094   state_ = header_byte1;
00095 }
00096 
00097 boost::tribool WebsocketFrameParser::consume(WebsocketFrame& frame, char input)
00098 {
00099   switch (state_)
00100   {
00101   case header_byte1:
00102     frame.header_bytes[0] = input;
00103     state_ = header_byte2;
00104     return boost::indeterminate;
00105   case header_byte2:
00106     frame.header_bytes[1] = input;
00107     if (frame.header.len < 126)
00108     {
00109       frame.length = frame.header.len;
00110       frame.content.reserve(frame.length);
00111       frame.content.resize(0);
00112       if (frame.header.mask)
00113         state_ = mask_byte1;
00114       else if (frame.length > 0)
00115         state_ = body;
00116       else
00117         return true;
00118     }
00119     else if (frame.header.len == 126)
00120     {
00121       frame.length = 0;
00122       state_ = length_2bytes_left;
00123     }
00124     else
00125     {
00126       frame.length = 0;
00127       state_ = length_8bytes_left;
00128     }
00129     return boost::indeterminate;
00130 
00131   case length_8bytes_left:
00132     frame.length |= ((uint64_t)(input & 0xFF) << 56);
00133     state_ = length_7bytes_left;
00134     return boost::indeterminate;
00135   case length_7bytes_left:
00136     frame.length |= ((uint64_t)(input & 0xFF) << 48);
00137     state_ = length_6bytes_left;
00138     return boost::indeterminate;
00139   case length_6bytes_left:
00140     frame.length |= ((uint64_t)(input & 0xFF) << 40);
00141     state_ = length_5bytes_left;
00142     return boost::indeterminate;
00143   case length_5bytes_left:
00144     frame.length |= ((uint64_t)(input & 0xFF) << 32);
00145     state_ = length_4bytes_left;
00146     return boost::indeterminate;
00147   case length_4bytes_left:
00148     frame.length |= ((uint64_t)(input & 0xFF) << 24);
00149     state_ = length_3bytes_left;
00150     return boost::indeterminate;
00151   case length_3bytes_left:
00152     frame.length |= ((uint64_t)(input & 0xFF) << 16);
00153     state_ = length_2bytes_left;
00154     return boost::indeterminate;
00155   case length_2bytes_left:
00156     frame.length |= ((uint64_t)(input & 0xFF) << 8);
00157     state_ = length_1bytes_left;
00158     return boost::indeterminate;
00159   case length_1bytes_left:
00160     frame.length |= ((uint64_t)(input & 0xFF) << 0);
00161     frame.content.reserve(frame.length);
00162     frame.content.resize(0);
00163     if (frame.header.mask)
00164       state_ = mask_byte1;
00165     else
00166       state_ = body;
00167     return boost::indeterminate;
00168 
00169 
00170   case mask_byte1:
00171     frame.mask[0] = input;
00172     state_ = mask_byte2;
00173     return boost::indeterminate;
00174   case mask_byte2:
00175     frame.mask[1] = input;
00176     state_ = mask_byte3;
00177     return boost::indeterminate;
00178   case mask_byte3:
00179     frame.mask[2] = input;
00180     state_ = mask_byte4;
00181     return boost::indeterminate;
00182   case mask_byte4:
00183     frame.mask[3] = input;
00184     if (frame.length > 0)
00185       state_ = body;
00186     else
00187       return true;
00188     return boost::indeterminate;
00189 
00190   case body:
00191     frame.content += input;
00192     if (frame.content.size() < frame.length)
00193       return boost::indeterminate;
00194     //unmask the frame
00195     if (frame.header.mask)
00196     {
00197       for (int i = 0; i < frame.length; ++i)
00198       {
00199         frame.content[i] = frame.content[i] ^ frame.mask[i % 4];
00200       }
00201     }
00202     return true;
00203   default:
00204     return false;
00205   }
00206 }
00207 
00208 WebsocketMessage::WebsocketMessage() : type(type_unknown) {}
00209 
00210 boost::tribool WebsocketFrameBuffer::consume(WebsocketMessage& message, WebsocketFrame& frame)
00211 {
00212   if (frame.header.opcode == WebsocketFrame::Header::opcode_continuation)
00213   {
00214     if (message.type == WebsocketMessage::type_unknown)
00215       return false;
00216     else
00217       message.content.append(frame.content);
00218   }
00219   else
00220   {
00221     switch (frame.header.opcode)
00222     {
00223     case WebsocketFrame::Header::opcode_text:
00224       message.type = WebsocketMessage::type_text;
00225       break;
00226     case WebsocketFrame::Header::opcode_binary:
00227       message.type = WebsocketMessage::type_binary;
00228       break;
00229     case WebsocketFrame::Header::opcode_close:
00230       message.type = WebsocketMessage::type_close;
00231       break;
00232     case WebsocketFrame::Header::opcode_ping:
00233       message.type = WebsocketMessage::type_ping;
00234       break;
00235     case WebsocketFrame::Header::opcode_pong:
00236       message.type = WebsocketMessage::type_pong;
00237       break;
00238     default:
00239       message.type = WebsocketMessage::type_unknown;
00240       return false;
00241     }
00242     message.content = frame.content;
00243   }
00244   if (frame.header.fin)
00245     return true;
00246   else
00247     return boost::indeterminate;
00248 }
00249 
00250 
00251 }


async_web_server_cpp
Author(s): Mitchell Wills
autogenerated on Thu Aug 27 2015 12:27:39