2724e54953409ff83670a1c6adb2cddc40f8bf19
[nikiroo-utils.git] / src / jexer / net / TelnetSocket.java
1 /**
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31 package jexer.net;
32
33 import java.io.InputStream;
34 import java.io.IOException;
35 import java.io.OutputStream;
36 import java.net.Socket;
37
38 /**
39 * This class provides a Socket that performs the telnet protocol to both
40 * establish an 8-bit clean no echo channel and expose window resize events
41 * to the Jexer ECMA48 backend.
42 */
43 public final class TelnetSocket extends Socket {
44
45 /**
46 * The wrapped socket.
47 */
48 private Socket socket;
49
50 /**
51 * The telnet-aware socket InputStream.
52 */
53 private TelnetInputStream input;
54
55 /**
56 * The telnet-aware socket OutputStream. Note package private access:
57 * input sends stuff to output.
58 */
59 TelnetOutputStream output;
60
61 // Telnet protocol special characters. Note package private access.
62 public static final int TELNET_SE = 240;
63 public static final int TELNET_NOP = 241;
64 public static final int TELNET_DM = 242;
65 public static final int TELNET_BRK = 243;
66 public static final int TELNET_IP = 244;
67 public static final int TELNET_AO = 245;
68 public static final int TELNET_AYT = 246;
69 public static final int TELNET_EC = 247;
70 public static final int TELNET_EL = 248;
71 public static final int TELNET_GA = 249;
72 public static final int TELNET_SB = 250;
73 public static final int TELNET_WILL = 251;
74 public static final int TELNET_WONT = 252;
75 public static final int TELNET_DO = 253;
76 public static final int TELNET_DONT = 254;
77 public static final int TELNET_IAC = 255;
78 public static final int C_NUL = 0x00;
79 public static final int C_LF = 0x0A;
80 public static final int C_CR = 0x0D;
81
82 /**
83 * Telnet protocol speaks to a Network Virtual Terminal (NVT).
84 */
85 class TelnetState {
86
87 // General status flags outside the NVT spec
88 boolean doInit;
89 boolean isServer;
90
91 // NVT flags
92 boolean echoMode;
93 boolean binaryMode;
94 boolean goAhead;
95 boolean doTermType;
96 boolean doTermSpeed;
97 boolean doNAWS;
98 boolean doEnvironment;
99 String terminal = "";
100
101 // Flags used by the TelnetInputStream
102 boolean iac;
103 boolean dowill;
104 int dowillType;
105 boolean subnegEnd;
106 boolean isEof;
107 boolean eofMsg;
108 boolean readCR;
109
110 // Flags used by the TelnetOutputStream
111 boolean writeCR;
112
113 /**
114 * Constuctor calls reset().
115 */
116 public TelnetState() {
117 reset();
118 }
119
120 /**
121 * Reset NVT to default state as per RFC 854.
122 */
123 public void reset() {
124 echoMode = false;
125 binaryMode = false;
126 goAhead = true;
127 doTermType = true;
128 doTermSpeed = true;
129 doNAWS = true;
130 doEnvironment = true;
131 doInit = true;
132 isServer = true;
133
134 iac = false;
135 dowill = false;
136 subnegEnd = false;
137 isEof = false;
138 eofMsg = false;
139 readCR = false;
140
141 writeCR = false;
142 }
143 }
144
145 /**
146 * State of the protocol. Note package private access.
147 */
148 TelnetState nvt;
149
150 /**
151 * See if telnet server/client is in ASCII mode.
152 *
153 * @return if true, this connection is in ASCII mode
154 */
155 public boolean isAscii() {
156 return (!nvt.binaryMode);
157 }
158
159 /**
160 * Creates a Socket that knows the telnet protocol.
161 *
162 * @param socket the underlying Socket
163 */
164 TelnetSocket(Socket socket) throws IOException {
165 super();
166 nvt = new TelnetState();
167 this.socket = socket;
168
169 output = new TelnetOutputStream(this, super.getOutputStream());
170 input = new TelnetInputStream(this, super.getInputStream(), output);
171
172 // Initiate the telnet protocol negotiation.
173 input.telnetSendOptions();
174 }
175
176 // Socket interface -------------------------------------------------------
177
178 /**
179 * Returns an input stream for this socket.
180 *
181 * @return the input stream
182 */
183 @Override
184 public InputStream getInputStream() throws IOException {
185 return input;
186 }
187
188 /**
189 * Returns an output stream for this socket.
190 *
191 * @return the output stream
192 */
193 @Override
194 public OutputStream getOutputStream() throws IOException {
195 return output;
196 }
197
198 }