Mercurial > 510Connectbot
view src/com/five_ten_sg/connectbot/transport/TN5250.java @ 41:9621ac4dd5eb tn5250
start tn5250 integration
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 10 Jun 2014 17:40:09 -0700 |
parents | 0395ca628303 |
children | 6b0f1ece1d91 |
line wrap: on
line source
/* * 510ConnectBot * Copyright 2014 Carl Byington * * 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 com.five_ten_sg.connectbot.transport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.tn5250j.framework.tn5250.Screen5250; import org.tn5250j.framework.tn5250.tnvt; import com.five_ten_sg.connectbot.R; import com.five_ten_sg.connectbot.bean.HostBean; import com.five_ten_sg.connectbot.bean.PortForwardBean; import com.five_ten_sg.connectbot.service.TerminalBridge; import com.five_ten_sg.connectbot.service.TerminalKeyListener; import com.five_ten_sg.connectbot.service.TerminalManager; import com.five_ten_sg.connectbot.util.HostDatabase; import android.content.Context; import android.net.Uri; import android.util.Log; import de.mud.terminal.vt320; /** * @author Carl Byington * */ public class TN5250 extends AbsTransport { private static final String PROTOCOL = "tn5250"; private static final String TAG = "ConnectBot.tn5250"; private static final int DEFAULT_PORT = 23; private Screen5250 screen52; private tnvt handler = null; private Socket socket; private boolean connected = false; static final Pattern hostmask; static { hostmask = Pattern.compile("^([0-9a-z.-]+)(:(\\d+))?$", Pattern.CASE_INSENSITIVE); } public TN5250() { super(); } /** * @return protocol part of the URI */ public static String getProtocolName() { return PROTOCOL; } /** * Encode the current transport into a URI that can be passed via intent calls. * @return URI to host */ public Uri getUri(String input) { Matcher matcher = hostmask.matcher(input); if (!matcher.matches()) return null; StringBuilder sb = new StringBuilder(); sb.append(PROTOCOL) .append("://") .append(matcher.group(1)); String portString = matcher.group(3); int port = DEFAULT_PORT; if (portString != null) { try { port = Integer.parseInt(portString); if (port < 1 || port > 65535) { port = DEFAULT_PORT; } } catch (NumberFormatException nfe) { // Keep the default port } } if (port != DEFAULT_PORT) { sb.append(':'); sb.append(port); } sb.append("/#") .append(Uri.encode(input)); Uri uri = Uri.parse(sb.toString()); return uri; } /** * Causes transport to connect to the target host. After connecting but before a * session is started, must call back to {@link TerminalBridge#onConnected()}. * After that call a session may be opened. */ @Override public void connect() { screen52 = new Screen5250(); handler = new tnvt(screen52, true, false, bridge, manager); handler.setSSLType("TLS"); screen52.setVT(handler); screen52.setBuffer(buffer); connected = handler.connect(host.getHostname(), host.getPort()); if (connected) bridge.onConnected(); } /** * Checks if read() will block. If there are no bytes remaining in * the underlying transport, return true. */ @Override public boolean willBlock() { // we don't use a relay thread between the transport and the vt320 buffer return true; } /** * Reads from the transport. Transport must support reading into a byte array * <code>buffer</code> at the start of <code>offset</code> and a maximum of * <code>length</code> bytes. If the remote host disconnects, throw an * {@link IOException}. * @param buffer byte buffer to store read bytes into * @param offset where to start writing in the buffer * @param length maximum number of bytes to read * @return number of bytes read * @throws IOException when remote host disconnects */ public int read(byte[] buffer, int offset, int length) throws IOException { // we don't use a relay thread between the transport and the vt320 buffer return 0; } /** * Writes to the transport. If the host is not yet connected, simply return without * doing anything. An {@link IOException} should be thrown if there is an error after * connection. * @param buffer bytes to write to transport * @throws IOException when there is a problem writing after connection */ public void write(byte[] buffer) throws IOException { } /** * Writes to the transport. See {@link #write(byte[])} for behavior details. * @param c character to write to the transport * @throws IOException when there is a problem writing after connection */ public void write(int c) throws IOException { } /** * Flushes the write commands to the transport. * @throws IOException when there is a problem writing after connection */ public void flush() throws IOException { } /** * Closes the connection to the terminal. */ public void close() { handler.disconnect(); connected = false; bridge.dispatchDisconnect(false); } /** * Tells the transport what dimensions the display is currently * @param columns columns of text * @param rows rows of text * @param width width in pixels * @param height height in pixels */ @Override public void setDimensions(int columns, int rows, int width, int height) { // do nothing } @Override public int getDefaultPort() { return DEFAULT_PORT; } @Override public boolean isConnected() { return connected; } @Override public boolean isSessionOpen() { return connected; } @Override public boolean isAuthenticated() { return connected; } @Override public String getDefaultNickname(String username, String hostname, int port) { if (port == DEFAULT_PORT) { return String.format("%s", hostname); } else { return String.format("%s:%d", hostname, port); } } @Override public void getSelectionArgs(Uri uri, Map<String, String> selection) { selection.put(HostDatabase.FIELD_HOST_PROTOCOL, PROTOCOL); selection.put(HostDatabase.FIELD_HOST_NICKNAME, uri.getFragment()); selection.put(HostDatabase.FIELD_HOST_HOSTNAME, uri.getHost()); int port = uri.getPort(); if (port < 0) port = DEFAULT_PORT; selection.put(HostDatabase.FIELD_HOST_PORT, Integer.toString(port)); } @Override public HostBean createHost(Uri uri) { HostBean host = new HostBean(); host.setProtocol(PROTOCOL); host.setHostname(uri.getHost()); int port = uri.getPort(); if (port < 0) port = DEFAULT_PORT; host.setPort(port); String nickname = uri.getFragment(); if (nickname == null || nickname.length() == 0) { host.setNickname(getDefaultNickname(host.getUsername(), host.getHostname(), host.getPort())); } else { host.setNickname(uri.getFragment()); } return host; } public String getFormatHint(Context context) { return String.format("%s:%s", context.getString(R.string.format_hostname), context.getString(R.string.format_port)); } @Override public boolean usesNetwork() { return true; } @Override public boolean needsRelay() { // we don't use a relay thread between the transport and the vt320 buffer return false; } }