Contiki 3.x
simpletelnet.c
1 /*
2  * Copyright (c) 2002, Adam Dunkels.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided
13  * with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  * products derived from this software without specific prior
16  * written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This file is part of the Contiki desktop environment
31  *
32  *
33  */
34 
35 #include <string.h>
36 
37 #include "contiki-net.h"
38 #include "lib/petsciiconv.h"
39 #include "ctk/ctk.h"
40 
41 #include "telnet.h"
42 #include "simpletelnet.h"
43 
44 /* Telnet window */
45 static struct ctk_window telnetwindow;
46 
47 static struct ctk_label telnethostlabel =
48  {CTK_LABEL(0, 0, 4, 1, "Host")};
49 static char telnethost[25];
50 static struct ctk_textentry telnethosttextentry =
51  {CTK_TEXTENTRY(4, 0, 24, 1, telnethost, 24)};
52 
53 static struct ctk_label telnetportlabel =
54  {CTK_LABEL(0, 1, 4, 1, "Port")};
55 static char telnetport[6];
56 static struct ctk_textentry telnetporttextentry =
57  {CTK_TEXTENTRY(4, 1, 5, 1, telnetport, 5)};
58 
59 static struct ctk_button telnetconnectbutton =
60  {CTK_BUTTON(2, 2, 7, "Connect")};
61 static struct ctk_button telnetdisconnectbutton =
62  {CTK_BUTTON(15, 2, 10, "Disconnect")};
63 
64 static char telnetline[31];
65 static struct ctk_textentry telnetlinetextentry =
66  {CTK_TEXTENTRY(0, 3, TELNET_ENTRY_WIDTH, 1, telnetline, TELNET_ENTRY_WIDTH)};
67 
68 static struct ctk_button telnetsendbutton =
69  {CTK_BUTTON(TELNET_ENTRY_WIDTH + 2, 3, 4, "Send")};
70 
71 static struct ctk_label telnetstatus =
72  {CTK_LABEL(0, TELNET_WINDOW_HEIGHT - 1, TELNET_WINDOW_WIDTH, 1, "")};
73 
74 static struct ctk_separator telnetsep1 =
75  {CTK_SEPARATOR(0, 4, TELNET_WINDOW_WIDTH)};
76 
77 static struct ctk_separator telnetsep2 =
78  {CTK_SEPARATOR(0, TELNET_WINDOW_HEIGHT - 2, TELNET_WINDOW_WIDTH)};
79 
80 static char telnettext[TELNET_WINDOW_WIDTH*TELNET_TEXTAREA_HEIGHT];
81 static struct ctk_label telnettextarea =
82  {CTK_LABEL(0, 5, TELNET_WINDOW_WIDTH, TELNET_TEXTAREA_HEIGHT, telnettext)};
83 
84 static struct telnet_state ts_appstate;
85 
86 #define ISO_NL 0x0a
87 #define ISO_CR 0x0d
88 
89 static char sendline[31+2];
90 
91 PROCESS(simpletelnet_process, "Telnet client");
92 
93 AUTOSTART_PROCESSES(&simpletelnet_process);
94 
95 /*-----------------------------------------------------------------------------------*/
96 static void
97 scrollup(void)
98 {
99  unsigned char i;
100  for(i = 1; i < TELNET_TEXTAREA_HEIGHT; ++i) {
101  memcpy(&telnettext[(i - 1) * TELNET_WINDOW_WIDTH], &telnettext[i * TELNET_WINDOW_WIDTH], TELNET_WINDOW_WIDTH);
102  }
103  memset(&telnettext[(TELNET_TEXTAREA_HEIGHT - 1) * TELNET_WINDOW_WIDTH], 0, TELNET_WINDOW_WIDTH);
104 }
105 /*-----------------------------------------------------------------------------------*/
106 static void
107 add_text(char *text)
108 {
109  unsigned char i;
110  unsigned int len;
111 
112  len = (unsigned int)strlen(text);
113 
114  i = 0;
115  while(len > 0) {
116  if(*text == '\n') {
117  scrollup();
118  i = 0;
119  } else if(*text == '\r') {
120  i = 0;
121  } else if(*text >= ' ') {
122  telnettext[(TELNET_TEXTAREA_HEIGHT - 1) * TELNET_WINDOW_WIDTH + i] = *text;
123  ++i;
124  if(i == TELNET_WINDOW_WIDTH) {
125  scrollup();
126  i = 0;
127  }
128  }
129  ++text;
130  --len;
131  }
132 
133  /* if(strlen(text) > 37) {
134  memcpy(&telnettext[9 * 38], text, 37);
135  } else {
136  memcpy(&telnettext[9 * 38], text, strlen(text));
137  }
138  */
139 }
140 /*-----------------------------------------------------------------------------------*/
141 static void
142 show(char *text)
143 {
144  add_text(text);
145  add_text("\n");
146  ctk_label_set_text(&telnetstatus, text);
147  ctk_window_redraw(&telnetwindow);
148 }
149 /*-----------------------------------------------------------------------------------*/
150 static void
151 connect(void)
152 {
153  uip_ipaddr_t addr, *addrptr;
154  uint16_t port;
155  char *cptr;
156  struct uip_conn *conn;
157 
158  /* Find the first space character in host and put a zero there
159  to end the string. */
160  for(cptr = telnethost; *cptr != ' ' && *cptr != 0; ++cptr);
161  *cptr = 0;
162 
163  addrptr = &addr;
164 #if UIP_UDP
165  if(uiplib_ipaddrconv(telnethost, &addr) == 0) {
166  if(resolv_lookup(telnethost, &addrptr) == RESOLV_STATUS_UNCACHED) {
167  resolv_query(telnethost);
168  show("Resolving host...");
169  return;
170  }
171  }
172 #else /* UIP_UDP */
173  uiplib_ipaddrconv(telnethost, &addr);
174 #endif /* UIP_UDP */
175 
176  port = 0;
177  for(cptr = telnetport; *cptr != ' ' && *cptr != 0; ++cptr) {
178  if(*cptr < '0' || *cptr > '9') {
179  show("Port number error");
180  return;
181  }
182  port = 10 * port + *cptr - '0';
183  }
184 
185 
186  conn = tcp_connect(addrptr, uip_htons(port), &ts_appstate);
187  if(conn == NULL) {
188  show("Out of memory error");
189  return;
190  }
191 
192  show("Connecting...");
193 
194 }
195 /*-----------------------------------------------------------------------------------*/
196 PROCESS_THREAD(simpletelnet_process, ev, data)
197 {
198  struct ctk_widget *w;
199  int sendlen;
200 
201  PROCESS_BEGIN();
202 
203  ctk_window_new(&telnetwindow, TELNET_WINDOW_WIDTH, TELNET_WINDOW_HEIGHT, "Simple telnet");
204 
205  strcpy(telnetport, "23");
206 
207  CTK_WIDGET_ADD(&telnetwindow, &telnethostlabel);
208  CTK_WIDGET_ADD(&telnetwindow, &telnetportlabel);
209  CTK_WIDGET_ADD(&telnetwindow, &telnethosttextentry);
210  CTK_WIDGET_ADD(&telnetwindow, &telnetporttextentry);
211  CTK_WIDGET_ADD(&telnetwindow, &telnetconnectbutton);
212  CTK_WIDGET_ADD(&telnetwindow, &telnetdisconnectbutton);
213  CTK_WIDGET_ADD(&telnetwindow, &telnetlinetextentry);
214  CTK_WIDGET_ADD(&telnetwindow, &telnetsendbutton);
215 
216  CTK_WIDGET_ADD(&telnetwindow, &telnetsep1);
217  CTK_WIDGET_ADD(&telnetwindow, &telnettextarea);
218 
219  CTK_WIDGET_ADD(&telnetwindow, &telnetsep2);
220  CTK_WIDGET_ADD(&telnetwindow, &telnetstatus);
221 
222  CTK_WIDGET_FOCUS(&telnetwindow, &telnethosttextentry);
223 
224  ctk_window_open(&telnetwindow);
225 
226  while(1) {
228  if(ev == ctk_signal_button_activate) {
229 
230  w = (struct ctk_widget *)data;
231  if(w == (struct ctk_widget *)&telnetsendbutton) {
232  strcpy(sendline, telnetline);
233  sendlen = (int)strlen(sendline);
234  petsciiconv_toascii(sendline, sendlen);
235  sendline[sendlen++] = ISO_CR;
236  sendline[sendlen++] = ISO_NL;
237  if(telnet_send(&ts_appstate, sendline, sendlen)) {
238  /* Could not send. */
239  ctk_label_set_text(&telnetstatus, "Could not send");
240  ctk_window_redraw(&telnetwindow);
241  /* } else {*/
242  /* Could send */
243  }
244  } else if(w == (struct ctk_widget *)&telnetdisconnectbutton) {
245  telnet_close(&ts_appstate);
246  show("Closing...");
247  } else if(w == (struct ctk_widget *)&telnetconnectbutton) {
248  connect();
249  ctk_window_redraw(&telnetwindow);
250  }
251 #if UIP_UDP
252  } else if(ev == resolv_event_found) {
253  if(strcmp(data, telnethost) == 0) {
254  if(resolv_lookup(telnethost, NULL) == RESOLV_STATUS_CACHED) {
255  connect();
256  } else {
257  show("Host not found");
258  }
259  }
260 #endif /* UIP_UDP */
261  } else if(
262 #if CTK_CONF_WINDOWCLOSE
263  ev == ctk_signal_window_close ||
264 #endif /* CTK_CONF_WINDOWCLOSE */
265  ev == PROCESS_EVENT_EXIT) {
266  process_exit(&simpletelnet_process);
267  ctk_window_close(&telnetwindow);
268  LOADER_UNLOAD();
269  } else if(ev == tcpip_event) {
270  telnet_app(data);
271  }
272  }
273  PROCESS_END();
274 }
275 /*-----------------------------------------------------------------------------------*/
276 void
277 telnet_connected(struct telnet_state *s)
278 {
279  show("Connected");
280 }
281 /*-----------------------------------------------------------------------------------*/
282 void
283 telnet_closed(struct telnet_state *s)
284 {
285  show("Connection closed");
286 }
287 /*-----------------------------------------------------------------------------------*/
288 void
289 telnet_sent(struct telnet_state *s)
290 {
291  petsciiconv_topetscii(sendline, sizeof(sendline));
292  scrollup();
293  add_text(sendline);
294  CTK_TEXTENTRY_CLEAR(&telnetlinetextentry);
295  ctk_window_redraw(&telnetwindow);
296 }
297 /*-----------------------------------------------------------------------------------*/
298 void
299 telnet_aborted(struct telnet_state *s)
300 {
301  show("Connection reset by peer");
302 }
303 /*-----------------------------------------------------------------------------------*/
304 void
305 telnet_timedout(struct telnet_state *s)
306 {
307  show("Connection timed out");
308 }
309 /*-----------------------------------------------------------------------------------*/
310 void
311 telnet_newdata(struct telnet_state *s, char *data, uint16_t len)
312 {
313  petsciiconv_topetscii(data, len);
314  data[len] = 0;
315  add_text(data);
316  ctk_window_redraw(&telnetwindow);
317 }
318 /*-----------------------------------------------------------------------------------*/
#define CTK_WIDGET_ADD(win, widg)
Add a widget to a window.
Definition: ctk.h:752
process_event_t ctk_signal_window_close
Emitted when a window is closed.
Definition: ctk.c:155
#define CTK_SEPARATOR(x, y, w)
Instantiating macro for the ctk_separator widget.
Definition: ctk.h:111
#define CTK_TEXTENTRY_CLEAR(e)
Clears a text entry widget and sets the cursor to the start of the text line.
Definition: ctk.h:231
process_event_t ctk_signal_button_activate
Same as ctk_signal_widget_activate.
Definition: ctk.c:126
Hostname was not found in the cache.
Definition: resolv.h:71
Hostname is fresh and usable.
Definition: resolv.h:68
void ctk_window_open(CC_REGISTER_ARG struct ctk_window *w)
Open a window, or bring window to front if already open.
Definition: ctk.c:347
#define CTK_WIDGET_FOCUS(win, widg)
Set focus to a widget.
Definition: ctk.h:763
void ctk_window_close(struct ctk_window *w)
Close a window if it is open.
Definition: ctk.c:400
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
Representation of a uIP TCP connection.
Definition: uip.h:1336
CCIF struct uip_conn * tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Open a TCP connection to the specified IP address and port.
#define CTK_TEXTENTRY(x, y, w, h, text, len)
Instantiating macro for the ctk_textentry widget.
Definition: ctk.h:275
#define ctk_label_set_text(l, t)
Set the text of a label.
Definition: ctk.h:849
#define NULL
The null pointer.
void ctk_window_redraw(struct ctk_window *w)
Redraw a window.
Definition: ctk.c:652
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
Definition: uiplib.h:71
#define CTK_LABEL(x, y, w, h, text)
Instantiating macro for the ctk_label widget.
Definition: ctk.h:171
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void ctk_window_new(struct ctk_window *window, unsigned char w, unsigned char h, char *title)
Create a new window.
Definition: ctk.c:732
CCIF process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
PETSCII/ASCII conversion functions.
#define LOADER_UNLOAD()
Unload a program from memory.
Definition: loader.h:104
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Definition: uip6.c:2298
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
process_event_t tcpip_event
The uIP event.
Definition: tcpip.c:75
#define CTK_BUTTON(x, y, w, text)
Instantiating macro for the ctk_button widget.
Definition: ctk.h:140
Representation of a CTK window.
Definition: ctk.h:506
The generic CTK widget structure that contains all other widget structures.
Definition: ctk.h:444
unsigned char w
The width of the widget in character coordinates.
Definition: ctk.h:464
CTK header file.
void process_exit(struct process *p)
Cause a process to exit.
Definition: process.c:202