1320 lines
24 KiB
Java

/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.filesys.server.oncrpc;
import java.net.*;
import org.alfresco.filesys.util.DataPacker;
/**
* ONC/RPC Request/Response Packet Class
*
* @author GKSpencer
*/
public class RpcPacket {
// Constants
//
// Default buffer size to allocate
private static final int DefaultBufferSize = 8192;
// Fragment header length
public static final int FragHeaderLen = 4;
// Fixed packet lengths
public static final int ResponseMismatchLen = 24;
public static final int ResponseAuthFailLen = 20;
// RPC data buffer
private byte[] m_buffer;
private int m_offset;
// Current buffer pack/unpack position and end of buffer position
private int m_pos;
private int m_endPos;
// Callers address, port and protocol
private InetAddress m_clientAddr;
private int m_clientPort;
private int m_protocol;
// RPC packet handler interface used to send an RPC response
private RpcPacketHandler m_pktHandler;
// Packet pool that owns this packet, if allocated from a pool
private RpcPacketPool m_ownerPool;
/**
* Default constructor
*/
public RpcPacket()
{
// Allocate the RPC buffer
m_buffer = new byte[DefaultBufferSize];
m_offset = FragHeaderLen;
m_pos = FragHeaderLen;
m_endPos = m_buffer.length;
}
/**
* Class constructor
*
* @param len int
*/
public RpcPacket(int len)
{
// Allocate the RPC buffer
m_buffer = new byte[len + FragHeaderLen];
m_offset = FragHeaderLen;
m_pos = FragHeaderLen;
m_endPos = m_buffer.length;
}
/**
* Class constructor
*
* @param len int
* @param owner RpcPacketPool
*/
protected RpcPacket(int len, RpcPacketPool owner)
{
this(len);
// Set the owner
setOwnerPacketPool(owner);
}
/**
* Class constructor
*
* @param buf byte[]
*/
public RpcPacket(byte[] buf)
{
m_buffer = buf;
m_offset = FragHeaderLen;
m_pos = FragHeaderLen;
m_endPos = buf.length;
}
/**
* Class constructor
*
* @param buf byte[]
* @param offset int
* @param len int
*/
public RpcPacket(byte[] buf, int offset, int len)
{
m_buffer = buf;
m_offset = offset;
m_pos = offset;
m_endPos = offset + len;
}
/**
* Determine if the packet handler is valid
*
* @return boolean
*/
public final boolean hasPacketHandler()
{
return m_pktHandler != null ? true : false;
}
/**
* Return the packet handler interface used to send/receive a packet
*
* @return RpcPacketHandler
*/
public final RpcPacketHandler getPacketHandler()
{
return m_pktHandler;
}
/**
* Detemrine if the packet is allocated from a packet pool
*
* @return boolean
*/
public final boolean isAllocatedFromPool()
{
return m_ownerPool != null ? true : false;
}
/**
* Return the packet pool that owns this packet
*
* @return RpcPacketPool
*/
public final RpcPacketPool getOwnerPacketPool()
{
return m_ownerPool;
}
/**
* Determine if the client address has been set
*
* @return boolean
*/
public final boolean hasClientAddress()
{
return m_clientAddr != null ? true : false;
}
/**
* Return the client network address
*
* @return InetAddress
*/
public final InetAddress getClientAddress()
{
return m_clientAddr;
}
/**
* Return the client port
*
* @return int
*/
public final int getClientPort()
{
return m_clientPort;
}
/**
* Return the client protocol
*
* @return int
*/
public final int getClientProtocol()
{
return m_protocol;
}
/**
* Return the client details as a string
*
* @return String
*/
public final String getClientDetails()
{
if (hasClientAddress() == false)
return "<Unknown>";
StringBuffer str = new StringBuffer(32);
str.append(getClientProtocol() == Rpc.TCP ? "T" : "U");
str.append(getClientAddress().getHostAddress());
str.append(":");
str.append(getClientPort());
return str.toString();
}
/**
* Return the current buffer position
*
* @return int
*/
public final int getPosition()
{
return m_pos;
}
/**
* Return the buffer
*
* @return byte[]
*/
public final byte[] getBuffer()
{
return m_buffer;
}
/**
* Return the available buffer size
*
* @return int
*/
public final int getAvailableLength()
{
return m_buffer.length - m_pos;
}
/**
* Return the used buffer length
*
* @return int
*/
public final int getLength()
{
return m_endPos - m_offset;
}
/**
* Return the RPC + fragment header length
*
* @return int
*/
public final int getTxLength()
{
if (m_offset == 0)
return m_endPos;
else
return (m_endPos - m_offset) + FragHeaderLen;
}
/**
* Return the start of data offset
*
* @return int
*/
public final int getOffset()
{
return m_offset;
}
/**
* Return the message type
*
* @return int
*/
public final int getMessageType()
{
return DataPacker.getInt(m_buffer, m_offset + 4);
}
/**
* Return the RPC version
*
* @return int
*/
public final int getRpcVersion()
{
return DataPacker.getInt(m_buffer, m_offset + 8);
}
/**
* Return the program id
*
* @return int
*/
public final int getProgramId()
{
return DataPacker.getInt(m_buffer, m_offset + 12);
}
/**
* Return the program version
*
* @return int
*/
public final int getProgramVersion()
{
return DataPacker.getInt(m_buffer, m_offset + 16);
}
/**
* Return the procedure id
*
* @return int
*/
public final int getProcedureId()
{
return DataPacker.getInt(m_buffer, m_offset + 20);
}
/**
* Return the credentials type
*
* @return int
*/
public final int getCredentialsType()
{
return DataPacker.getInt(m_buffer, m_offset + 24);
}
/**
* Return the credentials length
*
* @return int
*/
public final int getCredentialsLength()
{
return DataPacker.getInt(m_buffer, m_offset + 28);
}
/**
* Return the verifier type
*
* @return int
*/
public final int getVerifierType()
{
return DataPacker.getInt(m_buffer, m_offset + getCredentialsLength() + 32);
}
/**
* Return the verifier length
*
* @return int
*/
public final int getVerifierLength()
{
return DataPacker.getInt(m_buffer, m_offset + getCredentialsLength() + 36);
}
/**
* Return the buffer offset to the verifier
*
* @return int
*/
public final int getVerifierOffset()
{
return m_offset + getCredentialsLength() + 40;
}
/**
* Return the procedure specific parameters offset
*
* @return int
*/
public final int getProcedureParameterOffset()
{
return m_offset + getCredentialsLength() + getVerifierLength() + 40;
}
/**
* Return the procedure parameters length
*
* @return int
*/
public final int getProcedureParameterLength()
{
return m_endPos - getProcedureParameterOffset();
}
/**
* Return the XID
*
* @return int
*/
public final int getXID()
{
return DataPacker.getInt(m_buffer, m_offset);
}
/**
* Check if the response has a success status
*
* @return boolean
*/
public final boolean hasSuccessStatus()
{
return getAcceptStatus() == Rpc.StsSuccess ? true : false;
}
/**
* Return the reply state
*
* @return int
*/
public final int getReplyState()
{
return DataPacker.getInt(m_buffer, 8);
}
/**
* Return the reject reply status
*
* @return int
*/
public final int getRejectStatus()
{
return DataPacker.getInt(m_buffer, 12);
}
/**
* Return the version mismatch low version
*
* @return int
*/
public final int getMismatchVersionLow()
{
return DataPacker.getInt(m_buffer, 16);
}
/**
* Return the version mismatch high version
*
* @return int
*/
public final int getMismatchVersionHigh()
{
return DataPacker.getInt(m_buffer, 20);
}
/**
* Return the authentication failure status
*
* @return int
*/
public final int getAuthFailStatus()
{
return DataPacker.getInt(m_buffer, 16);
}
/**
* Return the accept status for the RPC response
*
* @return int
*/
public final int getAcceptStatus()
{
int pos = DataPacker.getInt(m_buffer, 16) + 20;
return DataPacker.getInt(m_buffer, pos);
}
/**
* Align the buffer position on a longword/32bit boundary
*
* @param ival
*/
protected final void alignPosition()
{
// Align the buffer position on the required boundary
m_pos = (m_pos + 3) & 0xFFFFFFFC;
}
/**
* Pack a byte value
*
* @param bval int
*/
public final void packByte(int bval)
{
m_buffer[m_pos++] = (byte) (bval & 0xFF);
}
/**
* Pack nulls
*
* @param len int
*/
public final void packNulls(int len)
{
for (int i = 0; i < len; i++)
m_buffer[m_pos++] = (byte) 0;
}
/**
* Pack an integer value
*
* @param ival int
*/
public final void packInt(int ival)
{
DataPacker.putInt(ival, m_buffer, m_pos);
m_pos += 4;
}
/**
* Pack a long value
*
* @param lval long
*/
public final void packLong(long lval)
{
DataPacker.putLong(lval, m_buffer, m_pos);
m_pos += 8;
}
/**
* Pack a byte array with a length
*
* @param buf byte[]
*/
public final void packByteArrayWithLength(byte[] buf)
{
DataPacker.putInt(buf.length, m_buffer, m_pos);
m_pos += 4;
System.arraycopy(buf, 0, m_buffer, m_pos, buf.length);
m_pos += buf.length;
alignPosition();
}
/**
* Pack a byte array
*
* @param buf byte[]
*/
public final void packByteArray(byte[] buf)
{
System.arraycopy(buf, 0, m_buffer, m_pos, buf.length);
m_pos += buf.length;
alignPosition();
}
/**
* Pack an integer array
*
* @param iarray int[]
*/
public final void packIntArrayWithLength(int[] iarray)
{
DataPacker.putInt(iarray.length, m_buffer, m_pos);
m_pos += 4;
for (int i = 0; i < iarray.length; i++)
{
DataPacker.putInt(iarray[i], m_buffer, m_pos);
m_pos += 4;
}
}
/**
* Pack a string
*
* @param str String
*/
public final void packString(String str)
{
DataPacker.putInt(str != null ? str.length() : 0, m_buffer, m_pos);
m_pos += 4;
if (str != null)
{
m_pos = DataPacker.putString(str, m_buffer, m_pos, false);
alignPosition();
}
}
/**
* Pack a port mapping structure
*
* @param portMap PortMapping
*/
public final void packPortMapping(PortMapping portMap)
{
DataPacker.putInt(portMap.getProgramId(), m_buffer, m_pos);
DataPacker.putInt(portMap.getVersionId(), m_buffer, m_pos + 4);
DataPacker.putInt(portMap.getProtocol(), m_buffer, m_pos + 8);
DataPacker.putInt(portMap.getPort(), m_buffer, m_pos + 12);
m_pos += 16;
}
/**
* Unpack an integer value
*
* @return int
*/
public final int unpackInt()
{
int val = DataPacker.getInt(m_buffer, m_pos);
m_pos += 4;
return val;
}
/**
* Unpack a long value
*
* @return long
*/
public final long unpackLong()
{
long val = DataPacker.getLong(m_buffer, m_pos);
m_pos += 8;
return val;
}
/**
* Unpack a string
*
* @return String
*/
public final String unpackString()
{
int len = unpackInt();
String str = "";
if (len > 0)
{
str = DataPacker.getString(m_buffer, m_pos, len);
m_pos += len;
alignPosition();
}
return str;
}
/**
* Unpack a byte array with a length
*
* @param buf byte[]
*/
public final void unpackByteArrayWithLength(byte[] buf)
{
int len = DataPacker.getInt(m_buffer, m_pos);
m_pos += 4;
if (len > 0)
{
System.arraycopy(m_buffer, m_pos, buf, 0, len);
m_pos += len;
}
alignPosition();
}
/**
* Unpack a byte array, using the buffer length
*
* @param buf byte[]
*/
public final void unpackByteArray(byte[] buf)
{
System.arraycopy(m_buffer, m_pos, buf, 0, buf.length);
m_pos += buf.length;
alignPosition();
}
/**
* Unpack an integer array, using the buffer length
*
* @param buf int[]
*/
public final void unpackIntArray(int[] buf)
{
for (int i = 0; i < buf.length; i++)
buf[i] = unpackInt();
}
/**
* Position the read pointer at the credentials data
*/
public final void positionAtCredentialsData()
{
m_pos = m_offset + 32;
}
/**
* Position the read pointer at the verifier data
*/
public final void positionAtVerifierData()
{
m_pos = getVerifierOffset();
}
/**
* Position the read pointer at the procedure specific parameters
*/
public final void positionAtParameters()
{
m_pos = getProcedureParameterOffset();
}
/**
* Skip a number of bytes in the buffer, rounded to the next int boundary
*
* @param cnt int
*/
public final void skipBytes(int cnt)
{
m_pos += (cnt + 3) & 0xFFFC;
}
/**
* Set the client details
*
* @param addr InetAddress
* @param port int
* @param protocol int
*/
public final void setClientDetails(InetAddress addr, int port, int protocol)
{
m_clientAddr = addr;
m_clientPort = port;
m_protocol = protocol;
}
/**
* Reset the buffer details
*
* @param buf byte[]
* @param offset int
* @param len int
*/
public final void setBuffer(byte[] buf, int offset, int len)
{
m_buffer = buf;
m_offset = offset;
m_pos = offset;
m_endPos = offset + len;
}
/**
* Reset the buffer details
*
* @param offset int
* @param len int
*/
public final void setBuffer(int offset, int len)
{
m_offset = offset;
m_pos = offset;
m_endPos = offset + len;
}
/**
* Set the used buffer length
*
* @param len int
*/
public final void setLength(int len)
{
m_endPos = len + m_offset;
// Set the fragment header, if the offset is non-zero
if (m_offset == FragHeaderLen)
DataPacker.putInt(getLength() + Rpc.LastFragment, m_buffer, 0);
}
/**
* Set the used buffer length
*/
public final void setLength()
{
m_endPos = m_pos;
// Set the fragment header, if the offset is non-zero
if (m_offset == FragHeaderLen)
DataPacker.putInt(getLength() + Rpc.LastFragment, m_buffer, 0);
}
/**
* Set the buffer position
*
* @param pos int
*/
public final void setPosition(int pos)
{
m_pos = pos;
}
/**
* Set the message type
*
* @param msgType int
*/
public final void setMessageType(int msgType)
{
DataPacker.putInt(msgType, m_buffer, m_offset + 4);
}
/**
* Set the RPC version
*
* @param rpcVer int
*/
public final void setRpcVersion(int rpcVer)
{
DataPacker.putInt(rpcVer, m_buffer, m_offset + 8);
}
/**
* Set the program id
*
* @param progId int
*/
public final void setProgramId(int progId)
{
DataPacker.putInt(progId, m_buffer, m_offset + 12);
}
/**
* Set the program version
*
* @param progVer int
*/
public final void setProgramVersion(int progVer)
{
DataPacker.putInt(progVer, m_buffer, m_offset + 16);
}
/**
* Set the procedure id
*
* @param procId int
*/
public final void setProcedureId(int procId)
{
DataPacker.putInt(procId, m_buffer, m_offset + 20);
}
/**
* Set the credentials type
*
* @param credtype int
*/
public final void setCredentialsType(int credtype)
{
DataPacker.putInt(credtype, m_buffer, m_offset + 24);
}
/**
* Set the credentials length
*
* @param credlen int
*/
public final void setCredentialsLength(int credlen)
{
DataPacker.putInt(credlen, m_buffer, m_offset + 28);
}
/**
* Set the reply state
*
* @param replySts int
*/
public final void setReplyState(int replySts)
{
DataPacker.putInt(replySts, m_buffer, m_offset + 8);
}
/**
* Set the reject status
*
* @param rejSts int
*/
public final void setRejectStatus(int rejSts)
{
DataPacker.putInt(rejSts, m_buffer, m_offset + 8);
}
/**
* Set the RPC mismatch values
*
* @param rpcLow int
* @param rpcHigh int
*/
public final void setRpcMismatch(int rpcLow, int rpcHigh)
{
DataPacker.putInt(rpcLow, m_buffer, m_offset + 12);
DataPacker.putInt(rpcHigh, m_buffer, m_offset + 16);
}
/**
* Set the authentication failure status
*
* @param authSts int
*/
public final void setAuthFailStatus(int authSts)
{
DataPacker.putInt(authSts, m_buffer, m_offset + 8);
}
/**
* Set the verifier type
*
* @param verftype int
*/
public final void setVerifierType(int verftype)
{
DataPacker.putInt(verftype, m_buffer, m_offset + getCredentialsLength() + 32);
}
/**
* Set the verifier length
*
* @param verflen int
*/
public final void setVerifierLength(int verflen)
{
DataPacker.putInt(verflen, m_buffer, m_offset + getCredentialsLength() + 36);
}
/**
* Set the associated packet handler interface for the packet
*
* @param pktHandler RpcPacketHandler
*/
public final void setPacketHandler(RpcPacketHandler pktHandler)
{
m_pktHandler = pktHandler;
}
/**
* Set the XID
*
* @param xid int
*/
public final void setXID(int xid)
{
DataPacker.putInt(xid, m_buffer, m_offset);
}
/**
* Set the owner packet pool, if the packet was allocated from a pool
*
* @param pool RpcPacketPool
*/
protected final void setOwnerPacketPool(RpcPacketPool pool)
{
m_ownerPool = pool;
}
/**
* Build an RPC request header, and set the buffer pointer ready to stream data into the parameter
* area of the request
*
* @param progId int
* @param verId int
* @param procId int
* @param credType int
* @param cred byte[]
* @param verfType int
* @param verf byte[]
*/
public final void buildRequestHeader(int progId, int verId, int procId, int credType, byte[] cred, int verfType,
byte[] verf)
{
// Generate an id for the request
setXID((int) (System.currentTimeMillis() & 0xFFFFFFFFL));
// Set the message type and RPC version (always version 2)
setMessageType(Rpc.Call);
setRpcVersion(Rpc.RpcVersion);
// Set the request details
setProgramId(progId);
setProgramVersion(verId);
setProcedureId(procId);
// Set the credentials type, length and value
setCredentialsType(credType);
setCredentialsLength(cred != null ? cred.length : 0);
if (cred != null)
System.arraycopy(cred, 0, m_buffer, m_offset + 32, cred.length);
// Set the verifier type, length and value
setVerifierType(verfType);
setVerifierLength(verf != null ? verf.length : 0);
if (verf != null)
{
int pos = getVerifierOffset();
System.arraycopy(verf, 0, m_buffer, pos, verf.length);
}
// Position the buffer pointer at the request parameter area
positionAtParameters();
}
/**
* Build a response header for a valid RPC response and set the buffer pointer ready to stream data
* into the parameter area of the response.
*/
public final void buildResponseHeader()
{
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallAccepted);
// Copy the verifier from the request
DataPacker.putInt(getVerifierType(), m_buffer, m_offset + 12);
int verfLen = getVerifierLength();
DataPacker.putInt(verfLen, m_buffer, m_offset + 16);
if (verfLen > 0)
System.arraycopy(m_buffer, getVerifierOffset(), m_buffer, m_offset + 20, verfLen);
// Indicate a success status
DataPacker.putInt(Rpc.StsSuccess, m_buffer, m_offset + 20 + verfLen);
// Set the buffer pointer for streaming the response parameters
m_pos = m_offset + 24 + verfLen;
setLength();
}
/**
* Build an error response packet where the RPC has been accepted but returns a status code in the parameter area.
*
* @param stsCode int
*/
public final void buildErrorResponse(int stsCode)
{
// Check if the RPC is a request or reply
boolean isReply = getMessageType() == Rpc.Reply;
// Set the reply header
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallAccepted);
// Copy the verifier from the request
int verfLen = 0;
if (isReply == false)
{
DataPacker.putInt(getVerifierType(), m_buffer, m_offset + 12);
verfLen = getVerifierLength();
DataPacker.putInt(verfLen, m_buffer, m_offset + 16);
if (verfLen > 0)
System.arraycopy(m_buffer, getVerifierOffset(), m_buffer, m_offset + 20, verfLen);
} else
{
// Get the verifier length from the reply
verfLen = DataPacker.getInt(m_buffer, m_offset + 16);
}
// Indicate a success status
DataPacker.putInt(Rpc.StsSuccess, m_buffer, m_offset + 20 + verfLen);
// Set the buffer pointer for streaming the response parameters
m_pos = m_offset + 24 + verfLen;
// Pack the service status code
DataPacker.putInt(stsCode, m_buffer, m_pos);
m_pos += 4;
setLength();
}
/**
* Build an RPC version mismatch response
*/
public final void buildRpcMismatchResponse()
{
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallDenied);
setRejectStatus(Rpc.StsRpcMismatch);
setRpcMismatch(Rpc.RpcVersion, Rpc.RpcVersion);
setLength(ResponseMismatchLen);
}
/**
* Build an RPC authentication failure response
*
* @param stsCode int
*/
public final void buildAuthFailResponse(int stsCode)
{
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallDenied);
setRejectStatus(Rpc.StsAuthError);
setAuthFailStatus(stsCode);
setLength(ResponseAuthFailLen);
}
/**
* Build an RPC accept error response
*
* @param stsCode int
*/
public final void buildAcceptErrorResponse(int stsCode)
{
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallAccepted);
// Copy the verifier from the request
DataPacker.putInt(getVerifierType(), m_buffer, m_offset + 12);
int verfLen = getVerifierLength();
DataPacker.putInt(verfLen, m_buffer, m_offset + 16);
if (verfLen > 0)
System.arraycopy(m_buffer, getVerifierOffset(), m_buffer, m_offset + 20, verfLen);
// Pack the status code
DataPacker.putInt(stsCode, m_buffer, m_offset + 20 + verfLen);
// Set the response length
setLength(m_offset + 24 + verfLen);
}
/**
* Build a program mismatch error response
*
* @param verLow int
* @param verHigh int
*/
public final void buildProgramMismatchResponse(int verLow, int verHigh)
{
setMessageType(Rpc.Reply);
setReplyState(Rpc.CallAccepted);
// Copy the verifier from the request
DataPacker.putInt(getVerifierType(), m_buffer, m_offset + 12);
int verfLen = getVerifierLength();
DataPacker.putInt(verfLen, m_buffer, m_offset + 16);
if (verfLen > 0)
System.arraycopy(m_buffer, getVerifierOffset(), m_buffer, m_offset + 20, verfLen);
// Pack the status code, and low/high version numbers
int pos = m_offset + 20 + verfLen;
DataPacker.putInt(Rpc.StsProgMismatch, m_buffer, pos);
DataPacker.putInt(verLow, m_buffer, pos + 4);
DataPacker.putInt(verHigh, m_buffer, pos + 8);
// Set the response length
setLength(pos + 12);
}
/**
* Return the RPC packet as a string
*
* @return String
*/
public String toString()
{
StringBuffer str = new StringBuffer(128);
// Dump the client details
str.append("[");
if (hasClientAddress())
{
str.append(getClientProtocol() == Rpc.TCP ? "T" : "U");
str.append(getClientAddress().getHostAddress());
str.append(":");
str.append(getClientPort());
} else
str.append("<Unknown>");
// Dump the call/response header
if (getMessageType() == Rpc.Call)
{
// Request packet
str.append("-Call,XID=0x");
str.append(Integer.toHexString(getXID()));
str.append(",RpcVer=");
str.append(getRpcVersion());
str.append(",ProgId=");
str.append(getProgramId());
str.append(",ProgVer=");
str.append(getProgramVersion());
str.append(",Proc=");
str.append(getProcedureId());
str.append(",CredType=");
str.append(getCredentialsType());
str.append(",CredLen=");
str.append(getCredentialsLength());
str.append(",VerfType");
str.append(getVerifierType());
str.append(",VerfLen=");
str.append(getVerifierLength());
str.append(",ParamLen=");
str.append(getProcedureParameterLength());
} else
{
// Response packet
str.append("-Reply,XID=0x");
str.append(Integer.toHexString(getXID()));
if (getReplyState() == Rpc.CallAccepted)
{
// Request accepted response
str.append(",Accepted");
} else
{
// Request denied response
str.append(",Denied");
if (getRejectStatus() == Rpc.StsRpcMismatch)
{
str.append(",RpcMismatch, Low=");
str.append(getMismatchVersionLow());
str.append("/High=");
str.append(getMismatchVersionHigh());
} else
{
str.append(",AuthError, Status=");
;
str.append(getAuthFailStatus());
}
}
}
// Check if the packet is allocated from a pool
if (isAllocatedFromPool())
str.append(",Pool");
str.append("]");
// Return the string
return str.toString();
}
}