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 + -
显示快捷键?