ctk-termtelnet.c

来自「伟大的Contiki工程, 短小精悍 的操作系统, 学习编程不可不看」· C语言 代码 · 共 656 行 · 第 1/2 页

C
656
字号
	      tns->tnsm.myOpt[opt].state = TNOS_YES;	      Reply(tns, TN_WILL, opt);	    }	    else {	      Reply(tns, TN_WONT, opt);	    }	    break;	  case TNOS_WANTNO_EMPTY:	    tns->tnsm.myOpt[opt].state = TNOS_NO;	    break;	  case TNOS_WANTNO_OPPOSITE:	    tns->tnsm.myOpt[opt].state = TNOS_YES;	    break;	  case TNOS_WANTYES_EMPTY:	    tns->tnsm.myOpt[opt].state = TNOS_YES;	    break;	  case TNOS_WANTYES_OPPOSITE:	    tns->tnsm.myOpt[opt].state = TNOS_WANTNO_EMPTY;	    Reply(tns, TN_WONT, opt);	    break;	  case TNOS_YES:	    break;	  }	  break;	  case TN_DONT:	    switch(tns->tnsm.myOpt[opt].state) {	    case TNOS_NO:	      break;	    case TNOS_WANTNO_EMPTY:	    case TNOS_WANTYES_EMPTY:	    case TNOS_WANTYES_OPPOSITE:	      tns->tnsm.myOpt[opt].state = TNOS_NO;	      break;	    case TNOS_WANTNO_OPPOSITE:	      tns->tnsm.myOpt[opt].state = TNOS_WANTYES_EMPTY;	      Reply(tns, TN_WILL, opt);	      break;	    case TNOS_YES:	      tns->tnsm.myOpt[opt].state = TNOS_NO;	      Reply(tns, TN_WONT, opt);	      break;	    }	    break;    }  }  else {    switch(cmd) {    case TN_WILL:      Reply(tns, TN_DONT, opt);      break;    case TN_WONT:      break;    case TN_DO:      Reply(tns, TN_WONT, opt);      break;    case TN_DONT:      break;    }  }}/*-----------------------------------------------------------------------------------*//* * Telnet data parsing *//*-----------------------------------------------------------------------------------*/static unsigned charparse_input(struct telnet_state* tns, unsigned char b){  unsigned char ret = 0;  switch(tns->tnsm.state) {  case TNS_IDLE:    if (b == TN_IAC) tns->tnsm.state = TNS_IAC;    else ret = 1;    break;  case TNS_IAC:    switch(b) {    case TN_SE:    case TN_NOP:    case TN_DM:    case TN_BRK:    case TN_IP:    case TN_AO:    case TN_AYT:    case TN_EC:    case TN_EL:    case TN_GA:      tns->tnsm.state = TNS_IDLE;      break;    case TN_SB:      tns->tnsm.state = TNS_SB;      break;    case TN_WILL:    case TN_WONT:    case TN_DO:    case TN_DONT:      tns->tnsm.cmd = b;      tns->tnsm.state = TNS_OPT;      break;    case TN_IAC:      tns->tnsm.state = TNS_IDLE;      ret = 1;      break;    default:      /* Drop unknown IACs */      tns->tnsm.state = TNS_IDLE;      break;    }    break;    case TNS_OPT:      HandleCommand(tns, tns->tnsm.cmd, b);      tns->tnsm.state = TNS_IDLE;      break;    case TNS_SB:      if (b == TN_IAC) {	tns->tnsm.state = TNS_SBIAC;      }      break;    case TNS_SBIAC:      if (b == TN_IAC) {	tns->tnsm.state = TNS_SB;      }      else if (b == TN_SE) {	tns->tnsm.state = TNS_IDLE;      }      else {	tns->tnsm.state = TNS_IDLE;      }      break;  }  return ret;}/*-----------------------------------------------------------------------------------*//* * Initialize telnet machine *//*-----------------------------------------------------------------------------------*/static voidtelnet_init(struct telnet_state* tns){  int i;  for (i = 0; i < TNSM_MAX_OPTIONS; i++) {    tns->tnsm.myOpt[i].state = TNOS_NO;    tns->tnsm.myOpt[i].wants = 0;    tns->tnsm.hisOpt[i].state = TNOS_NO;    tns->tnsm.hisOpt[i].wants = 0;  }  tns->tnsm.state = TNS_IDLE;}/*-----------------------------------------------------------------------------------*//* * Allocate a telnet session structure (including terminal state) *//*-----------------------------------------------------------------------------------*/static struct telnet_state*alloc_state(){  for (i=0; i < NUM_CONNS; i++) {    if (states[i].state == TTS_FREE) {      states[i].termstate = ctk_term_alloc_state();      if (states[i].termstate != NULL) {	for (j = 0; j < TNQLEN; j++) {	  states[i].sendq[j] = 0;	}	telnet_init(&states[i]);        states[i].state = TTS_IDLE;        return &(states[i]);      }    }  }  return NULL;}/*-----------------------------------------------------------------------------------*//* * Free a telnet session structure (including terminal state) *//*-----------------------------------------------------------------------------------*/static voidfree_state(struct telnet_state* tns){  if (tns != NULL) {    ctk_term_dealloc_state(tns->termstate);    tns->state = TTS_FREE;  }}/*-----------------------------------------------------------------------------------*//* * A packet is successfully sent *//*-----------------------------------------------------------------------------------*/static voidacked(struct telnet_state* tns){  /* Were we sending a telnet option packet? */  if (tns->state == TTS_SEND_TNDATA) {    /* Yes, free it and update queue */    if (tns->sendq[0] != 0) {      memb_free(&telnetbuf, (char*)(tns->sendq[0]));      for (i=1; i < TNQLEN; i++) {	tns->sendq[i-1] = tns->sendq[i];      }      tns->sendq[TNQLEN-1] = 0;      /* No options left. Go idle */      if (tns->sendq[0] == 0) {	tns->state = TTS_IDLE;      }    }  }  /* Or were we sending application date ? */  else if (tns->state == TTS_SEND_APPDATA) {    /* Inform application that data is sent successfully */    ctk_term_sent(tns->termstate);    tns->state = TTS_IDLE;  }}/*-----------------------------------------------------------------------------------*//* * Send data on a connections *//*-----------------------------------------------------------------------------------*/static voidsenddata(struct telnet_state* tns){  /* Check if there are any option packets to send */  if (tns->state == TTS_IDLE || tns->state == TTS_SEND_TNDATA) {    if (tns->sendq[0] != 0) {      tns->state = TTS_SEND_TNDATA;      uip_send(tns->sendq[0],3);    }  }  /* Check if terminal wants to send any data */  if (tns->state == TTS_IDLE || tns->state == TTS_SEND_APPDATA) {    u16_t len = ctk_term_send(tns->termstate, (unsigned char*)uip_appdata, (unsigned short)uip_mss());    if (len > 0) {      tns->state = TTS_SEND_APPDATA;      uip_send(uip_appdata, len);    }  }}/*-----------------------------------------------------------------------------------*//* * uIP callback *//*-----------------------------------------------------------------------------------*/static voidctk_termtelnet_appcall(void *state){  struct telnet_state *tns;  tns = (struct telnet_state*)(state);  if(uip_connected()) {    if(tns == NULL) {      tns = alloc_state();      if(tns == NULL) {	uip_close();	return;      }      tcp_markconn(uip_conn, (void *)tns);    }    /* Try to negotiate some options */    EnableHisOpt(tns, TNO_SGA);    EnableMyOpt(tns,TNO_SGA);    EnableMyOpt(tns,TNO_ECHO);    /* Request update of screen */    ctk_term_redraw(tns->termstate);    senddata(tns);  } else if(uip_closed() || uip_aborted()) {    free_state(tns);    return;  }  if (uip_acked()) {    acked(tns);  }  if (uip_newdata()) {    for(j = 0; j < uip_datalen(); j++) {      if (parse_input(tns, uip_appdata[j])) {	/* Pass it uppwards */	ctk_term_input(tns->termstate, uip_appdata[j]);      }    }  }  if(uip_rexmit() ||     uip_newdata() ||     uip_acked()) {    senddata(tns);  } else if(uip_poll()) {    if (tns->state == TTS_IDLE) {      senddata(tns);    }  }}/*-----------------------------------------------------------------------------------*//* * Init function *//*-----------------------------------------------------------------------------------*/LOADER_INIT_FUNC(ctk_termtelnet_init, arg){  arg_free(arg);  if(id == EK_ID_NONE) {    memb_init(&telnetbuf);    for (i=0; i < NUM_CONNS; i++) {      states[i].state = TTS_FREE;    }    id = ek_start(&p);  }}/*-----------------------------------------------------------------------------------*/EK_EVENTHANDLER(eventhandler, ev, data){  if(ev == EK_EVENT_INIT) {    tcp_listen(HTONS(PORT));  } else if(ev == tcpip_event) {    ctk_termtelnet_appcall(data);  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?