OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [uIP_Demo_Rowley_ARM7/] [uip/] [telnetd.c] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/**
2
 * \addtogroup exampleapps
3
 * @{
4
 */
5
 
6
/**
7
 * \defgroup telnetd Telnet server
8
 * @{
9
 *
10
 * The uIP telnet server provides a command based interface to uIP. It
11
 * allows using the "telnet" application to access uIP, and implements
12
 * the required telnet option negotiation.
13
 *
14
 * The code is structured in a way which makes it possible to add
15
 * commands without having to rewrite the main telnet code. The main
16
 * telnet code calls two callback functions, telnetd_connected() and
17
 * telnetd_input(), when a telnet connection has been established and
18
 * when a line of text arrives on a telnet connection. These two
19
 * functions can be implemented in a way which suits the particular
20
 * application or environment in which the uIP system is intended to
21
 * be run.
22
 *
23
 * The uIP distribution contains an example telnet shell
24
 * implementation that provides a basic set of commands.
25
 */
26
 
27
/**
28
 * \file
29
 * Implementation of the Telnet server.
30
 * \author Adam Dunkels <adam@dunkels.com>
31
 */
32
 
33
/*
34
 * Copyright (c) 2003, Adam Dunkels.
35
 * All rights reserved.
36
 *
37
 * Redistribution and use in source and binary forms, with or without
38
 * modification, are permitted provided that the following conditions
39
 * are met:
40
 * 1. Redistributions of source code must retain the above copyright
41
 *    notice, this list of conditions and the following disclaimer.
42
 * 2. Redistributions in binary form must reproduce the above copyright
43
 *    notice, this list of conditions and the following disclaimer in the
44
 *    documentation and/or other materials provided with the distribution.
45
 * 3. The name of the author may not be used to endorse or promote
46
 *    products derived from this software without specific prior
47
 *    written permission.
48
 *
49
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
50
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
53
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
55
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
57
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
58
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60
 *
61
 * This file is part of the uIP TCP/IP stack.
62
 *
63
 * $Id: telnetd.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
64
 *
65
 */
66
 
67
#include "uip.h"
68
#include "memb.h"
69
#include "telnetd.h"
70
#include <string.h>
71
 
72
#define ISO_nl       0x0a
73
#define ISO_cr       0x0d
74
 
75
MEMB(linemem, TELNETD_LINELEN, TELNETD_NUMLINES);
76
 
77
static u8_t i;
78
 
79
#define STATE_NORMAL 0
80
#define STATE_IAC    1
81
#define STATE_WILL   2
82
#define STATE_WONT   3
83
#define STATE_DO     4  
84
#define STATE_DONT   5
85
#define STATE_CLOSE  6
86
 
87
#define TELNET_IAC   255
88
#define TELNET_WILL  251
89
#define TELNET_WONT  252
90
#define TELNET_DO    253
91
#define TELNET_DONT  254
92
/*-----------------------------------------------------------------------------------*/
93
static char *
94
alloc_line(void)
95
{
96
  return memb_alloc(&linemem);
97
}
98
/*-----------------------------------------------------------------------------------*/
99
static void
100
dealloc_line(char *line)
101
{
102
  memb_free(&linemem, line);
103
}
104
/*-----------------------------------------------------------------------------------*/
105
static void
106
sendline(struct telnetd_state *s, char *line)
107
{
108
  static unsigned int i;
109
  for(i = 0; i < TELNETD_NUMLINES; ++i) {
110
    if(s->lines[i] == NULL) {
111
      s->lines[i] = line;
112
      break;
113
    }
114
  }
115
  if(i == TELNETD_NUMLINES) {
116
    dealloc_line(line);
117
  }
118
}
119
/*-----------------------------------------------------------------------------------*/
120
/**
121
 * Close a telnet session.
122
 *
123
 * This function can be called from a telnet command in order to close
124
 * the connection.
125
 *
126
 * \param s The connection which is to be closed.
127
 *
128
 */
129
/*-----------------------------------------------------------------------------------*/
130
void
131
telnetd_close(struct telnetd_state *s)
132
{
133
  s->state = STATE_CLOSE;
134
}
135
/*-----------------------------------------------------------------------------------*/
136
/**
137
 * Print a prompt on a telnet connection.
138
 *
139
 * This function can be called by the telnet command shell in order to
140
 * print out a command prompt.
141
 *
142
 * \param s A telnet connection.
143
 *
144
 * \param str The command prompt.
145
 *
146
 */
147
/*-----------------------------------------------------------------------------------*/
148
void
149
telnetd_prompt(struct telnetd_state *s, char *str)
150
{
151
  char *line;
152
  line = alloc_line();
153
  if(line != NULL) {
154
    strncpy(line, str, TELNETD_LINELEN);
155
    sendline(s, line);
156
  }
157
}
158
/*-----------------------------------------------------------------------------------*/
159
/**
160
 * Print out a string on a telnet connection.
161
 *
162
 * This function can be called from a telnet command parser in order
163
 * to print out a string of text on the connection. The two strings
164
 * given as arguments to the function will be concatenated, a carrige
165
 * return and a new line character will be added, and the line is
166
 * sent.
167
 *
168
 * \param s The telnet connection.
169
 *
170
 * \param str1 The first string.
171
 *
172
 * \param str2 The second string.
173
 *
174
 */
175
/*-----------------------------------------------------------------------------------*/
176
void
177
telnetd_output(struct telnetd_state *s, char *str1, char *str2)
178
{
179
  static unsigned len;
180
  char *line;
181
 
182
  line = alloc_line();
183
  if(line != NULL) {
184
    len = strlen(str1);
185
    strncpy(line, str1, TELNETD_LINELEN);
186
    if(len < TELNETD_LINELEN) {
187
      strncpy(line + len, str2, TELNETD_LINELEN - len);
188
    }
189
    len = strlen(line);
190
    if(len < TELNETD_LINELEN - 2) {
191
      line[len] = ISO_cr;
192
      line[len+1] = ISO_nl;
193
      line[len+2] = 0;
194
    }
195
    sendline(s, line);
196
  }
197
}
198
/*-----------------------------------------------------------------------------------*/
199
/**
200
 * Initialize the telnet server.
201
 *
202
 * This function will perform the necessary initializations and start
203
 * listening on TCP port 23.
204
 */
205
/*-----------------------------------------------------------------------------------*/
206
void
207
telnetd_init(void)
208
{
209
  memb_init(&linemem);
210
  uip_listen(HTONS(23));
211
}
212
/*-----------------------------------------------------------------------------------*/
213
static void
214
acked(struct telnetd_state *s)
215
{
216
  dealloc_line(s->lines[0]);
217
  for(i = 1; i < TELNETD_NUMLINES; ++i) {
218
    s->lines[i - 1] = s->lines[i];
219
  }
220
}
221
/*-----------------------------------------------------------------------------------*/
222
static void
223
senddata(struct telnetd_state *s)
224
{
225
  if(s->lines[0] != NULL) {
226
    uip_send(s->lines[0], strlen(s->lines[0]));
227
  }
228
}
229
/*-----------------------------------------------------------------------------------*/
230
static void
231
getchar(struct telnetd_state *s, u8_t c)
232
{
233
  if(c == ISO_cr) {
234
    return;
235
  }
236
 
237
  s->buf[(int)s->bufptr] = c;
238
  if(s->buf[(int)s->bufptr] == ISO_nl ||
239
     s->bufptr == sizeof(s->buf) - 1) {
240
    if(s->bufptr > 0) {
241
      s->buf[(int)s->bufptr] = 0;
242
    }
243
    telnetd_input(s, s->buf);
244
    s->bufptr = 0;
245
  } else {
246
    ++s->bufptr;
247
  }
248
}
249
/*-----------------------------------------------------------------------------------*/
250
static void
251
sendopt(struct telnetd_state *s, u8_t option, u8_t value)
252
{
253
  char *line;
254
  line = alloc_line();
255
  if(line != NULL) {
256
    line[0] = TELNET_IAC;
257
    line[1] = option;
258
    line[2] = value;
259
    line[3] = 0;
260
    sendline(s, line);
261
  }
262
}
263
/*-----------------------------------------------------------------------------------*/
264
static void
265
newdata(struct telnetd_state *s)
266
{
267
  u16_t len;
268
  u8_t c;
269
 
270
 
271
  len = uip_datalen();
272
 
273
  while(len > 0 && s->bufptr < sizeof(s->buf)) {
274
    c = *uip_appdata;
275
    ++uip_appdata;
276
    --len;
277
    switch(s->state) {
278
    case STATE_IAC:
279
      if(c == TELNET_IAC) {
280
        getchar(s, c);
281
        s->state = STATE_NORMAL;
282
      } else {
283
        switch(c) {
284
        case TELNET_WILL:
285
          s->state = STATE_WILL;
286
          break;
287
        case TELNET_WONT:
288
          s->state = STATE_WONT;
289
          break;
290
        case TELNET_DO:
291
          s->state = STATE_DO;
292
          break;
293
        case TELNET_DONT:
294
          s->state = STATE_DONT;
295
          break;
296
        default:
297
          s->state = STATE_NORMAL;
298
          break;
299
        }
300
      }
301
      break;
302
    case STATE_WILL:
303
      /* Reply with a DONT */
304
      sendopt(s, TELNET_DONT, c);
305
      s->state = STATE_NORMAL;
306
      break;
307
 
308
    case STATE_WONT:
309
      /* Reply with a DONT */
310
      sendopt(s, TELNET_DONT, c);
311
      s->state = STATE_NORMAL;
312
      break;
313
    case STATE_DO:
314
      /* Reply with a WONT */
315
      sendopt(s, TELNET_WONT, c);
316
      s->state = STATE_NORMAL;
317
      break;
318
    case STATE_DONT:
319
      /* Reply with a WONT */
320
      sendopt(s, TELNET_WONT, c);
321
      s->state = STATE_NORMAL;
322
      break;
323
    case STATE_NORMAL:
324
      if(c == TELNET_IAC) {
325
        s->state = STATE_IAC;
326
      } else {
327
        getchar(s, c);
328
      }
329
      break;
330
    }
331
 
332
 
333
  }
334
 
335
}
336
/*-----------------------------------------------------------------------------------*/
337
void
338
telnetd_app(void)
339
{
340
  struct telnetd_state *s;
341
 
342
  s = (struct telnetd_state *)uip_conn->appstate;
343
 
344
  if(uip_connected()) {
345
 
346
    for(i = 0; i < TELNETD_NUMLINES; ++i) {
347
      s->lines[i] = NULL;
348
    }
349
    s->bufptr = 0;
350
    s->state = STATE_NORMAL;
351
 
352
    telnetd_connected(s);
353
    senddata(s);
354
    return;
355
  }
356
 
357
  if(s->state == STATE_CLOSE) {
358
    s->state = STATE_NORMAL;
359
    uip_close();
360
    return;
361
  }
362
 
363
  if(uip_closed()) {
364
    telnetd_output(s, "Connection closed", "");
365
  }
366
 
367
 
368
  if(uip_aborted()) {
369
    telnetd_output(s, "Connection reset", "");
370
  }
371
 
372
  if(uip_timedout()) {
373
    telnetd_output(s, "Connection timed out", "");
374
  }
375
 
376
  if(uip_acked()) {
377
    acked(s);
378
  }
379
 
380
  if(uip_newdata()) {
381
    newdata(s);
382
  }
383
 
384
  if(uip_rexmit() ||
385
     uip_newdata() ||
386
     uip_acked()) {
387
    senddata(s);
388
  } else if(uip_poll()) {
389
    senddata(s);
390
  }
391
}
392
/*-----------------------------------------------------------------------------------*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.