Embed:
(wiki syntax)
Show/hide line numbers
Websocket.cpp
00001 #define __DEBUG__ 4 //Maximum verbosity 00002 #ifndef __MODULE__ 00003 #define __MODULE__ "Websocket.cpp" 00004 #endif 00005 00006 #include "core/fwk.h" 00007 00008 #include "Websocket.h" 00009 #include <string> 00010 00011 00012 Websocket::Websocket(char * url) : m_sockHandle(-1) { 00013 //server_ip = NULL; 00014 00015 std::memset(&m_sockAddr, 0, sizeof(struct sockaddr_in)); 00016 00017 fillFields(url); 00018 } 00019 00020 00021 void Websocket::fillFields(char * url) { 00022 char *res = NULL; 00023 char *res1 = NULL; 00024 00025 char buf[50]; 00026 strcpy(buf, url); 00027 00028 res = strtok(buf, ":"); 00029 if (strcmp(res, "ws")) { 00030 #ifdef DEBUG 00031 printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); 00032 #endif 00033 } else { 00034 //ip_domain and port 00035 res = strtok(NULL, "/"); 00036 00037 //path 00038 res1 = strtok(NULL, " "); 00039 if (res1 != NULL) { 00040 path = res1; 00041 } 00042 00043 //ip_domain 00044 res = strtok(res, ":"); 00045 00046 //port 00047 res1 = strtok(NULL, " "); 00048 //port 00049 if (res1 != NULL) { 00050 port = res1; 00051 } else { 00052 port = "80"; 00053 } 00054 00055 if (res != NULL) { 00056 ip_domain = res; 00057 00058 //if we use ethernet, we must decode ip address or use dnsresolver 00059 strcpy(buf, res); 00060 00061 //we try to decode the ip address 00062 if (buf[0] >= '0' && buf[0] <= '9') { 00063 res = strtok(buf, "."); 00064 int i = 0; 00065 int ip[4]; 00066 while (res != NULL) { 00067 ip[i] = atoi(res); 00068 res = strtok(NULL, "."); 00069 i++; 00070 } 00071 //server_ip = new IpAddr(ip[0], ip[1], ip[2], ip[3]); 00072 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() 00073 00074 } 00075 } 00076 } 00077 } 00078 00079 00080 bool Websocket::connect() { 00081 char cmd[192]; 00082 00083 //Resolve DNS if needed 00084 if(m_sockAddr.sin_addr.s_addr == 0) 00085 { 00086 DBG("Resolving DNS socket"); 00087 struct hostent *server = socket::gethostbyname(ip_domain.c_str()); 00088 if(server == NULL) 00089 { 00090 return false; 00091 } 00092 memcpy((char*)&m_sockAddr.sin_addr.s_addr, (char*)server->h_addr_list[0], server->h_length); 00093 } 00094 00095 m_sockAddr.sin_family = AF_INET; 00096 m_sockAddr.sin_port = htons(atoi(port.c_str())); 00097 00098 //Create socket 00099 DBG("Creating socket"); 00100 m_sockHandle = socket::socket(AF_INET, SOCK_STREAM, 0); 00101 if (m_sockHandle < 0) 00102 { 00103 ERR("Could not create socket"); 00104 return false; 00105 } 00106 DBG("Handle is %d",m_sockHandle); 00107 00108 //Connect 00109 DBG("Connecting socket to %s:%d", inet_ntoa(m_sockAddr.sin_addr), ntohs(m_sockAddr.sin_port)); 00110 int ret = socket::connect(m_sockHandle, (const struct sockaddr *)&m_sockAddr, sizeof(m_sockAddr)); 00111 if (ret < 0) 00112 { 00113 socket::close(m_sockHandle); 00114 ERR("Could not connect"); 00115 return false; 00116 } 00117 00118 m_connected = true; 00119 00120 DBG("Sending HTTP request"); 00121 //send websocket HTTP header 00122 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); 00123 write((uint8_t*)cmd, strlen(cmd)); 00124 00125 sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); 00126 write((uint8_t*)cmd, strlen(cmd)); 00127 00128 sprintf(cmd, "Upgrade: WebSocket\r\n"); 00129 write((uint8_t*)cmd, strlen(cmd)); 00130 00131 sprintf(cmd, "Connection: Upgrade\r\n"); 00132 write((uint8_t*)cmd, strlen(cmd)); 00133 00134 // socket::send(m_sockHandle, "Origin: null\r\n", strlen("Origin: null\r\n"), 0); 00135 00136 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n"); 00137 write((uint8_t*)cmd, strlen(cmd)); 00138 00139 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n"); 00140 ret = write((uint8_t*)cmd, strlen(cmd)); 00141 if(ret < 0) 00142 { 00143 close(); 00144 ERR("Could not send request"); 00145 m_connected = false; 00146 return false; 00147 } 00148 00149 DBG("Waiting for answer"); 00150 ret = read((uint8_t*)cmd, 0, 192); 00151 if(ret < 0) 00152 { 00153 close(); 00154 ERR("Could not receive answer"); 00155 m_connected = false; 00156 return false; 00157 } 00158 cmd[ret] = '\0'; 00159 00160 DBG("Comparing answer"); 00161 if( strstr(cmd, "Sec-WebSocket-Accept: DdLWT/1JcX+nQFHebYP+rqEx5xI=") == NULL ) 00162 { 00163 ERR("Wrong answer from server, got \"%s\" instead", cmd); 00164 do{ 00165 ret = read((uint8_t*)cmd, 0, 192); 00166 if(ret < 0) 00167 { 00168 ERR("Could not receive answer"); 00169 return false; 00170 } 00171 cmd[ret] = '\0'; 00172 printf("%s",cmd); 00173 } while(ret > 0); 00174 close(); 00175 m_connected = false; 00176 return false; 00177 } 00178 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()); 00179 return true; 00180 } 00181 00182 void Websocket::sendLength(uint32_t len) { 00183 if (len < 126) { 00184 sendChar(len | (1<<7)); 00185 } else if (len < 65535) { 00186 sendChar(126 | (1<<7)); 00187 sendChar(len & 0xff); 00188 sendChar((len >> 8) & 0xff); 00189 } else { 00190 sendChar(127 | (1<<7)); 00191 for (int i = 0; i < 8; i++) { 00192 sendChar((len >> i*8) & 0xff); 00193 } 00194 } 00195 } 00196 00197 void Websocket::sendChar(uint8_t c) { 00198 write(&c, 1); 00199 } 00200 00201 bool Websocket::readChar(uint8_t* pC, bool block) 00202 { 00203 int ret = read(pC, 1, block?36000000:3000); 00204 if(ret < 0) 00205 { 00206 return false; 00207 } 00208 return true; 00209 } 00210 00211 void Websocket::sendOpcode(uint8_t opcode) { 00212 sendChar(0x80 | (opcode & 0x0f)); 00213 } 00214 00215 void Websocket::sendMask() { 00216 for (int i = 0; i < 4; i++) { 00217 sendChar(0); 00218 } 00219 } 00220 00221 void Websocket::send(char * str) { 00222 sendOpcode(0x01); 00223 sendLength(strlen(str)); 00224 sendMask(); 00225 00226 write((uint8_t*)str, strlen(str)); 00227 } 00228 00229 00230 00231 bool Websocket::read(char * message) { 00232 int i = 0; 00233 //int length_buffer = 0; 00234 uint32_t len_msg; 00235 char opcode = 0; 00236 uint8_t c; 00237 char mask[4] = {0, 0, 0, 0}; 00238 Timer tmr; 00239 00240 //length_buffer = wifi->readable(); 00241 00242 // read the opcode 00243 tmr.start(); 00244 while (true) { 00245 if (tmr.read() > 3) { 00246 return false; 00247 } 00248 if(!readChar((uint8_t*)&c, false)) 00249 { 00250 return false; 00251 } 00252 00253 opcode = c; 00254 if (opcode == 0x81) { 00255 break; 00256 } 00257 } 00258 #ifdef DEBUG 00259 printf("opcode: 0x%X\r\n", opcode); 00260 #endif 00261 readChar((uint8_t*)&c); 00262 len_msg = c & 0x7f; 00263 if (len_msg == 126) { 00264 readChar((uint8_t*)&c); 00265 len_msg = c; 00266 readChar((uint8_t*)&c); 00267 len_msg += c << 8; 00268 } else if (len_msg == 127) { 00269 len_msg = 0; 00270 for (i = 0; i < 8; i++) { 00271 readChar((uint8_t*)&c); 00272 len_msg += c << i*8; 00273 } 00274 } 00275 if(len_msg == 0) { 00276 return false; 00277 } 00278 #ifdef DEBUG 00279 printf("length: %d\r\n", len_msg); 00280 #endif 00281 if ((len_msg & 0x80)) { 00282 for (i = 0; i < 4; i++) 00283 readChar((uint8_t*)&c); 00284 mask[i] = c; 00285 } 00286 00287 00288 00289 for (i = 0; i < len_msg; i++) { 00290 readChar((uint8_t*)&c); 00291 message[i] = c ^ mask[i % 4]; 00292 } 00293 00294 message[len_msg] = 0; 00295 return true; 00296 } 00297 00298 bool Websocket::close() { 00299 if((m_sockHandle < 0) || !m_connected) 00300 { 00301 return false; 00302 } 00303 m_connected = false; 00304 int ret = socket::close(m_sockHandle); 00305 if (ret < 0) 00306 { 00307 ERR("Could not disconnect"); 00308 return false; 00309 } 00310 return true; 00311 } 00312 00313 00314 00315 bool Websocket::connected() { 00316 return m_connected; 00317 } 00318 00319 std::string Websocket::getPath() { 00320 return path; 00321 } 00322 00323 int Websocket::waitReadable(uint32_t timeout) 00324 { 00325 //Creating FS set 00326 fd_set socksSet; 00327 FD_ZERO(&socksSet); 00328 FD_SET(m_sockHandle, &socksSet); 00329 struct timeval t_val; 00330 t_val.tv_sec = timeout / 1000; 00331 t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000; 00332 int ret = socket::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val); 00333 if(ret <= 0 || !FD_ISSET(m_sockHandle, &socksSet)) 00334 { 00335 return -1; //Timeout 00336 } 00337 return 0; 00338 } 00339 00340 int Websocket::waitWriteable(uint32_t timeout) 00341 { 00342 //Creating FS set 00343 fd_set socksSet; 00344 FD_ZERO(&socksSet); 00345 FD_SET(m_sockHandle, &socksSet); 00346 struct timeval t_val; 00347 t_val.tv_sec = timeout / 1000; 00348 t_val.tv_usec = (timeout - (t_val.tv_sec * 1000)) * 1000; 00349 int ret = socket::select(FD_SETSIZE, NULL, &socksSet, NULL, &t_val); 00350 if(ret <= 0 || !FD_ISSET(m_sockHandle, &socksSet)) 00351 { 00352 return -1; //Timeout 00353 } 00354 return 0; 00355 } 00356 00357 int Websocket::read(uint8_t* buf, int minLen, int maxLen, uint32_t timeout) 00358 { 00359 if(!m_connected) 00360 { 00361 return -1; 00362 } 00363 int readLen = 0; 00364 do 00365 { 00366 int ret = waitReadable(timeout); 00367 if(ret == -1) 00368 { 00369 WARN("Wait readable returned %d",ret); 00370 close(); 00371 return -1; 00372 } 00373 ret = socket::recv(m_sockHandle, buf + readLen, maxLen - readLen, 0/*MSG_DONTWAIT*/); 00374 if(ret > 0) 00375 { 00376 readLen += ret; 00377 } 00378 else if(ret==0) //Connection closed 00379 { 00380 WARN("Recv returned %d",ret); 00381 return readLen; 00382 } 00383 else 00384 { 00385 WARN("Recv returned %d",ret); 00386 close(); 00387 return -1; 00388 } 00389 } while(readLen < minLen); 00390 return readLen; 00391 } 00392 00393 int Websocket::write(uint8_t* buf, int len, uint32_t timeout) 00394 { 00395 if(!m_connected) 00396 { 00397 return -1; 00398 } 00399 int writtenLen = 0; 00400 do 00401 { 00402 int ret = waitWriteable(timeout); 00403 if(ret == -1) 00404 { 00405 WARN("Wait writeable returned %d",ret); 00406 close(); 00407 return -1; 00408 } 00409 ret = socket::send(m_sockHandle, buf + writtenLen, len - writtenLen, 0/*MSG_DONTWAIT*/); //FIXME Probably DO WAIT to avoid overflow 00410 if(ret > 0) 00411 { 00412 writtenLen += ret; 00413 } 00414 else if(ret==0) //Connection closed 00415 { 00416 WARN("Send returned %d",ret); 00417 return writtenLen; 00418 } 00419 else 00420 { 00421 WARN("Send returned %d",ret); 00422 close(); //Must reset 00423 return -1; 00424 } 00425 } while(writtenLen < len); 00426 return writtenLen; 00427 } 00428 00429 void Websocket::timeoutHandler() 00430 { 00431 00432 }
Generated on Tue Jul 26 2022 14:04:27 by 1.7.2