/* * Copyright (C) 2017 by Fonoster Inc (http://fonoster.com) * http://astivetoolkit.org * * This file is part of Astive Toolkit(ATK) * * Licensed 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.astivetoolkit.telnet; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketPermission; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import org.astivetoolkit.server.security.AstPolicy; import org.astivetoolkit.server.security.AstPolicyUtil; import org.astivetoolkit.util.AppLocale; import org.astivetoolkit.util.NetUtil; /** * Default implementation of Astive Server - Telnet service. * * @since 1.0 */ public abstract class TelnetServer extends ServerSocket implements Runnable { private static final Logger LOG = Logger.getLogger(TelnetServer.class); private static String promptSymbol = ColorsANSI.BRIGHT + "[astive]$ " + ColorsANSI.SANE; private InetAddress bindAddr; private int backlog; private int port; /** * Create a new TelnetServer with bindAddr, backlog and port not * initialized. * * @throws IOException when unable to perform IO operations. */ public TelnetServer() throws IOException { } /** * Create a new TelnetServer with port, backlog and bindAddr. * * @param port port to where the service should bound. * @param backlog maximum connections in queue. After that all connections * will be dropped. * @param bindAddr address to where the service should be bound. * @throws IOException when unable to perform IO operations. */ public TelnetServer(int port, int backlog, InetAddress bindAddr) throws IOException { super(); this.port = port; this.backlog = backlog; this.bindAddr = bindAddr; } /** * Returns a list with all applications deployed into the server. * * @return a list of string with the applications running into the server. */ public abstract List<String> lookup(); /** * {@inheritDoc} */ @Override public void run() { try { if (!NetUtil.isPortAvailable(port)) { throw new RuntimeException(AppLocale.getI18n("unableToOpenPortError", new Object[]{port})); } InetSocketAddress inet = new InetSocketAddress(bindAddr, port); bind(inet, backlog); while (true) { Socket client = accept(); StringBuilder sbr = new StringBuilder(); sbr.append(client.getInetAddress().getHostAddress()); sbr.append(":"); sbr.append(port); SocketPermission sp = new SocketPermission(sbr.toString(), AstPolicy.DEFAULT_ACTION); if (!AstPolicyUtil.hasPermission(sp)) { client.close(); continue; } BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream())); writer.println(AppLocale.getI18n("messageTelnetIntro")); writer.println(AppLocale.getI18n("messageTelnetHelp")); writer.print(promptSymbol); writer.flush(); while (true) { String commandStr = reader.readLine(); TelnetCommand command = TelnetCommand.get(commandStr); if (command == null) { writer.println(AppLocale.getI18n("messageTelnetCommandNotFound")); writer.print(promptSymbol); writer.flush(); continue; } if (command.equals(TelnetCommand.STOP)) { stop(); break; } if (command.equals(TelnetCommand.SYSTEM)) { writer.println(AppLocale.getI18n("messageTelnetCommandNotImpl")); writer.print(promptSymbol); writer.flush(); continue; } if (command.equals(TelnetCommand.HELP)) { StringBuilder sb = new StringBuilder(65); sb.append("stop"); sb.append("\n"); sb.append(" "); sb.append("system"); sb.append("\n"); sb.append(" "); sb.append("help"); sb.append("\n"); sb.append(" "); sb.append("lookup"); sb.append("\n"); sb.append(" "); sb.append("exit"); sb.append("\n"); sb.append(" "); sb.append("version"); writer.println(sb.toString()); writer.print(promptSymbol); writer.flush(); continue; } if (command.equals(TelnetCommand.LOOKUP)) { StringBuilder sb = new StringBuilder(30); Iterator<String> i = lookup().iterator(); while (i.hasNext()) { String appInfo = i.next(); sb.append(appInfo); if (i.hasNext()) { sb.append("\n"); } } if (sb.toString().isEmpty()) { writer.println(AppLocale.getI18n("messageTelnetEmptyResults")); } else { writer.println(sb.toString()); } writer.print(promptSymbol); writer.flush(); continue; } if (command.equals(TelnetCommand.EXIT)) { client.close(); break; } if (command.equals(TelnetCommand.VERSION)) { writer.println(version()); writer.print(promptSymbol); writer.flush(); continue; } } } } catch (IOException ex) { LOG.error(AppLocale.getI18n("errorUnableToCommunicateWithAdminDaemon", new Object[]{ex.getMessage()})); } } /** * Stop the TelnetServer */ public abstract void stop(); /** * List all * <code>server</code> configurations. */ public abstract String system(); /** * Returns the version of the running server. * * @return server instance version. */ public abstract String version(); }