comparison src/com/five_ten_sg/connectbot/service/Relay.java @ 0:0ce5cc452d02

initial version
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 10:41:19 -0700
parents
children 77ac18bc1b2f
comparison
equal deleted inserted replaced
-1:000000000000 0:0ce5cc452d02
1 /*
2 * ConnectBot: simple, powerful, open-source SSH client for Android
3 * Copyright 2007 Kenny Root, Jeffrey Sharkey
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package com.five_ten_sg.connectbot.service;
19
20 import java.io.IOException;
21 import java.nio.ByteBuffer;
22 import java.nio.CharBuffer;
23 import java.nio.charset.Charset;
24 import java.nio.charset.CharsetDecoder;
25 import java.nio.charset.CoderResult;
26 import java.nio.charset.CodingErrorAction;
27
28 import org.apache.harmony.niochar.charset.additional.IBM437;
29
30 import com.five_ten_sg.connectbot.transport.AbsTransport;
31 import android.graphics.Paint;
32 import android.text.AndroidCharacter;
33 import android.util.Log;
34 import de.mud.terminal.vt320;
35
36 /**
37 * @author Kenny Root
38 */
39 public class Relay implements Runnable {
40 private static final String TAG = "ConnectBot.Relay";
41
42 private static final int BUFFER_SIZE = 4096;
43
44 private TerminalBridge bridge;
45
46 private Charset currentCharset;
47 private CharsetDecoder decoder;
48
49 private AbsTransport transport;
50
51 private vt320 buffer;
52
53 private ByteBuffer byteBuffer;
54 private CharBuffer charBuffer;
55
56 private byte[] byteArray;
57 private char[] charArray;
58
59 private void eastAsianWidthMeasure(char[] charArray, int start, int end,
60 byte[] wideAttribute, Paint paint, int charWidth) {
61 AndroidCharacter.getEastAsianWidths(charArray, start, end - start, wideAttribute);
62 }
63
64 public Relay(TerminalBridge bridge, AbsTransport transport, vt320 buffer, String encoding) {
65 setCharset(encoding);
66 this.bridge = bridge;
67 this.transport = transport;
68 this.buffer = buffer;
69 }
70
71 public void setCharset(String encoding) {
72 Log.d("ConnectBot.Relay", "changing charset to " + encoding);
73 Charset charset;
74
75 if (encoding.equals("CP437"))
76 charset = new IBM437("IBM437",
77 new String[] { "IBM437", "CP437" });
78 else
79 charset = Charset.forName(encoding);
80
81 if (charset == currentCharset || charset == null)
82 return;
83
84 CharsetDecoder newCd = charset.newDecoder();
85 newCd.onUnmappableCharacter(CodingErrorAction.REPLACE);
86 newCd.onMalformedInput(CodingErrorAction.REPLACE);
87 currentCharset = charset;
88
89 synchronized (this) {
90 decoder = newCd;
91 }
92 }
93
94 public Charset getCharset() {
95 return currentCharset;
96 }
97
98 public void run() {
99 byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
100 charBuffer = CharBuffer.allocate(BUFFER_SIZE);
101 /* for East Asian character widths */
102 byte[] wideAttribute = new byte[BUFFER_SIZE];
103 byteArray = byteBuffer.array();
104 charArray = charBuffer.array();
105 CoderResult result;
106 int bytesRead = 0;
107 byteBuffer.limit(0);
108 int bytesToRead;
109 int offset;
110 int charWidth;
111
112 try {
113 while (true) {
114 charWidth = bridge.charWidth;
115 bytesToRead = byteBuffer.capacity() - byteBuffer.limit();
116 offset = byteBuffer.arrayOffset() + byteBuffer.limit();
117 if (transport.willBlock()) buffer.testChanged();
118 bytesRead = transport.read(byteArray, offset, bytesToRead);
119
120 if (bytesRead > 0) {
121 byteBuffer.limit(byteBuffer.limit() + bytesRead);
122
123 synchronized (this) {
124 result = decoder.decode(byteBuffer, charBuffer, false);
125 }
126
127 if (result.isUnderflow() &&
128 byteBuffer.limit() == byteBuffer.capacity()) {
129 byteBuffer.compact();
130 byteBuffer.limit(byteBuffer.position());
131 byteBuffer.position(0);
132 }
133
134 offset = charBuffer.position();
135 eastAsianWidthMeasure(charArray, 0, offset, wideAttribute, bridge.defaultPaint, charWidth);
136 buffer.putString(charArray, wideAttribute, 0, charBuffer.position());
137 bridge.propagateConsoleText(charArray, charBuffer.position());
138 charBuffer.clear();
139 bridge.redraw();
140 }
141 }
142 }
143 catch (IOException e) {
144 Log.e(TAG, "Problem while handling incoming data in relay thread", e);
145 }
146 }
147 }