All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.oncrpc.RpcPacket Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

There is a newer version: 1.4.0
Show newest version
/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */

package org.filesys.oncrpc;

import java.io.UnsupportedEncodingException;
import java.net.InetAddress;

import org.filesys.util.DataPacker;
import org.filesys.util.UTF8Normalizer;

/**
 * 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;

    // UTF-8 string normalizer
    private static UTF8Normalizer _utf8Normalizer = new UTF8Normalizer();

    //	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 Rpc.ProtocolId 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;

    // Set the lease time for packets allocated from the pool
    private long m_leaseTime;

    // Associated RPC packet
    private RpcPacket m_assocPacket;

    /**
     * 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 Rpc.ProtocolId
     */
    public final Rpc.ProtocolId getClientProtocol() {
        return m_protocol;
    }

    /**
     * Return the client details as a string
     *
     * @return String
     */
    public final String getClientDetails() {
        if (hasClientAddress() == false)
            return "";

        StringBuffer str = new StringBuffer(32);
        str.append(getClientProtocol().name());
        str.append(getClientAddress().getHostAddress());
        str.append(":");
        str.append(getClientPort());

        return str.toString();
    }

    /**
     * Check if the packet has a lease
     *
     * @return boolean
     */
    public final boolean hasLeaseTime() {
        return m_leaseTime != 0 ? true : false;
    }

    /**
     * Return the packet lease time
     *
     * @return long
     */
    public final long getLeaseTime() {
        return m_leaseTime;
    }

    /**
     * Clear the lease time
     */
    public final void clearLeaseTime() {
        m_leaseTime = 0L;
    }

    /**
     * Set the packet lease time
     *
     * @param tmo long
     */
    public final void setLeaseTime( long tmo) {
        m_leaseTime = tmo;
    }

    /**
     * Check if there is an associated RPC packet
     *
     * @return boolean
     */
    public final boolean hasAssociatedPacket() {
        return m_assocPacket != null ? true : false;
    }

    /**
     * Return the associated packet
     *
     * @return RpcPacket
     */
    public final RpcPacket getAssociatedPacket() {
        return m_assocPacket;
    }

    /**
     * Set the associated RPC packet
     *
     * @param assocPkt RpcPacket
     */
    public final void setAssociatedPacket(RpcPacket assocPkt) {
        m_assocPacket = assocPkt;
    }

    /**
     * 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 length of the request header
     *
     * @return int
     */
    public final int getRequestHeaderLength() {
        int hdrLen = 28 + 8 + 8;

        hdrLen += getCredentialsLength();
        hdrLen += getVerifierLength();

        return hdrLen;
    }

    /**
     * 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 Rpc.MessageType
     */
    public final Rpc.MessageType getMessageType() {
        return Rpc.MessageType.fromInt(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 AuthType
     */
    public final AuthType getCredentialsType() {
        return AuthType.fromInt(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.AcceptSts.Success ? true : false;
    }

    /**
     * Return the reply state
     *
     * @return Rpc.CallStatus
     */
    public final Rpc.CallStatus getReplyState() {
        return Rpc.CallStatus.fromInt(DataPacker.getInt(m_buffer, 8));
    }

    /**
     * Return the reject reply status
     *
     * @return Rpc.RejectSts
     */
    public final Rpc.RejectSts getRejectStatus() {
        return Rpc.RejectSts.fromInt(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 Rpc.AcceptSts
     */
    public final Rpc.AcceptSts getAcceptStatus() {
        int pos = DataPacker.getInt(m_buffer, 16) + 20;
        return Rpc.AcceptSts.fromInt(DataPacker.getInt(m_buffer, pos));
    }

    /**
     * Align the buffer position on a longword/32bit boundary
     */
    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.getBytes().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 UTF-8 string
     *
     * @param str String
     */
    public final void packUTF8String(String str) {
        byte[] strByts = null;

        try {
            if (str != null)
                strByts = str.getBytes("UTF-8");
        }
        catch (Exception ex) {
        }

        DataPacker.putInt(strByts != null ? strByts.length : 0, m_buffer, m_pos);
        m_pos += 4;
        if (str != null) {
            System.arraycopy(strByts, 0, m_buffer, m_pos, strByts.length);
            m_pos += strByts.length;
            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().intValue(), 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 UTF-8 string
     *
     * @return String
     */
    public final String unpackUTF8String() {
        int len = unpackInt();

        String str = "";
        if (len > 0) {

            // Check for any bytes with the high bit set, run the string through
            // the UTF-8 normalizer if any are found
            boolean utf8 = false;
            int idx = 0;

            while (utf8 == false && idx < len) {
                if (((int) m_buffer[m_pos + idx] & 0x80) != 0)
                    utf8 = true;
                else
                    idx++;
            }

            // Normalize the UTF-8 bytes
            if (utf8 == true) {

                // Create a UTF8 string and normalize
                try {
                    str = new String(m_buffer, m_pos, len, "UTF8");
                    str = _utf8Normalizer.normalize(str);
                }
                catch (UnsupportedEncodingException ex) {
                }
            } else {

                // Unpack the bytes into a string
                str = DataPacker.getString(m_buffer, m_pos, len);
            }

            // Update the buffer position
            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) {
            if (len > buf.length)
                System.arraycopy(m_buffer, m_pos, buf, 0, buf.length);
            else
                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 Rpc.ProtocolId
     */
    public final void setClientDetails(InetAddress addr, int port, Rpc.ProtocolId 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 Rpc.MessageType
     */
    public final void setMessageType(Rpc.MessageType msgType) {
        DataPacker.putInt(msgType.intValue(), 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 Rpc.CallStatus
     */
    public final void setReplyState(Rpc.CallStatus replySts) {
        DataPacker.putInt(replySts.intValue(), m_buffer, m_offset + 8);
    }

    /**
     * Set the reject status
     *
     * @param rejSts Rpc.RejectSts
     */
    public final void setRejectStatus(Rpc.RejectSts rejSts) {
        DataPacker.putInt(rejSts.intValue(), 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 Rpc.AuthSts
     */
    public final void setAuthFailStatus(Rpc.AuthSts authSts) {
        DataPacker.putInt(authSts.intValue(), 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.MessageType.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.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Accepted);

        //	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.AcceptSts.Success.intValue(), 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.MessageType.Reply;

        // Set the reply header
        setMessageType(Rpc.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Accepted);

        //	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.AcceptSts.Success.intValue(), 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.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Denied);
        setRejectStatus(Rpc.RejectSts.RpcMismatch);
        setRpcMismatch(Rpc.RpcVersion, Rpc.RpcVersion);

        setLength(ResponseMismatchLen);
    }

    /**
     * Build an RPC authentication failure response
     *
     * @param stsCode Rpc.AuthSts
     */
    public final void buildAuthFailResponse(Rpc.AuthSts stsCode) {
        setMessageType(Rpc.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Denied);
        setRejectStatus(Rpc.RejectSts.AuthError);
        setAuthFailStatus(stsCode);

        setLength(ResponseAuthFailLen);
    }

    /**
     * Build an RPC accept error response
     *
     * @param stsCode Rpc.AcceptSts
     */
    public final void buildAcceptErrorResponse(Rpc.AcceptSts stsCode) {
        setMessageType(Rpc.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Accepted);

        //	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.intValue(), 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.MessageType.Reply);
        setReplyState(Rpc.CallStatus.Accepted);

        //	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.AcceptSts.ProgMismatch.intValue(), 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().name());
            str.append(getClientAddress().getHostAddress());
            str.append(":");
            str.append(getClientPort());
        } else
            str.append("");

        //	Dump the call/response header
        if (getMessageType() == Rpc.MessageType.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.CallStatus.Accepted) {

                //	Request accepted response
                str.append(",Accepted");
            } else {

                //	Request denied response
                str.append(",Denied");

                if (getRejectStatus() == Rpc.RejectSts.RpcMismatch) {
                    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");

        // Check if there is an associated packet
        if ( hasAssociatedPacket())
            str.append(",Assoc");

        str.append("]");

        //	Return the string
        return str.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy