36 #include "contiki-lib.h"
37 #include "contiki-net.h"
46 PROCESS(telnetd_process,
"Telnet server");
48 AUTOSTART_PROCESSES(&telnetd_process);
50 #ifndef TELNETD_CONF_LINELEN
51 #define TELNETD_CONF_LINELEN 80
53 #ifndef TELNETD_CONF_NUMLINES
54 #define TELNETD_CONF_NUMLINES 25
57 #ifdef TELNETD_CONF_REJECT
58 extern char telnetd_reject_text[];
60 static char telnetd_reject_text[] =
61 "Too many connections, please try again later.";
64 struct telnetd_state {
65 char buf[TELNETD_CONF_LINELEN + 1];
69 #define STATE_NORMAL 0
76 struct timer silence_timer;
78 static struct telnetd_state s;
80 #define TELNET_IAC 255
81 #define TELNET_WILL 251
82 #define TELNET_WONT 252
84 #define TELNET_DONT 254
89 #define PRINTF(...) printf(__VA_ARGS__)
95 char bufmem[TELNETD_CONF_NUMLINES * TELNETD_CONF_LINELEN];
100 static struct telnetd_buf buf;
102 static uint8_t connected;
104 #define MAX_SILENCE_TIME (CLOCK_SECOND * 30)
106 #define MIN(a, b) ((a) < (b)? (a): (b))
109 buf_init(
struct telnetd_buf *buf)
112 buf->size = TELNETD_CONF_NUMLINES * TELNETD_CONF_LINELEN;
116 buf_append(
struct telnetd_buf *buf,
const char *data,
int len)
120 PRINTF(
"buf_append len %d (%d) '%.*s'\n", len, buf->ptr, len, data);
121 copylen = MIN(len, buf->size - buf->ptr);
122 memcpy(&buf->bufmem[buf->ptr], data, copylen);
123 petsciiconv_toascii(&buf->bufmem[buf->ptr], copylen);
130 buf_copyto(
struct telnetd_buf *buf,
char *to,
int len)
132 memcpy(to, &buf->bufmem[0], len);
136 buf_pop(
struct telnetd_buf *buf,
int len)
140 PRINTF(
"buf_pop len %d (%d)\n", len, buf->ptr);
141 poplen = MIN(len, buf->ptr);
142 memcpy(&buf->bufmem[0], &buf->bufmem[poplen], buf->ptr - poplen);
147 buf_len(
struct telnetd_buf *buf)
166 buf_append(&buf, str, (
int)strlen(str));
172 if(len1 > 0 && str1[len1 - 1] ==
'\n') {
175 if(len2 > 0 && str2[len2 - 1] ==
'\n') {
182 telnetd_gui_output(str1, len1, str2, len2);
184 buf_append(&buf, str1, len1);
185 buf_append(&buf, str2, len2);
186 buf_append(&buf,
"\r\n", 2);
192 s.state = STATE_CLOSE;
205 petsciiconv_toascii(telnetd_reject_text, strlen(telnetd_reject_text));
212 telnetd_appcall(data);
213 }
else if(ev == PROCESS_EVENT_EXIT) {
217 telnetd_gui_eventhandler(ev, data);
228 buf_pop(&buf, s.numsent);
235 len = MIN(buf_len(&buf),
uip_mss());
236 PRINTF(
"senddata len %d\n", len);
245 PRINTF(
"telnetd: get_char '%c' %d %d\n", c, c, s.bufptr);
251 if(c != ISO_nl && c != ISO_cr) {
252 s.buf[(int)s.bufptr] = c;
255 if(((c == ISO_nl || c == ISO_cr) && s.bufptr > 0) ||
256 s.bufptr ==
sizeof(s.buf)) {
257 if(s.bufptr <
sizeof(s.buf)) {
258 s.buf[(int)s.bufptr] = 0;
260 petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);
261 PRINTF(
"telnetd: get_char '%.*s'\n", s.bufptr, s.buf);
268 sendopt(uint8_t option, uint8_t value)
271 line[0] = (char)TELNET_IAC;
275 petsciiconv_topetscii(line, 4);
276 buf_append(&buf, line, 4);
287 PRINTF(
"newdata len %d '%.*s'\n", len, len, (
char *)
uip_appdata);
290 while(len > 0 && s.bufptr <
sizeof(s.buf)) {
292 PRINTF(
"newdata char '%c' %d %d state %d\n", c, c, len, s.state);
297 if(c == TELNET_IAC) {
299 s.state = STATE_NORMAL;
303 s.state = STATE_WILL;
306 s.state = STATE_WONT;
312 s.state = STATE_DONT;
315 s.state = STATE_NORMAL;
322 sendopt(TELNET_DONT, c);
323 s.state = STATE_NORMAL;
328 sendopt(TELNET_DONT, c);
329 s.state = STATE_NORMAL;
333 sendopt(TELNET_WONT, c);
334 s.state = STATE_NORMAL;
338 sendopt(TELNET_WONT, c);
339 s.state = STATE_NORMAL;
342 if(c == TELNET_IAC) {
353 telnetd_appcall(
void *ts)
359 s.state = STATE_NORMAL;
362 timer_set(&s.silence_timer, MAX_SILENCE_TIME);
365 uip_send(telnetd_reject_text, strlen(telnetd_reject_text));
372 if(s.state == STATE_CLOSE) {
373 s.state = STATE_NORMAL;
384 timer_set(&s.silence_timer, MAX_SILENCE_TIME);
388 timer_set(&s.silence_timer, MAX_SILENCE_TIME);
398 timer_set(&s.silence_timer, MAX_SILENCE_TIME);
void shell_prompt(char *str)
Print a prompt.
void shell_stop(void)
Stop the shell.
void shell_init(void)
Initialize the shell.
#define PROCESS_BEGIN()
Define the beginning of a process.
Representation of a uIP TCP connection.
#define uip_aborted()
Has the connection been aborted by the other end?
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_newdata()
Is new incoming data available?
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
Main header file for the Contiki shell
#define NULL
The null pointer.
void shell_input(char *commandline, int commandline_len)
Send a line of input to the shell.
#define uip_poll()
Is the connection being polled by uIP?
void shell_quit(void)
Quit the shell.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
void shell_start(void)
Start the shell.
#define uip_acked()
Has previously sent data been acknowledged?
#define uip_connected()
Has the connection just been connected?
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
PETSCII/ASCII conversion functions.
#define LOADER_UNLOAD()
Unload a program from memory.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define PROCESS(name, strname)
Declare a process.
#define uip_close()
Close the current connection.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
process_event_t tcpip_event
The uIP event.
#define uip_timedout()
Has the connection timed out?
void process_start(struct process *p, process_data_t data)
Start a process.
CCIF void tcp_listen(uint16_t port)
Open a TCP port.
void shell_default_output(const char *text1, int len1, const char *text2, int len2)
Print a line of output from the shell.
#define uip_closed()
Has the connection been closed by the other end?
void shell_exit(void)
Request shell exit.
int timer_expired(struct timer *t)
Check if a timer has expired.
void process_exit(struct process *p)
Cause a process to exit.
uip_appdata
Pointer to the application data in the packet buffer.
#define uip_rexmit()
Do we need to retransmit previously data?