blob: 1f3259b3fef0a681f67c8c03ff0f8c51059976f7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.gogo.jline.telnet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.List;
import org.apache.felix.gogo.jline.Shell;
import org.apache.felix.gogo.jline.Shell.Context;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.CommandSession;
import org.jline.builtins.Options;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
import org.jline.terminal.Terminal.Signal;
import org.jline.terminal.TerminalBuilder;
/*
* a very simple Telnet server.
* real remote access should be via ssh.
*/
public class Telnet {
public static final String[] functions = {"telnetd"};
private static final int defaultPort = 2019;
private final CommandProcessor processor;
private PortListener portListener;
private int port;
private String ip;
public Telnet(CommandProcessor procesor) {
this.processor = procesor;
}
public void telnetd(CommandSession session, String[] argv) throws IOException {
final String[] usage = {"telnetd - start simple telnet server",
"Usage: telnetd [-i ip] [-p port] start | stop | status",
" -i --ip=INTERFACE listen interface (default=127.0.0.1)",
" -p --port=PORT listen port (default=" + defaultPort + ")",
" -? --help show help"};
Options opt = Options.compile(usage).parse(argv);
List<String> args = opt.args();
if (opt.isSet("help") || args.isEmpty()) {
opt.usage(System.err);
return;
}
String command = args.get(0);
if ("start".equals(command)) {
if (portListener != null) {
throw new IllegalStateException("telnetd is already running on port " + port);
}
ip = opt.get("ip");
port = opt.getNumber("port");
start(session);
status();
} else if ("stop".equals(command)) {
if (portListener == null) {
throw new IllegalStateException("telnetd is not running.");
}
stop();
} else if ("status".equals(command)) {
status();
} else {
throw opt.usageError("bad command: " + command);
}
}
private void status() {
if (portListener != null) {
System.out.println("telnetd is running on " + ip + ":" + port);
} else {
System.out.println("telnetd is not running.");
}
}
private void start(CommandSession session) {
ConnectionManager connectionManager = new ConnectionManager(1000, 5 * 60 * 1000, 5 * 60 * 1000, 60 * 1000, null, null, false) {
@Override
protected Connection createConnection(ThreadGroup threadGroup, ConnectionData newCD) {
return new Connection(threadGroup, newCD) {
TelnetIO telnetIO;
@Override
protected void doRun() throws Exception {
telnetIO = new TelnetIO();
telnetIO.setConnection(this);
telnetIO.initIO();
InputStream in = new InputStream() {
@Override
public int read() throws IOException {
return telnetIO.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int r = read();
if (r >= 0) {
b[off] = (byte) r;
return 1;
} else {
return -1;
}
}
};
PrintStream out = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
telnetIO.write(b);
}
@Override
public void flush() throws IOException {
telnetIO.flush();
}
});
Terminal terminal = TerminalBuilder.builder()
.type(getConnectionData().getNegotiatedTerminalType().toLowerCase())
.streams(in, out)
.system(false)
.name("telnet")
.build();
terminal.setSize(new Size(getConnectionData().getTerminalColumns(), getConnectionData().getTerminalRows()));
terminal.setAttributes(Shell.getTerminal(session).getAttributes());
addConnectionListener(new ConnectionListener() {
@Override
public void connectionIdle(ConnectionEvent ce) {
}
@Override
public void connectionTimedOut(ConnectionEvent ce) {
}
@Override
public void connectionLogoutRequest(ConnectionEvent ce) {
}
@Override
public void connectionSentBreak(ConnectionEvent ce) {
}
@Override
public void connectionTerminalGeometryChanged(ConnectionEvent ce) {
terminal.setSize(new Size(getConnectionData().getTerminalColumns(), getConnectionData().getTerminalRows()));
terminal.raise(Signal.WINCH);
}
});
PrintStream pout = new PrintStream(terminal.output());
CommandSession session = processor.createSession(terminal.input(), pout, pout);
session.put(Shell.VAR_TERMINAL, terminal);
Context context = new Context() {
@Override
public String getProperty(String name) {
return System.getProperty(name);
}
@Override
public void exit() {
close();
}
};
new Shell(context, processor).gosh(session, new String[]{"--login"});
}
@Override
protected void doClose() {
telnetIO.closeOutput();
telnetIO.closeInput();
}
};
}
};
portListener = new PortListener("gogo", port, 10);
portListener.setConnectionManager(connectionManager);
portListener.start();
}
private void stop() {
portListener.stop();
portListener = null;
}
}