2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 Kevin Lamonte
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import java
.io
.InputStream
;
32 import java
.io
.IOException
;
33 import java
.io
.OutputStream
;
34 import java
.net
.Socket
;
37 * This class provides a Socket that performs the telnet protocol to both
38 * establish an 8-bit clean no echo channel and expose window resize events
39 * to the Jexer ECMA48 backend.
41 public class TelnetSocket
extends Socket
{
43 // ------------------------------------------------------------------------
44 // Constants --------------------------------------------------------------
45 // ------------------------------------------------------------------------
47 // Telnet protocol special characters. Note package private access.
48 static final int TELNET_SE
= 240;
49 static final int TELNET_NOP
= 241;
50 static final int TELNET_DM
= 242;
51 static final int TELNET_BRK
= 243;
52 static final int TELNET_IP
= 244;
53 static final int TELNET_AO
= 245;
54 static final int TELNET_AYT
= 246;
55 static final int TELNET_EC
= 247;
56 static final int TELNET_EL
= 248;
57 static final int TELNET_GA
= 249;
58 static final int TELNET_SB
= 250;
59 static final int TELNET_WILL
= 251;
60 static final int TELNET_WONT
= 252;
61 static final int TELNET_DO
= 253;
62 static final int TELNET_DONT
= 254;
63 static final int TELNET_IAC
= 255;
64 static final int C_NUL
= 0x00;
65 static final int C_LF
= 0x0A;
66 static final int C_CR
= 0x0D;
68 // ------------------------------------------------------------------------
69 // Variables --------------------------------------------------------------
70 // ------------------------------------------------------------------------
73 * The telnet-aware socket InputStream.
75 private TelnetInputStream input
;
78 * The telnet-aware socket OutputStream.
80 private TelnetOutputStream output
;
84 * If true, this is a server socket (i.e. created by accept()).
86 boolean isServer
= true;
89 * If true, telnet ECHO mode is set such that local echo is off and
90 * remote echo is on. This is appropriate for server sockets.
92 boolean echoMode
= false;
95 * If true, telnet BINARY mode is enabled. We always want this to
96 * ensure a Unicode-safe stream.
98 boolean binaryMode
= false;
101 * If true, the SUPPRESS-GO-AHEAD option is enabled. We always want
104 boolean goAhead
= true;
107 * If true, request the client terminal type.
109 boolean doTermType
= true;
112 * If true, request the client terminal speed.
114 boolean doTermSpeed
= true;
117 * If true, request the Negotiate About Window Size option to
118 * determine the client text width/height.
120 boolean doNAWS
= true;
123 * If true, request the New Environment option to obtain the client
124 * LOGNAME, USER, and LANG variables.
126 boolean doEnvironment
= true;
129 * The terminal type reported by the client.
131 String terminalType
= "";
134 * The terminal speed reported by the client.
136 String terminalSpeed
= "";
138 // ------------------------------------------------------------------------
139 // Constructors -----------------------------------------------------------
140 // ------------------------------------------------------------------------
143 * Creates a Socket that knows the telnet protocol. Note package private
144 * access, this is only used by TelnetServerSocket.
146 * @throws IOException if an I/O error occurs
148 TelnetSocket() throws IOException
{
152 // ------------------------------------------------------------------------
153 // Socket -----------------------------------------------------------------
154 // ------------------------------------------------------------------------
157 * Returns an input stream for this socket.
159 * @return the input stream
160 * @throws IOException if an I/O error occurs
163 public InputStream
getInputStream() throws IOException
{
165 assert (output
== null);
166 output
= new TelnetOutputStream(this, super.getOutputStream());
167 input
= new TelnetInputStream(this, super.getInputStream(), output
);
168 input
.telnetSendOptions();
174 * Returns an output stream for this socket.
176 * @return the output stream
177 * @throws IOException if an I/O error occurs
180 public OutputStream
getOutputStream() throws IOException
{
181 if (output
== null) {
182 assert (input
== null);
183 output
= new TelnetOutputStream(this, super.getOutputStream());
184 input
= new TelnetInputStream(this, super.getInputStream(), output
);
185 input
.telnetSendOptions();
190 // ------------------------------------------------------------------------
191 // TelnetSocket -----------------------------------------------------------
192 // ------------------------------------------------------------------------
195 * See if telnet server/client is in ASCII mode.
197 * @return if true, this connection is in ASCII mode
199 public boolean isAscii() {
200 return (!binaryMode
);