Mercurial > 510Connectbot
comparison app/src/main/java/org/tn5250j/framework/tn5250/DataStreamProducer.java @ 445:8fa8e73e2f5c
update to tn5250j version 0.7.7, svn r1270
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 04 Jan 2016 15:52:25 -0800 |
parents | d29cce60f393 |
children | 5ce5235adde6 |
comparison
equal
deleted
inserted
replaced
444:5a74f1b7c1db | 445:8fa8e73e2f5c |
---|---|
1 package org.tn5250j.framework.tn5250; | 1 package org.tn5250j.framework.tn5250; |
2 | 2 |
3 import java.io.BufferedInputStream; | 3 import java.io.BufferedInputStream; |
4 import java.io.BufferedOutputStream; | |
5 import java.io.ByteArrayOutputStream; | 4 import java.io.ByteArrayOutputStream; |
6 import java.io.EOFException; | |
7 import java.io.FileNotFoundException; | |
8 import java.io.FileOutputStream; | |
9 import java.io.IOException; | 5 import java.io.IOException; |
10 import java.net.SocketException; | 6 import java.net.SocketException; |
11 import java.util.concurrent.BlockingQueue; | 7 import java.util.concurrent.BlockingQueue; |
8 | |
9 import static org.tn5250j.framework.tn5250.Stream5250.OPCODE_OFFSET; | |
10 | |
12 import java.util.Timer; | 11 import java.util.Timer; |
13 import java.util.TimerTask; | 12 import java.util.TimerTask; |
14 | 13 |
15 import org.tn5250j.encoding.ICodePage; | |
16 | |
17 import android.util.Log; | 14 import android.util.Log; |
18 | 15 |
19 | 16 |
20 public class DataStreamProducer implements Runnable { | 17 public class DataStreamProducer implements Runnable { |
18 private static final int MINIMAL_PARTIAL_STREAM_LEN = 2; | |
21 private static final String TAG = "DataStreamProducer"; | 19 private static final String TAG = "DataStreamProducer"; |
22 private tnvt vt; | 20 private tnvt vt; |
23 private BufferedInputStream bin; | 21 private BufferedInputStream bin; |
24 private ByteArrayOutputStream baosin; | 22 private ByteArrayOutputStream baosin; |
25 private Thread me; | |
26 private byte[] saveStream; | 23 private byte[] saveStream; |
27 private final BlockingQueue<Object> dsq; | 24 private final BlockingQueue<Object> dsq; |
28 private byte[] abyte2; | 25 private byte[] dataStream; |
29 private FileOutputStream fw; | 26 private DataStreamDumper dataStreamDumper = new DataStreamDumper(); |
30 private BufferedOutputStream dw; | |
31 private boolean dumpBytes = false; | |
32 private ICodePage codePage; | |
33 | 27 |
34 | 28 |
35 | 29 |
36 public DataStreamProducer(tnvt vt, BufferedInputStream bin, BlockingQueue<Object> queue, byte[] init) { | 30 public DataStreamProducer(tnvt vt, BufferedInputStream bin, BlockingQueue<Object> queue, byte[] init) { |
37 this.bin = bin; | 31 this.bin = bin; |
38 this.vt = vt; | 32 this.vt = vt; |
39 baosin = new ByteArrayOutputStream(); | 33 baosin = new ByteArrayOutputStream(); |
40 dsq = queue; | 34 dsq = queue; |
41 abyte2 = init; | 35 dataStream = init; |
42 } | |
43 | |
44 public void setInputStream(ByteArrayOutputStream is) { | |
45 baosin = is; | |
46 } | 36 } |
47 | 37 |
48 public final void run() { | 38 public final void run() { |
49 boolean done = false; | 39 boolean done = false; |
50 me = Thread.currentThread(); | 40 Thread me = Thread.currentThread(); |
51 // load the first response screen | 41 // load the first response screen |
52 loadStream(abyte2, 0); | 42 loadStream(dataStream, 0); |
53 | 43 |
54 while (!done) { | 44 while (!done) { |
55 try { | 45 try { |
56 byte[] abyte0 = readIncoming(); | 46 byte[] abyte0 = readIncoming(); |
57 | 47 |
79 Log.w(TAG, " DataStreamProducer thread interrupted and stopping " + se.getMessage()); | 69 Log.w(TAG, " DataStreamProducer thread interrupted and stopping " + se.getMessage()); |
80 done = true; | 70 done = true; |
81 } | 71 } |
82 catch (IOException ioe) { | 72 catch (IOException ioe) { |
83 Log.w(TAG, ioe.getMessage()); | 73 Log.w(TAG, ioe.getMessage()); |
84 | 74 if (me.isInterrupted()) done = true; |
85 if (me.isInterrupted()) | |
86 done = true; | |
87 } | 75 } |
88 catch (Exception ex) { | 76 catch (Exception ex) { |
89 Log.w(TAG, ex.getMessage()); | 77 Log.w(TAG, ex.getMessage()); |
90 | 78 if (me.isInterrupted()) done = true; |
91 if (me.isInterrupted()) | 79 } |
92 done = true; | 80 } |
93 } | 81 } |
94 } | 82 |
95 } | 83 private void loadStream(byte streamBuffer[], int offset) { |
96 | 84 |
97 private final void loadStream(byte abyte0[], int i) { | 85 int partialLen = (streamBuffer[offset] & 0xff) << 8 | streamBuffer[offset + 1] & 0xff; |
98 int j = 0; | 86 int bufferLen = streamBuffer.length; |
99 int size = 0; | 87 |
100 | 88 Log.d(TAG, "loadStream() offset=" + offset + " partialLen=" + partialLen + " bufferLen=" + bufferLen); |
101 if (saveStream == null) { | 89 |
102 j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; | 90 if (saveStream != null) { |
103 size = abyte0.length; | 91 log.debug("partial stream found"); |
104 } | 92 bufferLen = saveStream.length + streamBuffer.length; |
105 else { | 93 byte[] inter = new byte[bufferLen]; |
106 size = saveStream.length + abyte0.length; | |
107 byte[] inter = new byte[size]; | |
108 System.arraycopy(saveStream, 0, inter, 0, saveStream.length); | 94 System.arraycopy(saveStream, 0, inter, 0, saveStream.length); |
109 System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length); | 95 System.arraycopy(streamBuffer, 0, inter, saveStream.length, streamBuffer.length); |
110 abyte0 = new byte[size]; | 96 streamBuffer = new byte[bufferLen]; |
111 System.arraycopy(inter, 0, abyte0, 0, size); | 97 System.arraycopy(inter, 0, streamBuffer, 0, bufferLen); |
112 saveStream = null; | 98 saveStream = null; |
113 inter = null; | 99 } |
114 j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; | 100 |
115 Log.d(TAG, "partial stream found"); | 101 if (partialLen > bufferLen) { |
116 } | 102 saveStream = new byte[streamBuffer.length]; |
117 | 103 Log.d(TAG, "partial stream saved"); |
118 if (j > size) { | 104 System.arraycopy(streamBuffer, 0, saveStream, 0, streamBuffer.length); |
119 saveStream = new byte[abyte0.length]; | 105 } else { |
120 System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length); | 106 int buf_len = partialLen + 2; |
121 Log.d(TAG, "partial stream saved"); | 107 byte[] buf = new byte[buf_len]; |
122 } | 108 if (isBufferShifted(partialLen, bufferLen) && isOpcodeShifted(streamBuffer, offset)) { |
123 else { | 109 log.debug("Invalid stream buffer detected. Ignoring the inserted byte."); |
124 byte abyte1[]; | 110 System.arraycopy(streamBuffer, offset, buf, 0, MINIMAL_PARTIAL_STREAM_LEN); |
125 | 111 System.arraycopy(streamBuffer, offset + MINIMAL_PARTIAL_STREAM_LEN + 1, buf, MINIMAL_PARTIAL_STREAM_LEN, partialLen); |
112 } else { | |
113 System.arraycopy(streamBuffer, offset, buf, 0, buf_len); | |
114 } | |
126 try { | 115 try { |
127 abyte1 = new byte[j + 2]; | 116 dsq.put(buf); |
128 System.arraycopy(abyte0, i, abyte1, 0, j + 2); | 117 if (streamBuffer.length > buf.length + offset + MINIMAL_PARTIAL_STREAM_LEN) |
129 dsq.put(abyte1); | 118 loadStream(streamBuffer, offset + buf_len); |
130 | 119 } catch (InterruptedException ex) { |
131 if (abyte0.length > abyte1.length + i) | 120 Log.w(TAG, "load stream error.", ex); |
132 loadStream(abyte0, i + j + 2); | 121 } |
133 } | 122 } |
134 catch (Exception ex) { | 123 } |
135 Log.w(TAG, "load stream error " + ex.getMessage()); | 124 |
136 // ex.printStackTrace(); | 125 private boolean isOpcodeShifted(byte[] streamBuffer, int offset) { |
137 // dump(abyte0); | 126 byte code = streamBuffer[offset + 1 + OPCODE_OFFSET]; |
138 } | 127 return (0 <= code && code <= 12); |
139 } | 128 } |
140 } | 129 |
141 | 130 private boolean isBufferShifted(int partialLen, int bufferLen) { |
142 public final byte[] readIncoming() | 131 return partialLen + MINIMAL_PARTIAL_STREAM_LEN + 1 == bufferLen; |
143 throws IOException { | 132 } |
133 | |
134 public final byte[] readIncoming() throws IOException { | |
144 boolean done = false; | 135 boolean done = false; |
145 boolean negotiate = false; | 136 boolean negotiate = false; |
146 baosin.reset(); | 137 baosin.reset(); |
147 int j = -1; | 138 int j = -1; |
148 int i = 0; | |
149 Timer timer = new Timer("data.stream", true); | 139 Timer timer = new Timer("data.stream", true); |
150 TimerTask task = null; | 140 TimerTask task = null; |
151 | 141 |
152 while (!done) { | 142 while (!done) { |
153 if (bin.available() == 0) { | 143 if (bin.available() == 0) { |
162 } | 152 } |
163 }; | 153 }; |
164 timer.schedule(task, 10); // 10 ms delay | 154 timer.schedule(task, 10); // 10 ms delay |
165 } | 155 } |
166 | 156 |
167 i = bin.read(); | 157 int i = bin.read(); |
168 | 158 |
169 if (task != null) { | 159 if (task != null) { |
170 task.cancel(); | 160 task.cancel(); |
171 task = null; | 161 task = null; |
172 } | 162 } |
233 // We should not return the bytes; | 223 // We should not return the bytes; |
234 // ==> restructured to return null after negotiation! | 224 // ==> restructured to return null after negotiation! |
235 // Impacts the run method! Added the null check. | 225 // Impacts the run method! Added the null check. |
236 byte[] rBytes = baosin.toByteArray(); | 226 byte[] rBytes = baosin.toByteArray(); |
237 | 227 |
238 if (dumpBytes) { | 228 dataStreamDumper.dump(rBytes); |
239 dump(rBytes); | |
240 } | |
241 | 229 |
242 if (negotiate) { | 230 if (negotiate) { |
243 if (bin.available() == 0) { | 231 if (bin.available() == 0) { |
244 task = new TimerTask() { | 232 task = new TimerTask() { |
245 public void run() { | 233 public void run() { |
267 } | 255 } |
268 | 256 |
269 return rBytes; | 257 return rBytes; |
270 } | 258 } |
271 | 259 |
272 protected final void toggleDebug(ICodePage cp) { | 260 protected void toggleDebug(ICodePage codePage) { |
273 if (codePage == null) | 261 dataStreamDumper.toggleDebug(codePage); |
274 codePage = cp; | 262 } |
275 | 263 |
276 dumpBytes = !dumpBytes; | |
277 | |
278 if (dumpBytes) { | |
279 try { | |
280 if (fw == null) { | |
281 fw = new FileOutputStream("log.txt"); | |
282 dw = new BufferedOutputStream(fw); | |
283 } | |
284 } | |
285 catch (FileNotFoundException fnfe) { | |
286 Log.w(TAG, fnfe.getMessage()); | |
287 } | |
288 } | |
289 else { | |
290 try { | |
291 if (dw != null) | |
292 dw.close(); | |
293 | |
294 if (fw != null) | |
295 fw.close(); | |
296 | |
297 dw = null; | |
298 fw = null; | |
299 codePage = null; | |
300 } | |
301 catch (IOException ioe) { | |
302 Log.w(TAG, ioe.getMessage()); | |
303 } | |
304 } | |
305 | |
306 Log.i(TAG, "Data Stream output is now " + dumpBytes); | |
307 } | |
308 | |
309 public void dump(byte[] abyte0) { | |
310 try { | |
311 Log.i(TAG, "\n Buffer Dump of data from AS400: "); | |
312 dw.write("\r\n Buffer Dump of data from AS400: ".getBytes()); | |
313 StringBuffer h = new StringBuffer(); | |
314 | |
315 for (int x = 0; x < abyte0.length; x++) { | |
316 if (x % 16 == 0) { | |
317 System.out.println(" " + h.toString()); | |
318 dw.write((" " + h.toString() + "\r\n").getBytes()); | |
319 h.setLength(0); | |
320 h.append("+0000"); | |
321 h.setLength(5 - Integer.toHexString(x).length()); | |
322 h.append(Integer.toHexString(x).toUpperCase()); | |
323 System.out.print(h.toString()); | |
324 dw.write(h.toString().getBytes()); | |
325 h.setLength(0); | |
326 } | |
327 | |
328 char ac = codePage.ebcdic2uni(abyte0[x]); | |
329 | |
330 if (ac < ' ') | |
331 h.append('.'); | |
332 else | |
333 h.append(ac); | |
334 | |
335 if (x % 4 == 0) { | |
336 System.out.print(" "); | |
337 dw.write((" ").getBytes()); | |
338 } | |
339 | |
340 if (Integer.toHexString(abyte0[x] & 0xff).length() == 1) { | |
341 System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); | |
342 dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); | |
343 } | |
344 else { | |
345 System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); | |
346 dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); | |
347 } | |
348 } | |
349 | |
350 System.out.println(); | |
351 dw.write("\r\n".getBytes()); | |
352 dw.flush(); | |
353 } | |
354 catch (EOFException _ex) { } | |
355 catch (Exception _ex) { | |
356 Log.w(TAG, "Cannot dump from host\n\r"); | |
357 } | |
358 } | |
359 | |
360 // public void dumpBytes() { | |
361 // byte shit[] = bk.buffer; | |
362 // for (int i = 0;i < shit.length;i++) | |
363 // System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<"); | |
364 // } | |
365 // | |
366 // public void dumpHexBytes(byte[] abyte) { | |
367 // byte shit[] = abyte; | |
368 // for (int i = 0;i < shit.length;i++) | |
369 // System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff))); | |
370 // } | |
371 | |
372 } |