Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Websocket.cpp
00001 #include "Websocket.h" 00002 #include <string> 00003 00004 //#define DEBUG 00005 00006 Websocket::Websocket(char * url, Wifly * wifi) { 00007 this->wifi = wifi; 00008 netif = WIF; 00009 fillFields(url); 00010 } 00011 00012 00013 #ifdef TARGET_LPC1768 00014 Websocket::Websocket(char * url) { 00015 server_ip = NULL; 00016 netif = ETH; 00017 eth_writeable = false; 00018 eth_readable = false; 00019 eth_connected = false; 00020 response_server_eth = false; 00021 new_msg = false; 00022 fillFields(url); 00023 00024 eth = new EthernetNetIf(); 00025 sock = new TCPSocket(); 00026 00027 EthernetErr ethErr = eth->setup(); 00028 #ifdef DEBUG 00029 if (ethErr) { 00030 printf("\r\nERROR %d in setup.\r\n", ethErr); 00031 } 00032 #endif 00033 00034 //we must use dnsresolver to find the ip address 00035 if (server_ip == NULL) { 00036 DNSResolver dr; 00037 server_ip = new IpAddr(); 00038 *server_ip = dr.resolveName(ip_domain.c_str()); 00039 #ifdef DEBUG 00040 printf("\r\nserver with dns=%d.%d.%d.%d\r\n", (*server_ip)[0], (*server_ip)[1], (*server_ip)[2], (*server_ip)[3]); 00041 #endif 00042 00043 } 00044 00045 IpAddr ipt = eth->getIp(); 00046 #ifdef DEBUG 00047 printf("\r\nmbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]); 00048 #endif 00049 00050 sock->setOnEvent(this, &Websocket::onTCPSocketEvent); 00051 } 00052 #endif //target 00053 00054 00055 void Websocket::fillFields(char * url) { 00056 char *res = NULL; 00057 char *res1 = NULL; 00058 00059 char buf[50]; 00060 strcpy(buf, url); 00061 00062 res = strtok(buf, ":"); 00063 if (strcmp(res, "ws")) { 00064 #ifdef DEBUG 00065 printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); 00066 #endif 00067 } else { 00068 //ip_domain and port 00069 res = strtok(NULL, "/"); 00070 00071 //path 00072 res1 = strtok(NULL, " "); 00073 if (res1 != NULL) { 00074 path = res1; 00075 } 00076 00077 //ip_domain 00078 res = strtok(res, ":"); 00079 00080 //port 00081 res1 = strtok(NULL, " "); 00082 //port 00083 if (res1 != NULL) { 00084 port = res1; 00085 } else { 00086 port = "80"; 00087 } 00088 00089 if (res != NULL) { 00090 ip_domain = res; 00091 00092 //if we use ethernet, we must decode ip address or use dnsresolver 00093 #ifdef TARGET_LPC1768 00094 if (netif == ETH) { 00095 strcpy(buf, res); 00096 00097 //we try to decode the ip address 00098 if (buf[0] >= '0' && buf[0] <= '9') { 00099 res = strtok(buf, "."); 00100 int i = 0; 00101 int ip[4]; 00102 while (res != NULL) { 00103 ip[i] = atoi(res); 00104 res = strtok(NULL, "."); 00105 i++; 00106 } 00107 server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]); 00108 #ifdef DEBUG 00109 printf("server without dns=%i.%i.%i.%i\n",(*server_ip)[0],(*server_ip)[1],(*server_ip)[2],(*server_ip)[3]); 00110 #endif 00111 } 00112 } 00113 #endif //target 00114 } 00115 } 00116 } 00117 00118 00119 bool Websocket::connect() { 00120 char cmd[50]; 00121 if (netif == WIF) { 00122 //enter in cmd mode 00123 wifi->exit(); 00124 while (!wifi->cmdMode()) { 00125 #ifdef DEBUG 00126 printf("cannot enter in CMD mode\r\n"); 00127 #endif 00128 wifi->send("a\r\n"); 00129 wait(0.2); 00130 wifi->exit(); 00131 if (!wifi->cmdMode()) 00132 return false; 00133 } 00134 00135 if (!wifi->send("set comm remote 0\r\n", "AOK")) { 00136 #ifdef DEBUG 00137 printf("Websocket::connect(): cannot set empty remote string\r\n"); 00138 #endif 00139 return false; 00140 } 00141 00142 //open the connection 00143 sprintf(cmd, "open %s %s\r\n", ip_domain.c_str(), port.c_str()); 00144 if (!wifi->send(cmd, "OPEN")) { 00145 if (wifi->send(cmd, "nected")) { 00146 #ifdef DEBUG 00147 printf("will try to close the conn\r\n"); 00148 #endif 00149 if (!wifi->send("close\r", "CLOS")) { 00150 return false; 00151 } 00152 if (!wifi->send(cmd, "OPEN")) 00153 return false; 00154 } else { 00155 return false; 00156 } 00157 } 00158 00159 //send websocket HTTP header 00160 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); 00161 wifi->send(cmd); 00162 wifi->send("Upgrade: websocket\r\n"); 00163 wifi->send("Connection: Upgrade\r\n"); 00164 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); 00165 wifi->send(cmd); 00166 wifi->send("Origin: null\r\n"); 00167 wifi->send("Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n"); 00168 if (!wifi->send("Sec-WebSocket-Version: 13\r\n\r\n", "DdLWT/1JcX+nQFHebYP+rqEx5xI=")) 00169 return false; 00170 00171 wifi->flush(); 00172 00173 //printf("\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()); 00174 return true; 00175 } 00176 #ifdef TARGET_LPC1768 00177 else if (netif == ETH) { 00178 Host server (*server_ip, atoi(port.c_str())); 00179 sock->close(); 00180 TCPSocketErr bindErr = sock->connect(server); 00181 if (bindErr) { 00182 #ifdef DEBUG 00183 printf("\r\nERROR binderr: %d\r\n", bindErr); 00184 #endif 00185 return false; 00186 } 00187 00188 Timer tmr; 00189 tmr.start(); 00190 00191 Timer stop; 00192 stop.start(); 00193 00194 int i = 0; 00195 while (true) { 00196 Net::poll(); 00197 if (stop.read() > 3) 00198 return false; 00199 if (tmr.read() > 0.05) { 00200 tmr.reset(); 00201 if (eth_connected) { 00202 switch (i) { 00203 case 0: 00204 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); 00205 sock->send(cmd, strlen(cmd)); 00206 i++; 00207 break; 00208 case 1: 00209 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); 00210 sock->send(cmd, strlen(cmd)); 00211 i++; 00212 break; 00213 case 2: 00214 sprintf(cmd, "Upgrade: WebSocket\r\n"); 00215 sock->send(cmd, strlen(cmd)); 00216 i++; 00217 break; 00218 case 3: 00219 sprintf(cmd, "Origin: null\r\n"); 00220 sock->send(cmd, strlen(cmd)); 00221 i++; 00222 break; 00223 case 4: 00224 sprintf(cmd, "Connection: Upgrade\r\n"); 00225 sock->send(cmd, strlen(cmd)); 00226 i++; 00227 break; 00228 case 5: 00229 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n"); 00230 sock->send(cmd, strlen(cmd)); 00231 i++; 00232 break; 00233 case 6: 00234 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n"); 00235 sock->send(cmd, strlen(cmd)); 00236 i++; 00237 break; 00238 case 7: 00239 if (response_server_eth) 00240 i++; 00241 else 00242 break; 00243 00244 default: 00245 break; 00246 } 00247 } 00248 if (i==8) { 00249 #ifdef DEBUG 00250 printf("\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()); 00251 #endif 00252 return true; 00253 } 00254 } 00255 } 00256 } 00257 #endif //target 00258 //the program shouldn't be here 00259 return false; 00260 } 00261 00262 void Websocket::sendLength(uint32_t len) { 00263 if (len < 126) { 00264 sendChar(len | (1<<7)); 00265 } else if (len < 65535) { 00266 sendChar(126 | (1<<7)); 00267 sendChar((len >> 8) & 0xff); 00268 sendChar(len & 0xff); 00269 } else { 00270 sendChar(127 | (1<<7)); 00271 for (int i = 0; i < 8; i++) { 00272 sendChar((len >> i*8) & 0xff); 00273 } 00274 } 00275 } 00276 00277 void Websocket::sendChar(uint8_t c) { 00278 if (netif == WIF) { 00279 wifi->putc(c); 00280 } 00281 #ifdef TARGET_LPC1768 00282 else if (netif == ETH) { 00283 Net::poll(); 00284 sock->send((const char *)&c, 1); 00285 } 00286 #endif 00287 } 00288 00289 void Websocket::sendOpcode(uint8_t opcode) { 00290 sendChar(0x80 | (opcode & 0x0f)); 00291 } 00292 00293 void Websocket::sendMask() { 00294 for (int i = 0; i < 4; i++) { 00295 sendChar(0); 00296 } 00297 } 00298 00299 void Websocket::send(char * str) { 00300 sendOpcode(0x01); 00301 sendLength(strlen(str)); 00302 sendMask(); 00303 if (netif == WIF) { 00304 wifi->send(str, NULL); 00305 } 00306 #ifdef TARGET_LPC1768 00307 else if (netif == ETH) { 00308 Net::poll(); 00309 sock->send(str, strlen(str)); 00310 } 00311 #endif //target 00312 } 00313 00314 00315 00316 bool Websocket::read(char * message) { 00317 int i = 0; 00318 int length_buffer = 0; 00319 uint64_t len_msg; 00320 char opcode = 0; 00321 char mask[4] = {0, 0, 0, 0}; 00322 Timer tmr; 00323 00324 if (netif == WIF) { 00325 length_buffer = wifi->readable(); 00326 00327 if (length_buffer > 1) { 00328 // read the opcode 00329 tmr.start(); 00330 while (true) { 00331 if (tmr.read() > 3) { 00332 return false; 00333 } 00334 if (wifi->readable()) { 00335 opcode = wifi->getc(); 00336 } 00337 if (opcode == 0x81) { 00338 break; 00339 } 00340 } 00341 #ifdef DEBUG 00342 printf("opcode: 0x%X\r\n", opcode); 00343 #endif 00344 len_msg = wifi->getc() & 0x7f; 00345 if (len_msg == 126) { 00346 len_msg = (wifi->getc() << 8); 00347 len_msg += wifi->getc(); 00348 } else if (len_msg == 127) { 00349 len_msg = 0; 00350 for (int i = 0; i < 8; i++) { 00351 len_msg += (wifi->getc() << (7-i)*8); 00352 } 00353 } 00354 if (len_msg == 0) { 00355 return false; 00356 } 00357 #ifdef DEBUG 00358 printf("length: %lld\r\n", len_msg); 00359 #endif 00360 if ((len_msg & 0x80)) { 00361 #ifdef DEBUG 00362 printf("will read mask\r\n"); 00363 #endif 00364 for (int i = 0; i < 4; i++) { 00365 mask[i] = wifi->getc(); 00366 #ifdef DEBUG 00367 printf("mask[%d]: %d\r\n", i, mask[i]); 00368 #endif 00369 } 00370 } else { 00371 #ifdef DEBUG 00372 printf("len not 0x80\r\n"); 00373 #endif 00374 } 00375 } else { 00376 return false; 00377 } 00378 00379 00380 for (i = 0; i < len_msg; i++) { 00381 message[i] = wifi->getc() ^ mask[i % 4]; 00382 } 00383 00384 message[len_msg] = 0; 00385 return true; 00386 } 00387 #ifdef TARGET_LPC1768 00388 else if (netif == ETH) { 00389 00390 uint32_t index = 0; 00391 Net::poll(); 00392 00393 if (new_msg) { 00394 tmr.start(); 00395 // read the opcode 00396 while (true) { 00397 if (tmr.read() > 3) { 00398 return false; 00399 } 00400 opcode = eth_rx[index++]; 00401 if (opcode == 0x81) { 00402 break; 00403 } 00404 } 00405 #ifdef DEBUG 00406 printf("opcode: 0x%X\r\n", opcode); 00407 #endif 00408 00409 len_msg = eth_rx[index++] & 0x7f; 00410 if (len_msg == 126) { 00411 len_msg = (eth_rx[index++] << 8); 00412 len_msg += eth_rx[index++]; 00413 } else if (len_msg == 127) { 00414 len_msg = 0; 00415 for (int i = 0; i < 8; i++) { 00416 len_msg += eth_rx[index++] << (7-i)*8; 00417 } 00418 } 00419 if (len_msg == 0) { 00420 return false; 00421 } 00422 #ifdef DEBUG 00423 printf("length: %lld\r\n", len_msg); 00424 #endif 00425 if ((len_msg & 0x80)) { 00426 for (int i = 0; i < 4; i++) 00427 mask[i] = eth_rx[index++]; 00428 } 00429 00430 for (i = 0; i < len_msg; i++) { 00431 message[i] = eth_rx[index++] ^ mask[i % 4]; 00432 } 00433 00434 message[len_msg] = 0; 00435 new_msg = false; 00436 return true; 00437 } 00438 return false; 00439 } 00440 #endif //target 00441 //the program shouldn't be here 00442 return false; 00443 } 00444 00445 bool Websocket::close() { 00446 sendOpcode(0x08); 00447 sendLength(0); 00448 sendMask(); 00449 if (netif == WIF) { 00450 00451 wait(0.25); 00452 if (!wifi->cmdMode()) { 00453 #ifdef DEBUG 00454 printf("Websocket::close: cannot enter in cmd mode\r\n"); 00455 #endif 00456 return false; 00457 } 00458 wait(0.25); 00459 00460 wifi->send("close\r", NULL); 00461 00462 if (!wifi->exit()) 00463 return false; 00464 } 00465 #ifdef TARGET_LPC1768 00466 else if (netif == ETH) { 00467 #ifdef TARGET_LPC1768 00468 Net::poll(); 00469 #endif //target 00470 00471 if (sock->close()) 00472 return false; 00473 return true; 00474 } 00475 #endif //target 00476 //the program shouldn't be here 00477 return false; 00478 } 00479 00480 00481 00482 bool Websocket::connected() { 00483 if (netif == WIF) { 00484 char str[10]; 00485 00486 // we have to wait at least 0.25s to enter in cmd mode whan we was sending tcp packets 00487 wait(0.25); 00488 if (!wifi->cmdMode()) { 00489 #ifdef DEBUG 00490 printf("Websocket::connected: cannot enter in cmd mode\r\n"); 00491 #endif 00492 return false; 00493 } 00494 wait(0.25); 00495 00496 wifi->send("show c\r\n", NULL, str); 00497 #ifdef DEBUG 00498 printf("Websocket::connected: str: %s\r\n", str); 00499 #endif 00500 00501 if (str[3] == '1') { 00502 if (!wifi->exit()) { 00503 #ifdef DEBUG 00504 printf("Websocket::connected: cannot exit\r\n"); 00505 #endif 00506 return false; 00507 } 00508 return true; 00509 } 00510 if (!wifi->exit()) { 00511 #ifdef DEBUG 00512 printf("Websocket::connected: cannot exit\r\n"); 00513 #endif 00514 } 00515 return false; 00516 } 00517 #ifdef TARGET_LPC1768 00518 else if (netif == ETH) { 00519 return eth_connected; 00520 } 00521 #endif //target 00522 //the program shouldn't be here 00523 return false; 00524 } 00525 00526 00527 std::string Websocket::getPath() { 00528 return path; 00529 } 00530 00531 00532 00533 00534 #ifdef TARGET_LPC1768 00535 void Websocket::onTCPSocketEvent(TCPSocketEvent e) { 00536 if (e == TCPSOCKET_CONNECTED) { 00537 eth_connected = true; 00538 #ifdef DEBUG 00539 printf("TCP Socket Connected\r\n"); 00540 #endif 00541 } else if (e == TCPSOCKET_WRITEABLE) { 00542 } else if (e == TCPSOCKET_READABLE) { 00543 int len = sock->recv(eth_rx, 512); 00544 eth_rx[len] = 0; 00545 new_msg = true; 00546 if (!response_server_eth) { 00547 string checking; 00548 size_t found = string::npos; 00549 checking = eth_rx; 00550 found = checking.find("DdLWT/1JcX+nQFHebYP+rqEx5xI="); 00551 if (found != string::npos) 00552 response_server_eth = true; 00553 } 00554 } else { 00555 #ifdef DEBUG 00556 printf("TCP Socket Fail\r\n"); 00557 #endif 00558 eth_connected = false; 00559 } 00560 } 00561 #endif //target 00562 00563
Generated on Fri Jul 15 2022 13:24:59 by
1.7.2