WebSocketsServer.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /**
  2. * @file WebSocketsServer.h
  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. #ifndef WEBSOCKETSSERVER_H_
  25. #define WEBSOCKETSSERVER_H_
  26. #include "WebSockets.h"
  27. #ifndef WEBSOCKETS_SERVER_CLIENT_MAX
  28. #define WEBSOCKETS_SERVER_CLIENT_MAX (5)
  29. #endif
  30. class WebSocketsServer : protected WebSockets {
  31. public:
  32. #ifdef __AVR__
  33. typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
  34. typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue);
  35. #else
  36. typedef std::function<void(uint8_t num, WStype_t type, uint8_t * payload, size_t length)> WebSocketServerEvent;
  37. typedef std::function<bool(String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
  38. #endif
  39. WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
  40. virtual ~WebSocketsServer(void);
  41. void begin(void);
  42. void close(void);
  43. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  44. void loop(void);
  45. #else
  46. // Async interface not need a loop call
  47. void loop(void) __attribute__((deprecated)) {}
  48. #endif
  49. void onEvent(WebSocketServerEvent cbEvent);
  50. void onValidateHttpHeader(
  51. WebSocketServerHttpHeaderValFunc validationFunc,
  52. const char * mandatoryHttpHeaders[],
  53. size_t mandatoryHttpHeaderCount);
  54. bool sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
  55. bool sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
  56. bool sendTXT(uint8_t num, char * payload, size_t length = 0, bool headerToPayload = false);
  57. bool sendTXT(uint8_t num, const char * payload, size_t length = 0);
  58. bool sendTXT(uint8_t num, String & payload);
  59. bool broadcastTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
  60. bool broadcastTXT(const uint8_t * payload, size_t length = 0);
  61. bool broadcastTXT(char * payload, size_t length = 0, bool headerToPayload = false);
  62. bool broadcastTXT(const char * payload, size_t length = 0);
  63. bool broadcastTXT(String & payload);
  64. bool sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload = false);
  65. bool sendBIN(uint8_t num, const uint8_t * payload, size_t length);
  66. bool broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload = false);
  67. bool broadcastBIN(const uint8_t * payload, size_t length);
  68. bool sendPing(uint8_t num, uint8_t * payload = NULL, size_t length = 0);
  69. bool sendPing(uint8_t num, String & payload);
  70. bool broadcastPing(uint8_t * payload = NULL, size_t length = 0);
  71. bool broadcastPing(String & payload);
  72. void disconnect(void);
  73. void disconnect(uint8_t num);
  74. void setAuthorization(const char * user, const char * password);
  75. void setAuthorization(const char * auth);
  76. int connectedClients(bool ping = false);
  77. #if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
  78. IPAddress remoteIP(uint8_t num);
  79. #endif
  80. protected:
  81. uint16_t _port;
  82. String _origin;
  83. String _protocol;
  84. String _base64Authorization; ///< Base64 encoded Auth request
  85. String * _mandatoryHttpHeaders;
  86. size_t _mandatoryHttpHeaderCount;
  87. WEBSOCKETS_NETWORK_SERVER_CLASS * _server;
  88. WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX];
  89. WebSocketServerEvent _cbEvent;
  90. WebSocketServerHttpHeaderValFunc _httpHeaderValidationFunc;
  91. bool _runnning;
  92. bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
  93. void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
  94. void clientDisconnect(WSclient_t * client);
  95. bool clientIsConnected(WSclient_t * client);
  96. #if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
  97. void handleNewClients(void);
  98. void handleClientData(void);
  99. #endif
  100. void handleHeader(WSclient_t * client, String * headerLine);
  101. /**
  102. * called if a non Websocket connection is coming in.
  103. * Note: can be override
  104. * @param client WSclient_t * ptr to the client struct
  105. */
  106. virtual void handleNonWebsocketConnection(WSclient_t * client) {
  107. DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] no Websocket connection close.\n", client->num);
  108. client->tcp->write(
  109. "HTTP/1.1 400 Bad Request\r\n"
  110. "Server: arduino-WebSocket-Server\r\n"
  111. "Content-Type: text/plain\r\n"
  112. "Content-Length: 32\r\n"
  113. "Connection: close\r\n"
  114. "Sec-WebSocket-Version: 13\r\n"
  115. "\r\n"
  116. "This is a Websocket server only!");
  117. clientDisconnect(client);
  118. }
  119. /**
  120. * called if a non Authorization connection is coming in.
  121. * Note: can be override
  122. * @param client WSclient_t * ptr to the client struct
  123. */
  124. virtual void handleAuthorizationFailed(WSclient_t * client) {
  125. client->tcp->write(
  126. "HTTP/1.1 401 Unauthorized\r\n"
  127. "Server: arduino-WebSocket-Server\r\n"
  128. "Content-Type: text/plain\r\n"
  129. "Content-Length: 45\r\n"
  130. "Connection: close\r\n"
  131. "Sec-WebSocket-Version: 13\r\n"
  132. "WWW-Authenticate: Basic realm=\"WebSocket Server\""
  133. "\r\n"
  134. "This Websocket server requires Authorization!");
  135. clientDisconnect(client);
  136. }
  137. /**
  138. * called for sending a Event to the app
  139. * @param num uint8_t
  140. * @param type WStype_t
  141. * @param payload uint8_t *
  142. * @param length size_t
  143. */
  144. virtual void runCbEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
  145. if(_cbEvent) {
  146. _cbEvent(num, type, payload, length);
  147. }
  148. }
  149. /*
  150. * Called at client socket connect handshake negotiation time for each http header that is not
  151. * a websocket specific http header (not Connection, Upgrade, Sec-WebSocket-*)
  152. * If the custom httpHeaderValidationFunc returns false for any headerName / headerValue passed, the
  153. * socket negotiation is considered invalid and the upgrade to websockets request is denied / rejected
  154. * This mechanism can be used to enable custom authentication schemes e.g. test the value
  155. * of a session cookie to determine if a user is logged on / authenticated
  156. */
  157. virtual bool execHttpHeaderValidation(String headerName, String headerValue) {
  158. if(_httpHeaderValidationFunc) {
  159. //return the value of the custom http header validation function
  160. return _httpHeaderValidationFunc(headerName, headerValue);
  161. }
  162. //no custom http header validation so just assume all is good
  163. return true;
  164. }
  165. private:
  166. /*
  167. * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
  168. * @param headerName String ///< the name of the header being checked
  169. */
  170. bool hasMandatoryHeader(String headerName);
  171. };
  172. #endif /* WEBSOCKETSSERVER_H_ */