SocketIOclient.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * SocketIOclient.cpp
  3. *
  4. * Created on: May 12, 2018
  5. * Author: links
  6. */
  7. #include "WebSockets.h"
  8. #include "WebSocketsClient.h"
  9. #include "SocketIOclient.h"
  10. SocketIOclient::SocketIOclient() {
  11. }
  12. SocketIOclient::~SocketIOclient() {
  13. }
  14. void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
  15. WebSocketsClient::beginSocketIO(host, port, url, protocol);
  16. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  17. initClient();
  18. }
  19. void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
  20. WebSocketsClient::beginSocketIO(host, port, url, protocol);
  21. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  22. initClient();
  23. }
  24. #if defined(HAS_SSL)
  25. void SocketIOclient::beginSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
  26. WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
  27. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  28. initClient();
  29. }
  30. void SocketIOclient::beginSSL(String host, uint16_t port, String url, String protocol) {
  31. WebSocketsClient::beginSocketIOSSL(host, port, url, protocol);
  32. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  33. initClient();
  34. }
  35. #if defined(SSL_BARESSL)
  36. void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
  37. WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
  38. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  39. initClient();
  40. }
  41. void SocketIOclient::beginSSLWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
  42. WebSocketsClient::beginSocketIOSSLWithCA(host, port, url, CA_cert, protocol);
  43. WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
  44. initClient();
  45. }
  46. void SocketIOclient::setSSLClientCertKey(const char * clientCert, const char * clientPrivateKey) {
  47. WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
  48. }
  49. void SocketIOclient::setSSLClientCertKey(BearSSL::X509List * clientCert, BearSSL::PrivateKey * clientPrivateKey) {
  50. WebSocketsClient::setSSLClientCertKey(clientCert, clientPrivateKey);
  51. }
  52. #endif
  53. #endif
  54. void SocketIOclient::configureEIOping(bool disableHeartbeat) {
  55. _disableHeartbeat = disableHeartbeat;
  56. }
  57. void SocketIOclient::initClient(void) {
  58. if(_client.cUrl.indexOf("EIO=4") != -1) {
  59. DEBUG_WEBSOCKETS("[wsIOc] found EIO=4 disable EIO ping on client\n");
  60. configureEIOping(true);
  61. }
  62. }
  63. /**
  64. * set callback function
  65. * @param cbEvent SocketIOclientEvent
  66. */
  67. void SocketIOclient::onEvent(SocketIOclientEvent cbEvent) {
  68. _cbEvent = cbEvent;
  69. }
  70. bool SocketIOclient::isConnected(void) {
  71. return WebSocketsClient::isConnected();
  72. }
  73. /**
  74. * send text data to client
  75. * @param num uint8_t client id
  76. * @param type socketIOmessageType_t
  77. * @param payload uint8_t *
  78. * @param length size_t
  79. * @param headerToPayload bool (see sendFrame for more details)
  80. * @return true if ok
  81. */
  82. bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) {
  83. bool ret = false;
  84. if(length == 0) {
  85. length = strlen((const char *)payload);
  86. }
  87. if(clientIsConnected(&_client) && _client.status == WSC_CONNECTED) {
  88. if(!headerToPayload) {
  89. // webSocket Header
  90. ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
  91. // Engine.IO / Socket.IO Header
  92. if(ret) {
  93. uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 };
  94. ret = WebSocketsClient::write(&_client, buf, 2);
  95. }
  96. if(ret && payload && length > 0) {
  97. ret = WebSocketsClient::write(&_client, payload, length);
  98. }
  99. return ret;
  100. } else {
  101. // TODO implement
  102. }
  103. }
  104. return false;
  105. }
  106. bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) {
  107. return send(type, (uint8_t *)payload, length);
  108. }
  109. bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) {
  110. return send(type, (uint8_t *)payload, length, headerToPayload);
  111. }
  112. bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) {
  113. return send(type, (uint8_t *)payload, length);
  114. }
  115. bool SocketIOclient::send(socketIOmessageType_t type, String & payload) {
  116. return send(type, (uint8_t *)payload.c_str(), payload.length());
  117. }
  118. /**
  119. * send text data to client
  120. * @param num uint8_t client id
  121. * @param payload uint8_t *
  122. * @param length size_t
  123. * @param headerToPayload bool (see sendFrame for more details)
  124. * @return true if ok
  125. */
  126. bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
  127. return send(sIOtype_EVENT, payload, length, headerToPayload);
  128. }
  129. bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
  130. return sendEVENT((uint8_t *)payload, length);
  131. }
  132. bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
  133. return sendEVENT((uint8_t *)payload, length, headerToPayload);
  134. }
  135. bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
  136. return sendEVENT((uint8_t *)payload, length);
  137. }
  138. bool SocketIOclient::sendEVENT(String & payload) {
  139. return sendEVENT((uint8_t *)payload.c_str(), payload.length());
  140. }
  141. void SocketIOclient::loop(void) {
  142. WebSocketsClient::loop();
  143. unsigned long t = millis();
  144. if(!_disableHeartbeat && (t - _lastHeartbeat) > EIO_HEARTBEAT_INTERVAL) {
  145. _lastHeartbeat = t;
  146. DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
  147. WebSocketsClient::sendTXT(eIOtype_PING);
  148. }
  149. }
  150. void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t length) {
  151. switch(type) {
  152. case WStype_DISCONNECTED:
  153. runIOCbEvent(sIOtype_DISCONNECT, NULL, 0);
  154. DEBUG_WEBSOCKETS("[wsIOc] Disconnected!\n");
  155. break;
  156. case WStype_CONNECTED: {
  157. DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
  158. // send message to server when Connected
  159. // Engine.io upgrade confirmation message (required)
  160. WebSocketsClient::sendTXT("2probe");
  161. WebSocketsClient::sendTXT(eIOtype_UPGRADE);
  162. runIOCbEvent(sIOtype_CONNECT, payload, length);
  163. } break;
  164. case WStype_TEXT: {
  165. if(length < 1) {
  166. break;
  167. }
  168. engineIOmessageType_t eType = (engineIOmessageType_t)payload[0];
  169. switch(eType) {
  170. case eIOtype_PING:
  171. payload[0] = eIOtype_PONG;
  172. DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
  173. WebSocketsClient::sendTXT(payload, length, false);
  174. break;
  175. case eIOtype_PONG:
  176. DEBUG_WEBSOCKETS("[wsIOc] get pong\n");
  177. break;
  178. case eIOtype_MESSAGE: {
  179. if(length < 2) {
  180. break;
  181. }
  182. socketIOmessageType_t ioType = (socketIOmessageType_t)payload[1];
  183. uint8_t * data = &payload[2];
  184. size_t lData = length - 2;
  185. switch(ioType) {
  186. case sIOtype_EVENT:
  187. DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
  188. break;
  189. case sIOtype_CONNECT:
  190. DEBUG_WEBSOCKETS("[wsIOc] connected (%d): %s\n", lData, data);
  191. return;
  192. case sIOtype_DISCONNECT:
  193. case sIOtype_ACK:
  194. case sIOtype_ERROR:
  195. case sIOtype_BINARY_EVENT:
  196. case sIOtype_BINARY_ACK:
  197. default:
  198. DEBUG_WEBSOCKETS("[wsIOc] Socket.IO Message Type %c (%02X) is not implemented\n", ioType, ioType);
  199. DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
  200. break;
  201. }
  202. runIOCbEvent(ioType, data, lData);
  203. } break;
  204. case eIOtype_OPEN:
  205. case eIOtype_CLOSE:
  206. case eIOtype_UPGRADE:
  207. case eIOtype_NOOP:
  208. default:
  209. DEBUG_WEBSOCKETS("[wsIOc] Engine.IO Message Type %c (%02X) is not implemented\n", eType, eType);
  210. DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
  211. break;
  212. }
  213. } break;
  214. case WStype_ERROR:
  215. case WStype_BIN:
  216. case WStype_FRAGMENT_TEXT_START:
  217. case WStype_FRAGMENT_BIN_START:
  218. case WStype_FRAGMENT:
  219. case WStype_FRAGMENT_FIN:
  220. case WStype_PING:
  221. case WStype_PONG:
  222. break;
  223. }
  224. }