zabuton library
Dependencies: CushionSock EthernetNetIf MbedJSONValue mbed
Websocket.cpp
00001 /* 00002 * modify by Suga 00003 */ 00004 #include "Websocket.h" 00005 #include <string> 00006 00007 #ifdef WIFLY 00008 Websocket::Websocket(char * url, Wifly * wifi) { 00009 this->wifi = wifi; 00010 netif = WIF; 00011 fillFields(url); 00012 } 00013 #endif 00014 00015 void Websocket::isr_dns (DNSReply r) { 00016 if (DNS_FOUND) { 00017 dns_status = 1; 00018 } else { 00019 dns_status = -1; 00020 } 00021 } 00022 00023 Websocket::Websocket(char * url, EthernetNetIf *e) { 00024 server_ip = NULL; 00025 netif = ETH; 00026 eth_writeable = false; 00027 eth_readable = false; 00028 eth_connected = false; 00029 response_server_eth = false; 00030 new_msg = false; 00031 fillFields(url); 00032 00033 #ifdef ETH_SETUP 00034 eth = new EthernetNetIf(); 00035 #else 00036 eth = e; 00037 #endif 00038 sock = new TCPSocket(); 00039 00040 #ifdef ETH_SETUP 00041 EthernetErr ethErr = eth->setup(); 00042 #ifdef DEBUG 00043 if (ethErr) { 00044 printf("\r\nERROR %d in setup.\r\n", ethErr); 00045 } 00046 #endif 00047 #endif 00048 00049 //we must use dnsresolver to find the ip address 00050 if (server_ip == NULL) { 00051 /* 00052 DNSResolver dr; 00053 server_ip = new IpAddr(); 00054 *server_ip = dr.resolveName(ip_domain.c_str()); 00055 */ 00056 DNSRequest dns; 00057 Timer timeout; 00058 server_ip = new IpAddr(); 00059 dns_status = 0; 00060 dns.setOnReply(this, &Websocket::isr_dns); 00061 if (dns.resolve(ip_domain.c_str()) != DNS_OK) return; 00062 timeout.reset(); 00063 timeout.start(); 00064 while (timeout.read_ms() < 15000) { 00065 if (dns_status) break; 00066 Net::poll(); 00067 } 00068 timeout.stop(); 00069 if (dns_status <= 0) return; 00070 dns.getResult(server_ip); 00071 dns.close(); 00072 #ifdef DEBUG 00073 printf("\r\nserver with dns=%i.%i.%i.%i\r\n",server_ip[0],server_ip[1],server_ip[2],server_ip[3]); 00074 #endif 00075 00076 } 00077 00078 IpAddr ipt = eth->getIp(); 00079 #ifdef DEBUG 00080 printf("\r\nmbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]); 00081 #endif 00082 00083 sock->setOnEvent(this, &Websocket::onTCPSocketEvent); 00084 } 00085 00086 00087 void Websocket::fillFields(char * url) { 00088 char *res = NULL; 00089 char *res1 = NULL; 00090 00091 char buf[50]; 00092 strcpy(buf, url); 00093 00094 res = strtok(buf, ":"); 00095 if (strcmp(res, "ws")) { 00096 #ifdef DEBUG 00097 printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); 00098 #endif 00099 } else { 00100 //ip_domain and port 00101 res = strtok(NULL, "/"); 00102 00103 //path 00104 res1 = strtok(NULL, " "); 00105 if (res1 != NULL) { 00106 path = res1; 00107 } 00108 00109 //ip_domain 00110 res = strtok(res, ":"); 00111 00112 //port 00113 res1 = strtok(NULL, " "); 00114 //port 00115 if (res1 != NULL) { 00116 port = res1; 00117 } else { 00118 port = "80"; 00119 } 00120 00121 if (res != NULL) { 00122 ip_domain = res; 00123 00124 //if we use ethernet, we must decode ip address or use dnsresolver 00125 if (netif == ETH) { 00126 strcpy(buf, res); 00127 00128 //we try to decode the ip address 00129 if (buf[0] >= '0' && buf[0] <= '9') { 00130 res = strtok(buf, "."); 00131 int i = 0; 00132 int ip[4]; 00133 while (res != NULL) { 00134 ip[i] = atoi(res); 00135 res = strtok(NULL, "."); 00136 i++; 00137 } 00138 server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]); 00139 #ifdef DEBUG 00140 printf("server without dns=%i.%i.%i.%i\n",(*server_ip)[0],(*server_ip)[1],(*server_ip)[2],(*server_ip)[3]); 00141 #endif 00142 } 00143 } 00144 } 00145 } 00146 } 00147 00148 00149 bool Websocket::connect() { 00150 char cmd[50]; 00151 #ifdef WIFLY 00152 if (netif == WIF) { 00153 wifi->send("exit\r", "NO"); 00154 //enter in cmd mode 00155 while (!wifi->send("$$$", "CMD")) { 00156 #ifdef DEBUG 00157 printf("cannot enter in CMD mode\r\n"); 00158 #endif 00159 wifi->exit(); 00160 } 00161 00162 00163 //open the connection 00164 sprintf(cmd, "open %s %s\r\n", ip_domain.c_str(), port.c_str()); 00165 if (!wifi->send(cmd, "OPEN*")) { 00166 #ifdef DEBUG 00167 printf("Websocket::connect cannot open\r\n"); 00168 #endif 00169 return false; 00170 } 00171 00172 00173 //send websocket HTTP header 00174 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); 00175 wifi->send(cmd, "NO"); 00176 00177 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); 00178 wifi->send(cmd, "NO"); 00179 00180 wifi->send("Upgrade: WebSocket\r\n", "NO"); 00181 00182 sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain.c_str(), port.c_str()); 00183 wifi->send(cmd, "NO"); 00184 00185 00186 wifi->send("Connection: Upgrade\r\n", "NO"); 00187 wifi->send("Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n", "NO"); 00188 wifi->send("Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n", "NO"); 00189 if (!wifi->send("^n:ds[4U", "8jKS'y:G*Co,Wxa-")) 00190 return false; 00191 #ifdef DEBUG 00192 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()); 00193 #endif 00194 return true; 00195 } else 00196 #endif 00197 if (netif == ETH) { 00198 Host server (*server_ip, atoi(port.c_str())); 00199 sock->close(); 00200 TCPSocketErr bindErr = sock->connect(server); 00201 if (bindErr) { 00202 #ifdef DEBUG 00203 printf("\r\nERROR binderr: %d\r\n", bindErr); 00204 #endif 00205 return false; 00206 } 00207 00208 Timer tmr; 00209 tmr.start(); 00210 00211 Timer stop; 00212 stop.start(); 00213 00214 int i = 0; 00215 while (true) { 00216 Net::poll(); 00217 if (stop.read() > 3) 00218 return false; 00219 if (tmr.read() > 0.01) { 00220 tmr.reset(); 00221 if (eth_connected) { 00222 switch (i) { 00223 case 0: 00224 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); 00225 sock->send(cmd, strlen(cmd)); 00226 i++; 00227 break; 00228 case 1: 00229 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); 00230 sock->send(cmd, strlen(cmd)); 00231 i++; 00232 break; 00233 case 2: 00234 sprintf(cmd, "Upgrade: WebSocket\r\n"); 00235 sock->send(cmd, strlen(cmd)); 00236 i++; 00237 break; 00238 case 3: 00239 sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain.c_str(), port.c_str()); 00240 sock->send(cmd, strlen(cmd)); 00241 i++; 00242 break; 00243 case 4: 00244 sprintf(cmd, "Connection: Upgrade\r\n"); 00245 sock->send(cmd, strlen(cmd)); 00246 i++; 00247 break; 00248 case 5: 00249 sprintf(cmd, "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"); 00250 sock->send(cmd, strlen(cmd)); 00251 i++; 00252 break; 00253 case 6: 00254 sprintf(cmd, "Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n"); 00255 sock->send(cmd, strlen(cmd)); 00256 i++; 00257 break; 00258 case 7: 00259 sock->send("^n:ds[4U", 8); 00260 i++; 00261 break; 00262 case 8: 00263 if (response_server_eth) 00264 i++; 00265 else 00266 break; 00267 00268 default: 00269 break; 00270 } 00271 } 00272 if (i==9) { 00273 #ifdef DEBUG 00274 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()); 00275 #endif 00276 return true; 00277 } 00278 } 00279 } 00280 } 00281 //the program shouldn't be here 00282 return false; 00283 } 00284 00285 void Websocket::send(char * str) { 00286 #ifdef WIFLY 00287 if (netif == WIF) { 00288 wifi->putc('\x00'); 00289 wifi->send(str, "NO"); 00290 wifi->putc('\xff'); 00291 } else 00292 #endif 00293 if (netif == ETH) { 00294 char c = '\x00'; 00295 Net::poll(); 00296 sock->send(&c, 1); 00297 sock->send(str, strlen(str)); 00298 c = '\xff'; 00299 sock->send(&c, 1); 00300 } 00301 } 00302 00303 bool Websocket::read(char * message) { 00304 int i = 0; 00305 00306 #ifdef WIFLY 00307 if (netif == WIF) { 00308 if (!wifi->read(message)) 00309 return false; 00310 00311 //we check if the first byte is 0x00 00312 if (message == NULL || message[0] != 0x00) { 00313 message = NULL; 00314 return false; 00315 } 00316 00317 while (message[i + 1] != 0xff && i < strlen(message + 1)) 00318 i++; 00319 00320 if (message[i+1] == 0xff) { 00321 message[i+1] = 0; 00322 memcpy(message, message + 1, strlen(message + 1) + 1); 00323 return true; 00324 } else { 00325 message = NULL; 00326 return false; 00327 } 00328 } else 00329 #endif 00330 if (netif == ETH) { 00331 Net::poll(); 00332 00333 if (new_msg) { 00334 if (eth_rx[0] != 0x00) { 00335 message = NULL; 00336 return false; 00337 } 00338 while (eth_rx[i + 1] != 0xff) { 00339 message[i] = eth_rx[i + 1]; 00340 i++; 00341 } 00342 message[i] = 0; 00343 new_msg = false; 00344 return true; 00345 } 00346 return false; 00347 } 00348 //the program shouldn't be here 00349 return false; 00350 } 00351 00352 bool Websocket::close() { 00353 #ifdef WIFLY 00354 if (netif == WIF) { 00355 if (!wifi->cmdMode()) { 00356 #ifdef DEBUG 00357 printf("Websocket::close: cannot enter in cmd mode\r\n"); 00358 #endif 00359 return false; 00360 } 00361 00362 wifi->send("close\r", "NO"); 00363 00364 if (!wifi->exit()) 00365 return false; 00366 } else 00367 #endif 00368 if (netif == ETH) { 00369 00370 if (sock->close()) 00371 return false; 00372 return true; 00373 } 00374 //the program shouldn't be here 00375 return false; 00376 } 00377 00378 00379 00380 bool Websocket::connected() { 00381 #ifdef WIFLY 00382 if (netif == WIF) { 00383 char str[10]; 00384 00385 wait(0.25); 00386 if (!wifi->cmdMode()) { 00387 #ifdef DEBUG 00388 printf("Websocket::connected: cannot enter in cmd mode\r\n"); 00389 #endif 00390 return false; 00391 } 00392 wait(0.25); 00393 00394 wifi->send("show c\r\n", "NO", str); 00395 00396 if (str[3] == '1') { 00397 if (!wifi->exit()) { 00398 #ifdef DEBUG 00399 printf("Websocket::connected: cannot exit\r\n"); 00400 #endif 00401 return false; 00402 } 00403 return true; 00404 } 00405 if (!wifi->exit()) { 00406 #ifdef DEBUG 00407 printf("Websocket::connected: cannot exit\r\n"); 00408 #endif 00409 } 00410 return false; 00411 } else 00412 #endif 00413 if (netif == ETH) { 00414 00415 return eth_connected; 00416 } 00417 //the program shouldn't be here 00418 return false; 00419 } 00420 00421 std::string Websocket::getPath() 00422 { 00423 return path; 00424 } 00425 00426 00427 00428 00429 void Websocket::onTCPSocketEvent(TCPSocketEvent e) { 00430 if (e == TCPSOCKET_CONNECTED) { 00431 eth_connected = true; 00432 #ifdef DEBUG 00433 printf("TCP Socket Connected\r\n"); 00434 #endif 00435 } else if (e == TCPSOCKET_WRITEABLE) { 00436 } else if (e == TCPSOCKET_READABLE) { 00437 int len = sock->recv(eth_rx, 512); 00438 eth_rx[len] = 0; 00439 new_msg = true; 00440 if (!response_server_eth) { 00441 string checking; 00442 size_t found = string::npos; 00443 checking = eth_rx; 00444 found = checking.find("HTTP"); 00445 if (found != string::npos) 00446 response_server_eth = true; 00447 } 00448 } else { 00449 #ifdef DEBUG 00450 printf("TCP Socket Fail\r\n"); 00451 #endif 00452 eth_connected = false; 00453 } 00454 } 00455 00456
Generated on Thu Jul 14 2022 08:11:09 by 1.7.2