adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 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. |
adamdunkels | 06f897e | 2004-06-06 05:59:20 +0000 | [diff] [blame] | 14 | * 3. The name of the author may not be used to endorse or promote |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 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 | * |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 32 | * $Id: simpletelnet.c,v 1.14 2005/04/16 14:17:32 oliverschmidt Exp $ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 33 | * |
| 34 | */ |
| 35 | |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 36 | #include <string.h> |
| 37 | |
| 38 | #include "ek.h" |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 39 | #include "petsciiconv.h" |
adamdunkels | db300d2 | 2004-02-24 09:57:49 +0000 | [diff] [blame] | 40 | #include "uiplib.h" |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 41 | #include "uip.h" |
| 42 | #include "ctk.h" |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 43 | #include "resolv.h" |
| 44 | #include "telnet.h" |
| 45 | #include "simpletelnet.h" |
adamdunkels | 8af703e | 2003-04-08 11:50:20 +0000 | [diff] [blame] | 46 | #include "loader.h" |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 47 | #include "tcpip.h" |
oliverschmidt | 3901c23 | 2004-06-13 09:48:32 +0000 | [diff] [blame] | 48 | |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 49 | /* Telnet window */ |
| 50 | static struct ctk_window telnetwindow; |
| 51 | |
| 52 | static struct ctk_label telnethostlabel = |
| 53 | {CTK_LABEL(1, 0, 4, 1, "Host")}; |
| 54 | static char telnethost[25]; |
| 55 | static struct ctk_textentry telnethosttextentry = |
| 56 | {CTK_TEXTENTRY(0, 1, 24, 1, telnethost, 24)}; |
| 57 | |
| 58 | static struct ctk_label telnetportlabel = |
| 59 | {CTK_LABEL(31, 0, 4, 1, "Port")}; |
| 60 | static char telnetport[6]; |
| 61 | static struct ctk_textentry telnetporttextentry = |
| 62 | {CTK_TEXTENTRY(30, 1, 5, 1, telnetport, 5)}; |
| 63 | |
| 64 | static struct ctk_button telnetconnectbutton = |
| 65 | {CTK_BUTTON(2, 3, 7, "Connect")}; |
| 66 | static struct ctk_button telnetdisconnectbutton = |
| 67 | {CTK_BUTTON(25, 3, 10, "Disconnect")}; |
| 68 | |
| 69 | static char telnetline[31]; |
| 70 | static struct ctk_textentry telnetlinetextentry = |
| 71 | {CTK_TEXTENTRY(0, 5, 30, 1, telnetline, 30)}; |
| 72 | |
| 73 | |
| 74 | static struct ctk_button telnetsendbutton = |
| 75 | {CTK_BUTTON(32, 5, 4, "Send")}; |
| 76 | |
| 77 | static struct ctk_label telnetstatus = |
| 78 | {CTK_LABEL(0, 19, 38, 1, "")}; |
| 79 | |
| 80 | static struct ctk_separator telnetsep1 = |
| 81 | {CTK_SEPARATOR(0, 7, 38)}; |
| 82 | |
| 83 | static struct ctk_separator telnetsep2 = |
| 84 | {CTK_SEPARATOR(0, 18, 38)}; |
| 85 | |
| 86 | static char telnettext[38*10]; |
| 87 | static struct ctk_label telnettextarea = |
| 88 | {CTK_LABEL(0, 8, 38, 10, telnettext)}; |
| 89 | |
| 90 | static struct telnet_state ts_appstate; |
| 91 | |
| 92 | #define ISO_NL 0x0a |
| 93 | #define ISO_CR 0x0d |
| 94 | |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 95 | static char sendline[31+2]; |
| 96 | |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 97 | EK_EVENTHANDLER(simpletelnet_eventhandler, ev, data); |
| 98 | EK_PROCESS(p, "Telnet client", EK_PRIO_NORMAL, |
| 99 | simpletelnet_eventhandler, NULL, NULL); |
| 100 | static ek_id_t id = EK_ID_NONE; |
| 101 | /* |
adamdunkels | 78c03dc | 2003-04-09 13:45:05 +0000 | [diff] [blame] | 102 | static DISPATCHER_SIGHANDLER(simpletelnet_sighandler, s, data); |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 103 | static struct dispatcher_proc p = |
adamdunkels | 78c03dc | 2003-04-09 13:45:05 +0000 | [diff] [blame] | 104 | {DISPATCHER_PROC("Simple telnet", NULL, simpletelnet_sighandler, |
adamdunkels | 2e41542 | 2003-04-10 09:04:49 +0000 | [diff] [blame] | 105 | telnet_app)}; |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 106 | static ek_id_t id;*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 107 | |
| 108 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | 8bb5cca | 2003-08-24 22:41:31 +0000 | [diff] [blame] | 109 | LOADER_INIT_FUNC(simpletelnet_init, arg) |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 110 | { |
| 111 | if(id == EK_ID_NONE) { |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 112 | id = ek_start(&p); |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 113 | } |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 114 | } |
| 115 | /*-----------------------------------------------------------------------------------*/ |
| 116 | static void |
| 117 | scrollup(void) |
| 118 | { |
| 119 | unsigned char i; |
| 120 | for(i = 1; i < 10; ++i) { |
| 121 | memcpy(&telnettext[(i - 1) * 38], &telnettext[i * 38], 38); |
| 122 | } |
| 123 | memset(&telnettext[9 * 38], 0, 38); |
| 124 | } |
| 125 | /*-----------------------------------------------------------------------------------*/ |
| 126 | static void |
| 127 | add_text(char *text) |
| 128 | { |
| 129 | unsigned char i; |
| 130 | unsigned int len; |
| 131 | |
| 132 | len = strlen(text); |
| 133 | |
| 134 | i = 0; |
| 135 | while(len > 0) { |
| 136 | if(*text == '\n') { |
| 137 | scrollup(); |
| 138 | i = 0; |
| 139 | } else if(*text == '\r') { |
| 140 | i = 0; |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 141 | } else if(*text >= ' ') { |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 142 | telnettext[9 * 38 + i] = *text; |
| 143 | ++i; |
| 144 | if(i == 38) { |
| 145 | scrollup(); |
| 146 | i = 0; |
| 147 | } |
| 148 | } |
| 149 | ++text; |
| 150 | --len; |
| 151 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 152 | |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 153 | /* if(strlen(text) > 37) { |
| 154 | memcpy(&telnettext[9 * 38], text, 37); |
| 155 | } else { |
| 156 | memcpy(&telnettext[9 * 38], text, strlen(text)); |
| 157 | } |
| 158 | */ |
| 159 | } |
| 160 | /*-----------------------------------------------------------------------------------*/ |
| 161 | static void |
| 162 | show(char *text) |
| 163 | { |
| 164 | add_text(text); |
| 165 | add_text("\n"); |
| 166 | ctk_label_set_text(&telnetstatus, text); |
| 167 | ctk_window_redraw(&telnetwindow); |
| 168 | } |
| 169 | /*-----------------------------------------------------------------------------------*/ |
| 170 | static void |
| 171 | connect(void) |
| 172 | { |
| 173 | u16_t addr[2], *addrptr; |
| 174 | u16_t port; |
| 175 | char *cptr; |
| 176 | struct uip_conn *conn; |
| 177 | |
| 178 | /* Find the first space character in host and put a zero there |
| 179 | to end the string. */ |
| 180 | for(cptr = telnethost; *cptr != ' ' && *cptr != 0; ++cptr); |
| 181 | *cptr = 0; |
| 182 | |
| 183 | addrptr = &addr[0]; |
adamdunkels | db300d2 | 2004-02-24 09:57:49 +0000 | [diff] [blame] | 184 | if(uiplib_ipaddrconv(telnethost, (unsigned char *)addr) == 0) { |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 185 | addrptr = resolv_lookup(telnethost); |
| 186 | if(addrptr == NULL) { |
| 187 | resolv_query(telnethost); |
| 188 | show("Resolving host..."); |
| 189 | return; |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | port = 0; |
| 194 | for(cptr = telnetport; *cptr != ' ' && *cptr != 0; ++cptr) { |
| 195 | if(*cptr < '0' || *cptr > '9') { |
| 196 | show("Port number error"); |
| 197 | return; |
| 198 | } |
| 199 | port = 10 * port + *cptr - '0'; |
| 200 | } |
| 201 | |
| 202 | |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 203 | conn = tcp_connect(addrptr, htons(port), &ts_appstate); |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 204 | if(conn == NULL) { |
| 205 | show("Out of memory error"); |
| 206 | return; |
| 207 | } |
| 208 | |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 209 | show("Connecting..."); |
| 210 | |
| 211 | } |
| 212 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 213 | EK_EVENTHANDLER(simpletelnet_eventhandler, ev, data) |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 214 | { |
| 215 | struct ctk_widget *w; |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 216 | int sendlen; |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 217 | EK_EVENTHANDLER_ARGS(ev, data); |
| 218 | |
| 219 | if(ev == EK_EVENT_INIT) { |
| 220 | /* Create Telnet window. */ |
| 221 | ctk_window_new(&telnetwindow, 38, 20, "Simple telnet"); |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 222 | |
| 223 | strcpy(telnetport, "23"); |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 224 | |
| 225 | CTK_WIDGET_ADD(&telnetwindow, &telnethostlabel); |
| 226 | CTK_WIDGET_ADD(&telnetwindow, &telnetportlabel); |
| 227 | CTK_WIDGET_ADD(&telnetwindow, &telnethosttextentry); |
| 228 | CTK_WIDGET_ADD(&telnetwindow, &telnetporttextentry); |
| 229 | CTK_WIDGET_ADD(&telnetwindow, &telnetconnectbutton); |
| 230 | CTK_WIDGET_ADD(&telnetwindow, &telnetdisconnectbutton); |
| 231 | CTK_WIDGET_ADD(&telnetwindow, &telnetlinetextentry); |
| 232 | CTK_WIDGET_ADD(&telnetwindow, &telnetsendbutton); |
| 233 | |
| 234 | CTK_WIDGET_ADD(&telnetwindow, &telnetsep1); |
| 235 | CTK_WIDGET_ADD(&telnetwindow, &telnettextarea); |
| 236 | |
| 237 | CTK_WIDGET_ADD(&telnetwindow, &telnetsep2); |
| 238 | CTK_WIDGET_ADD(&telnetwindow, &telnetstatus); |
| 239 | |
| 240 | CTK_WIDGET_FOCUS(&telnetwindow, &telnethosttextentry); |
| 241 | |
| 242 | /* Attach as a listener to the CTK button press signal. */ |
| 243 | /* dispatcher_listen(ctk_signal_button_activate); |
| 244 | dispatcher_listen(ctk_signal_window_close); |
| 245 | dispatcher_listen(resolv_signal_found);*/ |
| 246 | |
| 247 | ctk_window_open(&telnetwindow); |
| 248 | |
| 249 | } else if(ev == ctk_signal_button_activate) { |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 250 | |
| 251 | w = (struct ctk_widget *)data; |
| 252 | if(w == (struct ctk_widget *)&telnetsendbutton) { |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 253 | strcpy(sendline, telnetline); |
| 254 | sendlen = strlen(sendline); |
| 255 | petsciiconv_toascii(sendline, sendlen); |
| 256 | sendline[sendlen++] = ISO_CR; |
| 257 | sendline[sendlen++] = ISO_NL; |
| 258 | if(telnet_send(&ts_appstate, sendline, sendlen)) { |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 259 | /* Could not send. */ |
| 260 | ctk_label_set_text(&telnetstatus, "Could not send"); |
| 261 | ctk_window_redraw(&telnetwindow); |
| 262 | /* } else {*/ |
| 263 | /* Could send */ |
| 264 | } |
| 265 | } else if(w == (struct ctk_widget *)&telnetdisconnectbutton) { |
| 266 | telnet_close(&ts_appstate); |
| 267 | show("Closing..."); |
| 268 | } else if(w == (struct ctk_widget *)&telnetconnectbutton) { |
| 269 | connect(); |
| 270 | ctk_window_redraw(&telnetwindow); |
| 271 | } |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 272 | } else if(ev == resolv_event_found) { |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 273 | if(strcmp(data, telnethost) == 0) { |
| 274 | if(resolv_lookup(telnethost) != NULL) { |
| 275 | connect(); |
| 276 | } else { |
| 277 | show("Host not found"); |
| 278 | } |
| 279 | } |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 280 | } else if(ev == ctk_signal_window_close || |
| 281 | ev == EK_EVENT_REQUEST_EXIT) { |
| 282 | ek_exit(); |
| 283 | ctk_window_close(&telnetwindow); |
oliverschmidt | b1041b8 | 2004-09-12 20:02:16 +0000 | [diff] [blame] | 284 | id = EK_ID_NONE; |
adamdunkels | 8af703e | 2003-04-08 11:50:20 +0000 | [diff] [blame] | 285 | LOADER_UNLOAD(); |
adamdunkels | f2f8cb2 | 2004-07-04 11:35:07 +0000 | [diff] [blame] | 286 | } else if(ev == tcpip_event) { |
| 287 | telnet_app(data); |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | /*-----------------------------------------------------------------------------------*/ |
| 291 | void |
| 292 | telnet_connected(struct telnet_state *s) |
| 293 | { |
| 294 | show("Connected"); |
| 295 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 296 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 297 | void |
| 298 | telnet_closed(struct telnet_state *s) |
| 299 | { |
| 300 | show("Connection closed"); |
| 301 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 302 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 303 | void |
| 304 | telnet_sent(struct telnet_state *s) |
| 305 | { |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 306 | petsciiconv_topetscii(sendline, sizeof(sendline)); |
| 307 | scrollup(); |
| 308 | add_text(sendline); |
| 309 | CTK_TEXTENTRY_CLEAR(&telnetlinetextentry); |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 310 | ctk_window_redraw(&telnetwindow); |
| 311 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 312 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 313 | void |
| 314 | telnet_aborted(struct telnet_state *s) |
| 315 | { |
| 316 | show("Connection reset by peer"); |
| 317 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 318 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 319 | void |
| 320 | telnet_timedout(struct telnet_state *s) |
| 321 | { |
| 322 | show("Connection timed out"); |
| 323 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 324 | /*-----------------------------------------------------------------------------------*/ |
adamdunkels | ca9ddcb | 2003-03-19 14:13:31 +0000 | [diff] [blame] | 325 | void |
| 326 | telnet_newdata(struct telnet_state *s, char *data, u16_t len) |
| 327 | { |
| 328 | petsciiconv_topetscii(data, len); |
| 329 | data[len] = 0; |
| 330 | add_text(data); |
| 331 | ctk_window_redraw(&telnetwindow); |
| 332 | } |
oliverschmidt | be6e4dc | 2005-04-16 14:17:32 +0000 | [diff] [blame] | 333 | /*-----------------------------------------------------------------------------------*/ |