ESP3D  3.0
Firmware for ESP boards connected to 3D Printer
telnet_server.cpp
Go to the documentation of this file.
1 /*
2  telnet_server.cpp - telnet server functions class
3 
4  Copyright (c) 2014 Luc Lebosse. All rights reserved.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
21 #include "../../include/esp3d_config.h"
22 
23 #if defined (TELNET_FEATURE)
24 #include <WiFiServer.h>
25 #include <WiFiClient.h>
26 #include "telnet_server.h"
27 #include "../../core/settings_esp3d.h"
28 #include "../../core/esp3doutput.h"
29 #include "../../core/commands.h"
30 
32 
33 #define TIMEOUT_TELNET_FLUSH 1500
34 
36 {
37  if(_telnetClients) {
38  _telnetClients.stop();
39  }
40 }
41 
43 {
44  if ( !_started || _telnetserver == NULL) {
45  return false;
46  }
47  //check if there are any new clients
48  if (_telnetserver->hasClient()) {
49  //find free/disconnected spot
50  if (!_telnetClients || !_telnetClients.connected()) {
51  if(_telnetClients) {
52  _telnetClients.stop();
53  }
54  _telnetClients = _telnetserver->available();
55  //new client
56  }
57  }
58  if (_telnetserver->hasClient()) {
59  //no free/disconnected spot so reject
60  _telnetserver->available().stop();
61  }
62  return _telnetClients.connected();
63 }
64 
66 {
67  static String res;
68  res = "0.0.0.0";
69  if (_telnetClients && _telnetClients.connected()) {
70  res = _telnetClients.remoteIP().toString();
71  }
72  return res.c_str();
73 }
74 
75 
77 {
78  _buffer_size = 0;
79  _started = false;
80  _isdebug = false;
81  _port = 0;
82  _buffer = nullptr;
83  _telnetserver = nullptr;
84 }
86 {
87  end();
88 }
89 
93 bool Telnet_Server::begin(uint16_t port, bool debug)
94 {
95  end();
97  return true;
98  }
99  //Get telnet port
100  if (port == 0) {
102  } else {
103  _port = port;
104  }
105  _isdebug = debug;
106  if (!_isdebug) {
107  _buffer= (uint8_t *)malloc(ESP3D_TELNET_BUFFER_SIZE +1);
108  if (!_buffer) {
109  return false;
110  }
111  }
112  //create instance
113  _telnetserver= new WiFiServer(_port);
114  if (!_telnetserver) {
115  return false;
116  }
117  _telnetserver->setNoDelay(true);
118  //start telnet server
119  _telnetserver->begin();
120  _started = true;
121  _lastflush = millis();
122  return _started;
123 }
128 {
129  _started = false;
130  _buffer_size = 0;
131  _port = 0;
132  _isdebug = false;
133  closeClient();
134  if (_telnetserver) {
135  delete _telnetserver;
136  _telnetserver = nullptr;
137  }
138 
139  if (_buffer) {
140  free(_buffer);
141  _buffer = nullptr;
142  }
143 }
144 
149 {
150  //nothing to reset
151  return true;
152 }
153 
155 {
156  return _started;
157 }
158 
160 {
161  Hal::wait(0);
162  if (isConnected()) {
163  //check clients for data
164  size_t len = _telnetClients.available();
165  if(len > 0) {
166  //if yes read them
167  uint8_t * sbuf = (uint8_t *)malloc(len);
168  if(sbuf) {
169  size_t count = _telnetClients.read(sbuf, len);
170  //push to buffer
171  if (count > 0) {
172  push2buffer(sbuf, count);
173  }
174  //free buffer
175  free(sbuf);
176  }
177  }
178 
179  }
180  //we cannot left data in buffer too long
181  //in case some commands "forget" to add \n
182  if (((millis() - _lastflush) > TIMEOUT_TELNET_FLUSH) && (_buffer_size > 0)) {
183  flushbuffer();
184  }
185 }
186 
187 void Telnet_Server::flushbuffer()
188 {
189  if (!_buffer || !_started) {
190  _buffer_size = 0;
191  return;
192  }
194  _buffer[_buffer_size] = 0x0;
195  //dispatch command
196  esp3d_commands.process(_buffer, _buffer_size, &output);
197  _lastflush = millis();
198  _buffer_size = 0;
199 }
200 
201 void Telnet_Server::push2buffer(uint8_t * sbuf, size_t len)
202 {
203  if (!_buffer) {
204  return;
205  }
206  for (size_t i = 0; i < len; i++) {
207  _lastflush = millis();
208  //command is defined
209  if (char(sbuf[i]) == '\n') {
210  if (_buffer_size < ESP3D_TELNET_BUFFER_SIZE) {
211  _buffer[_buffer_size] = sbuf[i];
212  _buffer_size++;
213  }
214  flushbuffer();
215  } else if (isPrintable (char(sbuf[i]) ) || char(sbuf[i]) == '\r') {
216  if (_buffer_size < ESP3D_TELNET_BUFFER_SIZE) {
217  _buffer[_buffer_size] = sbuf[i];
218  _buffer_size++;
219  } else {
220  flushbuffer();
221  _buffer[_buffer_size] = sbuf[i];
222  _buffer_size++;
223  }
224  } else { //it is not printable char
225  //clean buffer first
226  if (_buffer_size > 0) {
227  flushbuffer();
228  }
229  //process char
230  _buffer[_buffer_size] = sbuf[i];
231  _buffer_size++;
232  flushbuffer();
233  }
234  }
235 }
236 
237 size_t Telnet_Server::write(uint8_t c)
238 {
239  return write(&c,1);
240 }
241 
242 size_t Telnet_Server::write(const uint8_t *buffer, size_t size)
243 {
244  if (isConnected() && (size>0)) {
245  if (availableForWrite() >= size) {
246  //push data to connected telnet client
247  return _telnetClients.write(buffer, size);
248  } else {
249  size_t sizetosend = size;
250  size_t sizesent = 0;
251  uint8_t *buffertmp=(uint8_t *)buffer;
252  uint32_t starttime = millis();
253  //loop until all is sent or timeout
254  while (sizetosend>0 && ((millis() - starttime) < 100)) {
255  size_t available = availableForWrite();
256  if(available>0) {
257  //in case less is sent
258  available = _telnetClients.write(&buffertmp[sizesent], (available >= sizetosend)?sizetosend:available);
259  sizetosend-=available;
260  sizesent+=available;
261  starttime=millis();
262  } else {
263  Hal::wait(5);
264  }
265  }
266  return sizesent;
267  }
268  }
269  return 0;
270 }
271 
273 {
274  if (!isConnected()) {
275  return 0;
276  }
277 #ifdef ARDUINO_ARCH_ESP32
278  return 128; //hard code for esp32
279 #endif //ARDUINO_ARCH_ESP32
280 #ifdef ARDUINO_ARCH_ESP8266
281  return _telnetClients.availableForWrite();
282 #endif //ARDUINO_ARCH_ESP8266
283 }
284 
286 {
287  if(isConnected()) {
288  return _telnetClients.available();
289  }
290  return 0;
291 }
292 
294 {
295  if(isConnected()) {
296  if(_telnetClients.available() > 0) {
297  return _telnetClients.read();
298  }
299  }
300  return -1;
301 }
302 
303 size_t Telnet_Server::readBytes(uint8_t * sbuf, size_t len)
304 {
305  if(isConnected()) {
306  if(_telnetClients.available() > 0) {
307  return _telnetClients.read(sbuf, len);
308  }
309  }
310  return 0;
311 }
312 
313 
315 {
316  _telnetClients.flush();
317 }
318 
319 #endif //TELNET_FEATURE
esp3d_commands
Commands esp3d_commands
Definition: commands.cpp:26
Telnet_Server::isConnected
bool isConnected()
Definition: telnet_server.cpp:42
Hal::wait
static void wait(uint32_t milliseconds)
Definition: hal.cpp:226
Telnet_Server::available
int available()
Definition: telnet_server.cpp:285
Telnet_Server::clientIPAddress
const char * clientIPAddress()
Definition: telnet_server.cpp:65
Telnet_Server::begin
bool begin(uint16_t port=0, bool debug=false)
Definition: telnet_server.cpp:93
telnet_server.h
Telnet_Server::end
void end()
Definition: telnet_server.cpp:127
ESP_TELNET_ON
#define ESP_TELNET_ON
Definition: settings_esp3d.h:66
Commands::process
void process(uint8_t *sbuf, size_t len, ESP3DOutput *output, level_authenticate_type auth=LEVEL_GUEST, ESP3DOutput *outputonly=nullptr)
Definition: commands.cpp:36
Telnet_Server::port
uint16_t port()
Definition: telnet_server.h:69
ESP_TELNET_PORT
#define ESP_TELNET_PORT
Definition: settings_esp3d.h:53
Telnet_Server::flush
void flush()
Definition: telnet_server.cpp:314
Telnet_Server::started
bool started()
Definition: telnet_server.cpp:154
telnet_server
Telnet_Server telnet_server
Definition: telnet_server.cpp:31
Telnet_Server::availableForWrite
uint availableForWrite()
Definition: telnet_server.cpp:272
Telnet_Server::reset
bool reset()
Definition: telnet_server.cpp:148
Telnet_Server
Definition: telnet_server.h:30
Telnet_Server::~Telnet_Server
~Telnet_Server()
Definition: telnet_server.cpp:85
Telnet_Server::Telnet_Server
Telnet_Server()
Definition: telnet_server.cpp:76
Telnet_Server::closeClient
void closeClient()
Definition: telnet_server.cpp:35
Settings_ESP3D::read_uint32
static uint32_t read_uint32(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:919
Telnet_Server::handle
void handle()
Definition: telnet_server.cpp:159
Settings_ESP3D::read_byte
static uint8_t read_byte(int pos, bool *haserror=NULL)
Definition: settings_esp3d.cpp:715
Telnet_Server::read
int read(void)
Definition: telnet_server.cpp:293
Telnet_Server::readBytes
size_t readBytes(uint8_t *sbuf, size_t len)
Definition: telnet_server.cpp:303
TIMEOUT_TELNET_FLUSH
#define TIMEOUT_TELNET_FLUSH
Definition: telnet_server.cpp:33
Telnet_Server::write
size_t write(uint8_t c)
Definition: telnet_server.cpp:237
ESP3D_TELNET_BUFFER_SIZE
#define ESP3D_TELNET_BUFFER_SIZE
Definition: telnet_server.h:28
ESP_TELNET_CLIENT
#define ESP_TELNET_CLIENT
Definition: esp3doutput.h:23
ESP3DOutput
Definition: esp3doutput.h:48