Source code: org/apache/derby/impl/drda/DDMReader.java
1 /*
2
3 Derby - Class org.apache.derby.impl.drda.DDMReader
4
5 Copyright 2001, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.impl.drda;
22 import org.apache.derby.iapi.services.sanity.SanityManager;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.math.BigDecimal;
27
28 /**
29 The DDMReader is used to read DRDA protocol. DRDA Protocol is divided into
30 three layers corresponding to the DDM three-tier architecture. For each layer,
31 their is a DSS (Data Stream Structure) defined.
32 Layer A Communications management services
33 Layer B Agent services
34 Layer C Data management services
35 <P>
36 At layer A are request, reply and data correlation, structure chaining,
37 continuation or termination of chains when errors are detected, interleaving
38 and multi-leaving request, reply, and data DSSs for multitasking environments.
39 For TCP/IP, the format of the DDM envelope is
40 2 bytes Length of the data
41 1 byte 'D0' - indicates DDM data
42 1 byte DDM format byte(DSSFMT) - type of DSS(RQSDSS,RPYDSS), whether it is
43 chained, information about the next chained DSS
44 2 bytes request correlation identifier
45 <P>
46 The correlation identifier ties together a request, the request data and the
47 reply. In a chained DSS, each request has a correlation identifier which
48 is higher than the previous request (all correlation identifiers must
49 be greater than 0).
50 <P>
51 At layer B are object mapping, object validation and command routing.
52 Layer B objects with data 5 bytes less than 32K bytes consist of
53 2 bytes Length
54 2 bytes Type of the object (code point)
55 Object data
56 Object data is either SCALAR or COLLECTION data. Scalar data consists of
57 a string of bytes formatted as the class description of the object required.
58 Collections consist of a set of objects in which the entries in the collection
59 are nested within the length/ code point of the collection.
60 <P>
61 Layer B objects with data >=32763 bytes long format is
62 2 bytes Length - length of class, length, and extended total length fields
63 (high order bit set, indicating >=32763)
64 2 bytes Type of the object (code point)
65 n bytes Extended total length - length of the object
66 (n = Length - 4)
67 Object data
68 <P>
69 At layer C are services each class of DDM object provides.
70
71 |-------------------------------------------|
72 Layer C | Specific | Specific | Specific |
73 | Commands | Replies | Scalars and |
74 | and their | and their | Collections |
75 |-------------------------------------------|----------------|
76 Layer B | Commands | Reply | Scalars and | Communications |
77 | | Messages | Collections | |
78 |-----------|---------------|---------------|----------------|
79 Layer A | RQSDSS | RPYDSS | OBJDSS | CMNDSS |
80 | | | | Mapped Data |
81 |-----------|---------------|---------------|----------------|
82 | DDM Data Stream Structures |
83 |------------------------------------------------------------|
84
85 DSS's may be chained so that more than one can be transmitted at a time
86 to improve performance.
87 For more details, see DRDA Volume 3 (Distributed Data Management(DDM)
88 Architecture (DDS definition)
89 */
90 class DDMReader
91 {
92 private final static int DEFAULT_BUFFER_SIZE = 32767;
93 private final static int MAX_MARKS_NESTING = 10;
94 private final static int NO_CODEPOINT = -1;
95 private final static int EMPTY_STACK = -1;
96 private final static boolean ADJUST_LENGTHS = true;
97 private final static boolean NO_ADJUST_LENGTHS = false;
98 private final static long MAX_EXTDTA_SIZE= Long.MAX_VALUE;
99 private static boolean internalTrace = true;
100
101 // magnitude represented in an int array, used in BigDecimal conversion
102 private static final int[][] tenRadixMagnitude = {
103 { 0x3b9aca00 }, // 10^9
104 { 0x0de0b6b3, 0xa7640000 }, // 10^18
105 { 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27
106 };
107
108 private DRDAConnThread agent;
109 private CcsidManager ccsidManager;
110
111 // data buffer
112 private byte[] buffer;
113 private int pos;
114 private int count;
115
116 // DDM object collection
117 // top of stack
118 private int topDdmCollectionStack;
119 // length of each object in the stack
120 private long[] ddmCollectionLenStack;
121
122 // DDM object length
123 private long ddmScalarLen;
124
125 // DSS Length
126 private int dssLength;
127
128 // DSS is larger than 32762 (continuation bit is set) so DSS is continued
129 private boolean dssIsContinued;
130
131 private boolean terminateChainOnErr;
132
133 // next DSS in the chain has the same correlator
134 private boolean dssIsChainedWithSameID;
135
136 // next DSS in the chain has a different correlator
137 private boolean dssIsChainedWithDiffID;
138
139 // correlation id for the current DSS
140 private int dssCorrelationID;
141
142 // previous corelation id
143 private int prevCorrelationID;
144
145 // current server codepoint
146 private int svrcod;
147
148 // trace object of the associated session
149 private DssTrace dssTrace;
150
151 // input stream
152 private InputStream inputStream;
153
154 // constructor
155 protected DDMReader (DRDAConnThread agent, DssTrace dssTrace)
156 {
157 buffer = new byte[DEFAULT_BUFFER_SIZE];
158 ddmCollectionLenStack = new long[MAX_MARKS_NESTING];
159 initialize(agent, dssTrace);
160 }
161 /**
162 * This constructor is used for testing the protocol
163 * It is used by TestProto to read the protocol returned by the
164 * server
165 */
166 protected DDMReader(CcsidManager ccsidManager, InputStream inputStream)
167 {
168 buffer = new byte[DEFAULT_BUFFER_SIZE];
169 ddmCollectionLenStack = new long[MAX_MARKS_NESTING];
170 this.ccsidManager = ccsidManager;
171 this.inputStream = inputStream;
172 initialize(null, null);
173 // turn off tracing
174 internalTrace = false;
175 }
176 /**
177 * This initializer is used for testing the protocol
178 * It is used by TestProto for the reader it uses
179 */
180 protected void initialize(InputStream inputStream)
181 {
182 this.inputStream = inputStream;
183 initialize(null, null);
184 }
185
186 /**
187 * Initialize values for this session, the reader is reused so we need to
188 * set null and 0 values
189 */
190 protected void initialize(DRDAConnThread agent, DssTrace dssTrace)
191 {
192 this.agent = agent;
193 if (agent != null)
194 {
195 ccsidManager = agent.ccsidManager;
196 inputStream = agent.getInputStream();
197 }
198 topDdmCollectionStack = EMPTY_STACK;
199 svrcod = 0;
200 pos = 0;
201 count = 0;
202 ddmScalarLen = 0;
203 dssLength = 0;
204 prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
205 dssCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
206 this.dssTrace = dssTrace;
207 }
208
209 protected boolean terminateChainOnErr()
210 {
211 return terminateChainOnErr;
212 }
213
214 /**
215 * Next DSS has same correlator as current DSS
216 *
217 * @return true if next DSS has the same correlator as current DSS
218 */
219 protected boolean isChainedWithSameID()
220 {
221 return dssIsChainedWithSameID;
222 }
223
224 /**
225 * Next DSS has different correlator than current DSS
226 *
227 * @return true if next DSS has a different correlator than current DSS
228 */
229 protected boolean isChainedWithDiffID()
230 {
231 return dssIsChainedWithDiffID;
232 }
233
234 /**
235 * Length of current DDM object
236 *
237 * @return length of DDM object
238 */
239 protected long getDdmLength()
240 {
241 return ddmScalarLen;
242 }
243
244 /**
245 * Is there more in this DDM object
246 *
247 * @return true if DDM length is > 0
248 */
249 protected boolean moreDdmData()
250 {
251 return ddmScalarLen > 0;
252 }
253
254 /**
255 * Is there more in this DDS object
256 *
257 * @return true if DDS length is > 0
258 */
259 protected boolean moreDssData()
260 {
261 return dssLength > 0;
262 }
263
264 /**
265 * Is there more data in the buffer
266 *
267 * @return true if there is more data in the buffer
268 */
269 protected boolean moreData()
270 {
271 return (pos - count) > 0;
272 }
273
274 /**
275 * Check for the command protocol
276 *
277 * @return true if this is a command; false otherwise
278 *
279 * @exception DRDProtocolException
280 */
281 protected boolean isCmd() throws DRDAProtocolException, java.io.UnsupportedEncodingException
282 {
283 ensureALayerDataInBuffer(4);
284 String val = new String(buffer, 0, 4, NetworkServerControlImpl.DEFAULT_ENCODING);
285 return NetworkServerControlImpl.isCmd(val);
286 }
287
288 /**
289 * Return buffer
290 *
291 *
292 * @return buffer
293 */
294 protected byte [] getBuffer()
295 {
296 return buffer;
297 }
298
299 /**
300 * Read DSS header
301 * DSS Header format is
302 * 2 bytes - length
303 * 1 byte - 'D0' - indicates DDM data
304 * 1 byte - DSS format
305 * |---|---------|----------|
306 * | 0 | flags | type |
307 * |---|---------|----------|
308 * | 0 | 1 2 3 | 4 5 6 7 |
309 * |---|---------|----------|
310 * bit 0 - '0'
311 * bit 1 - '0' - unchained, '1' - chained
312 * bit 2 - '0' - do not continue on error, '1' - continue on error
313 * bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
314 * same correlator
315 * type - 1 - Request DSS
316 * - 2 - Reply DSS
317 * - 3 - Object DSS
318 * - 4 - Communications DSS
319 * - 5 - Request DSS where no reply is expected
320 * 2 bytes - request correlation id
321 *
322 * @exception DRDProtocolException
323 */
324 protected int readDssHeader () throws DRDAProtocolException
325 {
326 ensureALayerDataInBuffer (6);
327
328 // read out the DSS length
329 dssLength = ((buffer[pos] & 0xff) << 8) +
330 ((buffer[pos + 1] & 0xff) << 0);
331 pos += 2;
332 // check for the continuation bit and update length as needed.
333 if ((dssLength & DssConstants.CONTINUATION_BIT) ==
334 DssConstants.CONTINUATION_BIT)
335 {
336 dssLength = DssConstants.MAX_DSS_LENGTH;
337 dssIsContinued = true;
338 }
339 else
340 {
341 dssIsContinued = false;
342 }
343
344 if (dssLength < 6)
345 agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,
346 DRDAProtocolException.NO_CODPNT_ARG);
347
348 // If the GDS id is not valid, or
349 // if the reply is not an RQSDSS nor
350 // a OBJDSS, then throw an exception.
351
352 if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)
353 agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,
354 DRDAProtocolException.NO_CODPNT_ARG);
355
356 int gdsFormatter = buffer[pos++] & 0xff;
357
358 if (((gdsFormatter & 0x0F) != DssConstants.DSSFMT_RQSDSS)
359 &&((gdsFormatter & 0x0F) != DssConstants.DSSFMT_OBJDSS))
360 {
361 agent.throwSyntaxrm(CodePoint.SYNERRCD_FBYTE_NOT_SUPPORTED,
362 DRDAProtocolException.NO_CODPNT_ARG);
363 }
364
365 // Determine if the current DSS is chained with the
366 // next DSS, with the same or different request ID.
367 if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN)
368 { // on indicates structure chained to next structure
369 if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
370 == DssConstants.DSSCHAIN_SAME_ID)
371 {
372 dssIsChainedWithSameID = true;
373 dssIsChainedWithDiffID = false;
374 }
375 else
376 {
377 dssIsChainedWithSameID = false;
378 dssIsChainedWithDiffID = true;
379 }
380 if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE)
381 == DssConstants.DSSCHAIN_ERROR_CONTINUE)
382 terminateChainOnErr = false;
383 else
384 terminateChainOnErr = true;
385 }
386 else
387 {
388 // chaining bit not b'1', make sure DSSFMT same id not b'1'
389 if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
390 == DssConstants.DSSCHAIN_SAME_ID)
391 { // Next DSS can not have same correlator
392 agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_SAME_NEXT_CORRELATOR,
393 DRDAProtocolException.NO_CODPNT_ARG);
394 }
395 // chaining bit not b'1', make sure no error continuation
396 if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE)
397 == DssConstants.DSSCHAIN_ERROR_CONTINUE)
398 { // must be 'do not continue on error'
399 agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,
400 DRDAProtocolException.NO_CODPNT_ARG);
401 }
402
403 dssIsChainedWithSameID = false;
404 dssIsChainedWithDiffID = false;
405 }
406
407 dssCorrelationID =
408 ((buffer[pos] & 0xff) << 8) +
409 ((buffer[pos + 1] & 0xff) << 0);
410 pos += 2;
411 if (SanityManager.DEBUG)
412 trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);
413
414 //check that correlationID is the same as previous
415 if (prevCorrelationID != DssConstants.CORRELATION_ID_UNKNOWN &&
416 dssCorrelationID != prevCorrelationID)
417 {
418 agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE,
419 DRDAProtocolException.NO_CODPNT_ARG);
420 }
421
422 // set up previous correlation id to check that next DSS is correctly
423 // formatted
424 if (dssIsChainedWithSameID)
425 prevCorrelationID = dssCorrelationID;
426 else
427 prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN;
428
429 dssLength -= 6;
430
431 return dssCorrelationID;
432 }
433 /**
434 * Read Reply DSS
435 * This is used in testing the protocol. We shouldn't see a reply
436 * DSS when we are servicing DRDA commands
437 *
438 * @exception DRDProtocolException
439 */
440 protected void readReplyDss() throws DRDAProtocolException
441 {
442 ensureALayerDataInBuffer (6);
443
444 // read out the DSS length
445 dssLength = ((buffer[pos++] & 0xff) << 8) +
446 ((buffer[pos++] & 0xff) << 0);
447
448 // check for the continuation bit and update length as needed.
449 if ((dssLength & DssConstants.CONTINUATION_BIT) ==
450 DssConstants.CONTINUATION_BIT)
451 {
452 dssLength = DssConstants.MAX_DSS_LENGTH;
453 dssIsContinued = true;
454 }
455 else
456 {
457 dssIsContinued = false;
458 }
459
460 if (dssLength < 6)
461 agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6,
462 DRDAProtocolException.NO_CODPNT_ARG);
463
464 // If the GDS id is not valid, throw exception
465
466 if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID)
467 agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0,
468 DRDAProtocolException.NO_CODPNT_ARG);
469
470 int gdsFormatter = buffer[pos++] & 0xff;
471
472 // Determine if the current DSS is chained with the
473 // next DSS, with the same or different request ID.
474 if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN)
475 { // on indicates structure chained to next structure
476 if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID)
477 == DssConstants.DSSCHAIN_SAME_ID)
478 {
479 dssIsChainedWithSameID = true;
480 dssIsChainedWithDiffID = false;
481 }
482 else
483 {
484 dssIsChainedWithSameID = false;
485 dssIsChainedWithDiffID = true;
486 }
487 }
488 else
489 {
490 dssIsChainedWithSameID = false;
491 dssIsChainedWithDiffID = false;
492 }
493
494 dssCorrelationID =
495 ((buffer[pos++] & 0xff) << 8) +
496 ((buffer[pos++] & 0xff) << 0);
497
498 if (SanityManager.DEBUG)
499 trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID);
500
501 dssLength -= 6;
502
503 }
504
505 /**
506 * Read the DDM Length and CodePoint
507 *
508 * @return - returns codepoint
509 *
510 * @exception DRDProtocolException
511 */
512 protected int readLengthAndCodePoint() throws DRDAProtocolException
513 {
514 ensureBLayerDataInBuffer (4, NO_ADJUST_LENGTHS);
515
516 ddmScalarLen =
517 ((buffer[pos++] & 0xff) << 8) +
518 ((buffer[pos++] & 0xff) << 0);
519
520 int codePoint =
521 ((buffer[pos++] & 0xff) << 8) +
522 ((buffer[pos++] & 0xff) << 0);
523 if (SanityManager.DEBUG)
524 trace("length = "+ ddmScalarLen + " codepoint = " + java.lang.Integer.toHexString(codePoint));
525 // SYNERRCD 0x0D - Object code point index not supported.
526 // the object codepoint index will not be checked here since
527 // the parse methods will catch any incorrect/unexpected codepoint values
528 // and report them as unsupported objects or parameters.
529
530 // Check if this DDM has extended length field
531 if ((ddmScalarLen & DssConstants.CONTINUATION_BIT) == DssConstants.CONTINUATION_BIT)
532 {
533 int numberOfExtendedLenBytes = ((int)ddmScalarLen -
534 DssConstants.CONTINUATION_BIT) - 4;
535 int adjustSize = 0;
536 ensureBLayerDataInBuffer (numberOfExtendedLenBytes, NO_ADJUST_LENGTHS);
537 switch (numberOfExtendedLenBytes) {
538 case 8:
539 ddmScalarLen =
540 ((buffer[pos++] & 0xff) << 56) +
541 ((buffer[pos++] & 0xff) << 48) +
542 ((buffer[pos++] & 0xff) << 40) +
543 ((buffer[pos++] & 0xff) << 32) +
544 ((buffer[pos++] & 0xff) << 24) +
545 ((buffer[pos++] & 0xff) << 16) +
546 ((buffer[pos++] & 0xff) << 8) +
547 ((buffer[pos++] & 0xff) << 0);
548 adjustSize = 12;
549 break;
550 case 6:
551 ddmScalarLen =
552 ((buffer[pos++] & 0xff) << 40) +
553 ((buffer[pos++] & 0xff) << 32) +
554 ((buffer[pos++] & 0xff) << 24) +
555 ((buffer[pos++] & 0xff) << 16) +
556 ((buffer[pos++] & 0xff) << 8) +
557 ((buffer[pos++] & 0xff) << 0);
558 adjustSize = 10;
559 break;
560 case 4:
561 ddmScalarLen =
562 ((buffer[pos++] & 0xff) << 24) +
563 ((buffer[pos++] & 0xff) << 16) +
564 ((buffer[pos++] & 0xff) << 8) +
565 ((buffer[pos++] & 0xff) << 0);
566 adjustSize = 8;
567 break;
568 default:
569 agent.throwSyntaxrm(CodePoint.SYNERRCD_INCORRECT_EXTENDED_LEN,
570 DRDAProtocolException.NO_CODPNT_ARG);
571 }
572
573 // adjust the lengths here. this is a special case since the
574 // extended length bytes do not include their own length.
575 for (int i = 0; i <= topDdmCollectionStack; i++) {
576 ddmCollectionLenStack[i] -= adjustSize;
577 }
578 dssLength -= adjustSize;
579 }
580 else {
581 if (ddmScalarLen < 4)
582 agent.throwSyntaxrm(CodePoint.SYNERRCD_OBJ_LEN_LESS_THAN_4,
583 DRDAProtocolException.NO_CODPNT_ARG);
584 adjustLengths (4);
585 }
586 return codePoint;
587 }
588
589 /**
590 * Read the CodePoint
591 *
592 * @return - returns codepoint
593 */
594 protected int readCodePoint()
595 {
596 return( ((buffer[pos++] & 0xff) << 8) +
597 ((buffer[pos++] & 0xff) << 0));
598 }
599
600 /**
601 * Push DDM Length on to collection stack
602 */
603 protected void markCollection()
604 {
605 ddmCollectionLenStack[++topDdmCollectionStack] = ddmScalarLen;
606 ddmScalarLen = 0;
607 }
608
609 /**
610 * Get the next CodePoint from a collection
611 * @return NO_CODEPOINT if collection stack is empty or remaining length is
612 * 0; otherwise, read length and code point
613 *
614 * @exception DRDProtocolException
615 */
616 protected int getCodePoint() throws DRDAProtocolException
617 {
618 if (topDdmCollectionStack == EMPTY_STACK)
619 {
620 return NO_CODEPOINT;
621 }
622 else
623 {
624 // if the collecion is exhausted then return NO_CODEPOINT
625 if (ddmCollectionLenStack[topDdmCollectionStack] == 0)
626 {
627 // done with this collection so remove it's length from the stack
628 ddmCollectionLenStack[topDdmCollectionStack--] = 0;
629 return NO_CODEPOINT;
630 }
631 else {
632 return readLengthAndCodePoint();
633 }
634 }
635 }
636 /**
637 * Get the next CodePoint from a collection and check that it matches the specified
638 * CodePoint
639 * @param codePointCheck - codePoint to check against
640 * @return codePoint
641 *
642 * @exception DRDProtocolException
643 */
644 protected int getCodePoint(int codePointCheck) throws DRDAProtocolException
645 {
646 int codePoint = getCodePoint();
647 if (codePoint != codePointCheck)
648 agent.missingCodePoint(codePoint);
649 return codePoint;
650 }
651 /**
652 * The following routines read different types from the input stream
653 * Data can be in network order or platform order depending on whether the
654 * data is part of the protocol or data being received
655 * The platform is determined by EXCSAT protocol
656 */
657
658 /**
659 * Read byte value
660 * @return value
661 *
662 * @exception DRDProtocolException
663 */
664 protected byte readByte () throws DRDAProtocolException
665 {
666 ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
667 return buffer[pos++];
668 }
669
670 /**
671 * Read byte value and mask out high order bytes before returning
672 * @return value
673 */
674 protected int readUnsignedByte () throws DRDAProtocolException
675 {
676 ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
677 return (int ) (buffer[pos++] & 0xff);
678 }
679
680 /**
681 * Read network short value
682 * @return value
683 *
684 * @exception DRDProtocolException
685 */
686 protected int readNetworkShort () throws DRDAProtocolException
687 {
688 ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
689 return ((buffer[pos++] & 0xff) << 8) +
690 ((buffer[pos++] & 0xff) << 0);
691 }
692
693 /**
694 * Read signed network short value
695 * @return value
696 *
697 * @exception DRDProtocolException
698 */
699 protected int readSignedNetworkShort () throws DRDAProtocolException
700 {
701 ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
702 return (short)(((buffer[pos++] & 0xff) << 8) +
703 ((buffer[pos++] & 0xff) << 0));
704 }
705 /**
706 * Read platform short value
707 * @return value
708 *
709 * @exception DRDProtocolException
710 */
711 protected short readShort (int byteOrder) throws DRDAProtocolException
712 {
713 ensureBLayerDataInBuffer (2, ADJUST_LENGTHS);
714 short s = SignedBinary.getShort (buffer, pos, byteOrder);
715
716 pos += 2;
717
718 return s;
719 }
720
721 /**
722 * Read network int value
723 * @return value
724 *
725 * @exception DRDProtocolException
726 */
727 protected int readNetworkInt () throws DRDAProtocolException
728 {
729 ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);
730 return ((buffer[pos++] & 0xff) << 24) +
731 ((buffer[pos++] & 0xff) << 16) +
732 ((buffer[pos++] & 0xff) << 8) +
733 ((buffer[pos++] & 0xff) << 0);
734 }
735
736 /**
737 * Read platform int value
738 * @return value
739 *
740 * @exception DRDProtocolException
741 */
742 protected int readInt (int byteOrder) throws DRDAProtocolException
743 {
744 ensureBLayerDataInBuffer (4, ADJUST_LENGTHS);
745 int i = SignedBinary.getInt (buffer, pos, byteOrder);
746
747 pos += 4;
748
749 return i;
750 }
751
752 /**
753 * Read network long value
754 * @return value
755 *
756 * @exception DRDProtocolException
757 */
758 protected long readNetworkLong () throws DRDAProtocolException
759 {
760 ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);
761
762 return ((buffer[pos++] & 0xffL) << 56) +
763 ((buffer[pos++] & 0xffL) << 48) +
764 ((buffer[pos++] & 0xffL) << 40) +
765 ((buffer[pos++] & 0xffL) << 32) +
766 ((buffer[pos++] & 0xffL) << 24) +
767 ((buffer[pos++] & 0xffL) << 16) +
768 ((buffer[pos++] & 0xffL) << 8) +
769 ((buffer[pos++] & 0xffL) << 0);
770 }
771
772
773 /**
774 * Read network six byte value and put it in a long v
775 * @return value
776 *
777 * @exception DRDProtocolException
778 */
779 protected long readNetworkSixByteLong() throws DRDAProtocolException
780 {
781 ensureBLayerDataInBuffer (6, ADJUST_LENGTHS);
782
783 return (
784 ((buffer[pos++] & 0xffL) << 40) +
785 ((buffer[pos++] & 0xffL) << 32) +
786 ((buffer[pos++] & 0xffL) << 24) +
787 ((buffer[pos++] & 0xffL) << 16) +
788 ((buffer[pos++] & 0xffL) << 8) +
789 ((buffer[pos++] & 0xffL) << 0));
790 }
791
792 /**
793 * Read platform long value
794 * @return value
795 *
796 * @exception DRDProtocolException
797 */
798 protected long readLong (int byteOrder) throws DRDAProtocolException
799 {
800 ensureBLayerDataInBuffer (8, ADJUST_LENGTHS);
801 long l = SignedBinary.getLong (buffer, pos, byteOrder);
802
803 pos += 8;
804
805 return l;
806 }
807
808 /**
809 * Read platform float value
810 * @return value
811 *
812 * @exception DRDProtocolException
813 */
814 protected float readFloat(int byteOrder) throws DRDAProtocolException
815 {
816 return Float.intBitsToFloat(readInt(byteOrder));
817 }
818
819 /**
820 * Read platform double value
821 * @return value
822 *
823 * @exception DRDProtocolException
824 */
825 protected double readDouble(int byteOrder) throws DRDAProtocolException
826 {
827 return Double.longBitsToDouble(readLong(byteOrder));
828 }
829
830 /**
831 * Read a BigDecimal value
832 * @param precision of the BigDecimal
833 * @param scale of the BigDecimal
834 * @return value
835 *
836 * @exception DRDProtocolException
837 */
838 protected BigDecimal readBigDecimal(int precision, int scale) throws DRDAProtocolException
839 {
840 // The byte-length of a packed decimal with precision p is always p/2 + 1
841 int length = precision / 2 + 1;
842
843 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
844
845 // check for sign.
846 int signum;
847 if ((buffer[pos+length-1] & 0x0F) == 0x0D)
848 signum = -1;
849 else
850 signum = 1;
851
852 if (precision <= 9) {
853 // can be handled by int without overflow.
854 int value = packedNybblesToInt(buffer, pos, 0, length*2-1);
855
856 // convert value to a byte array of magnitude.
857 byte[] magnitude = new byte[4];
858 magnitude[0] = (byte)(value >>> 24);
859 magnitude[1] = (byte)(value >>> 16);
860 magnitude[2] = (byte)(value >>> 8);
861 magnitude[3] = (byte)(value);
862
863 pos += length;
864 return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
865 }
866 else if (precision <= 18) {
867 // can be handled by long without overflow.
868 long value = packedNybblesToLong(buffer, pos, 0, length*2-1);
869
870 // convert value to a byte array of magnitude.
871 byte[] magnitude = new byte[8];
872 magnitude[0] = (byte)(value >>> 56);
873 magnitude[1] = (byte)(value >>> 48);
874 magnitude[2] = (byte)(value >>> 40);
875 magnitude[3] = (byte)(value >>> 32);
876 magnitude[4] = (byte)(value >>> 24);
877 magnitude[5] = (byte)(value >>> 16);
878 magnitude[6] = (byte)(value >>> 8);
879 magnitude[7] = (byte)(value);
880
881 pos += length;
882 return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
883 }
884 else if (precision <= 27) {
885 // get the value of last 9 digits (5 bytes).
886 int lo = packedNybblesToInt(buffer, pos, (length-5)*2, 9);
887 // get the value of another 9 digits (5 bytes).
888 int me = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);
889 // get the value of the rest digits.
890 int hi = packedNybblesToInt(buffer, pos, 0, (length-10)*2+1);
891
892 // compute the int array of magnitude.
893 int[] value = computeMagnitude(new int[] {hi, me, lo});
894
895 // convert value to a byte array of magnitude.
896 byte[] magnitude = new byte[12];
897 magnitude[0] = (byte)(value[0] >>> 24);
898 magnitude[1] = (byte)(value[0] >>> 16);
899 magnitude[2] = (byte)(value[0] >>> 8);
900 magnitude[3] = (byte)(value[0]);
901 magnitude[4] = (byte)(value[1] >>> 24);
902 magnitude[5] = (byte)(value[1] >>> 16);
903 magnitude[6] = (byte)(value[1] >>> 8);
904 magnitude[7] = (byte)(value[1]);
905 magnitude[8] = (byte)(value[2] >>> 24);
906 magnitude[9] = (byte)(value[2] >>> 16);
907 magnitude[10] = (byte)(value[2] >>> 8);
908 magnitude[11] = (byte)(value[2]);
909
910 pos += length;
911 return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
912 }
913 else if (precision <= 31) {
914 // get the value of last 9 digits (5 bytes).
915 int lo = packedNybblesToInt(buffer, pos, (length-5)*2, 9);
916 // get the value of another 9 digits (5 bytes).
917 int meLo = packedNybblesToInt(buffer, pos, (length-10)*2+1, 9);
918 // get the value of another 9 digits (5 bytes).
919 int meHi = packedNybblesToInt(buffer, pos, (length-14)*2, 9);
920 // get the value of the rest digits.
921 int hi = packedNybblesToInt(buffer, pos, 0, (length-14)*2);
922
923 // compute the int array of magnitude.
924 int[] value = computeMagnitude(new int[] {hi, meHi, meLo, lo});
925
926 // convert value to a byte array of magnitude.
927 byte[] magnitude = new byte[16];
928 magnitude[0] = (byte)(value[0] >>> 24);
929 magnitude[1] = (byte)(value[0] >>> 16);
930 magnitude[2] = (byte)(value[0] >>> 8);
931 magnitude[3] = (byte)(value[0]);
932 magnitude[4] = (byte)(value[1] >>> 24);
933 magnitude[5] = (byte)(value[1] >>> 16);
934 magnitude[6] = (byte)(value[1] >>> 8);
935 magnitude[7] = (byte)(value[1]);
936 magnitude[8] = (byte)(value[2] >>> 24);
937 magnitude[9] = (byte)(value[2] >>> 16);
938 magnitude[10] = (byte)(value[2] >>> 8);
939 magnitude[11] = (byte)(value[2]);
940 magnitude[12] = (byte)(value[3] >>> 24);
941 magnitude[13] = (byte)(value[3] >>> 16);
942 magnitude[14] = (byte)(value[3] >>> 8);
943 magnitude[15] = (byte)(value[3]);
944
945 pos += length;
946 return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
947 }
948 else {
949 pos += length;
950 // throw an exception here if nibbles is greater than 31
951 throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!");
952 }
953 }
954
955
956
957 byte[] getExtData (boolean checkNullability) throws DRDAProtocolException
958 {
959 return getExtData(ddmScalarLen, checkNullability);
960 }
961
962
963 byte[] getExtData (long desiredLength, boolean checkNullability) throws DRDAProtocolException
964 {
965 boolean readHeader;
966 int copySize;
967 ByteArrayOutputStream baos;
968 boolean isLengthAndNullabilityUnknown = false;
969
970
971 if (desiredLength != -1) {
972 // allocate a stream based on a known amount of data
973 baos = new ByteArrayOutputStream ((int) desiredLength);
974 }
975 else {
976 // allocate a stream to hold an unknown amount of data
977 baos = new ByteArrayOutputStream ();
978 //isLengthAndNullabilityUnknown = true;
979 // If we aren't given a length get the whole thing.
980 desiredLength = MAX_EXTDTA_SIZE;
981 }
982
983
984 // check for a null EXTDTA value, if it is nullable and if streaming
985 if (checkNullability)
986 if (isEXTDTANull())
987 return null;
988
989 // set the amount to read for the first segment
990 copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers
991
992
993 //if (checkNullability) // don't count the null byte we've already read
994 //copySize--;
995
996 do {
997 // determine if a continuation header needs to be read after the data
998 if (dssIsContinued)
999 readHeader = true;
1000 else
1001 readHeader = false;
1002
1003 // read the segment
1004 ensureALayerDataInBuffer (copySize);
1005 adjustLengths (copySize);
1006 baos.write (buffer, pos, copySize);
1007 pos += copySize;
1008 desiredLength -= copySize;
1009
1010 // read the continuation header, if necessary
1011 if (readHeader)
1012 readDSSContinuationHeader ();
1013
1014 copySize = (int) Math.min(dssLength,desiredLength); //note: has already been adjusted for headers
1015
1016 }
1017 while (readHeader == true && desiredLength > 0);
1018
1019 return baos.toByteArray();
1020 }
1021
1022
1023 // reads a DSS continuation header
1024 // prereq: pos is positioned on the first byte of the two-byte header
1025 // post: dssIsContinued is set to true if the continuation bit is on, false otherwise
1026 // dssLength is set to DssConstants.MAXDSS_LEN - 2 (don't count the header for the next read)
1027 // helper method for getEXTDTAData
1028 private void readDSSContinuationHeader () throws DRDAProtocolException
1029 {
1030 ensureALayerDataInBuffer(2);
1031
1032 dssLength =
1033 ((buffer[pos++]&0xFF) << 8) +
1034 ((buffer[pos++]&0xFF) << 0);
1035
1036 if ((dssLength & 0x8000) == 0x8000) {
1037 dssLength = DssConstants.MAX_DSS_LENGTH;
1038 dssIsContinued = true;
1039 }
1040 else {
1041 dssIsContinued = false;
1042 }
1043 // it is a syntax error if the dss continuation header length
1044 // is less than or equal to two
1045 if (dssLength <= 2) {
1046 agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_CONT_LESS_OR_EQUAL_2,
1047 DRDAProtocolException.NO_CODPNT_ARG);
1048 }
1049
1050 dssLength -= 2; // avoid consuming the DSS cont header
1051 }
1052
1053// checks the null EXTDTA byte
1054 // returns true if null, false otherwise
1055 // helper method for getEXTDTAData
1056 private boolean isEXTDTANull () throws DRDAProtocolException
1057 {
1058 // make sure that the null byte is in the buffer
1059 ensureALayerDataInBuffer (1);
1060 adjustLengths (1);
1061
1062 // examine the null byte
1063 byte nullByte = buffer[pos++];
1064 if (nullByte == (byte)0x00)
1065 return false;
1066
1067 return true;
1068 }
1069
1070
1071 /**
1072 * Convert a range of packed nybbles (up to 9 digits without overflow) to an int.
1073 * Note that for performance purpose, it does not do array-out-of-bound checking.
1074 * @param buffer buffer to read from
1075 * @param offset offset in the buffer
1076 * @param startNybble start nybble
1077 * @param numberOfNybbles number of nybbles
1078 * @return an int value
1079 */
1080 private int packedNybblesToInt (byte[] buffer,
1081 int offset,
1082 int startNybble,
1083 int numberOfNybbles)
1084 {
1085 int value = 0;
1086
1087 int i = startNybble / 2;
1088 if ((startNybble % 2) != 0) {
1089 // process low nybble of the first byte if necessary.
1090 value += buffer[offset+i] & 0x0F;
1091 i++;
1092 }
1093
1094 int endNybble = startNybble + numberOfNybbles -1;
1095 for (; i<(endNybble+1)/2; i++) {
1096 value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
1097 value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
1098 }
1099
1100 if ((endNybble % 2) == 0) {
1101 // process high nybble of the last byte if necessary.
1102 value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
1103 }
1104
1105 return value;
1106 }
1107
1108 /**
1109 * Convert a range of packed nybbles (up to 18 digits without overflow) to a long.
1110 * Note that for performance purpose, it does not do array-out-of-bound checking.
1111 * @param buffer buffer to read from
1112 * @param offset offset in the buffer
1113 * @param startNybble start nybble
1114 * @param numberOfNybbles number of nybbles
1115 * @return an long value
1116 */
1117 private long packedNybblesToLong (byte[] buffer,
1118 int offset,
1119 int startNybble,
1120 int numberOfNybbles)
1121 {
1122 long value = 0;
1123
1124 int i = startNybble / 2;
1125 if ((startNybble % 2) != 0) {
1126 // process low nybble of the first byte if necessary.
1127 value += buffer[offset+i] & 0x0F;
1128 i++;
1129 }
1130
1131 int endNybble = startNybble + numberOfNybbles -1;
1132 for (; i<(endNybble+1)/2; i++) {
1133 value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
1134 value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
1135 }
1136
1137 if ((endNybble % 2) == 0) {
1138 // process high nybble of the last byte if necessary.
1139 value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
1140 }
1141
1142 return value;
1143 }
1144
1145 /**
1146 * Compute the int array of magnitude from input value segments.
1147 * @param input value segments
1148 * @return array of int magnitudes
1149 */
1150 private int[] computeMagnitude(int[] input)
1151 {
1152 int length = input.length;
1153 int[] mag = new int[length];
1154
1155 mag[length-1] = input[length-1];
1156 for (int i=0; i<length-1; i++) {
1157 int carry = 0;
1158 int j = tenRadixMagnitude[i].length-1;
1159 int k = length-1;
1160 for (; j>=0; j--, k--) {
1161 long product = (input[length-2-i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL)
1162 + (mag[k] & 0xFFFFFFFFL) // add previous value
1163 + (carry & 0xFFFFFFFFL); // add carry
1164 carry = (int) (product >>> 32);
1165 mag[k] = (int) (product & 0xFFFFFFFFL);
1166 }
1167 mag[k] = (int) carry;
1168 }
1169 return mag;
1170 }
1171
1172 /**
1173 * Read boolean value
1174 * @return value
1175 *
1176 * @exception DRDProtocolException
1177 */
1178 protected boolean readBoolean () throws DRDAProtocolException
1179 {
1180 ensureBLayerDataInBuffer (1, ADJUST_LENGTHS);
1181 return buffer[pos++] != 0;
1182 }
1183
1184 /**
1185 * Read encrypted string
1186 * @param decryptM decryption manager
1187 * @param securityMechanism security mechanism
1188 * @param initVector initialization vector for cipher
1189 * @param sourcePublicKey public key (as in Deffie-Hellman algorithm)
1190 * from source (encryptor)
1191 * @return decrypted string
1192 *
1193 * @exception DRDProtocolException, SQLException(wrapping any exception in decryption)
1194 */
1195 protected String readEncryptedString (DecryptionManager decryptM, int securityMechanism,
1196 byte[] initVector, byte[] sourcePublicKey)
1197 throws DRDAProtocolException, java.sql.SQLException
1198 {
1199 byte[] cipherText = readBytes();
1200 byte[] plainText = null;
1201 plainText = decryptM.decryptData(cipherText, securityMechanism, initVector,
1202 sourcePublicKey);
1203 if (plainText == null)
1204 return null;
1205 else
1206 return ccsidManager.convertToUCS2(plainText);
1207 }
1208
1209 /**
1210 * Read string value
1211 * Strings in DRDA protocol are encoded in EBCDIC by default so we
1212 * need to convert to UCS2
1213 * @param length - length of string to read
1214 * @return value
1215 *
1216 * @exception DRDProtocolException
1217 */
1218 protected String readString (int length) throws DRDAProtocolException
1219 {
1220 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1221
1222 String result = ccsidManager.convertToUCS2 (buffer, pos, length);
1223 pos += length;
1224 return result;
1225 }
1226
1227 /**
1228 * Read encoded string value
1229 * @param length - length of string to read
1230 * @return value
1231 *
1232 * @exception DRDProtocolException
1233 */
1234 protected String readString (int length, String encoding)
1235 throws DRDAProtocolException
1236 {
1237 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1238 String s = null;
1239
1240 try {
1241 s = new String (buffer, pos, length, encoding);
1242 }
1243 catch (java.io.UnsupportedEncodingException e) {
1244 agent.agentError("UnsupportedEncodingException in readString, encoding = "
1245 + encoding);
1246 e.printStackTrace(agent.getServer().logWriter);
1247 }
1248
1249 pos += length;
1250 return s;
1251 }
1252
1253 /**
1254 * Read string value in DDM data with default encoding
1255 * @return value
1256 *
1257 * @exception DRDProtocolException
1258 */
1259 protected String readStringData()
1260 throws DRDAProtocolException
1261 {
1262 return readString((int)ddmScalarLen, NetworkServerControlImpl.DEFAULT_ENCODING);
1263 }
1264
1265 /**
1266 * Read specified length of string value in DDM data with default encoding
1267 * @param length - length of string to read
1268 * @return value
1269 *
1270 * @exception DRDProtocolException
1271 */
1272 protected String readStringData(int length)
1273 throws DRDAProtocolException
1274 {
1275 return readString(length, NetworkServerControlImpl.DEFAULT_ENCODING);
1276 }
1277
1278 /**
1279 * Read length delimited string value in DDM data with default encoding
1280 * @return value
1281 *
1282 * @exception DRDProtocolException
1283 */
1284 protected String readLDStringData(String encoding)
1285 throws DRDAProtocolException
1286 {
1287 int length = readNetworkShort();
1288 return readString(length, encoding);
1289 }
1290
1291 /**
1292 * Read string value
1293 * @param length - length of string to read
1294 * @return value
1295 *
1296 * @exception DRDProtocolException
1297 */
1298 protected String readString () throws DRDAProtocolException
1299 {
1300 return readString((int)ddmScalarLen);
1301 }
1302
1303 /**
1304 * Read byte string value
1305 * @param length - length of string to read
1306 * @return byte array
1307 *
1308 * @exception DRDProtocolException
1309 */
1310 protected byte[] readBytes (int length) throws DRDAProtocolException
1311 {
1312 byte[] b;
1313
1314 if (length < dssLength)
1315 {
1316 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1317 b = new byte[length];
1318 System.arraycopy(buffer,pos,b,0,length);
1319 pos +=length;
1320 }
1321 else
1322 b = getExtData(length,false);
1323 return b;
1324 }
1325
1326 /**
1327 * Read byte string value
1328 * @return byte array
1329 *
1330 * @exception DRDProtocolException
1331 */
1332 protected byte[] readBytes () throws DRDAProtocolException
1333 {
1334 return readBytes((int)ddmScalarLen);
1335 }
1336
1337 /**
1338 * Skip byte string value
1339 * @param length - length of string to skip
1340 *
1341 * @exception DRDProtocolException
1342 */
1343 protected void skipBytes (int length) throws DRDAProtocolException
1344 {
1345 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1346 pos += length;
1347 }
1348
1349 /**
1350 * Skip byte string value
1351 *
1352 * @exception DRDAProtocolException
1353 */
1354 protected void skipBytes () throws DRDAProtocolException
1355 {
1356 skipBytes((int)ddmScalarLen);
1357 }
1358
1359 /**
1360 * Skip remaining DSS
1361 *
1362 * @exception DRDAProtocolException
1363 */
1364 protected void skipDss() throws DRDAProtocolException
1365 {
1366 skipBytes((int)dssLength);
1367 topDdmCollectionStack = EMPTY_STACK;
1368 ddmScalarLen = 0;
1369 dssLength = 0;
1370
1371 }
1372
1373 protected void clearBuffer() throws DRDAProtocolException
1374 {
1375 skipBytes(java.lang.Math.min(dssLength, count - pos));
1376 dssIsChainedWithSameID = false;
1377 dssIsChainedWithDiffID = false;
1378 }
1379
1380 /**
1381 * Convert EBCDIC byte array to unicode string
1382 *
1383 * @param buf - byte array
1384 * @return string
1385 */
1386 protected String convertBytes(byte[] buf)
1387 {
1388 return ccsidManager.convertToUCS2 (buf, 0, buf.length);
1389 }
1390
1391 // Private methods
1392 /**
1393 * Adjust remaining length
1394 *
1395 * @param length - adjustment length
1396 */
1397 private void adjustLengths(int length)
1398 {
1399 ddmScalarLen -= length;
1400 for (int i = 0; i <= topDdmCollectionStack; i++) {
1401 ddmCollectionLenStack[i] -= length;
1402 }
1403 dssLength -= length;
1404 }
1405
1406 /********************************************************************/
1407 /* NetworkServerControl command protocol reading routines
1408 */
1409 /********************************************************************/
1410 /**
1411 * Read string value
1412 * @param length - length of string to read
1413 * @return value
1414 *
1415 * @exception DRDProtocolException
1416 */
1417 protected String readCmdString (int length) throws DRDAProtocolException, java.io.UnsupportedEncodingException
1418 {
1419 if (length == 0)
1420 return null;
1421
1422 ensureBLayerDataInBuffer (length, ADJUST_LENGTHS);
1423 String result = new String (buffer, pos, length,
1424 NetworkServerControlImpl.DEFAULT_ENCODING);
1425 pos += length;
1426 return result;
1427 }
1428 /**
1429 * Read string value
1430 * @return value
1431 *
1432 * @exception DRDProtocolException
1433 */
1434 protected String readCmdString () throws DRDAProtocolException, java.io.UnsupportedEncodingException
1435 {
1436 int length = readNetworkShort();
1437 return readCmdString(length);
1438
1439 }
1440
1441 /**************************************************************************/
1442 /* Private methods
1443 /**************************************************************************/
1444 /**
1445 * Make sure a certain amount of Layer A data is in the buffer.
1446 * The data will be in the buffer after this method is called.
1447 *
1448 * @param desiredDataSize - amount of data we need
1449 *
1450 * @exception DRDAProtocolException
1451 */
1452 private void ensureALayerDataInBuffer (int desiredDataSize)
1453 throws DRDAProtocolException
1454 {
1455 // calulate the the number of bytes in the buffer.
1456 int avail = count - pos;
1457
1458 // read more bytes off the network if the data is not in the buffer already.
1459 if (avail < desiredDataSize)
1460 {
1461 fill (desiredDataSize - avail);
1462 }
1463 }
1464 /**
1465 * Make sure a certain amount of Layer B data is in the buffer.
1466 * The data will be in the buffer after this method is called.
1467 *
1468 * @param desiredDataSize - amount of data we need
1469 * @param adjustLen - whether to adjust the remaining lengths
1470 *
1471 * @exception DRDProtocolException
1472 */
1473 private void ensureBLayerDataInBuffer (int desiredDataSize, boolean adjustLen)
1474 throws DRDAProtocolException
1475 {
1476 if (dssIsContinued)
1477 {
1478 if (desiredDataSize > dssLength)
1479 {
1480 int continueDssHeaderCount =
1481 (((desiredDataSize - dssLength) / DssConstants.MAX_DSS_LENGTH) + 1);
1482 compressBLayerData (continueDssHeaderCount);
1483 }
1484 }
1485 else
1486 {
1487 ensureALayerDataInBuffer (desiredDataSize);
1488 }
1489 if (adjustLen)
1490 adjustLengths(desiredDataSize);
1491 }
1492
1493 /**
1494 * Compress B Layer data if extended total length is used
1495 * by removing the continuation headers
1496 *
1497 * @param continueDssHeaderCount - amount of data we need
1498 *
1499 * @exception throws DRDAProtocolException
1500 */
1501 private void compressBLayerData (int continueDssHeaderCount)
1502 throws DRDAProtocolException
1503 {
1504
1505
1506 // jump to the last continuation header.
1507 int tempPos = 0;
1508 for (int i = 0; i < continueDssHeaderCount; i++)
1509 {
1510 // the first may be less than the size of a full DSS
1511 if (i == 0)
1512 {
1513 // only jump by the number of bytes remaining in the current DSS
1514 tempPos = pos + dssLength;
1515 }
1516 else
1517 {
1518 // all other jumps are for a full continued DSS
1519 tempPos += DssConstants.MAX_DSS_LENGTH;
1520 }
1521 }
1522
1523
1524 // for each of the DSS headers to remove,
1525 // read out the continuation header and increment the DSS length by the
1526 // size of the continuation bytes, then shift the continuation data as needed.
1527 int shiftSize = 0;
1528 int bytesToShift = 0;
1529 int continueHeaderLength = 0;
1530 int newdssLength = 0;
1531
1532
1533 for (int i = 0; i < continueDssHeaderCount; i++)
1534 {
1535 continueHeaderLength = ((buffer[tempPos] & 0xff) << 8) +
1536 ((buffer[tempPos + 1] & 0xff) << 0);
1537
1538 if (i == 0)
1539 {
1540 // if this is the last one (farthest down stream and first to strip out)
1541
1542 if ((