WebSocketsServer.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. /**
  2. * @file WebSocketsServer.cpp
  3. * @date 20.05.2015
  4. * @author Markus Sattler
  5. *
  6. * Copyright (c) 2015 Markus Sattler. All rights reserved.
  7. * This file is part of the WebSockets for Arduino.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. #include "WebSockets.h"
  25. #include "WebSocketsServer.h"
  26. WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol) {
  27. _port = port;
  28. _origin = origin;
  29. _protocol = protocol;
  30. _runnning = false;
  31. _server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
  32. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  33. _server->onClient([](void * s, AsyncClient * c) {
  34. ((WebSocketsServer *)s)->newClient(new AsyncTCPbuffer(c));
  35. },
  36. this);
  37. #endif
  38. _cbEvent = NULL;
  39. _httpHeaderValidationFunc = NULL;
  40. _mandatoryHttpHeaders = NULL;
  41. _mandatoryHttpHeaderCount = 0;
  42. memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX));
  43. }
  44. WebSocketsServer::~WebSocketsServer() {
  45. // disconnect all clients
  46. close();
  47. if(_mandatoryHttpHeaders)
  48. delete[] _mandatoryHttpHeaders;
  49. _mandatoryHttpHeaderCount = 0;
  50. }
  51. /**
  52. * called to initialize the Websocket server
  53. */
  54. void WebSocketsServer::begin(void) {
  55. WSclient_t * client;
  56. // init client storage
  57. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  58. client = &_clients[i];
  59. client->num = i;
  60. client->status = WSC_NOT_CONNECTED;
  61. client->tcp = NULL;
  62. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  63. client->isSSL = false;
  64. client->ssl = NULL;
  65. #endif
  66. client->cUrl = "";
  67. client->cCode = 0;
  68. client->cKey = "";
  69. client->cProtocol = "";
  70. client->cVersion = 0;
  71. client->cIsUpgrade = false;
  72. client->cIsWebsocket = false;
  73. client->base64Authorization = "";
  74. client->cWsRXsize = 0;
  75. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  76. client->cHttpLine = "";
  77. #endif
  78. }
  79. #ifdef ESP8266
  80. randomSeed(RANDOM_REG32);
  81. #elif defined(ESP32)
  82. #define DR_REG_RNG_BASE 0x3ff75144
  83. randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
  84. #else
  85. // TODO find better seed
  86. randomSeed(millis());
  87. #endif
  88. _runnning = true;
  89. _server->begin();
  90. DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n");
  91. }
  92. void WebSocketsServer::close(void) {
  93. _runnning = false;
  94. disconnect();
  95. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
  96. _server->close();
  97. #elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  98. _server->end();
  99. #else
  100. // TODO how to close server?
  101. #endif
  102. }
  103. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  104. /**
  105. * called in arduino loop
  106. */
  107. void WebSocketsServer::loop(void) {
  108. if(_runnning) {
  109. handleNewClients();
  110. handleClientData();
  111. }
  112. }
  113. #endif
  114. /**
  115. * set callback function
  116. * @param cbEvent WebSocketServerEvent
  117. */
  118. void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) {
  119. _cbEvent = cbEvent;
  120. }
  121. /*
  122. * Sets the custom http header validator function
  123. * @param httpHeaderValidationFunc WebSocketServerHttpHeaderValFunc ///< pointer to the custom http header validation function
  124. * @param mandatoryHttpHeaders[] const char* ///< the array of named http headers considered to be mandatory / must be present in order for websocket upgrade to succeed
  125. * @param mandatoryHttpHeaderCount size_t ///< the number of items in the mandatoryHttpHeaders array
  126. */
  127. void WebSocketsServer::onValidateHttpHeader(
  128. WebSocketServerHttpHeaderValFunc validationFunc,
  129. const char * mandatoryHttpHeaders[],
  130. size_t mandatoryHttpHeaderCount) {
  131. _httpHeaderValidationFunc = validationFunc;
  132. if(_mandatoryHttpHeaders)
  133. delete[] _mandatoryHttpHeaders;
  134. _mandatoryHttpHeaderCount = mandatoryHttpHeaderCount;
  135. _mandatoryHttpHeaders = new String[_mandatoryHttpHeaderCount];
  136. for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
  137. _mandatoryHttpHeaders[i] = mandatoryHttpHeaders[i];
  138. }
  139. }
  140. /*
  141. * send text data to client
  142. * @param num uint8_t client id
  143. * @param payload uint8_t *
  144. * @param length size_t
  145. * @param headerToPayload bool (see sendFrame for more details)
  146. * @return true if ok
  147. */
  148. bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
  149. if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
  150. return false;
  151. }
  152. if(length == 0) {
  153. length = strlen((const char *)payload);
  154. }
  155. WSclient_t * client = &_clients[num];
  156. if(clientIsConnected(client)) {
  157. return sendFrame(client, WSop_text, payload, length, true, headerToPayload);
  158. }
  159. return false;
  160. }
  161. bool WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t length) {
  162. return sendTXT(num, (uint8_t *)payload, length);
  163. }
  164. bool WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) {
  165. return sendTXT(num, (uint8_t *)payload, length, headerToPayload);
  166. }
  167. bool WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) {
  168. return sendTXT(num, (uint8_t *)payload, length);
  169. }
  170. bool WebSocketsServer::sendTXT(uint8_t num, String & payload) {
  171. return sendTXT(num, (uint8_t *)payload.c_str(), payload.length());
  172. }
  173. /**
  174. * send text data to client all
  175. * @param payload uint8_t *
  176. * @param length size_t
  177. * @param headerToPayload bool (see sendFrame for more details)
  178. * @return true if ok
  179. */
  180. bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool headerToPayload) {
  181. WSclient_t * client;
  182. bool ret = true;
  183. if(length == 0) {
  184. length = strlen((const char *)payload);
  185. }
  186. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  187. client = &_clients[i];
  188. if(clientIsConnected(client)) {
  189. if(!sendFrame(client, WSop_text, payload, length, true, headerToPayload)) {
  190. ret = false;
  191. }
  192. }
  193. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
  194. delay(0);
  195. #endif
  196. }
  197. return ret;
  198. }
  199. bool WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) {
  200. return broadcastTXT((uint8_t *)payload, length);
  201. }
  202. bool WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) {
  203. return broadcastTXT((uint8_t *)payload, length, headerToPayload);
  204. }
  205. bool WebSocketsServer::broadcastTXT(const char * payload, size_t length) {
  206. return broadcastTXT((uint8_t *)payload, length);
  207. }
  208. bool WebSocketsServer::broadcastTXT(String & payload) {
  209. return broadcastTXT((uint8_t *)payload.c_str(), payload.length());
  210. }
  211. /**
  212. * send binary data to client
  213. * @param num uint8_t client id
  214. * @param payload uint8_t *
  215. * @param length size_t
  216. * @param headerToPayload bool (see sendFrame for more details)
  217. * @return true if ok
  218. */
  219. bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
  220. if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
  221. return false;
  222. }
  223. WSclient_t * client = &_clients[num];
  224. if(clientIsConnected(client)) {
  225. return sendFrame(client, WSop_binary, payload, length, true, headerToPayload);
  226. }
  227. return false;
  228. }
  229. bool WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t length) {
  230. return sendBIN(num, (uint8_t *)payload, length);
  231. }
  232. /**
  233. * send binary data to client all
  234. * @param payload uint8_t *
  235. * @param length size_t
  236. * @param headerToPayload bool (see sendFrame for more details)
  237. * @return true if ok
  238. */
  239. bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload) {
  240. WSclient_t * client;
  241. bool ret = true;
  242. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  243. client = &_clients[i];
  244. if(clientIsConnected(client)) {
  245. if(!sendFrame(client, WSop_binary, payload, length, true, headerToPayload)) {
  246. ret = false;
  247. }
  248. }
  249. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
  250. delay(0);
  251. #endif
  252. }
  253. return ret;
  254. }
  255. bool WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) {
  256. return broadcastBIN((uint8_t *)payload, length);
  257. }
  258. /**
  259. * sends a WS ping to Client
  260. * @param num uint8_t client id
  261. * @param payload uint8_t *
  262. * @param length size_t
  263. * @return true if ping is send out
  264. */
  265. bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) {
  266. if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
  267. return false;
  268. }
  269. WSclient_t * client = &_clients[num];
  270. if(clientIsConnected(client)) {
  271. return sendFrame(client, WSop_ping, payload, length);
  272. }
  273. return false;
  274. }
  275. bool WebSocketsServer::sendPing(uint8_t num, String & payload) {
  276. return sendPing(num, (uint8_t *)payload.c_str(), payload.length());
  277. }
  278. /**
  279. * sends a WS ping to all Client
  280. * @param payload uint8_t *
  281. * @param length size_t
  282. * @return true if ping is send out
  283. */
  284. bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) {
  285. WSclient_t * client;
  286. bool ret = true;
  287. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  288. client = &_clients[i];
  289. if(clientIsConnected(client)) {
  290. if(!sendFrame(client, WSop_ping, payload, length)) {
  291. ret = false;
  292. }
  293. }
  294. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
  295. delay(0);
  296. #endif
  297. }
  298. return ret;
  299. }
  300. bool WebSocketsServer::broadcastPing(String & payload) {
  301. return broadcastPing((uint8_t *)payload.c_str(), payload.length());
  302. }
  303. /**
  304. * disconnect all clients
  305. */
  306. void WebSocketsServer::disconnect(void) {
  307. WSclient_t * client;
  308. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  309. client = &_clients[i];
  310. if(clientIsConnected(client)) {
  311. WebSockets::clientDisconnect(client, 1000);
  312. }
  313. }
  314. }
  315. /**
  316. * disconnect one client
  317. * @param num uint8_t client id
  318. */
  319. void WebSocketsServer::disconnect(uint8_t num) {
  320. if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
  321. return;
  322. }
  323. WSclient_t * client = &_clients[num];
  324. if(clientIsConnected(client)) {
  325. WebSockets::clientDisconnect(client, 1000);
  326. }
  327. }
  328. /*
  329. * set the Authorization for the http request
  330. * @param user const char *
  331. * @param password const char *
  332. */
  333. void WebSocketsServer::setAuthorization(const char * user, const char * password) {
  334. if(user && password) {
  335. String auth = user;
  336. auth += ":";
  337. auth += password;
  338. _base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length());
  339. }
  340. }
  341. /**
  342. * set the Authorizatio for the http request
  343. * @param auth const char * base64
  344. */
  345. void WebSocketsServer::setAuthorization(const char * auth) {
  346. if(auth) {
  347. _base64Authorization = auth;
  348. }
  349. }
  350. /**
  351. * count the connected clients (optional ping them)
  352. * @param ping bool ping the connected clients
  353. */
  354. int WebSocketsServer::connectedClients(bool ping) {
  355. WSclient_t * client;
  356. int count = 0;
  357. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  358. client = &_clients[i];
  359. if(client->status == WSC_CONNECTED) {
  360. if(ping != true || sendPing(i)) {
  361. count++;
  362. }
  363. }
  364. }
  365. return count;
  366. }
  367. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  368. /**
  369. * get an IP for a client
  370. * @param num uint8_t client id
  371. * @return IPAddress
  372. */
  373. IPAddress WebSocketsServer::remoteIP(uint8_t num) {
  374. if(num < WEBSOCKETS_SERVER_CLIENT_MAX) {
  375. WSclient_t * client = &_clients[num];
  376. if(clientIsConnected(client)) {
  377. return client->tcp->remoteIP();
  378. }
  379. }
  380. return IPAddress();
  381. }
  382. #endif
  383. //#################################################################################
  384. //#################################################################################
  385. //#################################################################################
  386. /**
  387. * handle new client connection
  388. * @param client
  389. */
  390. bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
  391. WSclient_t * client;
  392. // search free list entry for client
  393. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  394. client = &_clients[i];
  395. // state is not connected or tcp connection is lost
  396. if(!clientIsConnected(client)) {
  397. client->tcp = TCPclient;
  398. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  399. client->isSSL = false;
  400. client->tcp->setNoDelay(true);
  401. #endif
  402. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  403. // set Timeout for readBytesUntil and readStringUntil
  404. client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
  405. #endif
  406. client->status = WSC_HEADER;
  407. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  408. IPAddress ip = client->tcp->remoteIP();
  409. DEBUG_WEBSOCKETS("[WS-Server][%d] new client from %d.%d.%d.%d\n", client->num, ip[0], ip[1], ip[2], ip[3]);
  410. #else
  411. DEBUG_WEBSOCKETS("[WS-Server][%d] new client\n", client->num);
  412. #endif
  413. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  414. client->tcp->onDisconnect(std::bind([](WebSocketsServer * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
  415. DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
  416. AsyncTCPbuffer ** sl = &server->_clients[client->num].tcp;
  417. if(*sl == obj) {
  418. client->status = WSC_NOT_CONNECTED;
  419. *sl = NULL;
  420. }
  421. return true;
  422. },
  423. this, std::placeholders::_1, client));
  424. client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
  425. #endif
  426. return true;
  427. break;
  428. }
  429. }
  430. return false;
  431. }
  432. /**
  433. *
  434. * @param client WSclient_t * ptr to the client struct
  435. * @param opcode WSopcode_t
  436. * @param payload uint8_t *
  437. * @param length size_t
  438. */
  439. void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) {
  440. WStype_t type = WStype_ERROR;
  441. switch(opcode) {
  442. case WSop_text:
  443. type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START;
  444. break;
  445. case WSop_binary:
  446. type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START;
  447. break;
  448. case WSop_continuation:
  449. type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
  450. break;
  451. case WSop_ping:
  452. type = WStype_PING;
  453. break;
  454. case WSop_pong:
  455. type = WStype_PONG;
  456. break;
  457. case WSop_close:
  458. default:
  459. break;
  460. }
  461. runCbEvent(client->num, type, payload, length);
  462. }
  463. /**
  464. * Disconnect an client
  465. * @param client WSclient_t * ptr to the client struct
  466. */
  467. void WebSocketsServer::clientDisconnect(WSclient_t * client) {
  468. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  469. if(client->isSSL && client->ssl) {
  470. if(client->ssl->connected()) {
  471. client->ssl->flush();
  472. client->ssl->stop();
  473. }
  474. delete client->ssl;
  475. client->ssl = NULL;
  476. client->tcp = NULL;
  477. }
  478. #endif
  479. if(client->tcp) {
  480. if(client->tcp->connected()) {
  481. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  482. client->tcp->flush();
  483. #endif
  484. client->tcp->stop();
  485. }
  486. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  487. client->status = WSC_NOT_CONNECTED;
  488. #else
  489. delete client->tcp;
  490. #endif
  491. client->tcp = NULL;
  492. }
  493. client->cUrl = "";
  494. client->cKey = "";
  495. client->cProtocol = "";
  496. client->cVersion = 0;
  497. client->cIsUpgrade = false;
  498. client->cIsWebsocket = false;
  499. client->cWsRXsize = 0;
  500. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  501. client->cHttpLine = "";
  502. #endif
  503. client->status = WSC_NOT_CONNECTED;
  504. DEBUG_WEBSOCKETS("[WS-Server][%d] client disconnected.\n", client->num);
  505. runCbEvent(client->num, WStype_DISCONNECTED, NULL, 0);
  506. }
  507. /**
  508. * get client state
  509. * @param client WSclient_t * ptr to the client struct
  510. * @return true = connected
  511. */
  512. bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
  513. if(!client->tcp) {
  514. return false;
  515. }
  516. if(client->tcp->connected()) {
  517. if(client->status != WSC_NOT_CONNECTED) {
  518. return true;
  519. }
  520. } else {
  521. // client lost
  522. if(client->status != WSC_NOT_CONNECTED) {
  523. DEBUG_WEBSOCKETS("[WS-Server][%d] client connection lost.\n", client->num);
  524. // do cleanup
  525. clientDisconnect(client);
  526. }
  527. }
  528. if(client->tcp) {
  529. // do cleanup
  530. DEBUG_WEBSOCKETS("[WS-Server][%d] client list cleanup.\n", client->num);
  531. clientDisconnect(client);
  532. }
  533. return false;
  534. }
  535. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  536. /**
  537. * Handle incoming Connection Request
  538. */
  539. void WebSocketsServer::handleNewClients(void) {
  540. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  541. while(_server->hasClient()) {
  542. #endif
  543. bool ok = false;
  544. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  545. // store new connection
  546. WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
  547. #else
  548. WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
  549. #endif
  550. if(!tcpClient) {
  551. DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
  552. return;
  553. }
  554. ok = newClient(tcpClient);
  555. if(!ok) {
  556. // no free space to handle client
  557. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  558. IPAddress ip = tcpClient->remoteIP();
  559. DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
  560. #else
  561. DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
  562. #endif
  563. tcpClient->stop();
  564. }
  565. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  566. delay(0);
  567. }
  568. #endif
  569. }
  570. /**
  571. * Handel incomming data from Client
  572. */
  573. void WebSocketsServer::handleClientData(void) {
  574. WSclient_t * client;
  575. for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
  576. client = &_clients[i];
  577. if(clientIsConnected(client)) {
  578. int len = client->tcp->available();
  579. if(len > 0) {
  580. //DEBUG_WEBSOCKETS("[WS-Server][%d][handleClientData] len: %d\n", client->num, len);
  581. switch(client->status) {
  582. case WSC_HEADER: {
  583. String headerLine = client->tcp->readStringUntil('\n');
  584. handleHeader(client, &headerLine);
  585. } break;
  586. case WSC_CONNECTED:
  587. WebSockets::handleWebsocket(client);
  588. break;
  589. default:
  590. WebSockets::clientDisconnect(client, 1002);
  591. break;
  592. }
  593. }
  594. }
  595. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
  596. delay(0);
  597. #endif
  598. }
  599. }
  600. #endif
  601. /*
  602. * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
  603. * @param headerName String ///< the name of the header being checked
  604. */
  605. bool WebSocketsServer::hasMandatoryHeader(String headerName) {
  606. for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
  607. if(_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName))
  608. return true;
  609. }
  610. return false;
  611. }
  612. /**
  613. * handles http header reading for WebSocket upgrade
  614. * @param client WSclient_t * ///< pointer to the client struct
  615. * @param headerLine String ///< the header being read / processed
  616. */
  617. void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
  618. static const char * NEW_LINE = "\r\n";
  619. headerLine->trim(); // remove \r
  620. if(headerLine->length() > 0) {
  621. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine->c_str());
  622. // websocket requests always start with GET see rfc6455
  623. if(headerLine->startsWith("GET ")) {
  624. // cut URL out
  625. client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
  626. //reset non-websocket http header validation state for this client
  627. client->cHttpHeadersValid = true;
  628. client->cMandatoryHeadersCount = 0;
  629. } else if(headerLine->indexOf(':') >= 0) {
  630. String headerName = headerLine->substring(0, headerLine->indexOf(':'));
  631. String headerValue = headerLine->substring(headerLine->indexOf(':') + 1);
  632. // remove space in the beginning (RFC2616)
  633. if(headerValue[0] == ' ') {
  634. headerValue.remove(0, 1);
  635. }
  636. if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
  637. headerValue.toLowerCase();
  638. if(headerValue.indexOf(WEBSOCKETS_STRING("upgrade")) >= 0) {
  639. client->cIsUpgrade = true;
  640. }
  641. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) {
  642. if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) {
  643. client->cIsWebsocket = true;
  644. }
  645. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
  646. client->cVersion = headerValue.toInt();
  647. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Key"))) {
  648. client->cKey = headerValue;
  649. client->cKey.trim(); // see rfc6455
  650. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) {
  651. client->cProtocol = headerValue;
  652. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) {
  653. client->cExtensions = headerValue;
  654. } else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Authorization"))) {
  655. client->base64Authorization = headerValue;
  656. } else {
  657. client->cHttpHeadersValid &= execHttpHeaderValidation(headerName, headerValue);
  658. if(_mandatoryHttpHeaderCount > 0 && hasMandatoryHeader(headerName)) {
  659. client->cMandatoryHeadersCount++;
  660. }
  661. }
  662. } else {
  663. DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
  664. }
  665. (*headerLine) = "";
  666. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
  667. client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
  668. #endif
  669. } else {
  670. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
  671. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cURL: %s\n", client->num, client->cUrl.c_str());
  672. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cIsUpgrade: %d\n", client->num, client->cIsUpgrade);
  673. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cIsWebsocket: %d\n", client->num, client->cIsWebsocket);
  674. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cKey: %s\n", client->num, client->cKey.c_str());
  675. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cProtocol: %s\n", client->num, client->cProtocol.c_str());
  676. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cExtensions: %s\n", client->num, client->cExtensions.c_str());
  677. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cVersion: %d\n", client->num, client->cVersion);
  678. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - base64Authorization: %s\n", client->num, client->base64Authorization.c_str());
  679. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cHttpHeadersValid: %d\n", client->num, client->cHttpHeadersValid);
  680. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cMandatoryHeadersCount: %d\n", client->num, client->cMandatoryHeadersCount);
  681. bool ok = (client->cIsUpgrade && client->cIsWebsocket);
  682. if(ok) {
  683. if(client->cUrl.length() == 0) {
  684. ok = false;
  685. }
  686. if(client->cKey.length() == 0) {
  687. ok = false;
  688. }
  689. if(client->cVersion != 13) {
  690. ok = false;
  691. }
  692. if(!client->cHttpHeadersValid) {
  693. ok = false;
  694. }
  695. if(client->cMandatoryHeadersCount != _mandatoryHttpHeaderCount) {
  696. ok = false;
  697. }
  698. }
  699. if(_base64Authorization.length() > 0) {
  700. String auth = WEBSOCKETS_STRING("Basic ");
  701. auth += _base64Authorization;
  702. if(auth != client->base64Authorization) {
  703. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] HTTP Authorization failed!\n", client->num);
  704. handleAuthorizationFailed(client);
  705. return;
  706. }
  707. }
  708. if(ok) {
  709. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Websocket connection incoming.\n", client->num);
  710. // generate Sec-WebSocket-Accept key
  711. String sKey = acceptKey(client->cKey);
  712. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - sKey: %s\n", client->num, sKey.c_str());
  713. client->status = WSC_CONNECTED;
  714. String handshake = WEBSOCKETS_STRING(
  715. "HTTP/1.1 101 Switching Protocols\r\n"
  716. "Server: arduino-WebSocketsServer\r\n"
  717. "Upgrade: websocket\r\n"
  718. "Connection: Upgrade\r\n"
  719. "Sec-WebSocket-Version: 13\r\n"
  720. "Sec-WebSocket-Accept: ");
  721. handshake += sKey + NEW_LINE;
  722. if(_origin.length() > 0) {
  723. handshake += WEBSOCKETS_STRING("Access-Control-Allow-Origin: ");
  724. handshake += _origin + NEW_LINE;
  725. }
  726. if(client->cProtocol.length() > 0) {
  727. handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: ");
  728. handshake += _protocol + NEW_LINE;
  729. }
  730. // header end
  731. handshake += NEW_LINE;
  732. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] handshake %s", client->num, (uint8_t *)handshake.c_str());
  733. write(client, (uint8_t *)handshake.c_str(), handshake.length());
  734. headerDone(client);
  735. // send ping
  736. WebSockets::sendFrame(client, WSop_ping);
  737. runCbEvent(client->num, WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
  738. } else {
  739. handleNonWebsocketConnection(client);
  740. }
  741. }
  742. }