37 #include "contiki-lib.h"
38 #include "contiki-net.h"
47 PROCESS(telnetd_process,
"Telnet server");
49 AUTOSTART_PROCESSES(&telnetd_process);
51 #ifndef TELNETD_CONF_LINELEN
52 #define TELNETD_CONF_LINELEN 80
54 #ifndef TELNETD_CONF_NUMLINES
55 #define TELNETD_CONF_NUMLINES 25
58 #ifdef TELNETD_CONF_REJECT
59 extern char telnetd_reject_text[];
61 static char telnetd_reject_text[] =
62 "Too many connections, please try again later.";
65 #ifndef TELNETD_CONF_MAX_IDLE_TIME
66 #define TELNETD_CONF_MAX_IDLE_TIME (CLOCK_SECOND * 30)
69 struct telnetd_state {
70 char buf[TELNETD_CONF_LINELEN + 1];
74 #define STATE_NORMAL 0
81 #if TELNETD_CONF_MAX_IDLE_TIME
82 struct timer silence_timer;
85 static struct telnetd_state s;
87 #define TELNET_IAC 255
88 #define TELNET_WILL 251
89 #define TELNET_WONT 252
91 #define TELNET_DONT 254
96 #define PRINTF(...) printf(__VA_ARGS__)
102 char bufmem[TELNETD_CONF_NUMLINES * TELNETD_CONF_LINELEN];
107 static struct telnetd_buf buf;
109 static uint8_t connected;
113 buf_init(
struct telnetd_buf *buf)
116 buf->size = TELNETD_CONF_NUMLINES * TELNETD_CONF_LINELEN;
120 buf_append(
struct telnetd_buf *buf,
const char *data,
int len)
124 PRINTF(
"buf_append len %d (%d) '%.*s'\n", len, buf->ptr, len, data);
125 copylen = MIN(len, buf->size - buf->ptr);
126 memcpy(&buf->bufmem[buf->ptr], data, copylen);
127 petsciiconv_toascii(&buf->bufmem[buf->ptr], copylen);
134 buf_copyto(
struct telnetd_buf *buf,
char *to,
int len)
136 memcpy(to, &buf->bufmem[0], len);
140 buf_pop(
struct telnetd_buf *buf,
int len)
144 PRINTF(
"buf_pop len %d (%d)\n", len, buf->ptr);
145 poplen = MIN(len, buf->ptr);
146 memcpy(&buf->bufmem[0], &buf->bufmem[poplen], buf->ptr - poplen);
151 buf_len(
struct telnetd_buf *buf)
170 buf_append(&buf, str, (
int)strlen(str));
176 static const char crnl[2] = {ISO_cr, ISO_nl};
178 if(len1 > 0 && str1[len1 - 1] ==
'\n') {
181 if(len2 > 0 && str2[len2 - 1] ==
'\n') {
188 telnetd_gui_output(str1, len1, str2, len2);
190 buf_append(&buf, str1, len1);
191 buf_append(&buf, str2, len2);
192 buf_append(&buf, crnl,
sizeof(crnl));
198 s.state = STATE_CLOSE;
211 petsciiconv_toascii(telnetd_reject_text, strlen(telnetd_reject_text));
218 telnetd_appcall(data);
219 }
else if(ev == PROCESS_EVENT_EXIT) {
223 telnetd_gui_eventhandler(ev, data);
234 buf_pop(&buf, s.numsent);
241 len = MIN(buf_len(&buf),
uip_mss());
242 PRINTF(
"senddata len %d\n", len);
251 PRINTF(
"telnetd: get_char '%c' %d %d\n", c, c, s.bufptr);
257 if(c != ISO_nl && c != ISO_cr) {
258 s.buf[(int)s.bufptr] = c;
261 if(((c == ISO_nl || c == ISO_cr) && s.bufptr > 0) ||
262 s.bufptr ==
sizeof(s.buf)) {
263 if(s.bufptr <
sizeof(s.buf)) {
264 s.buf[(int)s.bufptr] = 0;
266 petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);
267 PRINTF(
"telnetd: get_char '%.*s'\n", s.bufptr, s.buf);
274 sendopt(uint8_t option, uint8_t value)
277 line[0] = (char)TELNET_IAC;
281 petsciiconv_topetscii(line, 4);
282 buf_append(&buf, line, 4);
293 PRINTF(
"newdata len %d '%.*s'\n", len, len, (
char *)
uip_appdata);
296 while(len > 0 && s.bufptr <
sizeof(s.buf)) {
298 PRINTF(
"newdata char '%c' %d %d state %d\n", c, c, len, s.state);
303 if(c == TELNET_IAC) {
305 s.state = STATE_NORMAL;
309 s.state = STATE_WILL;
312 s.state = STATE_WONT;
318 s.state = STATE_DONT;
321 s.state = STATE_NORMAL;
328 sendopt(TELNET_DONT, c);
329 s.state = STATE_NORMAL;
334 sendopt(TELNET_DONT, c);
335 s.state = STATE_NORMAL;
339 sendopt(TELNET_WONT, c);
340 s.state = STATE_NORMAL;
344 sendopt(TELNET_WONT, c);
345 s.state = STATE_NORMAL;
348 if(c == TELNET_IAC) {
359 telnetd_appcall(
void *ts)
365 s.state = STATE_NORMAL;
368 #if TELNETD_CONF_MAX_IDLE_TIME
369 timer_set(&s.silence_timer, TELNETD_CONF_MAX_IDLE_TIME);
373 uip_send(telnetd_reject_text, strlen(telnetd_reject_text));
380 if(s.state == STATE_CLOSE) {
381 s.state = STATE_NORMAL;
392 #if TELNETD_CONF_MAX_IDLE_TIME
393 timer_set(&s.silence_timer, TELNETD_CONF_MAX_IDLE_TIME);
398 #if TELNETD_CONF_MAX_IDLE_TIME
399 timer_set(&s.silence_timer, TELNETD_CONF_MAX_IDLE_TIME);
409 #if TELNETD_CONF_MAX_IDLE_TIME
411 timer_set(&s.silence_timer, TELNETD_CONF_MAX_IDLE_TIME);
415 #if TELNETD_CONF_MAX_IDLE_TIME
#define uip_acked()
Has previously sent data been acknowledged?
Representation of a uIP TCP connection.
void shell_prompt(char *str)
Print a prompt.
static void newdata(void)
process_event_t tcpip_event
The uIP event.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Default definitions of C compiler quirk work-arounds.
Main header file for the Contiki shell
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
PETSCII/ASCII conversion functions.
#define uip_closed()
Has the connection been closed by the other end?
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
void tcp_listen(uint16_t port)
Open a TCP port.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
uip_appdata
Pointer to the application data in the packet buffer.
void shell_init(void)
Initialize the shell.
void process_exit(struct process *p)
Cause a process to exit.
void shell_quit(void)
Quit the shell.
void shell_default_output(const char *text1, int len1, const char *text2, int len2)
Print a line of output from the shell.
void shell_stop(void)
Stop the shell.
#define uip_aborted()
Has the connection been aborted by the other end?
#define LOADER_UNLOAD()
Unload a program from memory.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
#define NULL
The null pointer.
void shell_input(char *commandline, int commandline_len)
Send a line of input to the shell.
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
#define uip_connected()
Has the connection just been connected?
void process_start(struct process *p, process_data_t data)
Start a process.
void shell_exit(void)
Request shell exit.
#define uip_rexmit()
Do we need to retransmit previously data?
#define uip_close()
Close the current connection.
#define uip_poll()
Is the connection being polled by uIP?
#define uip_timedout()
Has the connection timed out?
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define uip_newdata()
Is new incoming data available?
void shell_start(void)
Start the shell.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define PROCESS_BEGIN()
Define the beginning of a process.