|
cwebs 0.2.1
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 00046 #define WS_DECLARE_STATE(name) \ 00047 static uint64 name \ 00048 ( struct ws_iwire * stream, const uint8 * data, uint64 size ); 00049 WS_DECLARE_STATE(_ws_idle); 00050 WS_DECLARE_STATE(_ws_wait); 00051 WS_DECLARE_STATE(_ws_parse_size_1); 00052 WS_DECLARE_STATE(_ws_parse_size_2); 00053 WS_DECLARE_STATE(_ws_parse_size_3); 00054 WS_DECLARE_STATE(_ws_parse_mask); 00055 WS_DECLARE_STATE(_ws_parse_data); 00056 WS_DECLARE_STATE(_ws_parse_data_1); 00057 WS_DECLARE_STATE(_ws_parse_data_2); 00058 00064 static uint64 _ws_idle 00065 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00066 { 00067 // signal start of message. 00068 stream->code = 0; 00069 if ( stream->new_message ) { 00070 stream->new_message(stream); 00071 } 00072 stream->state = &_ws_wait; 00073 return (0); 00074 } 00075 00080 static void _ws_done ( struct ws_iwire * stream ) 00081 { 00082 if ( stream->end_fragment ) { 00083 stream->end_fragment(stream); 00084 } 00085 stream->state = &_ws_wait; 00086 if ( stream->last ) 00087 { 00088 if ( stream->end_message ) { 00089 stream->end_message(stream); 00090 } 00091 stream->code = 0; 00092 stream->state = &_ws_idle; 00093 } 00094 } 00095 00101 static uint64 _ws_wait 00102 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00103 { 00104 uint64 used = 0; 00105 uint8 code = 0; 00106 while ( used < size ) 00107 { 00108 // fetch next byte. 00109 const uint8 byte = data[used++]; 00110 // parse fields. 00111 stream->last = ((byte & 0x80) != 0); 00112 stream->eval = ((byte & 0x70) >> 4); 00113 code = ((byte & 0x0f) >> 0); 00114 // for fragmented messags, the opcode is set on the first frame 00115 // only and is required to be 0 on subsequent frames. 00116 if ((stream->code != 0) && (code != 0)) 00117 { 00118 // don't be fussy unless peer sends a different opcode. 00119 if ( stream->code != code ) 00120 { 00121 // ... 00122 } 00123 } 00124 if ( stream->code == 0 ) { 00125 stream->code = code; 00126 } 00127 // done. look at fragment size. 00128 stream->state = &_ws_parse_size_1; break; 00129 } 00130 return (used); 00131 } 00132 00145 static uint64 _ws_parse_size_1 00146 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00147 { 00148 uint64 used = 0; 00149 while ( used < size ) 00150 { 00151 // fetch next byte. 00152 const uint8 byte = data[used++]; 00153 // parse fields. 00154 stream->usem = ((byte & 0x80) != 0); 00155 stream->data[0] = ((byte & 0x7f) >> 0); 00156 stream->size = 1; 00157 // parse extended size, if necessary. 00158 if ( stream->data[0] == 126 ) { 00159 stream->size = 0; 00160 stream->state = &_ws_parse_size_2; break; 00161 } 00162 if ( stream->data[0] == 127 ) { 00163 stream->size = 0; 00164 stream->state = &_ws_parse_size_3; break; 00165 } 00166 // commit size. 00167 stream->pass = stream->data[0]; 00168 if ( stream->new_fragment ) { 00169 stream->new_fragment(stream, stream->pass); 00170 } 00171 stream->size = 0; 00172 // start parsing mask. 00173 stream->state = &_ws_parse_mask; break; 00174 } 00175 return (used); 00176 } 00177 00185 static uint64 _ws_parse_size_2 00186 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00187 { 00188 uint64 used = 0; 00189 while ( used < size ) 00190 { 00191 // fetch next byte. 00192 const uint8 byte = data[used++]; 00193 // store it in the staging area. 00194 stream->data[stream->size++] = byte; 00195 // stop parsing when done. 00196 if ( stream->size == 2 ) 00197 { 00198 const uint16 size = 00199 (((uint16)stream->data[0] << 8) 00200 |((uint16)stream->data[1] << 0)); 00201 stream->pass = size; 00202 if ( stream->new_fragment ) { 00203 stream->new_fragment(stream, stream->pass); 00204 } 00205 stream->size = 0; 00206 // start parsing mask. 00207 stream->state = &_ws_parse_mask; break; 00208 } 00209 } 00210 return (used); 00211 } 00212 00220 static uint64 _ws_parse_size_3 00221 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00222 { 00223 uint64 used = 0; 00224 while ( used < size ) 00225 { 00226 // fetch next byte. 00227 const uint8 byte = data[used++]; 00228 // store it in the staging area. 00229 stream->data[stream->size++] = byte; 00230 // stop parsing when done. 00231 if ( stream->size == 8 ) 00232 { 00233 // assemble fragment size. 00234 const uint64 size = 00235 (((uint64)stream->data[0] << 56) 00236 |((uint64)stream->data[1] << 48) 00237 |((uint64)stream->data[2] << 40) 00238 |((uint64)stream->data[3] << 32) 00239 |((uint64)stream->data[4] << 24) 00240 |((uint64)stream->data[5] << 16) 00241 |((uint64)stream->data[6] << 8) 00242 |((uint64)stream->data[7] << 0)); 00243 // notify start of fragment. 00244 stream->pass = size; 00245 if ( stream->new_fragment ) { 00246 stream->new_fragment(stream, size); 00247 } 00248 stream->size = 0; 00249 // start parsing mask. 00250 stream->state = &_ws_parse_mask; break; 00251 } 00252 } 00253 return (used); 00254 } 00255 00263 static uint64 _ws_parse_mask 00264 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00265 { 00266 // there's no easy way to check for complete submissal of frame 00267 // payload for empty frames. the do-while loop in the '_feed()' 00268 // method guarantees this function will be called at least once. 00269 // complete the frame right away if it is empty, this avoids 00270 // complicating the simple '_feed()' method. 00271 uint64 used = 0; 00272 if ( !stream->usem ) 00273 { 00274 stream->used = 0; 00275 stream->state = &_ws_parse_data; 00276 // fast-track to next message (see comment above). 00277 if ( stream->pass == 0 ) { 00278 return (_ws_parse_data(stream, data+used, size-used)); 00279 } 00280 return (used); 00281 } 00282 while ( used < size ) 00283 { 00284 // fetch next byte. 00285 const uint8 byte = data[used++]; 00286 // store it in the staging area. 00287 stream->data[stream->size++] = byte; 00288 // stop parsing when done. 00289 if ( stream->size == 4 ) 00290 { 00291 // store mask. 00292 stream->mask[0] = stream->data[0]; 00293 stream->mask[1] = stream->data[1]; 00294 stream->mask[2] = stream->data[2]; 00295 stream->mask[3] = stream->data[3]; 00296 stream->size = 0; 00297 // start parsing data. 00298 stream->used = 0; 00299 stream->state = &_ws_parse_data; break; 00300 } 00301 } 00302 // fast-track to next message (see comment above). 00303 if ( stream->pass == 0 ) { 00304 return (used + _ws_parse_data(stream, data+used, size-used)); 00305 } 00306 return (used); 00307 } 00308 00315 static uint64 _ws_parse_data_1 00316 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00317 { 00318 // don't smear across frames. 00319 const uint64 used = MIN(stream->pass, size); 00320 // pass all possible data. 00321 stream->accept_content(stream, data, used); 00322 // update cursors. 00323 stream->pass -= used; 00324 stream->used += used; 00325 // prepare for next frame. 00326 if ( stream->pass == 0 ) { 00327 _ws_done(stream); 00328 } 00329 return (used); 00330 } 00331 00338 static uint64 _ws_parse_data_2 00339 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00340 { 00341 uint64 used = 0; 00342 uint8 bufdata[256]; 00343 uint8 bufsize = 0; 00344 // don't smear across frame boundaries. 00345 size = MIN(stream->pass, size); 00346 // start parsing data. 00347 while ( used < size ) 00348 { 00349 // copy butes to buffer and un-mask. 00350 for ( bufsize = 0; (bufsize < size); ++bufsize ) { 00351 bufdata[bufsize] = data[used++] ^ stream->mask[stream->used++%4]; 00352 } 00353 // pass data to stream owner. 00354 stream->accept_content(stream, bufdata, bufsize); 00355 } 00356 // adjust cursors. 00357 stream->pass -= used; 00358 // prepare for next frame. 00359 if ( stream->pass == 0 ) { 00360 _ws_done(stream); 00361 } 00362 return (used); 00363 } 00364 00373 static uint64 _ws_parse_data 00374 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00375 { 00376 return (stream->usem? 00377 _ws_parse_data_2(stream, data, size) : 00378 _ws_parse_data_1(stream, data, size)); 00379 } 00380 00387 static uint64 _ws_iwire_feed 00388 ( struct ws_iwire * stream, const uint8 * data, uint64 size ) 00389 { 00390 uint64 used = 0; 00391 do { 00392 // Note: invoking the state handler might move the parser to a new 00393 // state. In the end, all data will be consumed by one state or 00394 // the other. 00395 used += (*stream->state)(stream, data+used, size-used); 00396 } 00397 while ( used < size ); 00398 return (used); 00399 } 00400 00401 void ws_iwire_init ( struct ws_iwire * stream ) 00402 { 00403 stream->new_message = 0; 00404 stream->end_message = 0; 00405 stream->new_fragment = 0; 00406 stream->end_fragment = 0; 00407 stream->accept_content = 0; 00408 stream->usem = 0; 00409 stream->size = 0; 00410 stream->code = 0; 00411 stream->good = 1; 00412 stream->state = &_ws_idle; 00413 } 00414 00415 uint64 ws_iwire_feed 00416 ( struct ws_iwire * stream, const void * data, uint64 size ) 00417 { 00418 return (_ws_iwire_feed(stream, (const uint8*)data, size)); 00419 } 00420 00421 int ws_iwire_mask ( const struct ws_iwire * stream ) 00422 { 00423 return (stream->usem); 00424 } 00425 00426 int ws_iwire_last ( const struct ws_iwire * stream ) 00427 { 00428 return (stream->last); 00429 } 00430 00431 int ws_iwire_ping ( const struct ws_iwire * stream ) 00432 { 00433 return (stream->code == 0x09); 00434 } 00435 00436 int ws_iwire_pong ( const struct ws_iwire * stream ) 00437 { 00438 return (stream->code == 0x0a); 00439 } 00440 00441 int ws_iwire_text ( const struct ws_iwire * stream ) 00442 { 00443 return (stream->code == 0x01); 00444 } 00445 00446 int ws_iwire_data ( const struct ws_iwire * stream ) 00447 { 00448 return (stream->code == 0x02); 00449 } 00450 00451 int ws_iwire_dead ( const struct ws_iwire * stream ) 00452 { 00453 return (stream->code == 0x08); 00454 } 00455