cwebs 0.2
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 
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 
 All Classes Files Functions