cwebs 0.2.1
WebSocket wire protocol
code/iwire.c
Go to the documentation of this file.
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 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines