-
Notifications
You must be signed in to change notification settings - Fork 10
/
api.txt
146 lines (93 loc) · 3.24 KB
/
api.txt
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
// Sending.
1. // Message based.
ws_send_msg()
2. // Frame based (One big message many frames)
ws_msg_begin() NONE -> MSG_BEGIN
ws_msg_frame_send()
|____________ws_msg_frame_data_begin() MSG_BEGIN -> IN_MSG
... ws_msg_frame_data_send() IN_MSG -> IN_MSG
... ws_msg_frame_data_send() IN_MSG -> IN_MSG
ws_msg_frame_send()
ws_msg_end()
3. // Stream (one huge frame)..
ws_msg_begin()
ws_msg_frame_data_begin() // Size is set here.
ws_msg_frame_data_send()
...
ws_msg_frame_data_send()
// Receiving
1. ws_on_msg(msg, is_binary)
2. ws_on_msg_begin(opcode, is_binary)
ws_on_msg_frame(payload)
ws_on_msg_end() ----> ws_on_msg()
3.
ws_on_msg_frame_begin() // If this is the first frame -> ws_on_msg_begin()
ws_on_msg_begin()
ws_on_msg_frame_data()
...
ws_on_msg_frame_data()
ws_on_msg_frame_end() ----> ws_on_msg_frame()
ws_on_msg_end()
* Add a "protocol validation" error, for when the frame is somehow incorrect, or the handshake fails.
- If msg_callback set, build msg from incoming frames and call on_msg
- If msg_begin is set, turn of on_msg (but still check for ping/pong)
(we won't start building the msg unless the user calls the default callback from its own callback)
- msg_begin/msg_frame/msg_end can only be set together:
- If the user decides to not call the default implementations
from his callbacks, its up to the user to assemble the message.
- The default callbacks uses an evbuffer to assemble the message.
- Should evbuffer_pullup be used to pass the payload of
frames to the user?:
<Received enough data for the entire frame>
if (frame_callbacks_are_set)
evbuffer_pullup... -> pass pointer to callback
in default callback:
(see below)
else
call default callback
in default callback:
bypass msg_frame payload msg
copy directly from bufferevent in-buffer to the msg evbuffer.
The evbuffer_remove_buffer() function moves exactly datlen bytes from src to the end of dst, copying as little as possible. If there are fewer than datlen bytes to move, it moves all the bytes. It returns the number of bytes moved.
After connection handshake...
process_data:
if no header is read yet:
- Got enough data to read header? Need more! return
- Read header (only remove as much as needed)
- Call handle_frame_begin
else
# We're in a frame!
- Read as much frame data as we have gotten, make sure we don't read more
than the frame payload though.
- Unmask data
- Call handle_frame_data with the frame payload.
- If we have read entire payload_len call handle_frame_end
handle_frame_begin:
if (control_frame)
Init separate control frame buffer
(control frames can come in the middle of a msg)
Don't call msg calbacks.
return
if !in_message
Init message buffer
in_message = true
msg_begin_cb(opcode)
frame_begin_cb(header)
handle_frame_data:
if (control_frame)
add data to control frame buffer
return
if (msg_frame_data_cb)
get payload from incoming buffer (evbuffer_pullup)
msg_frame_data_cb(payload)
else
handle_frame_end:
if (control frame):
process_control_frame
# No message callback.
return
frame_end_cb()
if (header.fin)
msg_end_cb()
in_message = false
unset header