|
cwebs 0.2
WebSocket wire protocol.
|
00001 // Copyright (c) 2011-2012, Andre Caron (andre.l.caron@gmail.com) 00002 // All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without 00005 // modification, are permitted provided that the following conditions are 00006 // met: 00007 // 00008 // Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // 00011 // Redistributions in binary form must reproduce the above copyright 00012 // notice, this list of conditions and the following disclaimer in the 00013 // documentation and/or other materials provided with the distribution. 00014 // 00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00016 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00017 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00018 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00019 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00021 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 00034 #include "iwire.h" 00035 00036 // 00037 // List all parser states in advance. 00038 // 00039 #define WS_DECLARE_STATE(name) \ 00040 static uint64 name \ 00041 ( struct ws_iwire * stream, const uint8 * data, uint64 size ); 00042 WS_DECLARE_STATE(_ws_idle); 00043 WS_DECLARE_STATE(_ws_wait); 00044 WS_DECLARE_STATE(_ws_parse_size_1); 00045 WS_DECLARE_STATE(_ws_parse_size_2); 00046 WS_DECLARE_STATE(_ws_parse_size_3); 00047 WS_DECLARE_STATE(_ws_parse_mask); 00048 WS_DECLARE_STATE(_ws_parse_data); 00049 WS_DECLARE_STATE(_ws_parse_data_1); 00050 WS_DECLARE_STATE(_ws_parse_data_2); 00051 00052 // 00053 // Initial state, waiting for a message to start. 00054 // 00055 static uint64 _ws_idle 00056 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00057 { 00058 // signal start of message. 00059 stream->code = 0; 00060 if ( stream->new_message ) { 00061 stream->new_message(stream); 00062 } 00063 stream->state = &_ws_wait; 00064 return (0); 00065 } 00066 00067 static void _ws_done ( struct ws_iwire * stream ) 00068 { 00069 if ( stream->end_fragment ) { 00070 stream->end_fragment(stream); 00071 } 00072 stream->state = &_ws_wait; 00073 if ( stream->last ) 00074 { 00075 if ( stream->end_message ) { 00076 stream->end_message(stream); 00077 } 00078 stream->code = 0; 00079 stream->state = &_ws_idle; 00080 } 00081 } 00082 00083 // 00084 // Parsing a fragmented message, waiting for next frame. 00085 // 00086 static uint64 _ws_wait 00087 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00088 { 00089 uint64 used = 0; 00090 uint8 code = 0; 00091 while ( used < size ) 00092 { 00093 // fetch next byte. 00094 const uint8 byte = data[used++]; 00095 // parse fields. 00096 stream->last = ((byte & 0x80) != 0); 00097 stream->eval = ((byte & 0x70) >> 4); 00098 code = ((byte & 0x0f) >> 0); 00099 // for fragmented messags, the opcode is set on the first frame 00100 // only and is required to be 0 on subsequent frames. 00101 if ((stream->code != 0) && (code != 0)) 00102 { 00103 // don't be fussy unless peer sends a different opcode. 00104 if ( stream->code != code ) 00105 { 00106 // ... 00107 } 00108 } 00109 if ( stream->code == 0 ) { 00110 stream->code = code; 00111 } 00112 // done. look at fragment size. 00113 stream->state = &_ws_parse_size_1; break; 00114 } 00115 return (used); 00116 } 00117 00118 // 00119 // Parsing a frame, waiting for 7-bit frame size to arrive. 00120 // 00121 static uint64 _ws_parse_size_1 00122 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00123 { 00124 uint64 used = 0; 00125 while ( used < size ) 00126 { 00127 // fetch next byte. 00128 const uint8 byte = data[used++]; 00129 // parse fields. 00130 stream->usem = ((byte & 0x80) != 0); 00131 stream->data[0] = ((byte & 0x7f) >> 0); 00132 stream->size = 1; 00133 // parse extended size, if necessary. 00134 if ( stream->data[0] == 126 ) { 00135 stream->size = 0; 00136 stream->state = &_ws_parse_size_2; break; 00137 } 00138 if ( stream->data[0] == 127 ) { 00139 stream->size = 0; 00140 stream->state = &_ws_parse_size_3; break; 00141 } 00142 // commit size. 00143 stream->pass = stream->data[0]; 00144 if ( stream->new_fragment ) { 00145 stream->new_fragment(stream, stream->pass); 00146 } 00147 stream->size = 0; 00148 // start parsing mask. 00149 stream->state = &_ws_parse_mask; break; 00150 } 00151 return (used); 00152 } 00153 00154 // 00155 // Parsing a frame, waiting for 16-bit frame size to arrive. 00156 // 00157 static uint64 _ws_parse_size_2 00158 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00159 { 00160 uint64 used = 0; 00161 while ( used < size ) 00162 { 00163 // fetch next byte. 00164 const uint8 byte = data[used++]; 00165 // store it in the staging area. 00166 stream->data[stream->size++] = byte; 00167 // stop parsing when done. 00168 if ( stream->size == 2 ) 00169 { 00170 const uint16 size = 00171 (((uint16)stream->data[0] << 8) 00172 |((uint16)stream->data[1] << 0)); 00173 stream->pass = size; 00174 if ( stream->new_fragment ) { 00175 stream->new_fragment(stream, stream->pass); 00176 } 00177 stream->size = 0; 00178 // start parsing mask. 00179 stream->state = &_ws_parse_mask; break; 00180 } 00181 } 00182 return (used); 00183 } 00184 00185 // 00186 // Parsing a frame, waiting for 64-bit frame size to arrive. 00187 // 00188 static uint64 _ws_parse_size_3 00189 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00190 { 00191 uint64 used = 0; 00192 while ( used < size ) 00193 { 00194 // fetch next byte. 00195 const uint8 byte = data[used++]; 00196 // store it in the staging area. 00197 stream->data[stream->size++] = byte; 00198 // stop parsing when done. 00199 if ( stream->size == 8 ) 00200 { 00201 // assemble fragment size. 00202 const uint64 size = 00203 (((uint64)stream->data[0] << 56) 00204 |((uint64)stream->data[1] << 48) 00205 |((uint64)stream->data[2] << 40) 00206 |((uint64)stream->data[3] << 32) 00207 |((uint64)stream->data[4] << 24) 00208 |((uint64)stream->data[5] << 16) 00209 |((uint64)stream->data[6] << 8) 00210 |((uint64)stream->data[7] << 0)); 00211 // notify start of fragment. 00212 stream->pass = size; 00213 if ( stream->new_fragment ) { 00214 stream->new_fragment(stream, size); 00215 } 00216 stream->size = 0; 00217 // start parsing mask. 00218 stream->state = &_ws_parse_mask; break; 00219 } 00220 } 00221 return (used); 00222 } 00223 00224 // 00225 // Parsing frame, waiting for mask to arrive. If the frame payload is not 00226 // masked, then simply forwards to the payload state. 00227 // 00228 static uint64 _ws_parse_mask 00229 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00230 { 00231 // there's no easy way to check for complete submissal of frame 00232 // payload for empty frames. the do-while loop in the '_feed()' 00233 // method guarantees this function will be called at least once. 00234 // complete the frame right away if it is empty, this avoids 00235 // complicating the simple '_feed()' method. 00236 uint64 used = 0; 00237 if ( !stream->usem ) 00238 { 00239 stream->used = 0; 00240 stream->state = &_ws_parse_data; 00241 // fast-track to next message (see comment above). 00242 if ( stream->pass == 0 ) { 00243 return (_ws_parse_data(stream, data+used, size-used)); 00244 } 00245 return (used); 00246 } 00247 while ( used < size ) 00248 { 00249 // fetch next byte. 00250 const uint8 byte = data[used++]; 00251 // store it in the staging area. 00252 stream->data[stream->size++] = byte; 00253 // stop parsing when done. 00254 if ( stream->size == 4 ) 00255 { 00256 // store mask. 00257 stream->mask[0] = stream->data[0]; 00258 stream->mask[1] = stream->data[1]; 00259 stream->mask[2] = stream->data[2]; 00260 stream->mask[3] = stream->data[3]; 00261 stream->size = 0; 00262 // start parsing data. 00263 stream->used = 0; 00264 stream->state = &_ws_parse_data; break; 00265 } 00266 } 00267 // fast-track to next message (see comment above). 00268 if ( stream->pass == 0 ) { 00269 return (used + _ws_parse_data(stream, data+used, size-used)); 00270 } 00271 return (used); 00272 } 00273 00274 // 00275 // Parsing message payload, forward data to owner. 00276 // 00277 static uint64 _ws_parse_data_1 00278 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00279 { 00280 // don't smear across frames. 00281 const uint64 used = MIN(stream->pass, size); 00282 // pass all possible data. 00283 stream->accept_content(stream, data, used); 00284 // update cursors. 00285 stream->pass -= used; 00286 stream->used += used; 00287 // prepare for next frame. 00288 if ( stream->pass == 0 ) { 00289 _ws_done(stream); 00290 } 00291 return (used); 00292 } 00293 00294 // 00295 // Parsing message payload, unmask data and forward to owner. 00296 // 00297 static uint64 _ws_parse_data_2 00298 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00299 { 00300 uint64 used = 0; 00301 uint8 bufdata[256]; 00302 uint8 bufsize = 0; 00303 // don't smear across frame boundaries. 00304 size = MIN(stream->pass, size); 00305 // start parsing data. 00306 while ( used < size ) 00307 { 00308 // copy butes to buffer and un-mask. 00309 for ( bufsize = 0; (bufsize < size); ++bufsize ) { 00310 bufdata[bufsize] = data[used++] ^ stream->mask[stream->used++%4]; 00311 } 00312 // pass data to stream owner. 00313 stream->accept_content(stream, bufdata, bufsize); 00314 } 00315 // adjust cursors. 00316 stream->pass -= used; 00317 // prepare for next frame. 00318 if ( stream->pass == 0 ) { 00319 _ws_done(stream); 00320 } 00321 return (used); 00322 } 00323 00324 // 00325 // Parsing frame payload, forward to mask or unmasked data handler. 00326 // 00327 static uint64 _ws_parse_data 00328 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00329 { 00330 return (stream->usem? 00331 _ws_parse_data_2(stream, data, size) : 00332 _ws_parse_data_1(stream, data, size)); 00333 } 00334 00335 void ws_iwire_init ( struct ws_iwire * stream ) 00336 { 00337 stream->new_message = 0; 00338 stream->end_message = 0; 00339 stream->new_fragment = 0; 00340 stream->end_fragment = 0; 00341 stream->accept_content = 0; 00342 stream->usem = 0; 00343 stream->size = 0; 00344 stream->code = 0; 00345 stream->good = 1; 00346 stream->state = &_ws_idle; 00347 } 00348 00349 uint64 _ws_iwire_feed 00350 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00351 { 00352 uint64 used = 0; 00353 do { 00354 // Note: invoking the state handler might move the parser to a new 00355 // state. In the end, all data will be consumed by one state or 00356 // the other. 00357 used += (*stream->state)(stream, data+used, size-used); 00358 } 00359 while ( used < size ); 00360 return (used); 00361 } 00362 00363 uint64 ws_iwire_feed 00364 ( struct ws_iwire * stream, const void * data, uint64 size ) 00365 { 00366 return (_ws_iwire_feed(stream, (const uint8*)data, size)); 00367 } 00368 00369 int ws_iwire_mask ( const struct ws_iwire * stream ) 00370 { 00371 return (stream->usem); 00372 } 00373 00374 int ws_iwire_last ( const struct ws_iwire * stream ) 00375 { 00376 return (stream->last); 00377 } 00378 00379 int ws_iwire_ping ( const struct ws_iwire * stream ) 00380 { 00381 return (stream->code == 0x09); 00382 } 00383 00384 int ws_iwire_pong ( const struct ws_iwire * stream ) 00385 { 00386 return (stream->code == 0x0a); 00387 } 00388 00389 int ws_iwire_text ( const struct ws_iwire * stream ) 00390 { 00391 return (stream->code == 0x01); 00392 } 00393 00394 int ws_iwire_data ( const struct ws_iwire * stream ) 00395 { 00396 return (stream->code == 0x02); 00397 } 00398 00399 int ws_iwire_dead ( const struct ws_iwire * stream ) 00400 { 00401 return (stream->code == 0x08); 00402 } 00403