aboutsummaryrefslogtreecommitdiff
path: root/liveapi/libuwsc/uwsc.h
blob: 72ba2d88bf538b382c095dda245408a1fd491009 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * MIT License
 *
 * Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef _UWSC_H
#define _UWSC_H

#include <ev.h>

#include "log.h"
#include "config.h"
#include "buffer.h"

#define HTTP_HEAD_LIMIT             4096
#define UWSC_MAX_CONNECT_TIME       5  /* second */
#define UWSC_BUFFER_PERSISTENT_SIZE 4096

/* WebSocket close status codes defined in RFC 6455, section 11.7 */
enum {
    UWSC_CLOSE_STATUS_NORMAL                = 1000,
    UWSC_CLOSE_STATUS_GOINGAWAY             = 1001,
    UWSC_CLOSE_STATUS_PROTOCOL_ERR          = 1002,
    UWSC_CLOSE_STATUS_UNACCEPTABLE_OPCODE   = 1003,
    UWSC_CLOSE_STATUS_RESERVED              = 1004,
    UWSC_CLOSE_STATUS_NO_STATUS             = 1005,
    UWSC_CLOSE_STATUS_ABNORMAL_CLOSE        = 1006,
    UWSC_CLOSE_STATUS_INVALID_PAYLOAD       = 1007,
    UWSC_CLOSE_STATUS_POLICY_VIOLATION      = 1008,
    UWSC_CLOSE_STATUS_MESSAGE_TOO_LARGE     = 1009,
    UWSC_CLOSE_STATUS_EXTENSION_REQUIRED    = 1010,
    UWSC_CLOSE_STATUS_UNEXPECTED_CONDITION  = 1011,
    UWSC_CLOSE_STATUS_TLS_FAILURE           = 1015
};

enum {
    UWSC_ERROR_IO = 1,
    UWSC_ERROR_INVALID_HEADER,
    UWSC_ERROR_SERVER_MASKED,
    UWSC_ERROR_NOT_SUPPORT,
    UWSC_ERROR_PING_TIMEOUT,
    UWSC_ERROR_CONNECT,
    UWSC_ERROR_SSL_HANDSHAKE
};

enum {
    CLIENT_STATE_CONNECTING,
    CLIENT_STATE_SSL_HANDSHAKE,
    CLIENT_STATE_HANDSHAKE,
    CLIENT_STATE_PARSE_MSG_HEAD,
    CLIENT_STATE_PARSE_MSG_PAYLEN,
    CLIENT_STATE_PARSE_MSG_PAYLOAD
};

enum {
    UWSC_OP_CONTINUE   = 0x0,
    UWSC_OP_TEXT       = 0x1,
    UWSC_OP_BINARY     = 0x2,
    UWSC_OP_CLOSE      = 0x8,
    UWSC_OP_PING       = 0x9,
    UWSC_OP_PONG       = 0xA
};

struct uwsc_frame {
    uint8_t opcode;
    size_t payloadlen;
};

struct uwsc_client {
    int sock;
    int state;
    struct ev_loop *loop;
    struct ev_io ior;
    struct ev_io iow;
    struct buffer rb;
    struct buffer wb;
    struct uwsc_frame frame;
    struct ev_timer timer;
    bool wait_pong;
    int ping_interval;
    ev_tstamp start_time;   /* Time stamp of begin connect */
    ev_tstamp last_ping;    /* Time stamp of last ping */
    int ntimeout;           /* Number of timeouts */
    char key[256];          /* Sec-WebSocket-Key */
    void *ssl;              /* Context wrap of openssl, wolfssl and mbedtls */

    void (*onopen)(struct uwsc_client *cl);
    void (*set_ping_interval)(struct uwsc_client *cl, int interval);
    void (*onmessage)(struct uwsc_client *cl, void *data, size_t len, bool binary);
    void (*onerror)(struct uwsc_client *cl, int err, const char *msg);
    void (*onclose)(struct uwsc_client *cl, int code, const char *reason);

    int (*send)(struct uwsc_client *cl, const void *data, size_t len, int op);
    int (*send_ex)(struct uwsc_client *cl, int op, int num, ...);
    int (*send_close)(struct uwsc_client *cl, int code, const char *reason);
    void (*ping)(struct uwsc_client *cl);
    void (*free)(struct uwsc_client *cl);
};

/*
 *  uwsc_new - creat an uwsc_client struct and connect to server
 *  @loop: If NULL will use EV_DEFAULT
 *  @url: A websock url. ws://xxx.com/xx or wss://xxx.com/xx
 *  @ping_interval: ping interval
 *  @extra_header: extra http header. Authorization: a1d4cdb1a3cd6a0e94aa3599afcddcf5\r\n
 */
struct uwsc_client *uwsc_new(struct ev_loop *loop, const char *url,
    int ping_interval, const char *extra_header);

int uwsc_init(struct uwsc_client *cl, struct ev_loop *loop, const char *url,
    int ping_interval, const char *extra_header);

#endif