NetBurner 3.5.0
PDF Version
 
websockets.h
1/*NB_REVISION*/
2
3/*NB_COPYRIGHT*/
4
5#ifndef __WEBSOCKETS_H
6#define __WEBSOCKETS_H
7
8// NB Definitions
9#include <predef.h>
10
11// NB Libs
12#include <buffers.h>
13#include <http.h>
14#include <iosys.h>
15#include <nbrtos.h>
16#include <nettypes.h>
17
18#define WS_BUFFER_SEGMENTS 4
19#define WS_MAX_SOCKS 4
20#define WS_BUFFER_MIN 10
21#define WS_ACCUM_DLY ((TICKS_PER_SECOND / 4) + 1)
22#define WS_FLUSH_TIMEOUT 0
23
24#define WS_FIN_BIT 0x80
25
26#define WS_OP_CONT 0x0
27#define WS_OP_TEXT 0x1
28#define WS_OP_BIN 0x2
29#define WS_OP_CLOSE 0x8
30#define WS_OP_PING 0x9
31#define WS_OP_PONG 0xA
32
33#define WS_SO_TEXT 0x8
34
35namespace NB
36{
37class WSCritObj;
38class WebSocket
39{
40 struct WS_Client_Short
41 {
42 uint8_t opAndFin;
43 uint8_t maskAndLen;
44 uint32_t mask;
45 uint8_t pData[];
46 } __attribute__((packed));
47 struct WS_Client_Med
48 {
49 uint8_t opAndFin;
50 uint8_t maskAndLen;
51 beuint16_t length;
52 uint32_t mask;
53 uint8_t pData[];
54 } __attribute__((packed));
55 struct WS_Client_Long
56 {
57 uint8_t opAndFin;
58 uint8_t maskAndLen;
59 beuint32_t lengthHi;
60 beuint32_t lengthLo;
61 uint32_t mask;
62 uint8_t pData[];
63 } __attribute__((packed));
64 struct WS_Server_Short
65 {
66 uint8_t opAndFin;
67 uint8_t maskAndLen;
68 uint8_t pData[];
69 } __attribute__((packed));
70 struct WS_Server_Med
71 {
72 uint8_t opAndFin;
73 uint8_t maskAndLen;
74 beuint16_t length;
75 uint8_t pData[];
76 } __attribute__((packed));
77 struct WS_Server_Long
78 {
79 uint8_t opAndFin;
80 uint8_t maskAndLen;
81 beuint32_t lengthHi;
82 beuint32_t lengthLo;
83 uint8_t pData[];
84 } __attribute__((packed));
85
86 enum WS_State
87 {
88 WS_INIT,
89 WS_CONNECTING,
90 WS_ESTABLISHED,
91 WS_CLOSE_PENDING,
92 WS_CLOSE_SENT,
93 WS_CLOSE_RECV,
94 WS_TCP_CLOSED,
95 WS_CLOSED,
96 WS_ABORT,
97 WS_FAIL
98 };
99
100 static const char *WS_StateStr(WS_State state);
101 enum WS_StatusCode
102 {
103 WS_STAT_NORM_CLOSE = 1000,
104 WS_STAT_GOING_AWAY = 1001,
105 WS_STAT_PROT_ERROR = 1002,
106 WS_STAT_UNACCEPT_TYPE = 1003,
107 WS_STAT_NONE = 1005, // Must not be sent
108 WS_STAT_NONE_ABNORMAL = 1006, // Must not be sent
109 WS_STAT_NOT_CONSISTENT = 1007,
110 WS_STAT_POLICY_VIOLATION = 1008,
111 WS_STAT_MSG_TOO_BIG = 1009,
112 WS_STAT_EXPECTED_EXTENSION = 1010,
113 WS_STAT_UNEXPECTED_COND = 1011,
114 WS_STAT_TLS_FAILURE = 1015, // Must not be sent
115 };
116
117 fifo_buffer_storage rxBuffer;
118 fifo_buffer_storage ctlBuffer;
119 fifo_buffer_storage txBuffer;
120
121 public:
122 int m_fd_tcp;
123 int m_fd_ws;
124 OS_CRIT socket_crit;
125
126 private:
127 WS_State m_state;
128 int m_options;
129 uint32_t m_SendTime;
130 uint32_t m_AccumDly;
131 bool m_serverNotClient;
132
133 volatile bool m_CtlBlock;
134 uint32_t m_currentIndex;
135 uint32_t m_remLen;
136
137 uint8_t m_frameHeadBuf[14];
138 uint8_t m_frameHeadNext;
139 bool m_gotLen;
140 uint32_t m_currentMask;
141 uint32_t m_remainingLen;
142
143 uint8_t m_txFrameHeadBuf[14];
144 uint8_t m_txFrameHeadNext;
145 uint8_t m_txFrameHeadLen;
146 uint32_t m_txCurrMask;
147 uint32_t m_txRemLen;
148 int m_txFlushInProgress;
149 bool m_txCtlSendInProgress;
150
151 struct PendingCtlWait {
152 OS_SEM sem;
153 PendingCtlWait *pNext;
154 };
155 PendingCtlWait *m_ctlWait;
156
157 uint32_t m_pingTick;
158 int m_pingLen;
159 OS_SEM *m_pingWaitSem;
160
161 uint32_t m_txBufferMin;
162
163 void ServerRxFromTCP();
164 bool ReadRemainingHeader();
165 void ProcessCtlFrame();
166 bool ValidatePong(uint32_t seed, uint32_t len);
167 void Close(bool closedAfterSend, uint16_t code = 0, const char *reason = NULL, int len = 0);
168 void RemoteClose();
169 void CleanUp();
170 void SendCtlFrame();
171 void Init(int fd_tcp, int fd_ws, bool serverNotClient);
172 void Flush_Header(uint8_t *buf, uint32_t mask, uint32_t len);
173
174 void AddCtlWait(PendingCtlWait *pWait);
175 void PostToCtlWait();
176
177 static uint32_t s_flushTick;
178 static fd_set s_pendingCtlSocks;
179 static OS_CRIT s_ws_crit_obj;
180 static bool s_bFinishedInit;
181
182 static void StaticInit();
183 static int GetNewSocket(int fd_tcp, bool serverNotClient);
184
185 static WebSocket *GetRecordFromTCP(int fd);
186
187 static int CoreConnect(IPADDR ip, const char *host, const char *resource, const char *protocol, int portnum, bool useSSL = false);
188
189 public:
190 int WriteData(const char *buf, int nbytes);
191 int ReadData(char *buf, int nbytes);
192 void Flush();
193 void Pong(uint32_t len);
194 inline WS_State GetState() { return m_state; }
195 int Ping(uint32_t len, uint32_t *sentTick);
196 int WaitForPingReply(uint32_t timeout);
197 int GetPingReplyTick(uint32_t *replyTick);
198
199 int setoption(int option);
200 int clroption(int option);
201 int getoption();
202
203 inline int GetWriteSpace() { return txBuffer.SpaceAvail(); }
204
205 static int s_openSocketCount; // really should be private, but can't figure how
206 static WebSocket WSSockStructs[WS_MAX_SOCKS];
207
208 static int ws_readwto(int fd, char *buf, int nbytes, int timeout);
209 static int ws_read(int fd, char *buf, int nbytes);
210 static int ws_write(int fd, const char *buf, int nbytes);
211 static int ws_externalclose(int fd);
212 static void ws_flush(int fd);
213 static int ws_setoption(int fd, int option);
214 static int ws_clroption(int fd, int option);
215 static int ws_getoption(int fd);
216
217 static WebSocket *GetWebSocketRecord(int fd);
218 static int promote_tcp_ws(int tcp_fd);
219 static void ws_read_notify(int fd); // tcp data rx callback
220 static void ws_write_notify(int fd); // tcp data tx space callback
221 static void GetFlushTime();
222
223 static void RunSkippedCallBack();
224
225 static int Connect(const char * host, const char * resource, const char * protocol, int portnum = 80, bool useSSL = false);
226 static inline int Connect(const char * host, const char * resource, int portnum = 80, bool useSSL = false)
227 { return Connect(host, resource, NULL, portnum, useSSL); }
228 static int Connect(IPADDR host, const char * resource, const char * protocol, int portnum = 80, bool useSSL = false);
229 static inline int Connect(IPADDR host, const char * resource, int portnum = 80, bool useSSL = false)
230 { return Connect(host, resource, NULL, portnum, useSSL); }
231
232 void DumpSock();
233 static void DumpSockets();
234 static int GetFreeWebSocketCount();
235};
236
237} // namespace NB
238
239int WSPing(int fd, uint32_t len, uint32_t *sentTick);
240int WSGetPingReplyTick(int fd, uint32_t *replyTick);
241int WSWaitForPingReply(int fd, uint32_t timeout);
242int WSUpgrade(HTTP_Request *req, int sock);
243#endif /* ----- #ifndef __WEBSOCKETS_H ----- */
NetBurner Buffers API.
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition ipv6_addr.h:41
NetBurner HTTP Web Server Header File.
NetBurner I/O System Library API.
NetBurner Real-Time Operating System (NBRTOS) API.
NetBurner IPADDR4 Class. See the IPADDR4 Class page for complete documentation.
HTTP Request Structure.
Definition http.h:69
An OS_CRIT object is used to establish critical sections of code that can only be run by one task at ...
Definition nbrtos.h:1084
Semaphores are used to control access to shared resources or or to communicate between tasks in a mul...
Definition nbrtos.h:386