blob: 5ba57e887efdc0718a11a095ca824b28dd6db433 [file] [log] [blame]
/*
* Copyright (c) 2002, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the Contiki desktop environment
*
* $Id: simpletelnet.c,v 1.14 2005/04/16 14:17:32 oliverschmidt Exp $
*
*/
#include <string.h>
#include "ek.h"
#include "petsciiconv.h"
#include "uiplib.h"
#include "uip.h"
#include "ctk.h"
#include "resolv.h"
#include "telnet.h"
#include "simpletelnet.h"
#include "loader.h"
#include "tcpip.h"
/* Telnet window */
static struct ctk_window telnetwindow;
static struct ctk_label telnethostlabel =
{CTK_LABEL(1, 0, 4, 1, "Host")};
static char telnethost[25];
static struct ctk_textentry telnethosttextentry =
{CTK_TEXTENTRY(0, 1, 24, 1, telnethost, 24)};
static struct ctk_label telnetportlabel =
{CTK_LABEL(31, 0, 4, 1, "Port")};
static char telnetport[6];
static struct ctk_textentry telnetporttextentry =
{CTK_TEXTENTRY(30, 1, 5, 1, telnetport, 5)};
static struct ctk_button telnetconnectbutton =
{CTK_BUTTON(2, 3, 7, "Connect")};
static struct ctk_button telnetdisconnectbutton =
{CTK_BUTTON(25, 3, 10, "Disconnect")};
static char telnetline[31];
static struct ctk_textentry telnetlinetextentry =
{CTK_TEXTENTRY(0, 5, 30, 1, telnetline, 30)};
static struct ctk_button telnetsendbutton =
{CTK_BUTTON(32, 5, 4, "Send")};
static struct ctk_label telnetstatus =
{CTK_LABEL(0, 19, 38, 1, "")};
static struct ctk_separator telnetsep1 =
{CTK_SEPARATOR(0, 7, 38)};
static struct ctk_separator telnetsep2 =
{CTK_SEPARATOR(0, 18, 38)};
static char telnettext[38*10];
static struct ctk_label telnettextarea =
{CTK_LABEL(0, 8, 38, 10, telnettext)};
static struct telnet_state ts_appstate;
#define ISO_NL 0x0a
#define ISO_CR 0x0d
static char sendline[31+2];
EK_EVENTHANDLER(simpletelnet_eventhandler, ev, data);
EK_PROCESS(p, "Telnet client", EK_PRIO_NORMAL,
simpletelnet_eventhandler, NULL, NULL);
static ek_id_t id = EK_ID_NONE;
/*
static DISPATCHER_SIGHANDLER(simpletelnet_sighandler, s, data);
static struct dispatcher_proc p =
{DISPATCHER_PROC("Simple telnet", NULL, simpletelnet_sighandler,
telnet_app)};
static ek_id_t id;*/
/*-----------------------------------------------------------------------------------*/
LOADER_INIT_FUNC(simpletelnet_init, arg)
{
if(id == EK_ID_NONE) {
id = ek_start(&p);
}
}
/*-----------------------------------------------------------------------------------*/
static void
scrollup(void)
{
unsigned char i;
for(i = 1; i < 10; ++i) {
memcpy(&telnettext[(i - 1) * 38], &telnettext[i * 38], 38);
}
memset(&telnettext[9 * 38], 0, 38);
}
/*-----------------------------------------------------------------------------------*/
static void
add_text(char *text)
{
unsigned char i;
unsigned int len;
len = strlen(text);
i = 0;
while(len > 0) {
if(*text == '\n') {
scrollup();
i = 0;
} else if(*text == '\r') {
i = 0;
} else if(*text >= ' ') {
telnettext[9 * 38 + i] = *text;
++i;
if(i == 38) {
scrollup();
i = 0;
}
}
++text;
--len;
}
/* if(strlen(text) > 37) {
memcpy(&telnettext[9 * 38], text, 37);
} else {
memcpy(&telnettext[9 * 38], text, strlen(text));
}
*/
}
/*-----------------------------------------------------------------------------------*/
static void
show(char *text)
{
add_text(text);
add_text("\n");
ctk_label_set_text(&telnetstatus, text);
ctk_window_redraw(&telnetwindow);
}
/*-----------------------------------------------------------------------------------*/
static void
connect(void)
{
u16_t addr[2], *addrptr;
u16_t port;
char *cptr;
struct uip_conn *conn;
/* Find the first space character in host and put a zero there
to end the string. */
for(cptr = telnethost; *cptr != ' ' && *cptr != 0; ++cptr);
*cptr = 0;
addrptr = &addr[0];
if(uiplib_ipaddrconv(telnethost, (unsigned char *)addr) == 0) {
addrptr = resolv_lookup(telnethost);
if(addrptr == NULL) {
resolv_query(telnethost);
show("Resolving host...");
return;
}
}
port = 0;
for(cptr = telnetport; *cptr != ' ' && *cptr != 0; ++cptr) {
if(*cptr < '0' || *cptr > '9') {
show("Port number error");
return;
}
port = 10 * port + *cptr - '0';
}
conn = tcp_connect(addrptr, htons(port), &ts_appstate);
if(conn == NULL) {
show("Out of memory error");
return;
}
show("Connecting...");
}
/*-----------------------------------------------------------------------------------*/
EK_EVENTHANDLER(simpletelnet_eventhandler, ev, data)
{
struct ctk_widget *w;
int sendlen;
EK_EVENTHANDLER_ARGS(ev, data);
if(ev == EK_EVENT_INIT) {
/* Create Telnet window. */
ctk_window_new(&telnetwindow, 38, 20, "Simple telnet");
strcpy(telnetport, "23");
CTK_WIDGET_ADD(&telnetwindow, &telnethostlabel);
CTK_WIDGET_ADD(&telnetwindow, &telnetportlabel);
CTK_WIDGET_ADD(&telnetwindow, &telnethosttextentry);
CTK_WIDGET_ADD(&telnetwindow, &telnetporttextentry);
CTK_WIDGET_ADD(&telnetwindow, &telnetconnectbutton);
CTK_WIDGET_ADD(&telnetwindow, &telnetdisconnectbutton);
CTK_WIDGET_ADD(&telnetwindow, &telnetlinetextentry);
CTK_WIDGET_ADD(&telnetwindow, &telnetsendbutton);
CTK_WIDGET_ADD(&telnetwindow, &telnetsep1);
CTK_WIDGET_ADD(&telnetwindow, &telnettextarea);
CTK_WIDGET_ADD(&telnetwindow, &telnetsep2);
CTK_WIDGET_ADD(&telnetwindow, &telnetstatus);
CTK_WIDGET_FOCUS(&telnetwindow, &telnethosttextentry);
/* Attach as a listener to the CTK button press signal. */
/* dispatcher_listen(ctk_signal_button_activate);
dispatcher_listen(ctk_signal_window_close);
dispatcher_listen(resolv_signal_found);*/
ctk_window_open(&telnetwindow);
} else if(ev == ctk_signal_button_activate) {
w = (struct ctk_widget *)data;
if(w == (struct ctk_widget *)&telnetsendbutton) {
strcpy(sendline, telnetline);
sendlen = strlen(sendline);
petsciiconv_toascii(sendline, sendlen);
sendline[sendlen++] = ISO_CR;
sendline[sendlen++] = ISO_NL;
if(telnet_send(&ts_appstate, sendline, sendlen)) {
/* Could not send. */
ctk_label_set_text(&telnetstatus, "Could not send");
ctk_window_redraw(&telnetwindow);
/* } else {*/
/* Could send */
}
} else if(w == (struct ctk_widget *)&telnetdisconnectbutton) {
telnet_close(&ts_appstate);
show("Closing...");
} else if(w == (struct ctk_widget *)&telnetconnectbutton) {
connect();
ctk_window_redraw(&telnetwindow);
}
} else if(ev == resolv_event_found) {
if(strcmp(data, telnethost) == 0) {
if(resolv_lookup(telnethost) != NULL) {
connect();
} else {
show("Host not found");
}
}
} else if(ev == ctk_signal_window_close ||
ev == EK_EVENT_REQUEST_EXIT) {
ek_exit();
ctk_window_close(&telnetwindow);
id = EK_ID_NONE;
LOADER_UNLOAD();
} else if(ev == tcpip_event) {
telnet_app(data);
}
}
/*-----------------------------------------------------------------------------------*/
void
telnet_connected(struct telnet_state *s)
{
show("Connected");
}
/*-----------------------------------------------------------------------------------*/
void
telnet_closed(struct telnet_state *s)
{
show("Connection closed");
}
/*-----------------------------------------------------------------------------------*/
void
telnet_sent(struct telnet_state *s)
{
petsciiconv_topetscii(sendline, sizeof(sendline));
scrollup();
add_text(sendline);
CTK_TEXTENTRY_CLEAR(&telnetlinetextentry);
ctk_window_redraw(&telnetwindow);
}
/*-----------------------------------------------------------------------------------*/
void
telnet_aborted(struct telnet_state *s)
{
show("Connection reset by peer");
}
/*-----------------------------------------------------------------------------------*/
void
telnet_timedout(struct telnet_state *s)
{
show("Connection timed out");
}
/*-----------------------------------------------------------------------------------*/
void
telnet_newdata(struct telnet_state *s, char *data, u16_t len)
{
petsciiconv_topetscii(data, len);
data[len] = 0;
add_text(data);
ctk_window_redraw(&telnetwindow);
}
/*-----------------------------------------------------------------------------------*/