Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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 ((