uIP 1.0
C:/asm/STM32-ethernet/ENC28J60prj/uip-master/apps/telnetd/telnetd.c
00001 /*
00002  * Copyright (c) 2003, Adam Dunkels.
00003  * Все права зарезервированы.
00004  *
00005  * Повторное распространение, использование в исходном и двоичном виде,
00006  * с модификацией или без - разрешается, если выполняются следующие
00007  * условия:
00008  * 1. Распространение исходного кода должно сохранить вышеуказанную пометку
00009  *    копирайта, этот список условий и следующую правовую оговорку.
00010  * 2. Распространение исходного кода должно сохранить вышеуказанную пометку
00011  *    копирайта, этот список условий и следующую правовую оговорку в
00012  *    документации и/или других материалах, которые будут предоставлены
00013  *    вместе с распространяемыми материалами.
00014  * 3. Имя автора не может использоваться, чтобы подтвердить или продвинуть
00015  *    продукты, написанные с использованием этого программного обеспечения
00016  *    без специального на то разрешения.
00017  *
00018  * ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ АВТОРОМ ``КАК ЕСТЬ'', БЕЗ
00019  * КАКОЙ-ЛИБО ЛЮБОЙ РАСШИРЕННОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ГАРАНТИИ, ВКЛЮЧАЯ,
00020  * НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ГАРАНТИИ ВЫСОКОГО СПРОСА И ПРИГОДНОСТИ
00021  * ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. АВТОР НИ ПРИ КАКИХ УСЛОВИЯХ НЕ ОТВЕТСТВЕНЕН
00022  * ЗА ЛЮБЫЕ УБЫТКИ - ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ОБРАЗЦОВЫЕ
00023  * ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ТРЕБОВАНИЯ
00024  * ЗАМЕНЫ ТОВАРА ИЛИ СЕРВИСА; ПОТЕРИ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ВЫГОДЫ;
00025  * ИЛИ ПРЕКРАЩЕНИЕ БИЗНЕСА), ОДНАКО ВЫЗВАННЫЕ ПО ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ,
00026  * ЛИБО В КОНТРАКТЕ, ПРЯМОЙ ОТВЕТСТВЕННОСТИ, ЛИБО В НАРУШЕНИИ ЗАКОННЫХ ПРАВ
00027  * (ВКЛЮЧАЯ ТАК ИЛИ ИНАЧЕ НЕБРЕЖНОСТЬ), ВОЗНИКАЮЩИЕ ВСЕГДА ИЗ ИСПОЛЬЗОВАНИЯ
00028  * ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ
00029  * ТАКОГО ПОВРЕЖДЕНИЯ.
00030  *
00031  * Этот файл является частью стека uIP TCP/IP.
00032  *
00033  * $Id: telnetd.c,v 1.2 2006/06/07 09:43:54 adam Exp $
00034  *
00035  */
00036 
00037 #include "uip.h"
00038 #include "telnetd.h"
00039 #include "memb.h"
00040 #include "shell.h"
00041 
00042 #include <string.h>
00043 
00044 #define ISO_nl       0x0a
00045 #define ISO_cr       0x0d
00046 
00047 struct telnetd_line {
00048   char line[TELNETD_CONF_LINELEN];
00049 };
00050 MEMB(linemem, struct telnetd_line, TELNETD_CONF_NUMLINES);
00051 
00052 #define STATE_NORMAL 0
00053 #define STATE_IAC    1
00054 #define STATE_WILL   2
00055 #define STATE_WONT   3
00056 #define STATE_DO     4
00057 #define STATE_DONT   5
00058 #define STATE_CLOSE  6
00059 
00060 static struct telnetd_state s;
00061 
00062 #define TELNET_IAC   255
00063 #define TELNET_WILL  251
00064 #define TELNET_WONT  252
00065 #define TELNET_DO    253
00066 #define TELNET_DONT  254
00067 /*---------------------------------------------------------------------------*/
00068 static char *
00069 alloc_line(void)
00070 {
00071   return memb_alloc(&linemem);
00072 }
00073 /*---------------------------------------------------------------------------*/
00074 static void
00075 dealloc_line(char *line)
00076 {
00077   memb_free(&linemem, line);
00078 }
00079 /*---------------------------------------------------------------------------*/
00080 void
00081 shell_quit(char *str)
00082 {
00083   s.state = STATE_CLOSE;
00084 }
00085 /*---------------------------------------------------------------------------*/
00086 static void
00087 sendline(char *line)
00088 {
00089   static unsigned int i;
00090   
00091   for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00092     if(s.lines[i] == NULL) {
00093       s.lines[i] = line;
00094       break;
00095     }
00096   }
00097   if(i == TELNETD_CONF_NUMLINES) {
00098     dealloc_line(line);
00099   }
00100 }
00101 /*---------------------------------------------------------------------------*/
00102 void
00103 shell_prompt(char *str)
00104 {
00105   char *line;
00106   line = alloc_line();
00107   if(line != NULL) {
00108     strncpy(line, str, TELNETD_CONF_LINELEN);
00109     /*    petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
00110     sendline(line);
00111   }
00112 }
00113 /*---------------------------------------------------------------------------*/
00114 void
00115 shell_output(char *str1, char *str2)
00116 {
00117   static unsigned len;
00118   char *line;
00119 
00120   line = alloc_line();
00121   if(line != NULL) {
00122     len = strlen(str1);
00123     strncpy(line, str1, TELNETD_CONF_LINELEN);
00124     if(len < TELNETD_CONF_LINELEN) {
00125       strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
00126     }
00127     len = strlen(line);
00128     if(len < TELNETD_CONF_LINELEN - 2) {
00129       line[len] = ISO_cr;
00130       line[len+1] = ISO_nl;
00131       line[len+2] = 0;
00132     }
00133     /*    petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
00134     sendline(line);
00135   }
00136 }
00137 /*---------------------------------------------------------------------------*/
00138 void
00139 telnetd_init(void)
00140 {
00141   uip_listen(HTONS(23));
00142   memb_init(&linemem);
00143   shell_init();
00144 }
00145 /*---------------------------------------------------------------------------*/
00146 static void
00147 acked(void)
00148 {
00149   static unsigned int i;
00150   
00151   while(s.numsent > 0) {
00152     dealloc_line(s.lines[0]);
00153     for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
00154       s.lines[i - 1] = s.lines[i];
00155     }
00156     s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
00157     --s.numsent;
00158   }
00159 }
00160 /*---------------------------------------------------------------------------*/
00161 static void
00162 senddata(void)
00163 {
00164   static char *bufptr, *lineptr;
00165   static int buflen, linelen;
00166   
00167   bufptr = uip_appdata;
00168   buflen = 0;
00169   for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
00170                                  s.lines[s.numsent] != NULL ; ++s.numsent) {
00171     lineptr = s.lines[s.numsent];
00172     linelen = strlen(lineptr);
00173     if(linelen > TELNETD_CONF_LINELEN) {
00174       linelen = TELNETD_CONF_LINELEN;
00175     }
00176     if(buflen + linelen < uip_mss()) {
00177       memcpy(bufptr, lineptr, linelen);
00178       bufptr += linelen;
00179       buflen += linelen;
00180     } else {
00181       break;
00182     }
00183   }
00184   uip_send(uip_appdata, buflen);
00185 }
00186 /*---------------------------------------------------------------------------*/
00187 static void
00188 closed(void)
00189 {
00190   static unsigned int i;
00191   
00192   for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00193     if(s.lines[i] != NULL) {
00194       dealloc_line(s.lines[i]);
00195     }
00196   }
00197 }
00198 /*---------------------------------------------------------------------------*/
00199 static void
00200 get_char(u8_t c)
00201 {
00202   if(c == ISO_cr) {
00203     return;
00204   }
00205   
00206   s.buf[(int)s.bufptr] = c;
00207   if(s.buf[(int)s.bufptr] == ISO_nl ||
00208      s.bufptr == sizeof(s.buf) - 1) {
00209     if(s.bufptr > 0) {
00210       s.buf[(int)s.bufptr] = 0;
00211       /*      petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/
00212     }
00213     shell_input(s.buf);
00214     s.bufptr = 0;
00215   } else {
00216     ++s.bufptr;
00217   }
00218 }
00219 /*---------------------------------------------------------------------------*/
00220 static void
00221 sendopt(u8_t option, u8_t value)
00222 {
00223   char *line;
00224   line = alloc_line();
00225   if(line != NULL) {
00226     line[0] = TELNET_IAC;
00227     line[1] = option;
00228     line[2] = value;
00229     line[3] = 0;
00230     sendline(line);
00231   }
00232 }
00233 /*---------------------------------------------------------------------------*/
00234 static void
00235 newdata(void)
00236 {
00237   u16_t len;
00238   u8_t c;
00239   char *dataptr;
00240     
00241   
00242   len = uip_datalen();
00243   dataptr = (char *)uip_appdata;
00244   
00245   while(len > 0 && s.bufptr < sizeof(s.buf)) {
00246     c = *dataptr;
00247     ++dataptr;
00248     --len;
00249     switch(s.state) {
00250     case STATE_IAC:
00251       if(c == TELNET_IAC) {
00252          get_char(c);
00253          s.state = STATE_NORMAL;
00254       } else {
00255          switch(c) {
00256          case TELNET_WILL:
00257             s.state = STATE_WILL;
00258             break;
00259          case TELNET_WONT:
00260             s.state = STATE_WONT;
00261             break;
00262          case TELNET_DO:
00263             s.state = STATE_DO;
00264             break;
00265          case TELNET_DONT:
00266             s.state = STATE_DONT;
00267             break;
00268          default:
00269             s.state = STATE_NORMAL;
00270             break;
00271          }
00272       }
00273       break;
00274     case STATE_WILL:
00275       /* Ответ с DONT */
00276       sendopt(TELNET_DONT, c);
00277       s.state = STATE_NORMAL;
00278       break;
00279       
00280     case STATE_WONT:
00281       /* Ответ с DONT */
00282       sendopt(TELNET_DONT, c);
00283       s.state = STATE_NORMAL;
00284       break;
00285     case STATE_DO:
00286       /* Ответ с WONT */
00287       sendopt(TELNET_WONT, c);
00288       s.state = STATE_NORMAL;
00289       break;
00290     case STATE_DONT:
00291       /* Ответ с WONT */
00292       sendopt(TELNET_WONT, c);
00293       s.state = STATE_NORMAL;
00294       break;
00295     case STATE_NORMAL:
00296       if(c == TELNET_IAC) {
00297          s.state = STATE_IAC;
00298       } else {
00299          get_char(c);
00300       }
00301       break;
00302     }
00303   }
00304 }
00305 /*---------------------------------------------------------------------------*/
00306 void
00307 telnetd_appcall(void)
00308 {
00309   static unsigned int i;
00310   if(uip_connected()) {
00311     /*    tcp_markconn(uip_conn, &s);*/
00312     for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
00313       s.lines[i] = NULL;
00314     }
00315     s.bufptr = 0;
00316     s.state = STATE_NORMAL;
00317 
00318     shell_start();
00319   }
00320 
00321   if(s.state == STATE_CLOSE) {
00322     s.state = STATE_NORMAL;
00323     uip_close();
00324     return;
00325   }
00326   
00327   if(uip_closed() ||
00328      uip_aborted() ||
00329      uip_timedout()) {
00330     closed();
00331   }
00332   
00333   if(uip_acked()) {
00334     acked();
00335   }
00336   
00337   if(uip_newdata()) {
00338     newdata();
00339   }
00340   
00341   if(uip_rexmit() ||
00342      uip_newdata() ||
00343      uip_acked() ||
00344      uip_connected() ||
00345      uip_poll()) {
00346     senddata();
00347   }
00348 }
00349 /*---------------------------------------------------------------------------*/