240 lines
6.7 KiB
C++
240 lines
6.7 KiB
C++
/*
|
|
telnet_server.cpp - telnet server functions class
|
|
|
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
|
|
#include "config.h"
|
|
|
|
#if defined (ENABLE_WIFI) && defined (ENABLE_TELNET)
|
|
|
|
#include "wifiservices.h"
|
|
|
|
#include "grbl.h"
|
|
|
|
#include "telnet_server.h"
|
|
#include "wificonfig.h"
|
|
#include <WiFi.h>
|
|
#include <Preferences.h>
|
|
#include "report.h"
|
|
#include "commands.h"
|
|
|
|
|
|
Telnet_Server telnet_server;
|
|
bool Telnet_Server::_setupdone = false;
|
|
uint16_t Telnet_Server::_port = 0;
|
|
WiFiServer * Telnet_Server::_telnetserver = NULL;
|
|
WiFiClient Telnet_Server::_telnetClients[MAX_TLNT_CLIENTS];
|
|
#ifdef ENABLE_TELNET_WELCOME_MSG
|
|
IPAddress Telnet_Server::_telnetClientsIP[MAX_TLNT_CLIENTS];
|
|
#endif
|
|
|
|
Telnet_Server::Telnet_Server(){
|
|
_RXbufferSize = 0;
|
|
_RXbufferpos = 0;
|
|
}
|
|
Telnet_Server::~Telnet_Server(){
|
|
end();
|
|
}
|
|
|
|
|
|
bool Telnet_Server::begin(){
|
|
|
|
bool no_error = true;
|
|
end();
|
|
Preferences prefs;
|
|
_RXbufferSize = 0;
|
|
_RXbufferpos = 0;;
|
|
prefs.begin(NAMESPACE, true);
|
|
int8_t penabled = prefs.getChar(TELNET_ENABLE_ENTRY, DEFAULT_TELNET_STATE);
|
|
//Get telnet port
|
|
_port = prefs.getUShort(TELNET_PORT_ENTRY, DEFAULT_TELNETSERVER_PORT);
|
|
prefs.end();
|
|
|
|
if (penabled == 0) return false;
|
|
//create instance
|
|
_telnetserver= new WiFiServer(_port, MAX_TLNT_CLIENTS);
|
|
_telnetserver->setNoDelay(true);
|
|
String s = "[MSG:TELNET Started " + String(_port) + "]\r\n";
|
|
grbl_send(CLIENT_ALL,(char *)s.c_str());
|
|
//start telnet server
|
|
_telnetserver->begin();
|
|
_setupdone = true;
|
|
return no_error;
|
|
}
|
|
|
|
void Telnet_Server::end(){
|
|
_setupdone = false;
|
|
_RXbufferSize = 0;
|
|
_RXbufferpos = 0;
|
|
if (_telnetserver) {
|
|
delete _telnetserver;
|
|
_telnetserver = NULL;
|
|
}
|
|
}
|
|
|
|
void Telnet_Server::clearClients(){
|
|
//check if there are any new clients
|
|
if (_telnetserver->hasClient()){
|
|
uint8_t i;
|
|
for(i = 0; i < MAX_TLNT_CLIENTS; i++){
|
|
//find free/disconnected spot
|
|
if (!_telnetClients[i] || !_telnetClients[i].connected()){
|
|
#ifdef ENABLE_TELNET_WELCOME_MSG
|
|
_telnetClientsIP[i] = IPAddress(0, 0, 0, 0);
|
|
#endif
|
|
if(_telnetClients[i]) _telnetClients[i].stop();
|
|
_telnetClients[i] = _telnetserver->available();
|
|
break;
|
|
}
|
|
}
|
|
if (i >= MAX_TLNT_CLIENTS) {
|
|
//no free/disconnected spot so reject
|
|
_telnetserver->available().stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t Telnet_Server::write(const uint8_t *buffer, size_t size){
|
|
|
|
size_t wsize = 0;
|
|
if ( !_setupdone || _telnetserver == NULL) {
|
|
log_d("[TELNET out blocked]");
|
|
return 0;
|
|
}
|
|
clearClients();
|
|
//log_d("[TELNET out]");
|
|
//push UART data to all connected telnet clients
|
|
for(uint8_t i = 0; i < MAX_TLNT_CLIENTS; i++){
|
|
if (_telnetClients[i] && _telnetClients[i].connected()){
|
|
//log_d("[TELNET out connected]");
|
|
wsize = _telnetClients[i].write(buffer, size);
|
|
COMMANDS::wait(0);
|
|
}
|
|
}
|
|
return wsize;
|
|
}
|
|
|
|
void Telnet_Server::handle(){
|
|
COMMANDS::wait(0);
|
|
//check if can read
|
|
if ( !_setupdone || _telnetserver == NULL) {
|
|
return;
|
|
}
|
|
clearClients();
|
|
//check clients for data
|
|
//uint8_t c;
|
|
for(uint8_t i = 0; i < MAX_TLNT_CLIENTS; i++){
|
|
if (_telnetClients[i] && _telnetClients[i].connected()){
|
|
#ifdef ENABLE_TELNET_WELCOME_MSG
|
|
if (_telnetClientsIP[i] != _telnetClients[i].remoteIP()){
|
|
report_init_message(CLIENT_TELNET);
|
|
_telnetClientsIP[i] = _telnetClients[i].remoteIP();
|
|
}
|
|
#endif
|
|
if(_telnetClients[i].available()){
|
|
uint8_t buf[1024];
|
|
COMMANDS::wait(0);
|
|
int readlen = _telnetClients[i].available();
|
|
int writelen = TELNETRXBUFFERSIZE - available();
|
|
if (readlen > 1024) readlen = 1024;
|
|
if (readlen > writelen) readlen = writelen;
|
|
if (readlen > 0) {
|
|
_telnetClients[i].read(buf, readlen);
|
|
push(buf, readlen);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
if (_telnetClients[i]) {
|
|
#ifdef ENABLE_TELNET_WELCOME_MSG
|
|
_telnetClientsIP[i] = IPAddress(0, 0, 0, 0);
|
|
#endif
|
|
_telnetClients[i].stop();
|
|
}
|
|
}
|
|
COMMANDS::wait(0);
|
|
}
|
|
}
|
|
|
|
int Telnet_Server::peek(void){
|
|
if (_RXbufferSize > 0)return _RXbuffer[_RXbufferpos];
|
|
else return -1;
|
|
}
|
|
|
|
int Telnet_Server::available(){
|
|
return _RXbufferSize;
|
|
}
|
|
|
|
int Telnet_Server::get_rx_buffer_available(){
|
|
return TELNETRXBUFFERSIZE - _RXbufferSize;
|
|
}
|
|
|
|
bool Telnet_Server::push (uint8_t data){
|
|
log_i("[TELNET]push %c",data);
|
|
if ((1 + _RXbufferSize) <= TELNETRXBUFFERSIZE){
|
|
int current = _RXbufferpos + _RXbufferSize;
|
|
if (current > TELNETRXBUFFERSIZE) current = current - TELNETRXBUFFERSIZE;
|
|
if (current > (TELNETRXBUFFERSIZE-1)) current = 0;
|
|
_RXbuffer[current] = data;
|
|
_RXbufferSize++;
|
|
log_i("[TELNET]buffer size %d",_RXbufferSize);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Telnet_Server::push (const uint8_t * data, int data_size){
|
|
if ((data_size + _RXbufferSize) <= TELNETRXBUFFERSIZE){
|
|
int data_processed = 0;
|
|
int current = _RXbufferpos + _RXbufferSize;
|
|
if (current > TELNETRXBUFFERSIZE) current = current - TELNETRXBUFFERSIZE;
|
|
for (int i = 0; i < data_size; i++){
|
|
if (current > (TELNETRXBUFFERSIZE-1)) current = 0;
|
|
if (char(data[i]) != '\r') {
|
|
_RXbuffer[current] = data[i];
|
|
current ++;
|
|
data_processed++;
|
|
}
|
|
COMMANDS::wait(0);
|
|
//vTaskDelay(1 / portTICK_RATE_MS); // Yield to other tasks
|
|
}
|
|
_RXbufferSize+=data_processed;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Telnet_Server::read(void){
|
|
|
|
if (_RXbufferSize > 0) {
|
|
int v = _RXbuffer[_RXbufferpos];
|
|
//log_d("[TELNET]read %c",char(v));
|
|
_RXbufferpos++;
|
|
if (_RXbufferpos > (TELNETRXBUFFERSIZE-1))_RXbufferpos = 0;
|
|
_RXbufferSize--;
|
|
return v;
|
|
} else return -1;
|
|
}
|
|
|
|
#endif // Enable TELNET && ENABLE_WIFI
|
|
|
|
#endif // ARDUINO_ARCH_ESP32
|