1 package kawa; 3 5 6 9 public class Telnet implements Runnable 10 { 11 boolean isServer; 12 final static int SE = 240; final static int NOP = 241; 19 final static int IP = 244; final static int EOF = 236; 22 23 final static int SB = 250; 24 25 27 public static final int WILL = 251; 28 30 public static final int WONT = 252; 31 32 35 public static final int DO = 253; 36 37 public static final int DONT = 254; 38 41 42 43 final static int IAC = 255; 44 45 public static final int ECHO = 1; 47 public static final int SUPPRESS_GO_AHEAD = 3; 48 final static int TM = 6; 49 final static int TTYPE = 24; 50 final static int NAWS = 31; 51 final static int LINEMODE = 34; 52 53 71 72 public short windowHeight, windowWidth; 73 public byte[] terminalType; 74 final byte preferredLineMode = 3; 76 java.io.InputStream sin; 77 java.io.OutputStream sout; 78 79 TelnetInputStream in; 80 TelnetOutputStream out; 81 82 public TelnetInputStream getInputStream() 83 { 84 return in; 85 } 86 87 public TelnetOutputStream getOutputStream() 88 { 89 return out; 90 } 91 92 99 final byte[] optionsState = new byte[256]; 100 101 102 final static int OPTION_NO = 0; 103 104 105 final static int OPTION_WANTNO = 1; 106 107 108 final static int OPTION_WANTNO_OPPOSITE = 2; 109 110 111 final static int OPTION_WANTYES = 3; 112 113 114 final static int OPTION_WANTYES_OPPOSITE = 4; 115 116 117 final static int OPTION_YES = 5; 118 119 133 boolean change (int command, int option) 134 { 135 if (option == TM) 136 return true; 137 if (isServer && option == NAWS) 138 return true; 139 if (isServer && command == WILL && option == LINEMODE) 140 { 141 byte[] buf = new byte[2]; 142 buf[0] = 1; buf[1] = preferredLineMode; 144 try 145 { 146 out.writeSubCommand(LINEMODE, buf); 147 } 148 catch (java.io.IOException ex) 149 { 150 } 152 return true; 153 } 154 if (isServer && command == WILL && option == TTYPE) 155 { 156 byte[] buf = new byte[1]; 157 buf[0] = 1; try 159 { 160 out.writeSubCommand(option, buf); 161 } 162 catch (java.io.IOException ex) 163 { 164 } 166 return true; 167 } 168 if (! isServer && option == ECHO) 169 { 170 if (command == DO) 171 return false; 172 if (command == WILL) 173 return true; 174 } 175 return false; 176 } 177 178 179 180 public void subCommand (byte[] buf, int off, int len) 181 { 182 int command = buf[off]; 183 switch (command) 184 { 185 case NAWS: 186 if (len == 5) 187 { 188 windowWidth = (short) ((buf[1] << 8) + (buf[2] & 0xFF)); 189 windowHeight = (short) ((buf[3] << 8) + (buf[4] & 0xFF)); 190 194 return; 195 } 196 break; 197 case TTYPE: 198 byte[] type = new byte[len-1]; 199 System.arraycopy(buf, 1, type, 0, len-1); 200 terminalType = type; 201 System.err.println("terminal type: '"+new String (type)+"'"); 202 return; 203 case LINEMODE: 204 System.err.println("SBCommand LINEMODE "+buf[1]+" len:"+len); 206 if (buf[1] == 3) { 208 for (int i = 2; i+2 < len; i += 3) 209 { 210 System.err.println(" "+buf[i]+","+buf[i+1]+","+buf[i+2]); 211 } 212 return; 213 } 214 break; 216 } 217 } 218 219 221 void handle (int command, int option) throws java.io.IOException 222 { 223 boolean otherSide = command < DO; 226 227 boolean wantOn = (command & 1) != 0; 229 byte state = optionsState[option]; 230 if (otherSide) 232 state >>= 3; 233 switch ((state >> 3) & 7) 234 { 235 case OPTION_YES: 236 if (wantOn) 237 return; state = OPTION_NO; 240 change(command, option); 241 out.writeCommand(otherSide ? DONT : WONT, option); 242 break; 243 case OPTION_NO: 244 if (! wantOn) 245 return; if (change (command, option)) 247 { 248 state = OPTION_YES; 249 out.writeCommand(otherSide ? DO : WILL, option); } 251 else 252 { 253 out.writeCommand(otherSide ? Telnet.DONT : Telnet.WONT, 254 option); 255 } 256 break; 257 case OPTION_WANTNO: 258 state = OPTION_NO; 259 break; 260 case OPTION_WANTNO_OPPOSITE: 261 state = OPTION_WANTYES; 266 out.writeCommand(otherSide ? Telnet.DO : Telnet.WILL, 267 option); 268 break; 269 case OPTION_WANTYES: 270 if (wantOn) 271 { 272 state = OPTION_YES; 273 change (command, option); 274 } 275 else 276 state = OPTION_NO; break; 278 case OPTION_WANTYES_OPPOSITE: 279 if (wantOn) 280 { 281 state = OPTION_WANTNO; 282 out.writeCommand(otherSide ? DONT : WONT, option); 283 } 284 else 285 { 286 state = OPTION_NO; 287 } 288 break; 289 } 290 if (otherSide) 291 state = (byte) ((optionsState[option] & 0xC7) | (state << 3)); 292 else 293 state = (byte) ((optionsState[option] & 0xF8) | state); 294 optionsState[option] = state; 295 } 296 297 299 public void request (int command, int option) throws java.io.IOException 300 { 301 boolean otherSide = command >= DO; 305 306 boolean wantOn = (command & 1) != 0; 308 309 byte state = optionsState[option]; 310 if (otherSide) 311 state >>= 3; 312 313 switch (state & 7) 314 { 315 case OPTION_NO: 316 if (wantOn) 317 { 318 state = OPTION_WANTYES; 319 out.writeCommand(command, option); 320 } 321 break; 323 case OPTION_YES: 324 if (! wantOn) 325 { 326 state = OPTION_WANTNO; 327 out.writeCommand(command, option); 328 } 329 break; 331 case OPTION_WANTNO: 332 if (wantOn) 333 state = OPTION_WANTNO_OPPOSITE; 334 break; 336 case OPTION_WANTNO_OPPOSITE: 337 if (! wantOn) 338 state = OPTION_WANTNO; 339 break; 341 case OPTION_WANTYES: 342 if (! wantOn) 343 state = OPTION_WANTYES_OPPOSITE; 344 case OPTION_WANTYES_OPPOSITE: 346 if (wantOn) 347 state = OPTION_WANTYES; 348 break; 350 } 351 352 if (otherSide) 353 state = (byte) ((optionsState[option] & 0xC7) | (state << 3)); 354 else 355 state = (byte) ((optionsState[option] & 0xF8) | state); 356 optionsState[option] = state; 357 } 358 359 static void usage () 360 { 361 System.err.println("Usage: [java] kawa.Telnet HOST [PORT#]"); 362 System.exit(-1); 363 } 364 365 public static void main (String [] args) 366 { 367 if (args.length == 0) 368 usage(); 369 String host = args[0]; 370 int port = 23; 371 if (args.length > 1) 372 { 373 port = Integer.parseInt(args[1]); 374 } 375 try 376 { 377 java.net.Socket socket = new java.net.Socket (host, port); 378 Telnet telnet = new Telnet(socket, false); 379 TelnetOutputStream tout = telnet.getOutputStream(); 380 Thread t = new Thread (telnet); 381 382 t.setPriority(Thread.currentThread().getPriority() + 1); 383 t.start(); 384 385 byte[] buffer = new byte[1024]; 386 for (;;) 387 { 388 int ch = System.in.read(); 389 if (ch < 0) 390 break; buffer[0] = (byte) ch; 392 int avail = System.in.available(); 393 if (avail > 0) 394 { 395 if (avail > buffer.length-1) 396 avail = buffer.length - 1; 397 avail = System.in.read(buffer, 1, avail); 398 } 399 tout.write(buffer, 0, avail+1); 400 } 401 t.stop(); 402 } 403 catch (Exception ex) 404 { 405 System.err.println(ex); 406 } 407 } 408 409 public Telnet (java.net.Socket socket, boolean isServer) 410 throws java.io.IOException 411 { 412 sin = socket.getInputStream(); 413 sout = socket.getOutputStream(); 414 out = new TelnetOutputStream(sout); 415 in = new TelnetInputStream(sin, this); 416 this.isServer = isServer; 417 } 418 419 public void run () 420 { 421 try 422 { 423 TelnetInputStream tin = getInputStream(); 424 byte[] buffer = new byte[1024]; 425 for (;;) 426 { 427 int ch = tin.read(); 428 if (ch < 0) 429 break; buffer[0] = (byte) ch; 431 int avail = tin.available(); 432 if (avail > 0) 433 { 434 if (avail > buffer.length-1) 435 avail = buffer.length - 1; 436 avail = tin.read(buffer, 1, avail); 437 } 438 System.out.write(buffer, 0, avail+1); 439 } 440 } 441 catch (java.io.IOException ex) 442 { 443 System.err.println(ex); 444 System.exit(-1); 445 } 446 } 447 } 448 | Popular Tags |