User | Revision | Line number | New contents of line |
donatien |
0:87e52bb764c5
|
1
|
#define __DEBUG__ 4 //Maximum verbosity
|
donatien |
0:87e52bb764c5
|
2
|
#ifndef __MODULE__
|
donatien |
0:87e52bb764c5
|
3
|
#define __MODULE__ "Websocket.cpp"
|
donatien |
0:87e52bb764c5
|
4
|
#endif
|
donatien |
0:87e52bb764c5
|
5
|
|
donatien |
0:87e52bb764c5
|
6
|
#include "core/fwk.h"
|
donatien |
0:87e52bb764c5
|
7
|
|
donatien |
0:87e52bb764c5
|
8
|
#include "Websocket.h"
|
donatien |
0:87e52bb764c5
|
9
|
#include <string>
|
donatien |
0:87e52bb764c5
|
10
|
|
donatien |
0:87e52bb764c5
|
11
|
|
donatien |
0:87e52bb764c5
|
12
|
Websocket::Websocket(char * url) : m_sockHandle(-1) {
|
donatien |
0:87e52bb764c5
|
13
|
//server_ip = NULL;
|
donatien |
0:87e52bb764c5
|
14
|
|
donatien |
0:87e52bb764c5
|
15
|
std::memset(&m_sockAddr, 0, sizeof(struct sockaddr_in));
|
donatien |
0:87e52bb764c5
|
16
|
|
donatien |
0:87e52bb764c5
|
17
|
fillFields(url);
|
donatien |
0:87e52bb764c5
|
18
|
}
|
donatien |
0:87e52bb764c5
|
19
|
|
donatien |
0:87e52bb764c5
|
20
|
|
donatien |
0:87e52bb764c5
|
21
|
void Websocket::fillFields(char * url) {
|
donatien |
0:87e52bb764c5
|
22
|
char *res = NULL;
|
donatien |
0:87e52bb764c5
|
23
|
char *res1 = NULL;
|
donatien |
0:87e52bb764c5
|
24
|
|
donatien |
0:87e52bb764c5
|
25
|
char buf[50];
|
donatien |
0:87e52bb764c5
|
26
|
strcpy(buf, url);
|
donatien |
0:87e52bb764c5
|
27
|
|
donatien |
0:87e52bb764c5
|
28
|
res = strtok(buf, ":");
|
donatien |
0:87e52bb764c5
|
29
|
if (strcmp(res, "ws")) {
|
donatien |
0:87e52bb764c5
|
30
|
#ifdef DEBUG
|
donatien |
0:87e52bb764c5
|
31
|
printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n");
|
donatien |
0:87e52bb764c5
|
32
|
#endif
|
donatien |
0:87e52bb764c5
|
33
|
} else {
|
donatien |
0:87e52bb764c5
|
34
|
//ip_domain and port
|
donatien |
0:87e52bb764c5
|
35
|
res = strtok(NULL, "/");
|
donatien |
0:87e52bb764c5
|
36
|
|
donatien |
0:87e52bb764c5
|
37
|
//path
|
donatien |
0:87e52bb764c5
|
38
|
res1 = strtok(NULL, " ");
|
donatien |
0:87e52bb764c5
|
39
|
if (res1 != NULL) {
|
donatien |
0:87e52bb764c5
|
40
|
path = res1;
|
donatien |
0:87e52bb764c5
|
41
|
}
|
donatien |
0:87e52bb764c5
|
42
|
|
donatien |
0:87e52bb764c5
|
43
|
//ip_domain
|
donatien |
0:87e52bb764c5
|
44
|
res = strtok(res, ":");
|
donatien |
0:87e52bb764c5
|
45
|
|
donatien |
0:87e52bb764c5
|
46
|
//port
|
donatien |
0:87e52bb764c5
|
47
|
res1 = strtok(NULL, " ");
|
donatien |
0:87e52bb764c5
|
48
|
//port
|
donatien |
0:87e52bb764c5
|
49
|
if (res1 != NULL) {
|
donatien |
0:87e52bb764c5
|
50
|
port = res1;
|
donatien |
0:87e52bb764c5
|
51
|
} else {
|
donatien |
0:87e52bb764c5
|
52
|
port = "80";
|
donatien |
0:87e52bb764c5
|
53
|
}
|
donatien |
0:87e52bb764c5
|
54
|
|
donatien |
0:87e52bb764c5
|
55
|
if (res != NULL) {
|
donatien |
0:87e52bb764c5
|
56
|
ip_domain = res;
|
donatien |
0:87e52bb764c5
|
57
|
|
donatien |
0:87e52bb764c5
|
58
|
//if we use ethernet, we must decode ip address or use dnsresolver
|
donatien |
0:87e52bb764c5
|
59
|
strcpy(buf, res);
|
donatien |
0:87e52bb764c5
|
60
|
|
donatien |
0:87e52bb764c5
|
61
|
//we try to decode the ip address
|
donatien |
0:87e52bb764c5
|
62
|
if (buf[0] >= '0' && buf[0] <= '9') {
|
donatien |
0:87e52bb764c5
|
63
|
res = strtok(buf, ".");
|
donatien |
0:87e52bb764c5
|
64
|
int i = 0;
|
donatien |
0:87e52bb764c5
|
65
|
int ip[4];
|
donatien |
0:87e52bb764c5
|
66
|
while (res != NULL) {
|
donatien |
0:87e52bb764c5
|
67
|
ip[i] = atoi(res);
|
donatien |
0:87e52bb764c5
|
68
|
res = strtok(NULL, ".");
|
donatien |
0:87e52bb764c5
|
69
|
i++;
|
donatien |
0:87e52bb764c5
|
70
|
}
|
donatien |
0:87e52bb764c5
|
71
|
//server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]);
|
donatien |
0:87e52bb764c5
|
72
|
m_sockAddr.sin_addr.s_addr = (ip[0] << 24) | (ip[1] << 16) | (ip[2] << 8) | ip[3]; //Could do this easier if using inet_pton()
|
donatien |
0:87e52bb764c5
|
73
|
|
donatien |
0:87e52bb764c5
|
74
|
}
|
donatien |
0:87e52bb764c5
|
75
|
}
|
donatien |
0:87e52bb764c5
|
76
|
}
|
donatien |
0:87e52bb764c5
|
77
|
}
|
donatien |
0:87e52bb764c5
|
78
|
|
donatien |
0:87e52bb764c5
|
79
|
|
donatien |
0:87e52bb764c5
|
80
|
bool Websocket::connect() {
|
donatien |
0:87e52bb764c5
|
81
|
char cmd[192];
|
donatien |
0:87e52bb764c5
|
82
|
|
donatien |
0:87e52bb764c5
|
83
|
//Resolve DNS if needed
|
donatien |
0:87e52bb764c5
|
84
|
if(m_sockAddr.sin_addr.s_addr == 0)
|
donatien |
0:87e52bb764c5
|
85
|
{
|
donatien |
0:87e52bb764c5
|
86
|
DBG("Resolving DNS socket");
|
donatien |
0:87e52bb764c5
|
87
|
struct hostent *server = socket::gethostbyname(ip_domain.c_str());
|
donatien |
0:87e52bb764c5
|
88
|
if(server == NULL)
|
donatien |
0:87e52bb764c5
|
89
|
{
|
donatien |
0:87e52bb764c5
|
90
|
return false;
|
donatien |
0:87e52bb764c5
|
91
|
}
|
donatien |
0:87e52bb764c5
|
92
|
memcpy((char*)&m_sockAddr.sin_addr.s_addr, (char*)server->h_addr_list[0], server->h_length);
|
donatien |
0:87e52bb764c5
|
93
|
}
|
donatien |
0:87e52bb764c5
|
94
|
|
donatien |
0:87e52bb764c5
|
95
|
m_sockAddr.sin_family = AF_INET;
|
donatien |
0:87e52bb764c5
|
96
|
m_sockAddr.sin_port = htons(atoi(port.c_str()));
|
donatien |
0:87e52bb764c5
|
97
|
|
donatien |
0:87e52bb764c5
|
98
|
//Create socket
|
donatien |
0:87e52bb764c5
|
99
|
DBG("Creating socket");
|
donatien |
0:87e52bb764c5
|
100
|
m_sockHandle = socket::socket(AF_INET, SOCK_STREAM, 0);
|
donatien |
0:87e52bb764c5
|
101
|
if (m_sockHandle < 0)
|
donatien |
0:87e52bb764c5
|
102
|
{
|
donatien |
0:87e52bb764c5
|
103
|
ERR("Could not create socket");
|
donatien |
0:87e52bb764c5
|
104
|
return false;
|
donatien |
0:87e52bb764c5
|
105
|
}
|
donatien |
0:87e52bb764c5
|
106
|
DBG("Handle is %d",m_sockHandle);
|
donatien |
0:87e52bb764c5
|
107
|
|
donatien |
0:87e52bb764c5
|
108
|
//Connect
|
donatien |
0:87e52bb764c5
|
109
|
DBG("Connecting socket to %s:%d", inet_ntoa(m_sockAddr.sin_addr), ntohs(m_sockAddr.sin_port));
|
donatien |
0:87e52bb764c5
|
110
|
int ret = socket::connect(m_sockHandle, (const struct sockaddr *)&m_sockAddr, sizeof(m_sockAddr));
|
donatien |
0:87e52bb764c5
|
111
|
if (ret < 0)
|
donatien |
0:87e52bb764c5
|
112
|
{
|
donatien |
0:87e52bb764c5
|
113
|
socket::close(m_sockHandle);
|
donatien |
0:87e52bb764c5
|
114
|
ERR("Could not connect");
|
donatien |
0:87e52bb764c5
|
115
|
return false;
|
donatien |
0:87e52bb764c5
|
116
|
}
|
donatien |
0:87e52bb764c5
|
117
|
|
donatien |
0:87e52bb764c5
|
118
|
m_connected = true;
|
donatien |
0:87e52bb764c5
|
119
|
|
donatien |
0:87e52bb764c5
|
120
|
DBG("Sending HTTP request");
|
donatien |
0:87e52bb764c5
|
121
|
//send websocket HTTP header
|
donatien |
0:87e52bb764c5
|
122
|
sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str());
|
donatien |
0:87e52bb764c5
|
123
|
write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
124
|
|
donatien |
0:87e52bb764c5
|
125
|
sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str());
|
donatien |
0:87e52bb764c5
|
126
|
write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
127
|
|
donatien |
0:87e52bb764c5
|
128
|
sprintf(cmd, "Upgrade: WebSocket\r\n");
|
donatien |
0:87e52bb764c5
|
129
|
write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
130
|
|
donatien |
0:87e52bb764c5
|
131
|
sprintf(cmd, "Connection: Upgrade\r\n");
|
donatien |
0:87e52bb764c5
|
132
|
write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
133
|
|
donatien |
0:87e52bb764c5
|
134
|
// socket::send(m_sockHandle, "Origin: null\r\n", strlen("Origin: null\r\n"), 0);
|
donatien |
0:87e52bb764c5
|
135
|
|
donatien |
0:87e52bb764c5
|
136
|
sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n");
|
donatien |
0:87e52bb764c5
|
137
|
write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
138
|
|
donatien |
0:87e52bb764c5
|
139
|
sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
|
donatien |
0:87e52bb764c5
|
140
|
ret = write((uint8_t*)cmd, strlen(cmd));
|
donatien |
0:87e52bb764c5
|
141
|
if(ret < 0)
|
donatien |
0:87e52bb764c5
|
142
|
{
|
donatien |
0:87e52bb764c5
|
143
|
close();
|
donatien |
0:87e52bb764c5
|
144
|
ERR("Could not send request");
|
donatien |
0:87e52bb764c5
|
145
|
m_connected = false;
|
donatien |
0:87e52bb764c5
|
146
|
return false;
|
donatien |
0:87e52bb764c5
|
147
|
}
|
donatien |
0:87e52bb764c5
|
148
|
|
donatien |
0:87e52bb764c5
|
149
|
DBG("Waiting for answer");
|
donatien |
0:87e52bb764c5
|
150
|
ret = read((uint8_t*)cmd, 0, 192);
|
donatien |
0:87e52bb764c5
|
151
|
if(ret < 0)
|
donatien |
0:87e52bb764c5
|
152
|
{
|
donatien |
0:87e52bb764c5
|
153
|
close();
|
donatien |
0:87e52bb764c5
|
154
|
ERR("Could not receive answer");
|
donatien |
0:87e52bb764c5
|
155
|
m_connected = false;
|
donatien |
0:87e52bb764c5
|
156
|
return false;
|
donatien |
0:87e52bb764c5
|
157
|
}
|
donatien |
0:87e52bb764c5
|
158
|
cmd[ret] = '\0';
|
donatien |
0:87e52bb764c5
|
159
|
|
donatien |
0:87e52bb764c5
|
160
|
DBG("Comparing answer");
|
donatien |
0:87e52bb764c5
|
161
|
if( strstr(cmd, "Sec-WebSocket-Accept: DdLWT/1JcX+nQFHebYP+rqEx5xI=") == NULL )
|
donatien |
0:87e52bb764c5
|
162
|
{
|
donatien |
0:87e52bb764c5
|
163
|
ERR("Wrong answer from server, got \"%s\" instead", cmd);
|
donatien |
0:87e52bb764c5
|
164
|
do{
|
donatien |
0:87e52bb764c5
|
165
|
ret = read((uint8_t*)cmd, 0, 192);
|
donatien |
0:87e52bb764c5
|
166
|
if(ret < 0)
|
donatien |
0:87e52bb764c5
|
167
|
{
|
donatien |
0:87e52bb764c5
|
168
|
ERR("Could not receive answer");
|
donatien |
0:87e52bb764c5
|
169
|
return false;
|
donatien |
0:87e52bb764c5
|
170
|
}
|
donatien |
0:87e52bb764c5
|
171
|
cmd[ret] = '\0';
|
donatien |
0:87e52bb764c5
|
172
|
printf("%s",cmd);
|
donatien |
0:87e52bb764c5
|
173
|
} while(ret > 0);
|
donatien |
0:87e52bb764c5
|
174
|
close();
|
donatien |
0:87e52bb764c5
|
175
|
m_connected = false;
|
donatien |
0:87e52bb764c5
|
176
|
return false;
|
donatien |
0:87e52bb764c5
|
177
|
}
|
donatien |
0:87e52bb764c5
|
178
|
DBG("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain.c_str(), this->path.c_str(), this->port.c_str());
|
donatien |
0:87e52bb764c5
|
179
|
return true;
|
donatien |
0:87e52bb764c5
|
180
|
}
|
donatien |
0:87e52bb764c5
|
181
|
|
donatien |
0:87e52bb764c5
|
182
|
void Websocket::sendLength(uint32_t len) {
|
donatien |
0:87e52bb764c5
|
183
|
if (len < 126) {
|
donatien |
0:87e52bb764c5
|
184
|
sendChar(len | (1<<7));
|
donatien |
0:87e52bb764c5
|
185
|
} else if (len < 65535) {
|
donatien |
0:87e52bb764c5
|
186
|
sendChar(126 | (1<<7));
|
donatien |
0:87e52bb764c5
|
187
|
sendChar(len & 0xff);
|
donatien |
0:87e52bb764c5
|
188
|
sendChar((len >> 8) & 0xff);
|
donatien |
0:87e52bb764c5
|
189
|
} else {
|
donatien |
0:87e52bb764c5
|
190
|
sendChar(127 | (1<<7));
|
donatien |
0:87e52bb764c5
|
191
|
for (int i = 0; i < 8; i++) {
|
donatien |
0:87e52bb764c5
|
192
|
sendChar((len >> i*8) & 0xff);
|
donatien |
0:87e52bb764c5
|
193
|
}
|
donatien |
0:87e52bb764c5
|
194
|
}
|
donatien |
0:87e52bb764c5
|
195
|
}
|
donatien |
0:87e52bb764c5
|
196
|
|
donatien |
0:87e52bb764c5
|
197
|
void Websocket::sendChar(uint8_t c) {
|
donatien |
0:87e52bb764c5
|
198
|
write(&c, 1);
|
donatien |
0:87e52bb764c5
|
199
|
}
|
donatien |
0:87e52bb764c5
|
200
|
|
donatien |
0:87e52bb764c5
|
201
|
bool Websocket::readChar(uint8_t* pC, bool block)
|
donatien |
0:87e52bb764c5
|
202
|
{
|
donatien |
0:87e52bb764c5
|
203
|
int ret = read(pC, 1, block?36000000:3000);
|
donatien |
0:87e52bb764c5
|
204
|
if(ret < 0)
|
donatien |
0:87e52bb764c5
|
205
|
{
|
donatien |
0:87e52bb764c5
|
206
|
return false;
|
donatien |
0:87e52bb764c5
|
207
|
}
|
donatien |
0:87e52bb764c5
|
208
|
return true;
|
donatien |
0:87e52bb764c5
|
209
|
}
|
donatien |
0:87e52bb764c5
|
210
|
|
donatien |
0:87e52bb764c5
|
211
|
void Websocket::sendOpcode(uint8_t opcode) {
|
donatien |
0:87e52bb764c5
|
212
|
sendChar(0x80 | (opcode & 0x0f));
|
donatien |
0:87e52bb764c5
|
213
|
}
|
donatien |
0:87e52bb764c5
|
214
|
|
donatien |
0:87e52bb764c5
|
215
|
void Websocket::sendMask() {
|
donatien |
0:87e52bb764c5
|
216
|
for (int i = 0; i < 4; i++) {
|
donatien |
0:87e52bb764c5
|
217
|
sendChar(0);
|
donatien |
0:87e52bb764c5
|
218
|
}
|
donatien |
0:87e52bb764c5
|
219
|
}
|
donatien |
0:87e52bb764c5
|
220
|
|
donatien |
0:87e52bb764c5
|
221
|
void Websocket::send(char * str) {
|
donatien |
0:87e52bb764c5
|
222
|
sendOpcode(0x01);
|
donatien |
0:87e52bb764c5
|
223
|
sendLength(strlen(str));
|
donatien |
0:87e52bb764c5
|
224
|
sendMask();
|
donatien |
0:87e52bb764c5
|
225
|
|
donatien |
0:87e52bb764c5
|
226
|
write((uint8_t*)str, strlen(str));
|
donatien |
0:87e52bb764c5
|
227
|
}
|
donatien |
0:87e52bb764c5
|
228
|
|
donatien |
0:87e52bb764c5
|
229
|
|
donatien |
0:87e52bb764c5
|
230
|
|
donatien |
0:87e52bb764c5
|
231
|
bool Websocket::read(char * message) {
|
donatien |
0:87e52bb764c5
|
232
|
int i = 0;
|
donatien |
0:87e52bb764c5
|
233
|
//int length_buffer = 0;
|
donatien |
0:87e52bb764c5
|
234
|
uint32_t len_msg;
|
donatien |
0:87e52bb764c5
|
235
|
char opcode = 0;
|
donatien |
0:87e52bb764c5
|
236
|
uint8_t c;
|
donatien |
0:87e52bb764c5
|
237
|
char mask[4] = {0, 0, 0, 0};
|
donatien |
0:87e52bb764c5
|
238
|
Timer tmr;
|
donatien |
0:87e52bb764c5
|
239
|
|
donatien |
0:87e52bb764c5
|
240
|
//length_buffer = wifi->readable();
|
donatien |
0:87e52bb764c5
|
241
|
|
donatien |
0:87e52bb764c5
|
242
|
// read the opcode
|
donatien |
0:87e52bb764c5
|
243
|
tmr.start();
|
donatien |
0:87e52bb764c5
|
244
|
while (true) {
|
donatien |
0:87e52bb764c5
|
245
|
if (tmr.read() > 3) {
|
donatien |
0:87e52bb764c5
|
246
|
return false;
|
donatien |
0:87e52bb764c5
|
247
|
}
|
donatien |
0:87e52bb764c5
|
248
|
if(!readChar((uint8_t*)&c, false))
|
donatien |
0:87e52bb764c5
|
249
|
{
|
donatien |
0:87e52bb764c5
|
250
|
return false;
|
donatien |
0:87e52bb764c5
|
251
|
}
|
donatien |
0:87e52bb764c5
|
252
|
|
donatien |
0:87e52bb764c5
|
253
|
opcode = c;
|
donatien |
0:87e52bb764c5
|
254
|
if (opcode == 0x81) {
|
donatien |
0:87e52bb764c5
|
255
|
break;
|
donatien |
0:87e52bb764c5
|
256
|
}
|
donatien |
0:87e52bb764c5
|
257
|
}
|
donatien |
0:87e52bb764c5
|
258
|
#ifdef DEBUG
|
donatien |
0:87e52bb764c5
|
259
|
printf("opcode: 0x%X\r\n", opcode);
|
donatien |
0:87e52bb764c5
|
260
|
#endif
|
donatien |
0:87e52bb764c5
|
261
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
262
|
len_msg = c & 0x7f;
|
donatien |
0:87e52bb764c5
|
263
|
if (len_msg == 126) {
|
donatien |
0:87e52bb764c5
|
264
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
265
|
len_msg = c;
|
donatien |
0:87e52bb764c5
|
266
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
267
|
len_msg += c << 8;
|
donatien |
0:87e52bb764c5
|
268
|
} else if (len_msg == 127) {
|
donatien |
0:87e52bb764c5
|
269
|
len_msg = 0;
|
donatien |
0:87e52bb764c5
|
270
|
for (i = 0; i < 8; i++) {
|
donatien |
0:87e52bb764c5
|
271
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
272
|
len_msg += c << i*8;
|
donatien |
0:87e52bb764c5
|
273
|
}
|
donatien |
0:87e52bb764c5
|
274
|
}
|
donatien |
0:87e52bb764c5
|
275
|
if(len_msg == 0) {
|
donatien |
0:87e52bb764c5
|
276
|
return false;
|
donatien |
0:87e52bb764c5
|
277
|
}
|
donatien |
0:87e52bb764c5
|
278
|
#ifdef DEBUG
|
donatien |
0:87e52bb764c5
|
279
|
printf("length: %d\r\n", len_msg);
|
donatien |
0:87e52bb764c5
|
280
|
#endif
|
donatien |
0:87e52bb764c5
|
281
|
if ((len_msg & 0x80)) {
|
donatien |
0:87e52bb764c5
|
282
|
for (i = 0; i < 4; i++)
|
donatien |
0:87e52bb764c5
|
283
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
284
|
mask[i] = c;
|
donatien |
0:87e52bb764c5
|
285
|
}
|
donatien |
0:87e52bb764c5
|
286
|
|
donatien |
0:87e52bb764c5
|
287
|
|
donatien |
0:87e52bb764c5
|
288
|
|
donatien |
0:87e52bb764c5
|
289
|
for (i = 0; i < len_msg; i++) {
|
donatien |
0:87e52bb764c5
|
290
|
readChar((uint8_t*)&c);
|
donatien |
0:87e52bb764c5
|
291
|
message[i] = c ^ mask[i % 4];
|
donatien |
0:87e52bb764c5
|
292
|
}
|
donatien |
0:87e52bb764c5
|
293
|
|
donatien |
0:87e52bb764c5
|
294
|
message[len_msg] = 0;
|
donatien |
0:87e52bb764c5
|
295
|
return true;
|
donatien |
0:87e52bb764c5
|
296
|
}
|
donatien |
0:87e52bb764c5
|
297
|
|
donatien |
0:87e52bb764c5
|
298
|
bool Websocket::close() {
|
donatien |
0:87e52bb764c5
|
299
|
if((m_sockHandle < 0) || !m_connected)
|
donatien |
0:87e52bb764c5
|
300
|
{
|
donatien |
0:87e52bb764c5
|
301
|
return false;
|
donatien |
0:87e52bb764c5
|
302
|
}
|
donatien |
0:87e52bb764c5
|
303
|
m_connected = false;
|
donatien |
0:87e52bb764c5
|
304
|
int ret = socket::close(m_sockHandle);
|
donatien |
0:87e52bb764c5
|
305
|
if (ret < 0)
|
donatien |
0:87e52bb764c5
|
306
|
{
|
donatien |
0:87e52bb764c5
|
307
|
ERR("Could not disconnect");
|
donatien |
0:87e52bb764c5
|
308
|
return false;
|
donatien |
0:87e52bb764c5
|
309
|
}
|
donatien |
0:87e52bb764c5
|
310
|
return true;
|
donatien |
0:87e52bb764c5
|
311
|
}
|
donatien |
0:87e52bb764c5
|
312
|
|
donatien |
0:87e52bb764c5
|
313
|
|
donatien |
0:87e52bb764c5
|
314
|
|
donatien |
0:87e52bb764c5
|
315
|
bool Websocket::connected() {
|
donatien |
0:87e52bb764c5
|
316
|
return m_connected;
|
donatien |
0:87e52bb764c5
|
317
|
}
|
donatien |
0:87e52bb764c5
|
318
|
|
donatien |
0:87e52bb764c5
|
319
|
std::string Websocket::getPath() {
|
donatien |
0:87e52bb764c5
|
320
|
return path;
|
donatien |
0:87e52bb764c5
|
321
|
}
|
donatien |
0:87e52bb764c5
|
322
|
|
donatien |
0:87e52bb764c5
|
323
|
int Websocket::waitReadable(uint32_t timeout)
|
donatien |
0:87e52bb764c5
|
324
|
{
|
donatien |
0:87e52bb764c5
|
325
|
//Creating FS set
|
donatien |
0:87e52bb764c5
|
326
|
fd_set socksSet;
|
donatien |
0:87e52bb764c5
|
327
|
FD_ZERO(&socksSet);
|
donatien |
0:87e52bb764c5
|
328
|
FD_SET(m_sockHandle, &socksSet);
|
donatien |
0:87e52bb764c5
|
329
|
struct timeval t_val;
|
donatien |
0:87e52bb764c5
|
330
|
t_val.tv_sec = timeout / 1000;
|
donatien |
0:87e52bb764c5
|
331
|
t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000;
|
donatien |
0:87e52bb764c5
|
332
|
int ret = socket::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val);
|
donatien |
0:87e52bb764c5
|
333
|
if(ret <= 0 || !FD_ISSET(m_sockHandle, &socksSet))
|
donatien |
0:87e52bb764c5
|
334
|
{
|
donatien |
0:87e52bb764c5
|
335
|
return -1; //Timeout
|
donatien |
0:87e52bb764c5
|
336
|
}
|
donatien |
0:87e52bb764c5
|
337
|
return 0;
|
donatien |
0:87e52bb764c5
|
338
|
}
|
donatien |
0:87e52bb764c5
|
339
|
|
donatien |
0:87e52bb764c5
|
340
|
int Websocket::waitWriteable(uint32_t timeout)
|
donatien |
0:87e52bb764c5
|
341
|
{
|
donatien |
0:87e52bb764c5
|
342
|
//Creating FS set
|
donatien |
0:87e52bb764c5
|
343
|
fd_set socksSet;
|
donatien |
0:87e52bb764c5
|
344
|
FD_ZERO(&socksSet);
|
donatien |
0:87e52bb764c5
|
345
|
FD_SET(m_sockHandle, &socksSet);
|
donatien |
0:87e52bb764c5
|
346
|
struct timeval t_val;
|
donatien |
0:87e52bb764c5
|
347
|
t_val.tv_sec = timeout / 1000;
|
donatien |
0:87e52bb764c5
|
348
|
t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000;
|
donatien |
0:87e52bb764c5
|
349
|
int ret = socket::select(FD_SETSIZE, NULL, &socksSet, NULL, &t_val);
|
donatien |
0:87e52bb764c5
|
350
|
if(ret <= 0 || !FD_ISSET(m_sockHandle, &socksSet))
|
donatien |
0:87e52bb764c5
|
351
|
{
|
donatien |
0:87e52bb764c5
|
352
|
return -1; //Timeout
|
donatien |
0:87e52bb764c5
|
353
|
}
|
donatien |
0:87e52bb764c5
|
354
|
return 0;
|
donatien |
0:87e52bb764c5
|
355
|
}
|
donatien |
0:87e52bb764c5
|
356
|
|
donatien |
0:87e52bb764c5
|
357
|
int Websocket::read(uint8_t* buf, int minLen, int maxLen, uint32_t timeout)
|
donatien |
0:87e52bb764c5
|
358
|
{
|
donatien |
0:87e52bb764c5
|
359
|
if(!m_connected)
|
donatien |
0:87e52bb764c5
|
360
|
{
|
donatien |
0:87e52bb764c5
|
361
|
return -1;
|
donatien |
0:87e52bb764c5
|
362
|
}
|
donatien |
0:87e52bb764c5
|
363
|
int readLen = 0;
|
donatien |
0:87e52bb764c5
|
364
|
do
|
donatien |
0:87e52bb764c5
|
365
|
{
|
donatien |
0:87e52bb764c5
|
366
|
int ret = waitReadable(timeout);
|
donatien |
0:87e52bb764c5
|
367
|
if(ret == -1)
|
donatien |
0:87e52bb764c5
|
368
|
{
|
donatien |
0:87e52bb764c5
|
369
|
WARN("Wait readable returned %d",ret);
|
donatien |
0:87e52bb764c5
|
370
|
close();
|
donatien |
0:87e52bb764c5
|
371
|
return -1;
|
donatien |
0:87e52bb764c5
|
372
|
}
|
donatien |
0:87e52bb764c5
|
373
|
ret = socket::recv(m_sockHandle, buf + readLen, maxLen - readLen, 0/*MSG_DONTWAIT*/);
|
donatien |
0:87e52bb764c5
|
374
|
if(ret > 0)
|
donatien |
0:87e52bb764c5
|
375
|
{
|
donatien |
0:87e52bb764c5
|
376
|
readLen += ret;
|
donatien |
0:87e52bb764c5
|
377
|
}
|
donatien |
0:87e52bb764c5
|
378
|
else if(ret==0) //Connection closed
|
donatien |
0:87e52bb764c5
|
379
|
{
|
donatien |
0:87e52bb764c5
|
380
|
WARN("Recv returned %d",ret);
|
donatien |
0:87e52bb764c5
|
381
|
return readLen;
|
donatien |
0:87e52bb764c5
|
382
|
}
|
donatien |
0:87e52bb764c5
|
383
|
else
|
donatien |
0:87e52bb764c5
|
384
|
{
|
donatien |
0:87e52bb764c5
|
385
|
WARN("Recv returned %d",ret);
|
donatien |
0:87e52bb764c5
|
386
|
close();
|
donatien |
0:87e52bb764c5
|
387
|
return -1;
|
donatien |
0:87e52bb764c5
|
388
|
}
|
donatien |
0:87e52bb764c5
|
389
|
} while(readLen < minLen);
|
donatien |
0:87e52bb764c5
|
390
|
return readLen;
|
donatien |
0:87e52bb764c5
|
391
|
}
|
donatien |
0:87e52bb764c5
|
392
|
|
donatien |
0:87e52bb764c5
|
393
|
int Websocket::write(uint8_t* buf, int len, uint32_t timeout)
|
donatien |
0:87e52bb764c5
|
394
|
{
|
donatien |
0:87e52bb764c5
|
395
|
if(!m_connected)
|
donatien |
0:87e52bb764c5
|
396
|
{
|
donatien |
0:87e52bb764c5
|
397
|
return -1;
|
donatien |
0:87e52bb764c5
|
398
|
}
|
donatien |
0:87e52bb764c5
|
399
|
int writtenLen = 0;
|
donatien |
0:87e52bb764c5
|
400
|
do
|
donatien |
0:87e52bb764c5
|
401
|
{
|
donatien |
0:87e52bb764c5
|
402
|
int ret = waitWriteable(timeout);
|
donatien |
0:87e52bb764c5
|
403
|
if(ret == -1)
|
donatien |
0:87e52bb764c5
|
404
|
{
|
donatien |
0:87e52bb764c5
|
405
|
WARN("Wait writeable returned %d",ret);
|
donatien |
0:87e52bb764c5
|
406
|
close();
|
donatien |
0:87e52bb764c5
|
407
|
return -1;
|
donatien |
0:87e52bb764c5
|
408
|
}
|
donatien |
0:87e52bb764c5
|
409
|
ret = socket::send(m_sockHandle, buf + writtenLen, len - writtenLen, 0/*MSG_DONTWAIT*/); //FIXME Probably DO WAIT to avoid overflow
|
donatien |
0:87e52bb764c5
|
410
|
if(ret > 0)
|
donatien |
0:87e52bb764c5
|
411
|
{
|
donatien |
0:87e52bb764c5
|
412
|
writtenLen += ret;
|
donatien |
0:87e52bb764c5
|
413
|
}
|
donatien |
0:87e52bb764c5
|
414
|
else if(ret==0) //Connection closed
|
donatien |
0:87e52bb764c5
|
415
|
{
|
donatien |
0:87e52bb764c5
|
416
|
WARN("Send returned %d",ret);
|
donatien |
0:87e52bb764c5
|
417
|
return writtenLen;
|
donatien |
0:87e52bb764c5
|
418
|
}
|
donatien |
0:87e52bb764c5
|
419
|
else
|
donatien |
0:87e52bb764c5
|
420
|
{
|
donatien |
0:87e52bb764c5
|
421
|
WARN("Send returned %d",ret);
|
donatien |
0:87e52bb764c5
|
422
|
close(); //Must reset
|
donatien |
0:87e52bb764c5
|
423
|
return -1;
|
donatien |
0:87e52bb764c5
|
424
|
}
|
donatien |
0:87e52bb764c5
|
425
|
} while(writtenLen < len);
|
donatien |
0:87e52bb764c5
|
426
|
return writtenLen;
|
donatien |
0:87e52bb764c5
|
427
|
}
|
donatien |
0:87e52bb764c5
|
428
|
|
donatien |
0:87e52bb764c5
|
429
|
void Websocket::timeoutHandler()
|
donatien |
0:87e52bb764c5
|
430
|
{
|
donatien |
0:87e52bb764c5
|
431
|
|
donatien |
0:87e52bb764c5
|
432
|
}
|