cwebs 0.2.1
WebSocket wire protocol
code/owire.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 "owire.h"
00035 #include <time.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00048 static void _ws_unsafe_random_mask ( struct ws_owire * stream, uint8 mask[4] )
00049 {
00050     mask[0] = rand() & 0xff;
00051     mask[1] = rand() & 0xff;
00052     mask[2] = rand() & 0xff;
00053     mask[3] = rand() & 0xff;
00054 }
00055 
00061 static void _ws_mask ( struct ws_owire * stream )
00062 {
00063     if ( (stream->data[1]&0x80) != 0 ) {
00064         stream->rand(stream, stream->data+10);
00065     }
00066 }
00067 
00073 static void _ws_head ( struct ws_owire * stream )
00074 {
00075     const uint8 size = (stream->data[1] & 0x7f);
00076     const uint8 usem = (stream->data[1] & 0x80);
00077     // compute prefix size.
00078     uint8 used = 0;
00079     if ( size < 126 ) {
00080         used = 2;
00081     }
00082     if ( size == 126 ) {
00083         used = 4;
00084     }
00085     if ( size == 127 ) {
00086         used = 10;
00087     }
00088     // pack header by moving mask.
00089     if ( usem && (size < 127) ) {
00090         memcpy(stream->data+used, stream->data+10, 4), used += 4;
00091     }
00092     // send packed header.
00093     stream->accept_content(stream, stream->data, used);
00094 }
00095 
00110 static uint64 _ws_fail
00111     ( struct ws_owire * stream, const uint8 * data, uint64 size )
00112 {
00113     stream->error = ws_owire_enotready;
00114     return (0);
00115 }
00116 
00127 static uint64 _ws_body_1
00128     ( struct ws_owire * stream, const uint8 * data, uint64 size )
00129 {
00130     // don't smear across frames.
00131     size = MIN(size, stream->pass);
00132     // pass all possible data.
00133     stream->accept_content(stream, data, size);
00134     // update cursors.
00135     stream->used += size;
00136     stream->pass -= size;
00137     // prepare for next frame.
00138     if ( stream->pass == 0 )
00139     {
00140     }
00141     return (size);
00142 }
00143 
00154 static uint64 _ws_body_2
00155     ( struct ws_owire * stream, const uint8 * data, uint64 size )
00156 {
00157     uint64 used = 0;
00158     uint8 bufdata[256];
00159     uint8 bufsize = 0;
00160     // don't smear across frame boundaries.
00161     size = MIN(stream->pass, size);
00162     // start parsing data.
00163     while ( used < size )
00164     {
00165         // copy butes to buffer and un-mask.
00166         const uint8 *const mask = stream->data+10;
00167         for ( bufsize = 0; (bufsize < size); ++bufsize ) {
00168             bufdata[bufsize] = data[used++] ^ mask[stream->used++%4];
00169         }
00170         // pass data to stream owner.
00171         stream->accept_content(stream, bufdata, bufsize);
00172     }
00173     // adjust cursors.
00174     stream->pass -= used;
00175     // prepare for next frame.
00176     if ( stream->pass == 0 )
00177     {
00178     }
00179     return (used);
00180 }
00181 
00192 static uint64 _ws_body
00193     ( struct ws_owire * stream, const uint8 * data, uint64 size )
00194 {
00195     return (((stream->data[1] & 0x80)==0)?
00196         _ws_body_1(stream, data, size) :
00197         _ws_body_2(stream, data, size));
00198 }
00199 
00212 static void ws_owire_put_full
00213     ( struct ws_owire * stream, const uint8 * data, uint64 size, uint8 code )
00214 {
00215     uint64 used = 0;
00216     uint64 part = 0;
00217     ws_owire_new_message(stream);
00218     if ((stream->auto_fragment == 0) || (size == 0))
00219     {
00220         ws_owire_new_frame(stream, size);
00221           ws_owire_last(stream);
00222           ws_owire_eval(stream, 0);
00223           ws_owire_code(stream, code);
00224           _ws_mask(stream);
00225           _ws_head(stream);
00226           _ws_body(stream, data, size);
00227         ws_owire_end_frame(stream);
00228     }
00229     else
00230     {
00231         while ( used < size )
00232         {
00233             part = MIN(size-used, stream->auto_fragment);
00234             ws_owire_new_frame(stream, part);
00235             {
00236                 if ( (used+part) >= size ) {
00237                     ws_owire_last(stream);
00238                 }
00239                 ws_owire_eval(stream, 0);
00240                 if ( used == 0 ) {
00241                     ws_owire_code(stream, code);
00242                 } else {
00243                     ws_owire_code(stream, 0);
00244                 }
00245                 if ( stream->auto_mask ) {
00246                     ws_owire_mask(stream);
00247                 }
00248                 _ws_mask(stream);
00249                 _ws_head(stream);
00250                 used += _ws_body(stream, data+used, part);
00251             }
00252             ws_owire_end_frame(stream);
00253         }
00254     }
00255     ws_owire_end_message(stream);
00256 }
00257 
00258 void ws_owire_init ( struct ws_owire * stream )
00259 {
00260     stream->accept_content = 0;
00261     stream->prng = 0;
00262     stream->rand = &_ws_unsafe_random_mask;
00263     stream->baton = 0;
00264     stream->auto_fragment = 0;
00265     stream->auto_mask = 0;
00266     stream->state = &_ws_fail;
00267     stream->pass = 0;
00268 }
00269 
00270 void ws_owire_new_message ( struct ws_owire * stream )
00271 {
00272     memset(stream->data, 0, 14);
00273     stream->state = &_ws_fail;
00274     stream->pass = 0;
00275 }
00276 
00277 void ws_owire_end_message ( struct ws_owire * stream )
00278 {
00279     memset(stream->data, 0, 14);
00280     stream->state = &_ws_fail;
00281     stream->pass = 0;
00282 }
00283 
00284 void ws_owire_new_frame ( struct ws_owire * stream, uint64 size )
00285 {
00286     memset(stream->data, 0, 14);
00287     stream->state = &_ws_fail;
00288     stream->pass = size;
00289     if ( size < 126 )
00290     {
00291         stream->data[1] &= 0x7f;
00292         stream->data[1] |= size;
00293     }
00294     else if ( size < 65537 )
00295     {
00296         stream->data[1] &= 0x7f;
00297         stream->data[1] |= 126;
00298         stream->data[2] = ((size >> 8) & 0xff);
00299         stream->data[3] = ((size >> 0) & 0xff);
00300     }
00301     else
00302     {
00303         stream->data[1] &= 0x7f;
00304         stream->data[1] |= 127;
00305         stream->data[2] = ((size >> 56) & 0xff);
00306         stream->data[3] = ((size >> 48) & 0xff);
00307         stream->data[4] = ((size >> 40) & 0xff);
00308         stream->data[5] = ((size >> 32) & 0xff);
00309         stream->data[6] = ((size >> 24) & 0xff);
00310         stream->data[7] = ((size >> 16) & 0xff);
00311         stream->data[8] = ((size >>  8) & 0xff);
00312         stream->data[9] = ((size >>  0) & 0xff);
00313     }
00314 }
00315 
00316 void ws_owire_end_frame ( struct ws_owire * stream )
00317 {
00318     memset(stream->data, 0, 14);
00319     stream->state = &_ws_fail;
00320     stream->pass = 0;
00321 }
00322 
00323 void ws_owire_last ( struct ws_owire * stream )
00324 {
00325     // set bit 8.
00326     stream->data[0] |= 0x80;
00327 }
00328 
00329 void ws_owire_eval ( struct ws_owire * stream, uint8 eval )
00330 {
00331     // clear, then set bits 5-7.
00332     stream->data[0] &= 0xf1;
00333     stream->data[0] |= ((eval & 0x07) << 4);
00334 }
00335 
00336 void ws_owire_code ( struct ws_owire * stream, uint8 code )
00337 {
00338     // clear, then set bits 5-7.
00339     stream->data[0] &= 0xf0;
00340     stream->data[0] |= (code & 0x0f);
00341 }
00342 
00343 void ws_owire_mask ( struct ws_owire * stream )
00344 {
00345     // set bit 8.
00346     stream->data[1] |= 0x80;
00347 }
00348 
00349 uint64 ws_owire_feed
00350     ( struct ws_owire * stream, const void * data, uint64 size )
00351 {
00352     return (stream->state(stream, static_cast<const uint8*>(data), size));
00353 }
00354 
00355 void ws_owire_put_text
00356     ( struct ws_owire * stream, const void * data, uint64 size )
00357 {
00358     ws_owire_put_full(stream, static_cast<const uint8*>(data), size, 0x01);
00359 }
00360 
00361 void ws_owire_put_data
00362     ( struct ws_owire * stream, const void * data, uint64 size )
00363 {
00364     ws_owire_put_full(stream, static_cast<const uint8*>(data), size, 0x02);
00365 }
00366 
00367 void ws_owire_put_kill
00368     ( struct ws_owire * stream, const void * data, uint64 size )
00369 {
00370     ws_owire_put_full(stream, static_cast<const uint8*>(data), size, 0x08);
00371 }
00372 
00373 void ws_owire_put_ping
00374     ( struct ws_owire * stream, const void * data, uint64 size )
00375 {
00376     ws_owire_put_full(stream, static_cast<const uint8*>(data), size, 0x09);
00377 }
00378 
00379 void ws_owire_put_pong
00380     ( struct ws_owire * stream, const void * data, uint64 size )
00381 {
00382     ws_owire_put_full(stream, static_cast<const uint8*>(data), size, 0x0a);
00383 }
00384 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines