📄 ddmreader.java
字号:
/* Derby - Class org.apache.derby.impl.drda.DDMReader Copyright 2001, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.impl.drda;import org.apache.derby.iapi.services.sanity.SanityManager;import java.io.IOException;import java.io.InputStream;import java.io.ByteArrayOutputStream;import java.math.BigDecimal;/** The DDMReader is used to read DRDA protocol. DRDA Protocol is divided into three layers corresponding to the DDM three-tier architecture. For each layer, their is a DSS (Data Stream Structure) defined. Layer A Communications management services Layer B Agent services Layer C Data management services <P> At layer A are request, reply and data correlation, structure chaining, continuation or termination of chains when errors are detected, interleaving and multi-leaving request, reply, and data DSSs for multitasking environments. For TCP/IP, the format of the DDM envelope is 2 bytes Length of the data 1 byte 'D0' - indicates DDM data 1 byte DDM format byte(DSSFMT) - type of DSS(RQSDSS,RPYDSS), whether it is chained, information about the next chained DSS 2 bytes request correlation identifier <P> The correlation identifier ties together a request, the request data and the reply. In a chained DSS, each request has a correlation identifier which is higher than the previous request (all correlation identifiers must be greater than 0). <P> At layer B are object mapping, object validation and command routing. Layer B objects with data 5 bytes less than 32K bytes consist of 2 bytes Length 2 bytes Type of the object (code point) Object data Object data is either SCALAR or COLLECTION data. Scalar data consists of a string of bytes formatted as the class description of the object required. Collections consist of a set of objects in which the entries in the collection are nested within the length/ code point of the collection. <P> Layer B objects with data >=32763 bytes long format is 2 bytes Length - length of class, length, and extended total length fields (high order bit set, indicating >=32763) 2 bytes Type of the object (code point) n bytes Extended total length - length of the object (n = Length - 4) Object data <P> At layer C are services each class of DDM object provides. |-------------------------------------------| Layer C | Specific | Specific | Specific | | Commands | Replies | Scalars and | | and their | and their | Collections | |-------------------------------------------|----------------| Layer B | Commands | Reply | Scalars and | Communications | | | Messages | Collections | | |-----------|---------------|---------------|----------------| Layer A | RQSDSS | RPYDSS | OBJDSS | CMNDSS | | | | | Mapped Data | |-----------|---------------|---------------|----------------| | DDM Data Stream Structures | |------------------------------------------------------------| DSS's may be chained so that more than one can be transmitted at a time to improve performance. For more details, see DRDA Volume 3 (Distributed Data Management(DDM) Architecture (DDS definition)*/class DDMReader{ private final static int DEFAULT_BUFFER_SIZE = 32767; private final static int MAX_MARKS_NESTING = 10; private final static int NO_CODEPOINT = -1; private final static int EMPTY_STACK = -1; private final static boolean ADJUST_LENGTHS = true; private final static boolean NO_ADJUST_LENGTHS = false; private final static long MAX_EXTDTA_SIZE= Long.MAX_VALUE; private static boolean internalTrace = true; // magnitude represented in an int array, used in BigDecimal conversion private static final int[][] tenRadixMagnitude = { { 0x3b9aca00 }, // 10^9 { 0x0de0b6b3, 0xa7640000 }, // 10^18 { 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27 }; private DRDAConnThread agent; private CcsidManager ccsidManager; // data buffer private byte[] buffer; private int pos; private int count; // DDM object collection // top of stack private int topDdmCollectionStack; // length of each object in the stack private long[] ddmCollectionLenStack; // DDM object length private long ddmScalarLen; // DSS Length private int dssLength; // DSS is larger than 32762 (continuation bit is set) so DSS is continued private boolean dssIsContinued; private boolean terminateChainOnErr; // next DSS in the chain has the same correlator private boolean dssIsChainedWithSameID; // next DSS in the chain has a different correlator private boolean dssIsChainedWithDiffID; // correlation id for the current DSS private int dssCorrelationID; // previous corelation id private int prevCorrelationID; // current server codepoint private int svrcod; // trace object of the associated session private DssTrace dssTrace; // input stream private InputStream inputStream; // constructor protected DDMReader (DRDAConnThread agent, DssTrace dssTrace) { buffer = new byte[DEFAULT_BUFFER_SIZE]; ddmCollectionLenStack = new long[MAX_MARKS_NESTING]; initialize(agent, dssTrace); } /** * This constructor is used for testing the protocol * It is used by TestProto to read the protocol returned by the * server */ protected DDMReader(CcsidManager ccsidManager, InputStream inputStream) { buffer = new byte[DEFAULT_BUFFER_SIZE]; ddmCollectionLenStack = new long[MAX_MARKS_NESTING]; this.ccsidManager = ccsidManager; this.inputStream = inputStream; initialize(null, null); // turn off tracing internalTrace = false; } /** * This initializer is used for testing the protocol * It is used by TestProto for the reader it uses */ protected void initialize(InputStream inputStream) { this.inputStream = inputStream; initialize(null, null); } /** * Initialize values for this session, the reader is reused so we need to * set null and 0 values */ protected void initialize(DRDAConnThread agent, DssTrace dssTrace) { this.agent = agent; if (agent != null) { ccsidManager = agent.ccsidManager; inputStream = agent.getInputStream(); } topDdmCollectionStack = EMPTY_STACK; svrcod = 0; pos = 0; count = 0; ddmScalarLen = 0; dssLength = 0; prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN; dssCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN; this.dssTrace = dssTrace; } protected boolean terminateChainOnErr() { return terminateChainOnErr; } /** * Next DSS has same correlator as current DSS * * @return true if next DSS has the same correlator as current DSS */ protected boolean isChainedWithSameID() { return dssIsChainedWithSameID; } /** * Next DSS has different correlator than current DSS * * @return true if next DSS has a different correlator than current DSS */ protected boolean isChainedWithDiffID() { return dssIsChainedWithDiffID; } /** * Length of current DDM object * * @return length of DDM object */ protected long getDdmLength() { return ddmScalarLen; } /** * Is there more in this DDM object * * @return true if DDM length is > 0 */ protected boolean moreDdmData() { return ddmScalarLen > 0; } /** * Is there more in this DDS object * * @return true if DDS length is > 0 */ protected boolean moreDssData() { return dssLength > 0; } /** * Is there more data in the buffer * * @return true if there is more data in the buffer */ protected boolean moreData() { return (pos - count) > 0; } /** * Check for the command protocol * * @return true if this is a command; false otherwise * * @exception DRDProtocolException */ protected boolean isCmd() throws DRDAProtocolException, java.io.UnsupportedEncodingException { ensureALayerDataInBuffer(4); String val = new String(buffer, 0, 4, NetworkServerControlImpl.DEFAULT_ENCODING); return NetworkServerControlImpl.isCmd(val); } /** * Return buffer * * * @return buffer */ protected byte [] getBuffer() { return buffer; } /** * Read DSS header * DSS Header format is * 2 bytes - length * 1 byte - 'D0' - indicates DDM data * 1 byte - DSS format * |---|---------|----------| * | 0 | flags | type | * |---|---------|----------| * | 0 | 1 2 3 | 4 5 6 7 | * |---|---------|----------| * bit 0 - '0' * bit 1 - '0' - unchained, '1' - chained * bit 2 - '0' - do not continue on error, '1' - continue on error * bit 3 - '0' - next DSS has different correlator, '1' - next DSS has * same correlator * type - 1 - Request DSS * - 2 - Reply DSS * - 3 - Object DSS * - 4 - Communications DSS * - 5 - Request DSS where no reply is expected * 2 bytes - request correlation id * * @exception DRDProtocolException */ protected int readDssHeader () throws DRDAProtocolException { ensureALayerDataInBuffer (6); // read out the DSS length dssLength = ((buffer[pos] & 0xff) << 8) + ((buffer[pos + 1] & 0xff) << 0); pos += 2; // check for the continuation bit and update length as needed. if ((dssLength & DssConstants.CONTINUATION_BIT) == DssConstants.CONTINUATION_BIT) { dssLength = DssConstants.MAX_DSS_LENGTH; dssIsContinued = true; } else { dssIsContinued = false; } if (dssLength < 6) agent.throwSyntaxrm(CodePoint.SYNERRCD_DSS_LESS_THAN_6, DRDAProtocolException.NO_CODPNT_ARG); // If the GDS id is not valid, or // if the reply is not an RQSDSS nor // a OBJDSS, then throw an exception. if ((buffer[pos++] & 0xff) != DssConstants.DSS_ID) agent.throwSyntaxrm(CodePoint.SYNERRCD_CBYTE_NOT_D0, DRDAProtocolException.NO_CODPNT_ARG); int gdsFormatter = buffer[pos++] & 0xff; if (((gdsFormatter & 0x0F) != DssConstants.DSSFMT_RQSDSS) &&((gdsFormatter & 0x0F) != DssConstants.DSSFMT_OBJDSS)) { agent.throwSyntaxrm(CodePoint.SYNERRCD_FBYTE_NOT_SUPPORTED, DRDAProtocolException.NO_CODPNT_ARG); } // Determine if the current DSS is chained with the // next DSS, with the same or different request ID. if ((gdsFormatter & DssConstants.DSSCHAIN) == DssConstants.DSSCHAIN) { // on indicates structure chained to next structure if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID) == DssConstants.DSSCHAIN_SAME_ID) { dssIsChainedWithSameID = true; dssIsChainedWithDiffID = false; } else { dssIsChainedWithSameID = false; dssIsChainedWithDiffID = true; } if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE) == DssConstants.DSSCHAIN_ERROR_CONTINUE) terminateChainOnErr = false; else terminateChainOnErr = true; } else { // chaining bit not b'1', make sure DSSFMT same id not b'1' if ((gdsFormatter & DssConstants.DSSCHAIN_SAME_ID) == DssConstants.DSSCHAIN_SAME_ID) { // Next DSS can not have same correlator agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_SAME_NEXT_CORRELATOR, DRDAProtocolException.NO_CODPNT_ARG); } // chaining bit not b'1', make sure no error continuation if ((gdsFormatter & DssConstants.DSSCHAIN_ERROR_CONTINUE) == DssConstants.DSSCHAIN_ERROR_CONTINUE) { // must be 'do not continue on error' agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE, DRDAProtocolException.NO_CODPNT_ARG); } dssIsChainedWithSameID = false; dssIsChainedWithDiffID = false; } dssCorrelationID = ((buffer[pos] & 0xff) << 8) + ((buffer[pos + 1] & 0xff) << 0); pos += 2; if (SanityManager.DEBUG) trace("dssLength = " + dssLength + " correlationID = " + dssCorrelationID); //check that correlationID is the same as previous if (prevCorrelationID != DssConstants.CORRELATION_ID_UNKNOWN && dssCorrelationID != prevCorrelationID) { agent.throwSyntaxrm(CodePoint.SYNERRCD_CHAIN_OFF_ERROR_CONTINUE, DRDAProtocolException.NO_CODPNT_ARG); } // set up previous correlation id to check that next DSS is correctly // formatted if (dssIsChainedWithSameID) prevCorrelationID = dssCorrelationID; else prevCorrelationID = DssConstants.CORRELATION_ID_UNKNOWN; dssLength -= 6; return dssCorrelationID; } /** * Read Reply DSS * This is used in testing the protocol. We shouldn't see a reply * DSS when we are servicing DRDA commands * * @exception DRDProtocolException */ protected void readReplyDss() throws DRDAProtocolException { ensureALayerDataInBuffer (6); // read out the DSS length dssLength = ((buffer[pos++] & 0xff) << 8) + ((buffer[pos++] & 0xff) << 0); // check for the continuation bit and update length as needed. if ((dssLength & DssConstants.CONTINUATION_BIT) == DssConstants.CONTINUATION_BIT) { dssLength = DssConstants.MAX_DSS_LENGTH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -