Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
libs/Network/uip/telnetd/telnetd.cpp@2:1df0b61d3b5a, 2014-02-28 (annotated)
- Committer:
- Michael J. Spencer
- Date:
- Fri Feb 28 18:52:52 2014 -0800
- Revision:
- 2:1df0b61d3b5a
Update to latest Smoothie.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Michael J. Spencer |
2:1df0b61d3b5a | 1 | /* |
Michael J. Spencer |
2:1df0b61d3b5a | 2 | * Copyright (c) 2003, Adam Dunkels. |
Michael J. Spencer |
2:1df0b61d3b5a | 3 | * All rights reserved. |
Michael J. Spencer |
2:1df0b61d3b5a | 4 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 5 | * Redistribution and use in source and binary forms, with or without |
Michael J. Spencer |
2:1df0b61d3b5a | 6 | * modification, are permitted provided that the following conditions |
Michael J. Spencer |
2:1df0b61d3b5a | 7 | * are met: |
Michael J. Spencer |
2:1df0b61d3b5a | 8 | * 1. Redistributions of source code must retain the above copyright |
Michael J. Spencer |
2:1df0b61d3b5a | 9 | * notice, this list of conditions and the following disclaimer. |
Michael J. Spencer |
2:1df0b61d3b5a | 10 | * 2. Redistributions in binary form must reproduce the above copyright |
Michael J. Spencer |
2:1df0b61d3b5a | 11 | * notice, this list of conditions and the following disclaimer in the |
Michael J. Spencer |
2:1df0b61d3b5a | 12 | * documentation and/or other materials provided with the distribution. |
Michael J. Spencer |
2:1df0b61d3b5a | 13 | * 3. The name of the author may not be used to endorse or promote |
Michael J. Spencer |
2:1df0b61d3b5a | 14 | * products derived from this software without specific prior |
Michael J. Spencer |
2:1df0b61d3b5a | 15 | * written permission. |
Michael J. Spencer |
2:1df0b61d3b5a | 16 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
Michael J. Spencer |
2:1df0b61d3b5a | 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
Michael J. Spencer |
2:1df0b61d3b5a | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
Michael J. Spencer |
2:1df0b61d3b5a | 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
Michael J. Spencer |
2:1df0b61d3b5a | 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
Michael J. Spencer |
2:1df0b61d3b5a | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
Michael J. Spencer |
2:1df0b61d3b5a | 23 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
Michael J. Spencer |
2:1df0b61d3b5a | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
Michael J. Spencer |
2:1df0b61d3b5a | 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
Michael J. Spencer |
2:1df0b61d3b5a | 26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
Michael J. Spencer |
2:1df0b61d3b5a | 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Michael J. Spencer |
2:1df0b61d3b5a | 28 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 29 | * This file is part of the uIP TCP/IP stack |
Michael J. Spencer |
2:1df0b61d3b5a | 30 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 31 | * $Id: telnetd.c,v 1.2 2006/06/07 09:43:54 adam Exp $ |
Michael J. Spencer |
2:1df0b61d3b5a | 32 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 33 | */ |
Michael J. Spencer |
2:1df0b61d3b5a | 34 | |
Michael J. Spencer |
2:1df0b61d3b5a | 35 | #include "uip.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 36 | #include "telnetd.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 37 | #include "shell.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 38 | |
Michael J. Spencer |
2:1df0b61d3b5a | 39 | #include <string.h> |
Michael J. Spencer |
2:1df0b61d3b5a | 40 | #include <stdlib.h> |
Michael J. Spencer |
2:1df0b61d3b5a | 41 | #include <stdio.h> |
Michael J. Spencer |
2:1df0b61d3b5a | 42 | |
Michael J. Spencer |
2:1df0b61d3b5a | 43 | #define ISO_nl 0x0a |
Michael J. Spencer |
2:1df0b61d3b5a | 44 | #define ISO_cr 0x0d |
Michael J. Spencer |
2:1df0b61d3b5a | 45 | |
Michael J. Spencer |
2:1df0b61d3b5a | 46 | #define STATE_NORMAL 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 47 | #define STATE_IAC 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 48 | #define STATE_WILL 2 |
Michael J. Spencer |
2:1df0b61d3b5a | 49 | #define STATE_WONT 3 |
Michael J. Spencer |
2:1df0b61d3b5a | 50 | #define STATE_DO 4 |
Michael J. Spencer |
2:1df0b61d3b5a | 51 | #define STATE_DONT 5 |
Michael J. Spencer |
2:1df0b61d3b5a | 52 | #define STATE_CLOSE 6 |
Michael J. Spencer |
2:1df0b61d3b5a | 53 | |
Michael J. Spencer |
2:1df0b61d3b5a | 54 | #define TELNET_IAC 255 |
Michael J. Spencer |
2:1df0b61d3b5a | 55 | #define TELNET_WILL 251 |
Michael J. Spencer |
2:1df0b61d3b5a | 56 | #define TELNET_WONT 252 |
Michael J. Spencer |
2:1df0b61d3b5a | 57 | #define TELNET_DO 253 |
Michael J. Spencer |
2:1df0b61d3b5a | 58 | #define TELNET_DONT 254 |
Michael J. Spencer |
2:1df0b61d3b5a | 59 | |
Michael J. Spencer |
2:1df0b61d3b5a | 60 | #define TELNET_LINEMODE 0x22 |
Michael J. Spencer |
2:1df0b61d3b5a | 61 | #define TELNET_GA 0x03 |
Michael J. Spencer |
2:1df0b61d3b5a | 62 | #define TELNET_X_PROMPT 0x55 |
Michael J. Spencer |
2:1df0b61d3b5a | 63 | |
Michael J. Spencer |
2:1df0b61d3b5a | 64 | //#define DEBUG_PRINTF(...) |
Michael J. Spencer |
2:1df0b61d3b5a | 65 | #define DEBUG_PRINTF printf |
Michael J. Spencer |
2:1df0b61d3b5a | 66 | |
Michael J. Spencer |
2:1df0b61d3b5a | 67 | static char *alloc_line(int size) |
Michael J. Spencer |
2:1df0b61d3b5a | 68 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 69 | return (char *)malloc(size); |
Michael J. Spencer |
2:1df0b61d3b5a | 70 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 71 | |
Michael J. Spencer |
2:1df0b61d3b5a | 72 | static void dealloc_line(char *line) |
Michael J. Spencer |
2:1df0b61d3b5a | 73 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 74 | free(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 75 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 76 | |
Michael J. Spencer |
2:1df0b61d3b5a | 77 | void Telnetd::close() |
Michael J. Spencer |
2:1df0b61d3b5a | 78 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 79 | state = STATE_CLOSE; |
Michael J. Spencer |
2:1df0b61d3b5a | 80 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 81 | |
Michael J. Spencer |
2:1df0b61d3b5a | 82 | int Telnetd::sendline(char *line) |
Michael J. Spencer |
2:1df0b61d3b5a | 83 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 84 | int i; |
Michael J. Spencer |
2:1df0b61d3b5a | 85 | for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) { |
Michael J. Spencer |
2:1df0b61d3b5a | 86 | if (lines[i] == NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 87 | lines[i] = line; |
Michael J. Spencer |
2:1df0b61d3b5a | 88 | return i; |
Michael J. Spencer |
2:1df0b61d3b5a | 89 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 90 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 91 | if (i == TELNETD_CONF_NUMLINES) { |
Michael J. Spencer |
2:1df0b61d3b5a | 92 | dealloc_line(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 93 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 94 | return TELNETD_CONF_NUMLINES; |
Michael J. Spencer |
2:1df0b61d3b5a | 95 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 96 | |
Michael J. Spencer |
2:1df0b61d3b5a | 97 | void Telnetd::output_prompt(const char *str) |
Michael J. Spencer |
2:1df0b61d3b5a | 98 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 99 | if(prompt) output(str); |
Michael J. Spencer |
2:1df0b61d3b5a | 100 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 101 | |
Michael J. Spencer |
2:1df0b61d3b5a | 102 | int Telnetd::output(const char *str) |
Michael J. Spencer |
2:1df0b61d3b5a | 103 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 104 | if(state == STATE_CLOSE) return -1; |
Michael J. Spencer |
2:1df0b61d3b5a | 105 | |
Michael J. Spencer |
2:1df0b61d3b5a | 106 | unsigned chunk = 256; // small chunk size so we don't allocate huge blocks, and must be less than mss |
Michael J. Spencer |
2:1df0b61d3b5a | 107 | unsigned len = strlen(str); |
Michael J. Spencer |
2:1df0b61d3b5a | 108 | char *line; |
Michael J. Spencer |
2:1df0b61d3b5a | 109 | if (len < chunk) { |
Michael J. Spencer |
2:1df0b61d3b5a | 110 | // can be sent in one tcp buffer |
Michael J. Spencer |
2:1df0b61d3b5a | 111 | line = alloc_line(len + 1); |
Michael J. Spencer |
2:1df0b61d3b5a | 112 | if (line != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 113 | strcpy(line, str); |
Michael J. Spencer |
2:1df0b61d3b5a | 114 | return sendline(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 115 | }else{ |
Michael J. Spencer |
2:1df0b61d3b5a | 116 | // out of memory treat like full |
Michael J. Spencer |
2:1df0b61d3b5a | 117 | return TELNETD_CONF_NUMLINES; |
Michael J. Spencer |
2:1df0b61d3b5a | 118 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 119 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 120 | // need to split line over multiple send lines |
Michael J. Spencer |
2:1df0b61d3b5a | 121 | int size = chunk; // size to copy |
Michael J. Spencer |
2:1df0b61d3b5a | 122 | int off = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 123 | int n= 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 124 | while (len >= chunk) { |
Michael J. Spencer |
2:1df0b61d3b5a | 125 | line = alloc_line(chunk + 1); |
Michael J. Spencer |
2:1df0b61d3b5a | 126 | if (line != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 127 | memcpy(line, str + off, size); |
Michael J. Spencer |
2:1df0b61d3b5a | 128 | line[size] = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 129 | n= sendline(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 130 | len -= size; |
Michael J. Spencer |
2:1df0b61d3b5a | 131 | off += size; |
Michael J. Spencer |
2:1df0b61d3b5a | 132 | }else{ |
Michael J. Spencer |
2:1df0b61d3b5a | 133 | // out of memory treat like full |
Michael J. Spencer |
2:1df0b61d3b5a | 134 | return TELNETD_CONF_NUMLINES; |
Michael J. Spencer |
2:1df0b61d3b5a | 135 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 136 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 137 | if (len > 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 138 | // send rest |
Michael J. Spencer |
2:1df0b61d3b5a | 139 | line = alloc_line(len + 1); |
Michael J. Spencer |
2:1df0b61d3b5a | 140 | if (line != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 141 | strcpy(line, str + off); |
Michael J. Spencer |
2:1df0b61d3b5a | 142 | n= sendline(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 143 | }else{ |
Michael J. Spencer |
2:1df0b61d3b5a | 144 | // out of memory treat like full |
Michael J. Spencer |
2:1df0b61d3b5a | 145 | return TELNETD_CONF_NUMLINES; |
Michael J. Spencer |
2:1df0b61d3b5a | 146 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 147 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 148 | return n; |
Michael J. Spencer |
2:1df0b61d3b5a | 149 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 150 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 151 | |
Michael J. Spencer |
2:1df0b61d3b5a | 152 | // check if we can queue or if queue is full |
Michael J. Spencer |
2:1df0b61d3b5a | 153 | int Telnetd::can_output() |
Michael J. Spencer |
2:1df0b61d3b5a | 154 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 155 | if(state == STATE_CLOSE) return -1; |
Michael J. Spencer |
2:1df0b61d3b5a | 156 | |
Michael J. Spencer |
2:1df0b61d3b5a | 157 | int i; |
Michael J. Spencer |
2:1df0b61d3b5a | 158 | int cnt = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 159 | for (i = 0; i < TELNETD_CONF_NUMLINES; ++i) { |
Michael J. Spencer |
2:1df0b61d3b5a | 160 | if (lines[i] == NULL) cnt++; |
Michael J. Spencer |
2:1df0b61d3b5a | 161 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 162 | return cnt < 4 ? 0 : 1; |
Michael J. Spencer |
2:1df0b61d3b5a | 163 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 164 | |
Michael J. Spencer |
2:1df0b61d3b5a | 165 | void Telnetd::acked(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 166 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 167 | while (numsent > 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 168 | dealloc_line(lines[0]); |
Michael J. Spencer |
2:1df0b61d3b5a | 169 | for (int i = 1; i < TELNETD_CONF_NUMLINES; ++i) { |
Michael J. Spencer |
2:1df0b61d3b5a | 170 | lines[i - 1] = lines[i]; |
Michael J. Spencer |
2:1df0b61d3b5a | 171 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 172 | lines[TELNETD_CONF_NUMLINES - 1] = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 173 | --numsent; |
Michael J. Spencer |
2:1df0b61d3b5a | 174 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 175 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 176 | |
Michael J. Spencer |
2:1df0b61d3b5a | 177 | void Telnetd::senddata(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 178 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 179 | // NOTE this sends as many lines as it can fit in one tcp frame |
Michael J. Spencer |
2:1df0b61d3b5a | 180 | // we need to keep the lines under the size of the tcp frame |
Michael J. Spencer |
2:1df0b61d3b5a | 181 | char *bufptr, *lineptr; |
Michael J. Spencer |
2:1df0b61d3b5a | 182 | int buflen, linelen; |
Michael J. Spencer |
2:1df0b61d3b5a | 183 | |
Michael J. Spencer |
2:1df0b61d3b5a | 184 | bufptr = (char *)uip_appdata; |
Michael J. Spencer |
2:1df0b61d3b5a | 185 | buflen = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 186 | for (numsent = 0; numsent < TELNETD_CONF_NUMLINES && lines[numsent] != NULL ; ++numsent) { |
Michael J. Spencer |
2:1df0b61d3b5a | 187 | lineptr = lines[numsent]; |
Michael J. Spencer |
2:1df0b61d3b5a | 188 | linelen = strlen(lineptr); |
Michael J. Spencer |
2:1df0b61d3b5a | 189 | if (buflen + linelen < uip_mss()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 190 | memcpy(bufptr, lineptr, linelen); |
Michael J. Spencer |
2:1df0b61d3b5a | 191 | bufptr += linelen; |
Michael J. Spencer |
2:1df0b61d3b5a | 192 | buflen += linelen; |
Michael J. Spencer |
2:1df0b61d3b5a | 193 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 194 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 195 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 196 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 197 | uip_send(uip_appdata, buflen); |
Michael J. Spencer |
2:1df0b61d3b5a | 198 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 199 | |
Michael J. Spencer |
2:1df0b61d3b5a | 200 | void Telnetd::get_char(u8_t c) |
Michael J. Spencer |
2:1df0b61d3b5a | 201 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 202 | if (c == ISO_cr) { |
Michael J. Spencer |
2:1df0b61d3b5a | 203 | return; |
Michael J. Spencer |
2:1df0b61d3b5a | 204 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 205 | |
Michael J. Spencer |
2:1df0b61d3b5a | 206 | buf[(int)bufptr] = c; |
Michael J. Spencer |
2:1df0b61d3b5a | 207 | if (buf[(int)bufptr] == ISO_nl || bufptr == sizeof(buf) - 1) { |
Michael J. Spencer |
2:1df0b61d3b5a | 208 | if (bufptr > 0) { |
Michael J. Spencer |
2:1df0b61d3b5a | 209 | buf[(int)bufptr] = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 210 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 211 | shell->input(buf); |
Michael J. Spencer |
2:1df0b61d3b5a | 212 | bufptr = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 213 | |
Michael J. Spencer |
2:1df0b61d3b5a | 214 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 215 | ++bufptr; |
Michael J. Spencer |
2:1df0b61d3b5a | 216 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 217 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 218 | |
Michael J. Spencer |
2:1df0b61d3b5a | 219 | // static void sendopt(u8_t option, u8_t value) |
Michael J. Spencer |
2:1df0b61d3b5a | 220 | // { |
Michael J. Spencer |
2:1df0b61d3b5a | 221 | // char *line; |
Michael J. Spencer |
2:1df0b61d3b5a | 222 | // line = alloc_line(4); |
Michael J. Spencer |
2:1df0b61d3b5a | 223 | // if (line != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 224 | // line[0] = TELNET_IAC; |
Michael J. Spencer |
2:1df0b61d3b5a | 225 | // line[1] = option; |
Michael J. Spencer |
2:1df0b61d3b5a | 226 | // line[2] = value; |
Michael J. Spencer |
2:1df0b61d3b5a | 227 | // line[3] = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 228 | // sendline(line); |
Michael J. Spencer |
2:1df0b61d3b5a | 229 | // } |
Michael J. Spencer |
2:1df0b61d3b5a | 230 | // } |
Michael J. Spencer |
2:1df0b61d3b5a | 231 | |
Michael J. Spencer |
2:1df0b61d3b5a | 232 | void Telnetd::newdata(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 233 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 234 | u16_t len; |
Michael J. Spencer |
2:1df0b61d3b5a | 235 | u8_t c; |
Michael J. Spencer |
2:1df0b61d3b5a | 236 | char *dataptr; |
Michael J. Spencer |
2:1df0b61d3b5a | 237 | |
Michael J. Spencer |
2:1df0b61d3b5a | 238 | len = uip_datalen(); |
Michael J. Spencer |
2:1df0b61d3b5a | 239 | dataptr = (char *)uip_appdata; |
Michael J. Spencer |
2:1df0b61d3b5a | 240 | |
Michael J. Spencer |
2:1df0b61d3b5a | 241 | while (len > 0 && bufptr < sizeof(buf)) { |
Michael J. Spencer |
2:1df0b61d3b5a | 242 | c = *dataptr; |
Michael J. Spencer |
2:1df0b61d3b5a | 243 | ++dataptr; |
Michael J. Spencer |
2:1df0b61d3b5a | 244 | --len; |
Michael J. Spencer |
2:1df0b61d3b5a | 245 | switch (state) { |
Michael J. Spencer |
2:1df0b61d3b5a | 246 | case STATE_IAC: |
Michael J. Spencer |
2:1df0b61d3b5a | 247 | if (c == TELNET_IAC) { |
Michael J. Spencer |
2:1df0b61d3b5a | 248 | get_char(c); |
Michael J. Spencer |
2:1df0b61d3b5a | 249 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 250 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 251 | switch (c) { |
Michael J. Spencer |
2:1df0b61d3b5a | 252 | case TELNET_WILL: |
Michael J. Spencer |
2:1df0b61d3b5a | 253 | state = STATE_WILL; |
Michael J. Spencer |
2:1df0b61d3b5a | 254 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 255 | case TELNET_WONT: |
Michael J. Spencer |
2:1df0b61d3b5a | 256 | state = STATE_WONT; |
Michael J. Spencer |
2:1df0b61d3b5a | 257 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 258 | case TELNET_DO: |
Michael J. Spencer |
2:1df0b61d3b5a | 259 | state = STATE_DO; |
Michael J. Spencer |
2:1df0b61d3b5a | 260 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 261 | case TELNET_DONT: |
Michael J. Spencer |
2:1df0b61d3b5a | 262 | state = STATE_DONT; |
Michael J. Spencer |
2:1df0b61d3b5a | 263 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 264 | default: |
Michael J. Spencer |
2:1df0b61d3b5a | 265 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 266 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 267 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 268 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 269 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 270 | case STATE_WILL: |
Michael J. Spencer |
2:1df0b61d3b5a | 271 | if (c == TELNET_LINEMODE) { |
Michael J. Spencer |
2:1df0b61d3b5a | 272 | //sendopt(TELNET_DO, c); |
Michael J. Spencer |
2:1df0b61d3b5a | 273 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 274 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 275 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 276 | |
Michael J. Spencer |
2:1df0b61d3b5a | 277 | case STATE_WONT: |
Michael J. Spencer |
2:1df0b61d3b5a | 278 | /* Reply with a DONT */ |
Michael J. Spencer |
2:1df0b61d3b5a | 279 | //sendopt(TELNET_DONT, c); |
Michael J. Spencer |
2:1df0b61d3b5a | 280 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 281 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 282 | case STATE_DO: |
Michael J. Spencer |
2:1df0b61d3b5a | 283 | if (c == TELNET_X_PROMPT) { |
Michael J. Spencer |
2:1df0b61d3b5a | 284 | prompt= true; |
Michael J. Spencer |
2:1df0b61d3b5a | 285 | }else if (c == TELNET_GA) { |
Michael J. Spencer |
2:1df0b61d3b5a | 286 | // enable prompt if telnet client running |
Michael J. Spencer |
2:1df0b61d3b5a | 287 | prompt= true; |
Michael J. Spencer |
2:1df0b61d3b5a | 288 | shell->setConsole(); // tell shell we are a console, as this is sent be telnet clients |
Michael J. Spencer |
2:1df0b61d3b5a | 289 | }else{ |
Michael J. Spencer |
2:1df0b61d3b5a | 290 | /* Reply with a WONT */ |
Michael J. Spencer |
2:1df0b61d3b5a | 291 | //sendopt(TELNET_WONT, c); |
Michael J. Spencer |
2:1df0b61d3b5a | 292 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 293 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 294 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 295 | case STATE_DONT: |
Michael J. Spencer |
2:1df0b61d3b5a | 296 | if (c == TELNET_X_PROMPT) { |
Michael J. Spencer |
2:1df0b61d3b5a | 297 | prompt= false; |
Michael J. Spencer |
2:1df0b61d3b5a | 298 | }else{ |
Michael J. Spencer |
2:1df0b61d3b5a | 299 | /* Reply with a WONT */ |
Michael J. Spencer |
2:1df0b61d3b5a | 300 | //sendopt(TELNET_WONT, c); |
Michael J. Spencer |
2:1df0b61d3b5a | 301 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 302 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 303 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 304 | case STATE_NORMAL: |
Michael J. Spencer |
2:1df0b61d3b5a | 305 | if (c == TELNET_IAC) { |
Michael J. Spencer |
2:1df0b61d3b5a | 306 | state = STATE_IAC; |
Michael J. Spencer |
2:1df0b61d3b5a | 307 | } else { |
Michael J. Spencer |
2:1df0b61d3b5a | 308 | get_char(c); |
Michael J. Spencer |
2:1df0b61d3b5a | 309 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 310 | break; |
Michael J. Spencer |
2:1df0b61d3b5a | 311 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 312 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 313 | |
Michael J. Spencer |
2:1df0b61d3b5a | 314 | // if the command queue is getting too big we stop TCP |
Michael J. Spencer |
2:1df0b61d3b5a | 315 | if(shell->queue_size() > 20) { |
Michael J. Spencer |
2:1df0b61d3b5a | 316 | DEBUG_PRINTF("Telnet: stopped: %d\n", shell->queue_size()); |
Michael J. Spencer |
2:1df0b61d3b5a | 317 | uip_stop(); |
Michael J. Spencer |
2:1df0b61d3b5a | 318 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 319 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 320 | |
Michael J. Spencer |
2:1df0b61d3b5a | 321 | void Telnetd::poll() |
Michael J. Spencer |
2:1df0b61d3b5a | 322 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 323 | if(first_time) { |
Michael J. Spencer |
2:1df0b61d3b5a | 324 | first_time= false; |
Michael J. Spencer |
2:1df0b61d3b5a | 325 | shell->start(); |
Michael J. Spencer |
2:1df0b61d3b5a | 326 | senddata(); |
Michael J. Spencer |
2:1df0b61d3b5a | 327 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 328 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 329 | |
Michael J. Spencer |
2:1df0b61d3b5a | 330 | Telnetd::Telnetd() |
Michael J. Spencer |
2:1df0b61d3b5a | 331 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 332 | DEBUG_PRINTF("Telnetd: ctor %p\n", this); |
Michael J. Spencer |
2:1df0b61d3b5a | 333 | for (int i = 0; i < TELNETD_CONF_NUMLINES; ++i) { |
Michael J. Spencer |
2:1df0b61d3b5a | 334 | lines[i] = NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 335 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 336 | |
Michael J. Spencer |
2:1df0b61d3b5a | 337 | first_time= true; |
Michael J. Spencer |
2:1df0b61d3b5a | 338 | bufptr = 0; |
Michael J. Spencer |
2:1df0b61d3b5a | 339 | state = STATE_NORMAL; |
Michael J. Spencer |
2:1df0b61d3b5a | 340 | prompt= false; |
Michael J. Spencer |
2:1df0b61d3b5a | 341 | shell= new Shell(this); |
Michael J. Spencer |
2:1df0b61d3b5a | 342 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 343 | |
Michael J. Spencer |
2:1df0b61d3b5a | 344 | Telnetd::~Telnetd() |
Michael J. Spencer |
2:1df0b61d3b5a | 345 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 346 | DEBUG_PRINTF("Telnetd: dtor %p\n", this); |
Michael J. Spencer |
2:1df0b61d3b5a | 347 | for (int i = 0; i < TELNETD_CONF_NUMLINES; ++i) { |
Michael J. Spencer |
2:1df0b61d3b5a | 348 | if (lines[i] != NULL) dealloc_line(lines[i]); |
Michael J. Spencer |
2:1df0b61d3b5a | 349 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 350 | delete shell; |
Michael J. Spencer |
2:1df0b61d3b5a | 351 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 352 | |
Michael J. Spencer |
2:1df0b61d3b5a | 353 | // static |
Michael J. Spencer |
2:1df0b61d3b5a | 354 | void Telnetd::appcall(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 355 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 356 | Telnetd *instance= reinterpret_cast<Telnetd *>(uip_conn->appstate); |
Michael J. Spencer |
2:1df0b61d3b5a | 357 | |
Michael J. Spencer |
2:1df0b61d3b5a | 358 | if (uip_connected()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 359 | // create a new telnet class instance |
Michael J. Spencer |
2:1df0b61d3b5a | 360 | instance= new Telnetd; |
Michael J. Spencer |
2:1df0b61d3b5a | 361 | DEBUG_PRINTF("Telnetd new instance: %p\n", instance); |
Michael J. Spencer |
2:1df0b61d3b5a | 362 | uip_conn->appstate= instance; // and store it in the appstate of the connection |
Michael J. Spencer |
2:1df0b61d3b5a | 363 | instance->rport= uip_conn->rport; |
Michael J. Spencer |
2:1df0b61d3b5a | 364 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 365 | |
Michael J. Spencer |
2:1df0b61d3b5a | 366 | if (uip_closed() || uip_aborted() || uip_timedout()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 367 | DEBUG_PRINTF("Telnetd: closed: %p\n", instance); |
Michael J. Spencer |
2:1df0b61d3b5a | 368 | if(instance != NULL) { |
Michael J. Spencer |
2:1df0b61d3b5a | 369 | delete instance; |
Michael J. Spencer |
2:1df0b61d3b5a | 370 | uip_conn->appstate= NULL; |
Michael J. Spencer |
2:1df0b61d3b5a | 371 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 372 | return; |
Michael J. Spencer |
2:1df0b61d3b5a | 373 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 374 | |
Michael J. Spencer |
2:1df0b61d3b5a | 375 | // sanity check |
Michael J. Spencer |
2:1df0b61d3b5a | 376 | if(instance == NULL || instance->rport != uip_conn->rport) { |
Michael J. Spencer |
2:1df0b61d3b5a | 377 | DEBUG_PRINTF("Telnetd: ERROR Null instance or rport is wrong: %p - %u, %d\n", instance, HTONS(uip_conn->rport), uip_flags); |
Michael J. Spencer |
2:1df0b61d3b5a | 378 | uip_abort(); |
Michael J. Spencer |
2:1df0b61d3b5a | 379 | return; |
Michael J. Spencer |
2:1df0b61d3b5a | 380 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 381 | |
Michael J. Spencer |
2:1df0b61d3b5a | 382 | if (instance->state == STATE_CLOSE) { |
Michael J. Spencer |
2:1df0b61d3b5a | 383 | uip_close(); |
Michael J. Spencer |
2:1df0b61d3b5a | 384 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 385 | |
Michael J. Spencer |
2:1df0b61d3b5a | 386 | |
Michael J. Spencer |
2:1df0b61d3b5a | 387 | if (uip_acked()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 388 | instance->acked(); |
Michael J. Spencer |
2:1df0b61d3b5a | 389 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 390 | |
Michael J. Spencer |
2:1df0b61d3b5a | 391 | if (uip_newdata()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 392 | instance->newdata(); |
Michael J. Spencer |
2:1df0b61d3b5a | 393 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 394 | |
Michael J. Spencer |
2:1df0b61d3b5a | 395 | if (uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 396 | instance->senddata(); |
Michael J. Spencer |
2:1df0b61d3b5a | 397 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 398 | |
Michael J. Spencer |
2:1df0b61d3b5a | 399 | if(uip_poll() && uip_stopped(uip_conn) && instance->shell->queue_size() < 5) { |
Michael J. Spencer |
2:1df0b61d3b5a | 400 | DEBUG_PRINTF("restarted %d - %p\n", instance->shell->queue_size(), instance); |
Michael J. Spencer |
2:1df0b61d3b5a | 401 | uip_restart(); |
Michael J. Spencer |
2:1df0b61d3b5a | 402 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 403 | |
Michael J. Spencer |
2:1df0b61d3b5a | 404 | if(uip_poll()) { |
Michael J. Spencer |
2:1df0b61d3b5a | 405 | instance->poll(); |
Michael J. Spencer |
2:1df0b61d3b5a | 406 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 407 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 408 | |
Michael J. Spencer |
2:1df0b61d3b5a | 409 | // static |
Michael J. Spencer |
2:1df0b61d3b5a | 410 | void Telnetd::init(void) |
Michael J. Spencer |
2:1df0b61d3b5a | 411 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 412 | uip_listen(HTONS(23)); |
Michael J. Spencer |
2:1df0b61d3b5a | 413 | } |