Skip to content

Commit 893f805

Browse files
committed
Added websocket source file
1 parent cbdbf5c commit 893f805

File tree

3 files changed

+242
-0
lines changed

3 files changed

+242
-0
lines changed

include/websocket.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Tianfeng Han <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
18+
19+
#ifndef SW_WEBSOCKET_H_
20+
#define SW_WEBSOCKET_H_
21+
22+
int swWebSocket_encode(char *data, int length);
23+
int swWebSocket_decode(char *data, int length);
24+
25+
#endif /* SW_WEBSOCKET_H_ */

src/protocol/WebSocket.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Tianfeng Han <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "swoole.h"
18+
19+
#define SW_WEBSOCKET_HEADER_LEN 2
20+
#define SW_WEBSOCKET_MASK_LEN 4
21+
#define SW_WEBSOCKET_EXT16_LENGTH 0x7E
22+
#define SW_WEBSOCKET_EXT16_MAX_LEN 0xFFFF
23+
#define SW_WEBSOCKET_EXT64_LENGTH 0x7F
24+
#define SW_WEBSOCKET_MASKED(frm) (frm->header.MASK)
25+
26+
#define SW_WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
27+
28+
typedef struct
29+
{
30+
/**
31+
* fin:1 rsv1:1 rsv2:1 rsv3:1 opcode:4
32+
*/
33+
struct
34+
{
35+
unsigned char OPCODE :4;
36+
unsigned char RSV3 :1;
37+
unsigned char RSV2 :1;
38+
unsigned char RSV1 :1;
39+
unsigned char FIN :1;
40+
unsigned char LENGTH :7;
41+
unsigned char MASK :1;
42+
} header;
43+
char mask[SW_WEBSOCKET_MASK_LEN];
44+
size_t length;
45+
char *payload;
46+
47+
} swWebSocket_frame;
48+
49+
50+
enum
51+
{
52+
WEBSOCKET_OPCODE_CONTINUATION_FRAME = 0x0,
53+
WEBSOCKET_OPCODE_TEXT_FRAME = 0x1,
54+
WEBSOCKET_OPCODE_BINARY_FRAME = 0x2,
55+
WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
56+
WEBSOCKET_OPCODE_PING = 0x9,
57+
WEBSOCKET_OPCODE_PONG = 0xa,
58+
59+
WEBSOCKET_CLOSE_NORMAL = 1000,
60+
WEBSOCKET_CLOSE_GOING_AWAY = 1001,
61+
WEBSOCKET_CLOSE_PROTOCOL_ERROR = 1002,
62+
WEBSOCKET_CLOSE_DATA_ERROR = 1003,
63+
WEBSOCKET_CLOSE_STATUS_ERROR = 1005,
64+
WEBSOCKET_CLOSE_ABNORMAL = 1006,
65+
WEBSOCKET_CLOSE_MESSAGE_ERROR = 1007,
66+
WEBSOCKET_CLOSE_POLICY_ERROR = 1008,
67+
WEBSOCKET_CLOSE_MESSAGE_TOO_BIG = 1009,
68+
WEBSOCKET_CLOSE_EXTENSION_MISSING = 1010,
69+
WEBSOCKET_CLOSE_SERVER_ERROR = 1011,
70+
WEBSOCKET_CLOSE_TLS = 1015,
71+
WEBSOCKET_VERSION = 13,
72+
73+
} SW_WEBSOCKET;
74+
75+
uint64_t hton64(uint64_t host);
76+
uint64_t ntoh64(uint64_t network);
77+
78+
static void swWebSocket_print_frame(swWebSocket_frame *frm);
79+
static void swWebSocket_unmask(swWebSocket_frame *frm);
80+
81+
int swWebSocket_encode(char *data, int length)
82+
{
83+
return SW_OK;
84+
}
85+
86+
uint64_t hton64(uint64_t host)
87+
{
88+
uint64_t ret = 0;
89+
uint32_t high, low;
90+
91+
low = host & 0xFFFFFFFF;
92+
high = (host >> 32) & 0xFFFFFFFF;
93+
low = htonl(low);
94+
high = htonl(high);
95+
ret = low;
96+
ret <<= 32;
97+
ret |= high;
98+
return ret;
99+
}
100+
101+
uint64_t ntoh64(uint64_t host)
102+
{
103+
uint64_t ret = 0;
104+
uint32_t high, low;
105+
106+
low = host & 0xFFFFFFFF;
107+
high = (host >> 32) & 0xFFFFFFFF;
108+
low = ntohl(low);
109+
high = ntohl(high);
110+
ret = low;
111+
ret <<= 32;
112+
ret |= high;
113+
return ret;
114+
}
115+
116+
int swWebSocket_decode(char *buf, int length)
117+
{
118+
swWebSocket_frame *frm = malloc(sizeof(swWebSocket_frame));
119+
bzero(frm, sizeof(swWebSocket_frame));
120+
121+
memcpy(frm, buf, 2);
122+
buf += SW_WEBSOCKET_HEADER_LEN;
123+
124+
/**
125+
* 126
126+
*/
127+
if (frm->header.LENGTH < 0x7E)
128+
{
129+
frm->length = frm->header.LENGTH;
130+
}
131+
/**
132+
* Short
133+
*/
134+
else if (0x7E == frm->header.LENGTH)
135+
{
136+
frm->length = ntohs(*((uint16_t *) buf));
137+
buf += sizeof(short);
138+
}
139+
else
140+
{
141+
frm->length = ntoh64(*((uint64_t *) buf));
142+
buf += sizeof(int64_t);
143+
}
144+
145+
if (frm->header.MASK)
146+
{
147+
memcpy(frm->mask, buf, SW_WEBSOCKET_MASK_LEN);
148+
buf += SW_WEBSOCKET_MASK_LEN;
149+
frm->payload = buf;
150+
151+
if (frm->length)
152+
{
153+
swWebSocket_unmask(frm);
154+
}
155+
}
156+
else
157+
{
158+
frm->payload = buf;
159+
}
160+
swWebSocket_print_frame(frm);
161+
162+
return SW_OK;
163+
}
164+
165+
static void swWebSocket_unmask(swWebSocket_frame *frm)
166+
{
167+
int i;
168+
for (i = 0; i < frm->length; i++)
169+
{
170+
frm->payload[i] = frm->payload[i] ^ frm->mask[i % SW_WEBSOCKET_MASK_LEN];
171+
}
172+
}
173+
174+
static void swWebSocket_print_frame(swWebSocket_frame *frm)
175+
{
176+
int i;
177+
printf("FIN: %x, RSV1: %d, RSV2: %d, RSV3: %d, opcode: %d, MASK: %d, length: %ld\n", frm->header.FIN,
178+
frm->header.RSV1, frm->header.RSV2, frm->header.RSV3, frm->header.OPCODE, frm->header.MASK,
179+
frm->length);
180+
181+
if (frm->length)
182+
{
183+
printf("payload: %s\n", frm->payload);
184+
}
185+
}
186+

tests/websocket.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Tianfeng Han <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "swoole.h"
18+
#include "tests.h"
19+
#include "websocket.h"
20+
21+
swUnitTest(ws_test1)
22+
{
23+
char buf[65536];
24+
int fd = open("./websocket.log", O_RDONLY);
25+
int len = swoole_sync_readfile(fd, buf, 65536) ;
26+
if (len > 0)
27+
{
28+
swWebSocket_decode(buf, len);
29+
}
30+
return 0;
31+
}

0 commit comments

Comments
 (0)