src/server/daemon/websocket.h

Mon, 26 Dec 2016 14:00:10 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 26 Dec 2016 14:00:10 +0100
changeset 127
84e206063b64
permissions
-rw-r--r--

adds minimal websocket implementation

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2016 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef WEBSOCKET_H
#define	WEBSOCKET_H

#include "../public/nsapi.h"

#ifdef	__cplusplus
extern "C" {
#endif
    
#define WS_FRAMEHEADER_BUFLEN 16

typedef struct WSParser  WSParser;
typedef struct WSFrame   WSFrame;

// WSMessage is defined in nsapi.h

struct WSFrame {
    uint8_t  header_complete;
    uint8_t  fin;
    uint8_t  mask;
    uint8_t  opcode;
    uint32_t masking_key;
    uint64_t payload_length;
};

struct WSParser {
    // input buffer size
    const char *inbuf; 
    // inbuf data length
    size_t     length;
    // current buffer position
    size_t     pos;
    
    // current message or NULL
    WSMessage  *current;
    // parser state: 0: parse frame, 1: get payload data
    int        state;
    // current payload length
    size_t     cur_plen;
    // current message frame
    WSFrame    frame;
    
    // tmp buffer for incomplete frame header
    char       tmpbuf[WS_FRAMEHEADER_BUFLEN];
    // length of tmpbuf
    size_t     tmplen;
    
    pool_handle_t *pool;
};

/*
 * creates a new websocket parser
 */
WSParser* websocket_parser(Session *sn);

/*
 * puts input data into the websocket parser
 * you can use websocket_get_message() after that
 */
void websocket_input(WSParser *parser, const char *data, size_t length);

/*
 * tries to read a complete websocket message
 * returns a pointer to an allocated WSMessage or NULL
 * sets error to 1 if an error occurs, otherwise to 0
 */
WSMessage* websocket_get_message(WSParser *parser, int *error);

/*
 * reads a websocket frame util begin of the payload data
 * returns position of payload data or 0 if the frame header is incomplete
 */
ssize_t websocket_get_frameheader(WSFrame *frame, const char *buf, size_t len);

/*
 * masks or unmasks data
 * this is done by a simple xor with each element in buf and mask
 */
void websocket_mask_data(char *buf, size_t len, uint32_t mask);


#ifdef	__cplusplus
}
#endif

#endif	/* WEBSOCKET_H */

mercurial