embkernel
 All Classes Functions Variables Typedefs Groups Pages
Telnet.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "Telnet.hpp"
7 #include "FsFile.hpp"
8 #include "FsDir.hpp"
9 #include "RtosHeap.hpp"
10 #include "FsDriveSdio.hpp"
11 #include "LibDebug.hpp"
12 
13 extern FsDriveSdio fsDriveSdio;
14 
15 Telnet::Telnet(int priority, size_t stackSize) :
16  NetServerTelnet(priority, stackSize) {
17  mEntries = (const ENTRY[] ) { //
18  { "help", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerHelp, "Display available commands" }, //
19  { "exit", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerExit, "Close telnet connection" }, //
20  { "sendmail", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerSendMail, "Send an e-mail" }, //
21  { "filetest", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileSpeedTest, "Test file system" }, //
22  { "filecreate", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileCreate, "Create file" }, //
23  { "filedelete", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileDelete, "Delete file" }, //
24  { "filelist", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileList, "List files in a folder" }, //
25  { "fileread", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileRead, "Read a file to screen" }, //
26  { "filewrite", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerFileWrite, "Write to an existing file" }, //
27  { "driveformat", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerDriveFormat, "Format drive" }, //
28  { "stat", (NetServerTelnet::CMD_HANDLER) &Telnet::handlerGetStatistics, "Get system statistics" }, //
29  { 0, 0, 0 } //
30  };
31 }
32 
33 Telnet::~Telnet() {
34 
35 }
36 
37 void Telnet::handlerHelp(int argc, char *argv[]) {
38  for (const ENTRY* entry = mEntries; entry->name; entry++) {
39  mSocket.printf("%-16s%s\r\n", entry->name, entry->descritpion);
40  }
41 }
42 
43 void Telnet::handlerExit(int argc, char *argv[]) {
44  mSocket.writeByte('\0');
45  mSocket.close();
46 }
47 
48 void Telnet::handlerSendMail(int argc, char *argv[]) {
49  if (argc != 2) {
50  mSocket.printf("Invalid arguments count, usage: sendmail to subject\r\n");
51  return;
52  }
53 
54  while (true) {
55  bool isSentOk = false;
56 
57  NetClientSmtp smtp;
58  mSocket.printf("Start sending mail to:%s, subject:%s\r\n", argv[0], argv[1]);
59  if (smtp.start("smtp.mail.yahoo.com", true, "mlib.test@yahoo.com", "JU9a*A#R$p", "mlib.test@yahoo.com", argv[0], argv[1])) {
60  mSocket.printf("Type content[ctrl+c to finish]:\r\n");
61  bool isExit = false;
62  while (!isExit) {
63  uint8_t c;
64  int result = mSocket.read(&c, 1);
65  if (result <= 0) {
66  break;
67  }
68  if (c == 0x03) { //Ctrl+c
69  break;
70  }
71  else if (c <= 0xFE) {
72  mSocket.writeByte(c);
73  smtp.queueBody("%c", c);
74  }
75  }
76  if (smtp.end()) {
77  isSentOk = true;
78  mSocket.printf("\r\n\r\nEmail sent\r\n");
79  }
80  }
81 
82  if (!isSentOk) {
83  mSocket.printf("\r\n\r\nSend email error!\r\n");
84  }
85 
86  smtp.closeConnection();
87 
88  break;
89  }
90 }
91 
92 void Telnet::handlerFileSpeedTest(int argc, char *argv[]) {
93  FsFile file;
94  FsDefs::RESULT result = file.create("0/TEST.TXT");
95  if (result != FsDefs::RES_SUCCESS) {
96  mSocket.printf("Create file error %s\r\n", FsDefs::getResultString(result));
97  return;
98  }
99 
100  const static size_t BUFFER_SIZE = 512;
101  uint8_t* buffer = (uint8_t*) malloc(BUFFER_SIZE);
102  if (!buffer) {
103  file.close();
104  mSocket.printf("Out of memory\r\n");
105  return;
106  }
107  for (size_t i = 0; i < BUFFER_SIZE; i++) {
108  buffer[i] = (i % 16) + 'A';
109  }
110  Rtos::TICK tick = Rtos::getTick();
111  size_t totalTransfered = 0;
112  for (int i = 0; i < 1024; i++) {
113  size_t transfered;
114  result = file.write(buffer, BUFFER_SIZE, &transfered);
115  totalTransfered += transfered;
116  if (result != FsDefs::RES_SUCCESS || transfered != BUFFER_SIZE) {
117  break;
118  }
119  if ((i + 1) % 8 == 0) {
120  mSocket.printf(".");
121  mSocket.flush();
122  }
123  if ((i + 1) % (8 * 64) == 0) {
124  mSocket.printf("\r\n");
125  }
126  }
127  mSocket.printf("\r\n");
128  unsigned int ms = Rtos::convertTickToMs(Rtos::getTick() - tick);
129  unsigned int speed = 0;
130  if (ms > 0) {
131  speed = totalTransfered / ms;
132  }
133  mSocket.printf("Written %ubytes in %lums (%ukBytes/s)\r\n", totalTransfered, ms, speed);
134 
135  result = file.close();
136  result = file.open("0/TEST.TXT");
137  if (result != FsDefs::RES_SUCCESS) {
138  free(buffer);
139  mSocket.printf("Open file error %s\r\n", FsDefs::getResultString(result));
140  return;
141  }
142 
143  tick = Rtos::getTick();
144  totalTransfered = 0;
145  for (int i = 0; i < 1024; i++) {
146  size_t transfered;
147  result = file.read(buffer, BUFFER_SIZE, &transfered);
148  totalTransfered += transfered;
149  if (result != FsDefs::RES_SUCCESS || transfered != BUFFER_SIZE) {
150  break;
151  }
152  if ((i + 1) % 8 == 0) {
153  mSocket.printf(".");
154  mSocket.flush();
155  }
156  if ((i + 1) % (8 * 64) == 0) {
157  mSocket.printf("\r\n");
158  }
159  }
160  mSocket.printf("\r\n");
161  ms = Rtos::convertTickToMs(Rtos::getTick() - tick);
162  speed = 0;
163  if (ms > 0) {
164  speed = totalTransfered / ms;
165  }
166  mSocket.printf("Read %ubytes in %lums (%ukBytes/s)\r\n", totalTransfered, ms, speed);
167  file.close();
168 
169  result = file.del("0/TEST.TXT");
170  if (result != FsDefs::RES_SUCCESS) {
171  free(buffer);
172  mSocket.printf("Delete file error %s\r\n", FsDefs::getResultString(result));
173  return;
174  }
175  mSocket.printf("File deleted\r\n");
176 
177  free(buffer);
178 }
179 
180 void Telnet::handlerFileCreate(int argc, char *argv[]) {
181  if (argc != 1) {
182  mSocket.printf("Invalid arguments count, usage: filecreate filename\r\n");
183  return;
184  }
185 
186  mSocket.printf("Creating file %s\r\n", argv[0]);
187 
188  FsFile file;
189  FsDefs::RESULT result = file.create(argv[0]);
190  if (result != FsDefs::RES_SUCCESS) {
191  mSocket.printf("Create file error %s\r\n", FsDefs::getResultString(result));
192  return;
193  }
194  result = file.close();
195  if (result != FsDefs::RES_SUCCESS) {
196  mSocket.printf("Close file error %s\r\n", FsDefs::getResultString(result));
197  return;
198  }
199  mSocket.printf("File created successfully\r\n");
200 }
201 
202 void Telnet::handlerFileDelete(int argc, char *argv[]) {
203  if (argc != 1) {
204  mSocket.printf("Invalid arguments count, usage: filedelete filename\r\n");
205  return;
206  }
207  FsFile file;
208  FsDefs::RESULT result = file.del(argv[0]);
209  if (result != FsDefs::RES_SUCCESS) {
210  mSocket.printf("Create file error %s\r\n", FsDefs::getResultString(result));
211  return;
212  }
213  mSocket.printf("File deleted successfully\r\n");
214 }
215 
216 void Telnet::handlerFileList(int argc, char *argv[]) {
217  if (argc != 1) {
218  mSocket.printf("Invalid arguments count, usage: filelist directory\r\n");
219  return;
220  }
221 
222  FsDir dir;
223  FsDefs::RESULT result = dir.open(argv[0]);
224  if (result != FsDefs::RES_SUCCESS) {
225  mSocket.printf("Open directory error %s\r\n", FsDefs::getResultString(result));
226  return;
227  }
228 
229  while (true) {
230  FsDir::ENTRY_INFO info;
231  result = dir.getNextEntry(&info);
232  if (result != FsDefs::RES_SUCCESS) {
233  break;
234  }
235  mSocket.printf("%04u-%02u-%02u ", info.createDate.bits.year + 1980, info.createDate.bits.month, info.createDate.bits.day);
236  mSocket.printf("%02uh%02um%02us ", info.createTime.bits.hours, info.createTime.bits.minutes, info.createTime.bits.seconds);
237  if (info.attributes.bits.directory) {
238  mSocket.printf(" <DIR> ");
239  }
240  else {
241  mSocket.printf("%10u ", (unsigned int) info.fileSize);
242  }
243  if (info.longFileName) {
244  mSocket.printf("%s\r\n", info.longFileName);
245  }
246  else {
247  mSocket.printf("%s\r\n", info.shortFileName);
248  }
249  }
250 
251  result = dir.close();
252  if (result != FsDefs::RES_SUCCESS) {
253  mSocket.printf("Close directory error %s\r\n", FsDefs::getResultString(result));
254  return;
255  }
256 
257 }
258 
259 void Telnet::handlerFileRead(int argc, char *argv[]) {
260  FsFile file;
261 
262  if (argc != 1) {
263  mSocket.printf("Invalid arguments count, usage: fileread filename\r\n");
264  return;
265  }
266 
267  FsDefs::RESULT result = file.open(argv[0]);
268  if (result != FsDefs::RES_SUCCESS) {
269  mSocket.printf("Open file error %s\r\n", FsDefs::getResultString(result));
270  return;
271  }
272 
273  const static size_t BUFFER_SIZE = 512;
274  uint8_t* buffer = (uint8_t*) malloc(BUFFER_SIZE);
275  if (!buffer) {
276  file.close();
277  mSocket.printf("Out of memory\r\n");
278  return;
279  }
280 
281  Rtos::TICK tick = Rtos::getTick();
282  size_t totalTransfered = 0;
283  while (true) {
284  size_t transfered;
285  result = file.read(buffer, BUFFER_SIZE, &transfered);
286  mSocket.write(buffer, transfered);
287  totalTransfered += transfered;
288  if (result != FsDefs::RES_SUCCESS || transfered != BUFFER_SIZE) {
289  break;
290  }
291 // mSocket.printf("%c", byte);
292 // if ((i + 1) % 64 == 0) {
293 // mSocket.printf("\r\n");
294 // }
295  }
296  free(buffer);
297  tick = Rtos::getTick() - tick;
298  mSocket.printf("\r\n\r\nRead %ubytes in %lums\r\n", totalTransfered, Rtos::convertTickToMs(tick) );
299 
300  file.close();
301 }
302 
303 void Telnet::handlerFileWrite(int argc, char *argv[]) {
304  FsFile file;
305 
306  if (argc != 1) {
307  mSocket.printf("Invalid arguments count, usage: filewrite filename\r\n");
308  return;
309  }
310 
311  FsDefs::RESULT result = file.open(argv[0]);
312  if (result != FsDefs::RES_SUCCESS) {
313  mSocket.printf("Open file error %s\r\n", FsDefs::getResultString(result));
314  return;
315  }
316  result = file.seek(file.getSize());
317  if (result != FsDefs::RES_SUCCESS) {
318  file.close();
319  mSocket.printf("Seek file error %s\r\n", FsDefs::getResultString(result));
320  return;
321  }
322 
323  mSocket.printf("Type content[ctrl+c to finish]:\r\n");
324  bool isExit = false;
325  while (!isExit) {
326  uint8_t c;
327  int read = mSocket.read(&c, 1);
328  if (read <= 0) {
329  break;
330  }
331  if (c == 0x03) { //Ctrl+c
332  break;
333  }
334  else if (c <= 0xFE) {
335  mSocket.writeByte(c);
336  size_t transfered;
337  result = file.write(&c, 1, &transfered);
338  if (result != FsDefs::RES_SUCCESS) {
339  mSocket.printf("\r\nWrite file error %s\r\n", FsDefs::getResultString(result));
340  break;
341  }
342  }
343  }
344  mSocket.printf("\r\nFinished\r\n");
345  file.close();
346 }
347 
348 void Telnet::handlerDriveFormat(int argc, char *argv[]) {
349  if (argc != 0) {
350  mSocket.printf("Invalid arguments count, usage: driveformat\r\n");
351  return;
352  }
353 
354  mSocket.printf("Formating drive\r\n");
355  ansiSaveCursorPosition();
356 
357  mCurrentPercent = -1;
358  FsDefs::RESULT result = Fs::format(&fsDriveSdio, this);
359  mSocket.printf("\r\n");
360  if (result != FsDefs::RES_SUCCESS) {
361  mSocket.printf("Drive format error %s\r\n", FsDefs::getResultString(result));
362  return;
363  }
364  else {
365  mSocket.printf("Disk formatted\r\n");
366  }
367 }
368 
369 void Telnet::handlerGetStatistics(int argc, char *argv[]) {
370  mSocket.printf("Heap:\r\n");
371  mSocket.printf("\tTotal memory: %ubytes\r\n", RtosHeap::getTotalMemory());
372  mSocket.printf("\tFree memory: %ubytes\r\n", RtosHeap::getFreeMemory());
373  mSocket.printf("\tBlock count: %ublocks\r\n", RtosHeap::getBlockCount());
374  mSocket.printf("\r\nNet memory:\r\n");
375  mSocket.printf("\tTotal memory: %ubytes\r\n", Net::getTotalMemory());
376  mSocket.printf("\tFree memory: %ubytes\r\n", Net::getFreeMemory());
377  mSocket.printf("\tBlock count: %ublocks\r\n", Net::getBlockCount());
378 }
379 
380 void Telnet::formatStatusUpdate(uint32_t current, uint32_t total) {
381  int percent = current * 100 / total;
382  if (mCurrentPercent != percent) {
383  ansiRestoreCursorPosition();
384  mCurrentPercent = percent;
385  mSocket.printf("%d%%", mCurrentPercent);
386  }
387 }
388 
389 void Telnet::onConnection() {
390  USER_DEBUG(LibLog::LEVEL_VERBOSE, "Telnet connected");
391  mSocket.printf("-EMB_KERNEL- (build on %s @ %s)\r\n[Type help for a list of commands]\r\n", __DATE__, __TIME__);
392 }
393 
394 void Telnet::onDisconnection() {
395  USER_DEBUG(LibLog::LEVEL_VERBOSE, "Telnet disconnected");
396 }