You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libtdevnc/libvncserver/ws_decode.h

146 lines
3.4 KiB

#ifndef _WS_DECODE_H_
#define _WS_DECODE_H_
#include <stdint.h>
#include <rfb/rfb.h>
#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#define WS_NTOH64(n) OSSwapBigToHostInt64(n)
#define WS_NTOH32(n) OSSwapBigToHostInt32(n)
#define WS_NTOH16(n) OSSwapBigToHostInt16(n)
#define WS_HTON64(n) OSSwapHostToBigInt64(n)
#define WS_HTON16(n) OSSwapHostToBigInt16(n)
#else
#define WS_NTOH64(n) htobe64(n)
#define WS_NTOH32(n) htobe32(n)
#define WS_NTOH16(n) htobe16(n)
#define WS_HTON64(n) htobe64(n)
#define WS_HTON16(n) htobe16(n)
#endif
#define B64LEN(__x) (((__x + 2) / 3) * 12 / 3)
#define WSHLENMAX 14LL /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */
#define WS_HYBI_MASK_LEN 4
#define ARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))) / (size_t)(!(sizeof(a) % sizeof((a[0])))))
struct ws_ctx_s;
typedef struct ws_ctx_s ws_ctx_t;
typedef int (*wsEncodeFunc)(rfbClientPtr cl, const char *src, int len, char **dst);
typedef int (*wsDecodeFunc)(ws_ctx_t *wsctx, char *dst, int len);
typedef int (*wsReadFunc)(void *ctx, char *dst, size_t len);
typedef struct ctxInfo_s{
void *ctxPtr;
wsReadFunc readFunc;
} ctxInfo_t;
enum {
/* header not yet received completely */
WS_HYBI_STATE_HEADER_PENDING,
/* data available */
WS_HYBI_STATE_DATA_AVAILABLE,
WS_HYBI_STATE_DATA_NEEDED,
/* received a complete frame */
WS_HYBI_STATE_FRAME_COMPLETE,
/* received part of a 'close' frame */
WS_HYBI_STATE_CLOSE_REASON_PENDING,
/* */
WS_HYBI_STATE_ERR
};
typedef union ws_mask_s {
char c[4];
uint32_t u;
} ws_mask_t;
/* XXX: The union and the structs do not need to be named.
* We are working around a bug present in GCC < 4.6 which prevented
* it from recognizing anonymous structs and unions.
* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=4784
*/
typedef struct
#if __GNUC__
__attribute__ ((__packed__))
#endif
ws_header_s {
unsigned char b0;
unsigned char b1;
union {
struct
#if __GNUC__
__attribute__ ((__packed__))
#endif
{
uint16_t l16;
ws_mask_t m16;
} s16;
struct
#if __GNUC__
__attribute__ ((__packed__))
#endif
{
uint64_t l64;
ws_mask_t m64;
} s64;
ws_mask_t m;
} u;
} ws_header_t;
typedef struct ws_header_data_s {
ws_header_t *data;
/** bytes read */
int nRead;
/** mask value */
ws_mask_t mask;
/** length of frame header including payload len, but without mask */
int headerLen;
/** length of the payload data */
uint64_t payloadLen;
/** opcode */
unsigned char opcode;
/** fin bit */
unsigned char fin;
} ws_header_data_t;
typedef struct ws_ctx_s {
char codeBufDecode[2048 + WSHLENMAX]; /* base64 + maximum frame header length */
char codeBufEncode[B64LEN(UPDATE_BUF_SIZE) + WSHLENMAX]; /* base64 + maximum frame header length */
char *writePos;
unsigned char *readPos;
int readlen;
int hybiDecodeState;
char carryBuf[3]; /* For base64 carry-over */
int carrylen;
int base64;
ws_header_data_t header;
uint64_t nReadPayload;
unsigned char continuation_opcode;
wsEncodeFunc encode;
wsDecodeFunc decode;
ctxInfo_t ctxInfo;
} ws_ctx_t;
enum
{
WS_OPCODE_CONTINUATION = 0x00,
WS_OPCODE_TEXT_FRAME = 0x01,
WS_OPCODE_BINARY_FRAME = 0x02,
WS_OPCODE_CLOSE = 0x08,
WS_OPCODE_PING = 0x09,
WS_OPCODE_PONG = 0x0A,
WS_OPCODE_INVALID = 0xFF
};
int webSocketsDecodeHybi(ws_ctx_t *wsctx, char *dst, int len);
void hybiDecodeCleanupComplete(ws_ctx_t *wsctx);
#endif