annotate src/com/five_ten_sg/connectbot/service/Relay.java @ 335:e25e377d29d3 ganymed

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