comparison app/src/main/java/com/five_ten_sg/connectbot/service/Relay.java @ 438:d29cce60f393

migrate from Eclipse to Android Studio
author Carl Byington <carl@five-ten-sg.com>
date Thu, 03 Dec 2015 11:23:55 -0800
parents src/com/five_ten_sg/connectbot/service/Relay.java@766176d84e73
children
comparison
equal deleted inserted replaced
437:208b31032318 438:d29cce60f393
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 import java.util.Timer;
28 import java.util.TimerTask;
29
30 import org.apache.harmony.niochar.charset.additional.IBM437;
31
32 import com.five_ten_sg.connectbot.transport.AbsTransport;
33 import android.graphics.Paint;
34 import android.text.AndroidCharacter;
35 import android.util.Log;
36 import de.mud.terminal.vt320;
37
38 /**
39 * @author Kenny Root
40 */
41 public class Relay implements Runnable {
42 private static final String TAG = "ConnectBot.Relay";
43
44 private static final int BUFFER_SIZE = 4096;
45
46 private TerminalBridge bridge;
47
48 private Charset currentCharset;
49 private CharsetDecoder decoder;
50
51 private AbsTransport transport;
52
53 private vt320 buffer;
54
55 private ByteBuffer byteBuffer;
56 private CharBuffer charBuffer;
57
58 private byte[] byteArray;
59 private char[] charArray;
60
61 private void eastAsianWidthMeasure(char[] charArray, int start, int end,
62 byte[] wideAttribute, Paint paint, int charWidth) {
63 AndroidCharacter.getEastAsianWidths(charArray, start, end - start, wideAttribute);
64 }
65
66 public Relay(TerminalBridge bridge, AbsTransport transport, vt320 buffer, String encoding) {
67 setCharset(encoding);
68 this.bridge = bridge;
69 this.transport = transport;
70 this.buffer = buffer;
71 }
72
73 public void setCharset(String encoding) {
74 Log.d("ConnectBot.Relay", "changing charset to " + encoding);
75 Charset charset;
76
77 if (encoding.equals("CP437"))
78 charset = new IBM437("IBM437",
79 new String[] { "IBM437", "CP437" });
80 else
81 charset = Charset.forName(encoding);
82
83 if (charset == currentCharset || charset == null)
84 return;
85
86 CharsetDecoder newCd = charset.newDecoder();
87 newCd.onUnmappableCharacter(CodingErrorAction.REPLACE);
88 newCd.onMalformedInput(CodingErrorAction.REPLACE);
89 currentCharset = charset;
90
91 synchronized (this) {
92 decoder = newCd;
93 }
94 }
95
96 public Charset getCharset() {
97 return currentCharset;
98 }
99
100 public void run() {
101 byteBuffer = ByteBuffer.allocate(BUFFER_SIZE);
102 charBuffer = CharBuffer.allocate(BUFFER_SIZE);
103 /* for East Asian character widths */
104 byte[] wideAttribute = new byte[BUFFER_SIZE];
105 byteArray = byteBuffer.array();
106 charArray = charBuffer.array();
107 CoderResult result;
108 int bytesRead = 0;
109 byteBuffer.limit(0);
110 int bytesToRead;
111 int offset;
112 int charWidth;
113 Timer timer = new Timer("relay.blocker", true);
114 TimerTask task = null;
115
116 try {
117 while (true) {
118 charWidth = bridge.charWidth;
119 bytesToRead = byteBuffer.capacity() - byteBuffer.limit();
120 offset = byteBuffer.arrayOffset() + byteBuffer.limit();
121
122 if (transport.willBlock()) {
123 task = new TimerTask() {
124 public void run() {
125 buffer.testChanged();
126 }
127 };
128 timer.schedule(task, 10); // 10 ms delay
129 }
130
131 bytesRead = transport.read(byteArray, offset, bytesToRead);
132
133 if (task != null) {
134 task.cancel();
135 task = null;
136 }
137
138 if (bytesRead > 0) {
139 byteBuffer.limit(byteBuffer.limit() + bytesRead);
140
141 synchronized (this) {
142 result = decoder.decode(byteBuffer, charBuffer, false);
143 }
144
145 if (result.isUnderflow() &&
146 byteBuffer.limit() == byteBuffer.capacity()) {
147 byteBuffer.compact();
148 byteBuffer.limit(byteBuffer.position());
149 byteBuffer.position(0);
150 }
151
152 offset = charBuffer.position();
153 eastAsianWidthMeasure(charArray, 0, offset, wideAttribute, bridge.defaultPaint, charWidth);
154 buffer.putString(charArray, wideAttribute, 0, charBuffer.position());
155 bridge.propagateConsoleText(charArray, charBuffer.position());
156 charBuffer.clear();
157 bridge.redraw();
158 }
159 }
160 }
161 catch (IOException e) {
162 Log.e(TAG, "Problem while handling incoming data in relay thread", e);
163 }
164
165 timer.cancel();
166 }
167 }