Mercurial > 510Connectbot
annotate src/org/tn5250j/framework/tn5250/DataStreamProducer.java @ 70:c56032728742 tn5250
use 5250 encryption config entry
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 13 Jun 2014 19:07:34 -0700 |
parents | 294435151b0c |
children | 8181cb01c64d |
rev | line source |
---|---|
3 | 1 package org.tn5250j.framework.tn5250; |
2 | |
3 import java.io.BufferedInputStream; | |
4 import java.io.BufferedOutputStream; | |
5 import java.io.ByteArrayOutputStream; | |
6 import java.io.EOFException; | |
7 import java.io.FileNotFoundException; | |
8 import java.io.FileOutputStream; | |
9 import java.io.IOException; | |
10 import java.net.SocketException; | |
11 import java.util.concurrent.BlockingQueue; | |
12 | |
13 import org.tn5250j.encoding.ICodePage; | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
14 import android.util.Log; |
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
15 |
3 | 16 |
17 public class DataStreamProducer implements Runnable { | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
18 private static final String TAG = "DataStreamProducer"; |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
19 private tnvt vt; |
3 | 20 private BufferedInputStream bin; |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
21 private vt320 buffer; |
3 | 22 private ByteArrayOutputStream baosin; |
23 private Thread me; | |
24 private byte[] saveStream; | |
25 private final BlockingQueue<Object> dsq; | |
26 private byte[] abyte2; | |
27 private FileOutputStream fw; | |
28 private BufferedOutputStream dw; | |
29 private boolean dumpBytes = false; | |
30 private ICodePage codePage; | |
31 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
32 |
3 | 33 |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
34 public DataStreamProducer(tnvt vt, BufferedInputStream bin, vt320 buffer, BlockingQueue<Object> queue, byte[] init) { |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
35 this.bin = bin; |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
36 this.vt = vt; |
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
37 this.buffer = buffer; |
3 | 38 baosin = new ByteArrayOutputStream(); |
39 dsq = queue; | |
40 abyte2 = init; | |
41 } | |
42 | |
43 public void setInputStream(ByteArrayOutputStream is) { | |
44 | |
45 baosin = is; | |
46 | |
47 } | |
48 | |
49 public final void run() { | |
50 | |
51 boolean done = false; | |
52 | |
53 me = Thread.currentThread(); | |
54 | |
55 // load the first response screen | |
56 loadStream(abyte2, 0); | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
57 |
3 | 58 while (!done) { |
59 try { | |
60 | |
61 byte[] abyte0 = readIncoming(); | |
62 | |
63 // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK | |
64 // Restructured to the readIncoming() method to return null | |
65 // on TIMING MARK. Don't process in that case (abyte0 == null)! | |
66 if (abyte0 != null) | |
67 { | |
68 // WVL - LDC : 16/07/2003 : TR.000345 | |
69 // When the socket has been closed, the reading returns | |
70 // no bytes (an empty byte arrray). | |
71 // But the loadStream fails on this, so we check it here! | |
72 if (abyte0.length > 0) | |
73 { | |
74 loadStream(abyte0, 0); | |
75 } | |
76 // WVL - LDC : 16/07/2003 : TR.000345 | |
77 // Returning no bytes means the input buffer has | |
78 // reached end-of-stream, so we do a disconnect! | |
79 else | |
80 { | |
81 done = true; | |
82 vt.disconnect(); | |
83 } | |
84 } | |
85 | |
86 } | |
87 | |
88 catch (SocketException se) { | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
89 Log.w(TAG," DataStreamProducer thread interrupted and stopping " + se.getMessage()); |
3 | 90 done = true; |
91 } | |
92 | |
93 catch (IOException ioe) { | |
94 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
95 Log.w(TAG,ioe.getMessage()); |
3 | 96 if (me.isInterrupted()) |
97 done = true; | |
98 | |
99 } | |
100 catch (Exception ex) { | |
101 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
102 Log.w(TAG,ex.getMessage()); |
3 | 103 if (me.isInterrupted()) |
104 done = true; | |
105 | |
106 } | |
107 } | |
108 } | |
109 | |
110 private final void loadStream(byte abyte0[], int i) { | |
111 | |
112 int j = 0; | |
113 int size = 0; | |
114 if (saveStream == null) { | |
115 j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; | |
116 size = abyte0.length; | |
117 } | |
118 else { | |
119 size = saveStream.length + abyte0.length; | |
120 byte[] inter = new byte[size]; | |
121 System.arraycopy(saveStream, 0, inter, 0, saveStream.length); | |
122 System.arraycopy(abyte0, 0, inter, saveStream.length, abyte0.length); | |
123 abyte0 = new byte[size]; | |
124 System.arraycopy(inter, 0, abyte0, 0, size); | |
125 saveStream = null; | |
126 inter = null; | |
127 j = (abyte0[i] & 0xff) << 8 | abyte0[i + 1] & 0xff; | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
128 Log.d(TAG,"partial stream found"); |
3 | 129 } |
130 | |
131 if (j > size) { | |
132 saveStream = new byte[abyte0.length]; | |
133 System.arraycopy(abyte0, 0, saveStream, 0, abyte0.length); | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
134 Log.d(TAG,"partial stream saved"); |
3 | 135 } |
136 else { | |
137 byte abyte1[]; | |
138 try { | |
139 abyte1 = new byte[j + 2]; | |
140 | |
141 System.arraycopy(abyte0, i, abyte1, 0, j + 2); | |
142 dsq.put(abyte1); | |
143 if(abyte0.length > abyte1.length + i) | |
144 loadStream(abyte0, i + j + 2); | |
145 } | |
146 catch (Exception ex) { | |
147 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
148 Log.w(TAG,"load stream error " + ex.getMessage()); |
3 | 149 // ex.printStackTrace(); |
150 // dump(abyte0); | |
151 | |
152 } | |
153 } | |
154 } | |
155 | |
156 public final byte[] readIncoming() | |
157 throws IOException { | |
158 | |
159 boolean done = false; | |
160 boolean negotiate = false; | |
161 | |
162 baosin.reset(); | |
163 int j = -1; | |
164 int i = 0; | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
165 |
3 | 166 while(!done) { |
69
294435151b0c
use 5250 encryption config entry
Carl Byington <carl@five-ten-sg.com>
parents:
25
diff
changeset
|
167 if (bin.available() == 0) buffer.testChanged(); |
3 | 168 i = bin.read(); |
169 | |
170 // WVL - LDC : 16/07/2003 : TR.000345 | |
171 // The inStream return -1 when end-of-stream is reached. This | |
172 // happens e.g. when the connection is closed from the AS/400. | |
173 // So we stop in this case! | |
174 // ==> an empty byte array is returned from this method. | |
175 if (i == -1) // nothing read! | |
176 { | |
177 done = true; | |
178 vt.disconnect(); | |
179 continue; | |
180 } | |
181 | |
182 // We use the values instead of the static values IAC and EOR | |
183 // because they are defined as bytes. | |
184 // | |
185 // The > if(i != 255 || j != 255) < is a hack for the double FF FF's | |
186 // that are being returned. I do not know why this is like this and | |
187 // can not find any documentation for it. It is also being returned | |
188 // on my Client Access tcp dump as well so they are handling it. | |
189 // | |
190 // my5250 | |
191 // 0000: 00 50 DA 44 C8 45 42 00 00 00 00 24 08 00 45 00 .P.D.EB....$..E. | |
192 // 0010: 04 2A BC F9 00 00 40 06 D0 27 C1 A8 33 04 C1 A8 .*....@..'..3... | |
193 // 0020: 33 58 00 17 04 18 6F A2 83 CB 00 1E D1 BA 50 18 3X....o.......P. | |
194 // 0030: 20 00 8A 9A 00 00 03 FF FF 12 A0 00 00 04 00 00 ............... | |
195 // --------------------------- || || ------------------------------------- | |
196 // 0040: 03 04 40 04 11 00 20 01 07 00 00 00 18 00 00 10 ..@... ......... | |
197 | |
198 if(j == 255 && i == 255) { | |
199 j = -1; | |
200 continue; | |
201 } | |
202 baosin.write(i); | |
203 // check for end of record EOR and IAC - FFEF | |
204 if(j == 255 && i == 239) | |
205 done = true; | |
206 | |
207 // This is to check for the TELNET TIMING MARK OPTION | |
208 // rfc860 explains this in more detail. When we receive it | |
209 // we will negotiate with the server by sending a WONT'T TIMING-MARK | |
210 // This will let the server know that we processed the information | |
211 // and are just waiting for the user to enter some data so keep the | |
212 // socket alive. This is more or less a AYT (ARE YOU THERE) or not. | |
213 if(i == 253 && j == 255) { | |
214 done = true; | |
215 negotiate = true; | |
216 } | |
217 j = i; | |
218 } | |
219 | |
220 // after the initial negotiation we might get other options such as | |
221 // timing marks ?????????????? do we ???????????? look at telnet spec | |
222 // yes we do. rfc860 explains about timing marks. | |
223 | |
224 // WVL - LDC : 17/05/2004 : Device name negotiations send TIMING MARK | |
225 // to existing device! | |
226 // Handled incorrectly: we cannot continue processing the TIMING MARK DO | |
227 // after we have handled it in the vt.negotiate() | |
228 // We should not return the bytes; | |
229 // ==> restructured to return null after negotiation! | |
230 // Impacts the run method! Added the null check. | |
231 byte[] rBytes = baosin.toByteArray(); | |
232 | |
233 if (dumpBytes) { | |
234 dump(rBytes); | |
235 } | |
236 | |
237 if (negotiate) { | |
238 // get the negotiation option | |
239 baosin.write(bin.read()); | |
240 vt.negotiate(rBytes); | |
241 | |
242 return null; | |
243 } | |
244 return rBytes; | |
245 } | |
246 | |
247 protected final void toggleDebug (ICodePage cp) { | |
248 | |
249 if (codePage == null) | |
250 codePage = cp; | |
251 | |
252 dumpBytes = !dumpBytes; | |
253 if (dumpBytes) { | |
254 | |
255 try { | |
256 if (fw == null) { | |
257 fw = new FileOutputStream("log.txt"); | |
258 dw = new BufferedOutputStream(fw); | |
259 } | |
260 } | |
261 catch (FileNotFoundException fnfe) { | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
262 Log.w(TAG,fnfe.getMessage()); |
3 | 263 } |
264 | |
265 } | |
266 else { | |
267 | |
268 try { | |
269 | |
270 if (dw != null) | |
271 dw.close(); | |
272 if (fw != null) | |
273 fw.close(); | |
274 dw = null; | |
275 fw = null; | |
276 codePage = null; | |
277 } | |
278 catch(IOException ioe) { | |
279 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
280 Log.w(TAG,ioe.getMessage()); |
3 | 281 } |
282 } | |
283 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
284 Log.i(TAG,"Data Stream output is now " + dumpBytes); |
3 | 285 } |
286 | |
287 public void dump (byte[] abyte0) { | |
288 try { | |
289 | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
290 Log.i(TAG,"\n Buffer Dump of data from AS400: "); |
3 | 291 dw.write("\r\n Buffer Dump of data from AS400: ".getBytes()); |
292 | |
293 StringBuffer h = new StringBuffer(); | |
294 for (int x = 0; x < abyte0.length; x++) { | |
295 if (x % 16 == 0) { | |
296 System.out.println(" " + h.toString()); | |
297 dw.write((" " + h.toString() + "\r\n").getBytes()); | |
298 | |
299 h.setLength(0); | |
300 h.append("+0000"); | |
301 h.setLength(5 - Integer.toHexString(x).length()); | |
302 h.append(Integer.toHexString(x).toUpperCase()); | |
303 | |
304 System.out.print(h.toString()); | |
305 dw.write(h.toString().getBytes()); | |
306 | |
307 h.setLength(0); | |
308 } | |
309 char ac = codePage.ebcdic2uni(abyte0[x]); | |
310 if (ac < ' ') | |
311 h.append('.'); | |
312 else | |
313 h.append(ac); | |
314 if (x % 4 == 0) { | |
315 System.out.print(" "); | |
316 dw.write((" ").getBytes()); | |
317 | |
318 } | |
319 | |
320 if (Integer.toHexString(abyte0[x] & 0xff).length() == 1){ | |
321 System.out.print("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); | |
322 dw.write(("0" + Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); | |
323 | |
324 } | |
325 else { | |
326 System.out.print(Integer.toHexString(abyte0[x] & 0xff).toUpperCase()); | |
327 dw.write((Integer.toHexString(abyte0[x] & 0xff).toUpperCase()).getBytes()); | |
328 } | |
329 | |
330 } | |
331 System.out.println(); | |
332 dw.write("\r\n".getBytes()); | |
333 | |
334 dw.flush(); | |
335 } | |
336 catch(EOFException _ex) { } | |
337 catch(Exception _ex) { | |
25
5949eb469a79
adding tn5250 files, native android logging
Carl Byington <carl@five-ten-sg.com>
parents:
3
diff
changeset
|
338 Log.w(TAG,"Cannot dump from host\n\r"); |
3 | 339 } |
340 | |
341 } | |
342 | |
343 // public void dumpBytes() { | |
344 // byte shit[] = bk.buffer; | |
345 // for (int i = 0;i < shit.length;i++) | |
346 // System.out.println(i + ">" + shit[i] + "< - ascii - >" + getASCIIChar(shit[i]) + "<"); | |
347 // } | |
348 // | |
349 // public void dumpHexBytes(byte[] abyte) { | |
350 // byte shit[] = abyte; | |
351 // for (int i = 0;i < shit.length;i++) | |
352 // System.out.println(i + ">" + shit[i] + "< hex >" + Integer.toHexString((shit[i] & 0xff))); | |
353 // } | |
354 | |
355 } |