ctk-termtelnet.c
来自「伟大的Contiki工程, 短小精悍 的操作系统, 学习编程不可不看」· C语言 代码 · 共 656 行 · 第 1/2 页
C
656 行
/* * Copyright (c) 2005, Swedish Institute of Computer Science * 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. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 operating system. * * @(#)$Id: ctk-termtelnet.c,v 1.1 2007/05/26 21:46:28 oliverschmidt Exp $ */#include "contiki.h"#include "loader.h"#include "memb.h"#include "ctk-term.h"#include "contiki-conf.h"/*-----------------------------------------------------------------------------------*//* * #defines and enums *//*-----------------------------------------------------------------------------------*//* Telnet special characters */#define TN_NULL 0#define TN_BL 7#define TN_BS 8#define TN_HT 9#define TN_LF 10#define TN_VT 11#define TN_FF 12#define TN_CR 13/* Commands preceeded by TN_IAC */#define TN_SE 240#define TN_NOP 241#define TN_DM 242#define TN_BRK 243#define TN_IP 244#define TN_AO 245#define TN_AYT 246#define TN_EC 247#define TN_EL 248#define TN_GA 249#define TN_SB 250#define TN_WILL 251#define TN_WONT 252#define TN_DO 253#define TN_DONT 254#define TN_IAC 255#define TNO_BIN 0#define TNO_ECHO 1#define TNO_SGA 3#define TNO_NAWS 31/* Telnet parsing states */enum { TNS_IDLE, TNS_IAC, TNS_OPT, TNS_SB, TNS_SBIAC};/* Telnet option negotiation states */enum { TNOS_NO, TNOS_WANTNO_EMPTY, TNOS_WANTNO_OPPOSITE, TNOS_WANTYES_EMPTY, TNOS_WANTYES_OPPOSITE, TNOS_YES};/* Telnet session states */enum { TTS_FREE, /* Not allocated */ TTS_IDLE, /* No data to send and nothing sent */ TTS_SEND_TNDATA, /* Sending telnet data */ TTS_SEND_APPDATA /* Sending data from upper layers */};/* Number of options supported (we only need ECHO(1) and SGA(3) options) */#define TNSM_MAX_OPTIONS 4/* Max option replies in output queue */#define TNQLEN 20/* Number of option buffer */#define OPTION_POOL_SIZE 20/* Maximum number of telnet sessions */#ifdef CTK_TERM_CONF_MAX_TELNET_CLIENTS#define NUM_CONNS CTK_TERM_CONF_MAX_TELNET_CLIENTS#else#define NUM_CONNS 1#endif#ifdef CTK_TERM_CONF_TELNET_PORT#define PORT CTK_TERM_CONF_TELNET_PORT#else#define PORT 23#endif/*-----------------------------------------------------------------------------------*//* * Structures *//*-----------------------------------------------------------------------------------*//* Telnet option state structure */struct TNOption { unsigned char state; unsigned char wants;};/* Telnet handling state structure */struct TNSMState{ struct TNOption myOpt[TNSM_MAX_OPTIONS]; struct TNOption hisOpt[TNSM_MAX_OPTIONS]; unsigned char cmd; unsigned char state;};/* Telnet session state */struct telnet_state{ unsigned char state; unsigned char* sendq[TNQLEN]; struct TNSMState tnsm; struct ctk_term_state* termstate;};/*-----------------------------------------------------------------------------------*//* * Local variables *//*-----------------------------------------------------------------------------------*//*static DISPATCHER_UIPCALL(ctk_termtelnet_appcall, state);*/static void ctk_termtelnet_appcall(void *state);EK_EVENTHANDLER(eventhandler, ev, data);EK_PROCESS(p, "CTK telnet server", EK_PRIO_NORMAL, eventhandler, NULL, NULL);/*static struct dispatcher_proc p = {DISPATCHER_PROC("CTK telnet server", NULL, NULL, ctk_termtelnet_appcall)};*/static ek_id_t id = EK_ID_NONE;/* Option negotiation buffer pool */struct size_3 { char size[3];};MEMB(telnetbuf, struct size_3, OPTION_POOL_SIZE);static int i,j;static struct telnet_state states[NUM_CONNS];/*-----------------------------------------------------------------------------------*//* * Send an option reply on a connection *//*-----------------------------------------------------------------------------------*/static voidReply(struct telnet_state* tns, unsigned char cmd, unsigned char opt){ unsigned char* buf = (unsigned char*)memb_alloc(&telnetbuf); if (buf != 0) { buf[0]=TN_IAC; buf[1]=cmd; buf[2]=opt; for (i=0; i < TNQLEN; i++) { if (tns->sendq[i] == 0) { tns->sendq[i] = buf; return; } } /* Queue is full. Drop it */ memb_free(&telnetbuf, (char*)buf); }}/*-----------------------------------------------------------------------------------*//* * Prepare for enabling one of remote side options. *//*-----------------------------------------------------------------------------------*/static voidEnableHisOpt(struct telnet_state* tns, unsigned char opt){ switch(tns->tnsm.hisOpt[opt].state) { case TNOS_NO: tns->tnsm.hisOpt[opt].wants = 1; tns->tnsm.hisOpt[opt].state = TNOS_WANTYES_EMPTY; Reply(tns, TN_DO, opt); break; case TNOS_WANTNO_EMPTY: tns->tnsm.hisOpt[opt].state = TNOS_WANTNO_OPPOSITE; break; case TNOS_WANTNO_OPPOSITE: break; case TNOS_WANTYES_EMPTY: tns->tnsm.hisOpt[opt].state = TNOS_YES; break; case TNOS_WANTYES_OPPOSITE: tns->tnsm.hisOpt[opt].state = TNOS_WANTYES_EMPTY; break; case TNOS_YES: break; }}/*-----------------------------------------------------------------------------------*//* * Prepare for enabling one of my options *//*-----------------------------------------------------------------------------------*/static voidEnableMyOpt(struct telnet_state* tns, unsigned char opt){ if (opt < TNSM_MAX_OPTIONS) { switch(tns->tnsm.myOpt[opt].state) { case TNOS_NO: tns->tnsm.myOpt[opt].wants = 1; tns->tnsm.myOpt[opt].state = TNOS_WANTYES_EMPTY; Reply(tns, TN_WILL, opt); break; case TNOS_WANTNO_EMPTY: tns->tnsm.myOpt[opt].state = TNOS_WANTNO_OPPOSITE; break; case TNOS_WANTNO_OPPOSITE: break; case TNOS_WANTYES_EMPTY: tns->tnsm.myOpt[opt].state = TNOS_YES; break; case TNOS_WANTYES_OPPOSITE: tns->tnsm.myOpt[opt].state = TNOS_WANTYES_EMPTY; break; case TNOS_YES: break; } }}/*-----------------------------------------------------------------------------------*//* * Implementation of option negotiation using the Q-method *//*-----------------------------------------------------------------------------------*/static voidHandleCommand(struct telnet_state* tns, unsigned char cmd, unsigned char opt){ if (opt < TNSM_MAX_OPTIONS) { /* Handling according to RFC 1143 "Q Method" */ switch(cmd) { case TN_WILL: switch(tns->tnsm.hisOpt[opt].state) { case TNOS_NO: if (tns->tnsm.hisOpt[opt].wants) { tns->tnsm.hisOpt[opt].state = TNOS_YES; Reply(tns, TN_DO, opt); } else { Reply(tns, TN_DONT, opt); } break; case TNOS_WANTNO_EMPTY: tns->tnsm.hisOpt[opt].state = TNOS_NO; break; case TNOS_WANTNO_OPPOSITE: tns->tnsm.hisOpt[opt].state = TNOS_YES; break; case TNOS_WANTYES_EMPTY: tns->tnsm.hisOpt[opt].state = TNOS_YES; break; case TNOS_WANTYES_OPPOSITE: tns->tnsm.hisOpt[opt].state = TNOS_WANTNO_EMPTY; Reply(tns, TN_DONT, opt); break; case TNOS_YES: break; } break; case TN_WONT: switch(tns->tnsm.hisOpt[opt].state) { case TNOS_NO: break; case TNOS_WANTNO_EMPTY: case TNOS_WANTYES_EMPTY: case TNOS_WANTYES_OPPOSITE: tns->tnsm.hisOpt[opt].state = TNOS_NO; break; case TNOS_WANTNO_OPPOSITE: tns->tnsm.hisOpt[opt].state = TNOS_WANTYES_EMPTY; Reply(tns, TN_DO, opt); break; case TNOS_YES: tns->tnsm.hisOpt[opt].state = TNOS_NO; Reply(tns, TN_DONT, opt); break; } break; case TN_DO: switch(tns->tnsm.myOpt[opt].state) { case TNOS_NO: if (tns->tnsm.myOpt[opt].wants) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?