ext/iodine/websocket_parser.h
/**
 * Consumes the data in the buffer, calling any callbacks required.
 *
 * Returns the remaining data in the existing buffer (can be 0).
 */
Consumes the data in the buffer, calling any callbacks required.
Returns the remaining data in the existing buffer (can be 0).
Consumes the data in the buffer calling any callbacks required . Returns the remaining data in the existing buffer ( can be 0 ) .
static uint64_t websocket_consume(void *buffer, uint64_t len, void *udata,
                                  uint8_t require_masking) {
  volatile struct websocket_packet_info_s info =
      websocket_buffer_peek(buffer, len);
  if (!info.head_length) {
#if DEBUG
    fprintf(stderr, "ERROR: WebSocket protocol error - malicious header.\n");
#endif
    websocket_on_protocol_error(udata);
    return 0;
  }
  if (info.head_length + info.packet_length > len)
    return len;
  uint64_t reminder = len;
  uint8_t *pos = (uint8_t *)buffer;
  while (info.head_length + info.packet_length <= reminder) {
    void *payload = (void *)(pos + info.head_length);
    if (info.masked) {
      uint32_t mask; 
      ((uint8_t *)(&mask))[0] = ((uint8_t *)(payload))[-4];
      ((uint8_t *)(&mask))[1] = ((uint8_t *)(payload))[-3];
      ((uint8_t *)(&mask))[2] = ((uint8_t *)(payload))[-2];
      ((uint8_t *)(&mask))[3] = ((uint8_t *)(payload))[-1];
      websocket_xmask(payload, info.packet_length, mask);
    } else if (require_masking && info.packet_length) {
#if DEBUG
      fprintf(stderr, "ERROR: WebSocket protocol error - unmasked data.\n");
#endif
      websocket_on_protocol_error(udata);
    }
    switch (pos[0] & 15) {
    case 0:
      websocket_on_unwrapped(udata, payload, info.packet_length, 0,
                             ((pos[0] >> 7) & 1), 0, ((pos[0] >> 4) & 7));
      break;
    case 1:
      websocket_on_unwrapped(udata, payload, info.packet_length, 1,
                             ((pos[0] >> 7) & 1), 1, ((pos[0] >> 4) & 7));
      break;
    case 2:
      websocket_on_unwrapped(udata, payload, info.packet_length, 1,
                             ((pos[0] >> 7) & 1), 0, ((pos[0] >> 4) & 7));
      break;
    case 8:
      websocket_on_protocol_close(udata);
      break;
    case 9:
      websocket_on_protocol_ping(udata, payload, info.packet_length);
      break;
    case 10:
      websocket_on_protocol_pong(udata, payload, info.packet_length);
      break;
    default:
#if DEBUG
      fprintf(stderr, "ERROR: WebSocket protocol error - unknown opcode %u\n",
              (unsigned int)(pos[0] & 15));
#endif
      websocket_on_protocol_error(udata);
    }
    reminder = reminder - (info.head_length + info.packet_length);
    if (!reminder)
      return 0;
    pos += info.head_length + info.packet_length;
    info = websocket_buffer_peek(pos, reminder);
  }
  memmove(buffer, (uint8_t *)buffer + len - reminder, reminder);
  return reminder;
}
static uint64_t websocket_consume ( void * buffer , uint64_t len , void * udata , uint8_t require_masking ) { volatile struct websocket_packet_info_s info = websocket_buffer_peek ( buffer , len ) ; if ( ! info . head_length ) { #if DEBUG fprintf ( stderr , " \n " ) ; #endif websocket_on_protocol_error ( udata ) ; return 0 ; } if ( info . head_length + info . packet_length > len ) return len ; uint64_t reminder = len ; uint8_t * pos = ( uint8_t * ) buffer ; while ( info . head_length + info . packet_length <= reminder ) { void * payload = ( void * ) ( pos + info . head_length ) ; if ( info . masked ) { uint32_t mask ; ( ( uint8_t * ) ( & mask ) ) [ 0 ] = ( ( uint8_t * ) ( payload ) ) [ -4 ] ; ( ( uint8_t * ) ( & mask ) ) [ 1 ] = ( ( uint8_t * ) ( payload ) ) [ -3 ] ; ( ( uint8_t * ) ( & mask ) ) [ 2 ] = ( ( uint8_t * ) ( payload ) ) [ -2 ] ; ( ( uint8_t * ) ( & mask ) ) [ 3 ] = ( ( uint8_t * ) ( payload ) ) [ -1 ] ; websocket_xmask ( payload , info . packet_length , mask ) ; } else if ( require_masking && info . packet_length ) { #if DEBUG fprintf ( stderr , " \n " ) ; #endif websocket_on_protocol_error ( udata ) ; } switch ( pos [ 0 ] & 15 ) { case 0 : websocket_on_unwrapped ( udata , payload , info . packet_length , 0 , ( ( pos [ 0 ] >> 7 ) & 1 ) , 0 , ( ( pos [ 0 ] >> 4 ) & 7 ) ) ; break ; case 1 : websocket_on_unwrapped ( udata , payload , info . packet_length , 1 , ( ( pos [ 0 ] >> 7 ) & 1 ) , 1 , ( ( pos [ 0 ] >> 4 ) & 7 ) ) ; break ; case 2 : websocket_on_unwrapped ( udata , payload , info . packet_length , 1 , ( ( pos [ 0 ] >> 7 ) & 1 ) , 0 , ( ( pos [ 0 ] >> 4 ) & 7 ) ) ; break ; case 8 : websocket_on_protocol_close ( udata ) ; break ; case 9 : websocket_on_protocol_ping ( udata , payload , info . packet_length ) ; break ; case 10 : websocket_on_protocol_pong ( udata , payload , info . packet_length ) ; break ; default : #if DEBUG fprintf ( stderr , " \n " , ( unsigned int ) ( pos [ 0 ] & 15 ) ) ; #endif websocket_on_protocol_error ( udata ) ; } reminder = reminder - ( info . head_length + info . packet_length ) ; if ( ! reminder ) return 0 ; pos += info . head_length + info . packet_length ; info = websocket_buffer_peek ( pos , reminder ) ; } memmove ( buffer , ( uint8_t * ) buffer + len - reminder , reminder ) ; return reminder ; }
Consumes the data in the buffer, calling any callbacks required.
Consumes the data in the buffer calling any callbacks required .
/* parse head */ /* unmask? */ /* masked */ // = ((uint32_t *)payload)[-1]; /* call callback */ /* continuation frame */ /* text frame */ /* data frame */ /* close frame */ /* ping frame */ /* pong frame */ /* step forward */ /* reset buffer state - support pipelining */