Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.3 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. TELNET MODULE
  3. Copyright (C) 2017-2018 by Xose Pérez <xose dot perez at gmail dot com>
  4. Parts of the code have been borrowed from Thomas Sarlandie's NetServer
  5. (https://github.com/sarfata/kbox-firmware/tree/master/src/esp)
  6. */
  7. #if TELNET_SUPPORT
  8. #include <ESPAsyncTCP.h>
  9. AsyncServer * _telnetServer;
  10. AsyncClient * _telnetClients[TELNET_MAX_CLIENTS];
  11. // -----------------------------------------------------------------------------
  12. // Private methods
  13. // -----------------------------------------------------------------------------
  14. void _telnetWebSocketOnSend(JsonObject& root) {
  15. root["telnetVisible"] = 1;
  16. root["telnetSTA"] = getSetting("telnetSTA", TELNET_STA).toInt() == 1;
  17. }
  18. void _telnetDisconnect(unsigned char clientId) {
  19. _telnetClients[clientId]->free();
  20. _telnetClients[clientId] = NULL;
  21. delete _telnetClients[clientId];
  22. wifiReconnectCheck();
  23. DEBUG_MSG_P(PSTR("[TELNET] Client #%d disconnected\n"), clientId);
  24. }
  25. bool _telnetWrite(unsigned char clientId, void *data, size_t len) {
  26. if (_telnetClients[clientId] && _telnetClients[clientId]->connected()) {
  27. return (_telnetClients[clientId]->write((const char*) data, len) > 0);
  28. }
  29. return false;
  30. }
  31. unsigned char _telnetWrite(void *data, size_t len) {
  32. unsigned char count = 0;
  33. for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
  34. if (_telnetWrite(i, data, len)) ++count;
  35. }
  36. return count;
  37. }
  38. void _telnetData(unsigned char clientId, void *data, size_t len) {
  39. // Capture close connection
  40. char * p = (char *) data;
  41. if ((strncmp(p, "close", 5) == 0) || (strncmp(p, "quit", 4) == 0)) {
  42. _telnetClients[clientId]->close();
  43. return;
  44. }
  45. // Inject into Embedis stream
  46. settingsInject(data, len);
  47. }
  48. void _telnetNewClient(AsyncClient *client) {
  49. if (client->localIP() != WiFi.softAPIP()) {
  50. bool telnetSTA = getSetting("telnetSTA", TELNET_STA).toInt() == 1;
  51. if (!telnetSTA) {
  52. DEBUG_MSG_P(PSTR("[TELNET] Rejecting - Only local connections\n"));
  53. client->onDisconnect([](void *s, AsyncClient *c) {
  54. c->free();
  55. delete c;
  56. });
  57. client->close(true);
  58. return;
  59. }
  60. }
  61. for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
  62. if (!_telnetClients[i] || !_telnetClients[i]->connected()) {
  63. _telnetClients[i] = client;
  64. client->onAck([i](void *s, AsyncClient *c, size_t len, uint32_t time) {
  65. }, 0);
  66. client->onData([i](void *s, AsyncClient *c, void *data, size_t len) {
  67. _telnetData(i, data, len);
  68. }, 0);
  69. client->onDisconnect([i](void *s, AsyncClient *c) {
  70. _telnetDisconnect(i);
  71. }, 0);
  72. client->onError([i](void *s, AsyncClient *c, int8_t error) {
  73. DEBUG_MSG_P(PSTR("[TELNET] Error %s (%d) on client #%u\n"), c->errorToString(error), error, i);
  74. }, 0);
  75. client->onTimeout([i](void *s, AsyncClient *c, uint32_t time) {
  76. DEBUG_MSG_P(PSTR("[TELNET] Timeout on client #%u at %lu\n"), i, time);
  77. c->close();
  78. }, 0);
  79. DEBUG_MSG_P(PSTR("[TELNET] Client #%u connected\n"), i);
  80. wifiReconnectCheck();
  81. return;
  82. }
  83. }
  84. DEBUG_MSG_P(PSTR("[TELNET] Rejecting - Too many connections\n"));
  85. client->onDisconnect([](void *s, AsyncClient *c) {
  86. c->free();
  87. delete c;
  88. });
  89. client->close(true);
  90. }
  91. // -----------------------------------------------------------------------------
  92. // Public API
  93. // -----------------------------------------------------------------------------
  94. bool telnetConnected() {
  95. for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
  96. if (_telnetClients[i] && _telnetClients[i]->connected()) return true;
  97. }
  98. return false;
  99. }
  100. unsigned char telnetWrite(unsigned char ch) {
  101. char data[1] = {ch};
  102. return _telnetWrite(data, 1);
  103. }
  104. void telnetSetup() {
  105. _telnetServer = new AsyncServer(TELNET_PORT);
  106. _telnetServer->onClient([](void *s, AsyncClient* c) {
  107. _telnetNewClient(c);
  108. }, 0);
  109. _telnetServer->begin();
  110. #if WEB_SUPPORT
  111. wsOnSendRegister(_telnetWebSocketOnSend);
  112. #endif
  113. DEBUG_MSG_P(PSTR("[TELNET] Listening on port %d\n"), TELNET_PORT);
  114. }
  115. #endif // TELNET_SUPPORT