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

org.filesys.smb.mailslot.SMBMailslotPacket 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.smb.mailslot;

import org.filesys.util.DataPacker;

/**
 * SMB Mailslot Packet Class
 *
 * @author gkspencer
 */
public class SMBMailslotPacket {

    //	SMB packet offsets
    public static final int SIGNATURE       = 0;
    public static final int COMMAND         = 4;
    public static final int ERRORCODE       = 5;
    public static final int ERRORCLASS      = 5;
    public static final int ERROR           = 7;
    public static final int FLAGS           = 9;
    public static final int FLAGS2          = 10;
    public static final int PIDHIGH         = 12;
    public static final int SID             = 18;
    public static final int SEQNO           = 20;
    public static final int TID             = 24;
    public static final int PID             = 26;
    public static final int UID             = 28;
    public static final int MID             = 30;
    public static final int WORDCNT         = 32;
    public static final int ANDXCOMMAND     = 33;
    public static final int ANDXRESERVED    = 34;
    public static final int PARAMWORDS      = 33;

    //	SMB packet header length for a transaction type request
    public static final int TRANS_HEADERLEN = 66;

    //	Minimum receive length for a valid SMB packet
    public static final int MIN_RXLEN       = 32;

    //	Default buffer size to allocate for SMB mailslot packets
    public static final int DEFAULT_BUFSIZE = 500;

    //	Flag bits
    public static final int FLG_SUBDIALECT  = 0x01;
    public static final int FLG_CASELESS    = 0x08;
    public static final int FLG_CANONICAL   = 0x10;
    public static final int FLG_OPLOCK      = 0x20;
    public static final int FLG_NOTIFY      = 0x40;
    public static final int FLG_RESPONSE    = 0x80;

    //	Flag2 bits
    public static final int FLG2_LONGFILENAMES  = 0x0001;
    public static final int FLG2_EXTENDEDATTRIB = 0x0002;
    public static final int FLG2_READIFEXE      = 0x2000;
    public static final int FLG2_LONGERRORCODE  = 0x4000;
    public static final int FLG2_UNICODE        = 0x8000;

    //	SMB packet buffer and offset
    private byte[] m_smbbuf;
    private int m_offset;

    //	Define the number of standard parameters for a server response
    private static final int STD_PARAMS = 14;

    //	SMB packet types we expect to receive in a mailslot
    public static final int Transaction     = 0x25;
    public static final int Transaction2    = 0x32;

    /**
     * Default constructor
     */
    public SMBMailslotPacket() {
        m_smbbuf = new byte[DEFAULT_BUFSIZE];
        m_offset = 0;
    }

    /**
     * Class constructor
     *
     * @param buf byte[]
     */
    public SMBMailslotPacket(byte[] buf) {
        m_smbbuf = buf;
        m_offset = 0;
    }

    /**
     * Class constructor
     *
     * @param buf byte[]
     * @param off int
     */
    public SMBMailslotPacket(byte[] buf, int off) {
        m_smbbuf = buf;
        m_offset = off;
    }

    /**
     * Reset the mailslot packet to use the specified buffer and offset
     *
     * @param buf    byte[]
     * @param offset int
     */
    public final void resetPacket(byte[] buf, int offset) {
        m_smbbuf = buf;
        m_offset = offset;
    }

    /**
     * Get the secondary command code
     *
     * @return Secondary command code
     */
    public final int getAndXCommand() {
        return (int) (m_smbbuf[ANDXCOMMAND + m_offset] & 0xFF);
    }

    /**
     * Return the byte array used for the SMB packet
     *
     * @return Byte array used for the SMB packet.
     */
    public final byte[] getBuffer() {
        return m_smbbuf;
    }

    /**
     * Return the total buffer size available to the SMB request
     *
     * @return Total SMB buffer length available.
     */
    public final int getBufferLength() {
        return m_smbbuf.length - m_offset;
    }

    /**
     * Get the data byte count for the SMB packet
     *
     * @return Data byte count
     */
    public final int getByteCount() {

        //	Calculate the offset of the byte count
        int pos = PARAMWORDS + (2 * getParameterCount());
        return (int) DataPacker.getIntelShort(m_smbbuf, pos);
    }

    /**
     * Get the data byte area offset within the SMB packet
     *
     * @return Data byte offset within the SMB packet.
     */
    public final int getByteOffset() {

        //	Calculate the offset of the byte buffer
        int pCnt = getParameterCount();
        int pos = WORDCNT + (2 * pCnt) + 3 + m_offset;
        return pos;
    }

    /**
     * Get the SMB command
     *
     * @return SMB command code.
     */
    public final int getCommand() {
        return (int) (m_smbbuf[COMMAND + m_offset] & 0xFF);
    }

    /**
     * Determine if normal or long error codes have been returned
     *
     * @return boolean
     */
    public final boolean hasLongErrorCode() {
        if ((getFlags2() & FLG2_LONGERRORCODE) == 0)
            return false;
        return true;
    }

    /**
     * Get the SMB error class
     *
     * @return SMB error class.
     */
    public final int getErrorClass() {
        return (int) m_smbbuf[ERRORCLASS + m_offset] & 0xFF;
    }

    /**
     * Get the SMB error code
     *
     * @return SMB error code.
     */
    public final int getErrorCode() {
        return (int) m_smbbuf[ERROR + m_offset] & 0xFF;
    }

    /**
     * Get the SMB flags value.
     *
     * @return SMB flags value.
     */
    public final int getFlags() {
        return (int) m_smbbuf[FLAGS + m_offset] & 0xFF;
    }

    /**
     * Get the SMB flags2 value.
     *
     * @return SMB flags2 value.
     */
    public final int getFlags2() {
        return (int) DataPacker.getIntelShort(m_smbbuf, FLAGS2 + m_offset);
    }

    /**
     * Calculate the total used packet length.
     *
     * @return Total used packet length.
     */
    public final int getLength() {
        return (getByteOffset() + getByteCount()) - m_offset;
    }

    /**
     * Get the long SMB error code
     *
     * @return Long SMB error code.
     */
    public final int getLongErrorCode() {
        return DataPacker.getIntelInt(m_smbbuf, ERRORCODE + m_offset);
    }

    /**
     * Get the multiplex identifier.
     *
     * @return Multiplex identifier.
     */
    public final int getMultiplexId() {
        return DataPacker.getIntelShort(m_smbbuf, MID + m_offset);
    }

    /**
     * Get a parameter word from the SMB packet.
     *
     * @param idx Parameter index (zero based).
     * @return Parameter word value.
     * @throws java.lang.IndexOutOfBoundsException If the parameter index is out of range.
     */
    public final int getParameter(int idx) throws java.lang.IndexOutOfBoundsException {

        //	Range check the parameter index
        if (idx > getParameterCount())
            throw new java.lang.IndexOutOfBoundsException();

        //	Calculate the parameter word offset
        int pos = WORDCNT + (2 * idx) + 1 + m_offset;
        return (int) (DataPacker.getIntelShort(m_smbbuf, pos) & 0xFFFF);
    }

    /**
     * Get the parameter count
     *
     * @return Parameter word count.
     */
    public final int getParameterCount() {
        return (int) m_smbbuf[WORDCNT + m_offset];
    }

    /**
     * Get the process indentifier (PID)
     *
     * @return Process identifier value.
     */
    public final int getProcessId() {
        return DataPacker.getIntelShort(m_smbbuf, PID + m_offset);
    }

    /**
     * Get the tree identifier (TID)
     *
     * @return Tree identifier (TID)
     */
    public final int getTreeId() {
        return DataPacker.getIntelShort(m_smbbuf, TID + m_offset);
    }

    /**
     * Get the user identifier (UID)
     *
     * @return User identifier (UID)
     */
    public final int getUserId() {
        return DataPacker.getIntelShort(m_smbbuf, UID + m_offset);
    }

    /**
     * Return the offset to the data block within the SMB packet. The data block is word aligned
     * within the byte buffer area of the SMB packet. This method must be called after the parameter
     * count and parameter block length have been set.
     *
     * @return int  Offset to the data block area.
     */
    public final int getDataBlockOffset() {

        //  Get the position of the parameter block
        int pos = (getParameterBlockOffset() + getParameter(3)) + m_offset;
        if ((pos & 0x01) != 0)
            pos++;
        return pos;
    }

    /**
     * Return the offset to the data block within the SMB packet. The data block is word aligned
     * within the byte buffer area of the SMB packet. This method must be called after the parameter
     * count has been set.
     *
     * @param prmLen Parameter block length, in bytes.
     * @return int    Offset to the data block area.
     */
    public final int getDataBlockOffset(int prmLen) {

        //  Get the position of the parameter block
        int pos = getParameterBlockOffset() + prmLen;
        if ((pos & 0x01) != 0)
            pos++;
        return pos;
    }

    /**
     * Return the parameter block offset where the parameter bytes should be placed.
     * This method must be called after the paramter count has been set. The parameter
     * offset is word aligned.
     *
     * @return int  Offset to the parameter block area.
     */
    public final int getParameterBlockOffset() {

        //  Get the offset to the byte buffer area of the SMB packet
        int pos = getByteOffset() + m_offset;
        if ((pos & 0x01) != 0)
            pos++;
        return pos;
    }

    /**
     * Return the data block offset.
     *
     * @return int  Offset to data block within packet.
     */
    public final int getRxDataBlock() {
        return getParameter(12) + m_offset;
    }

    /**
     * Return the received transaction data block length.
     *
     * @return int
     */
    public final int getRxDataBlockLength() {
        return getParameter(11);
    }

    /**
     * Get the required transact parameter word (16 bit).
     *
     * @param prmIdx int
     * @return int
     */
    public final int getRxParameter(int prmIdx) {

        //  Get the parameter block offset
        int pos = getRxParameterBlock();

        //  Get the required transact parameter word.
        pos += prmIdx * 2; // 16 bit words
        return DataPacker.getIntelShort(getBuffer(), pos);
    }

    /**
     * Return the position of the parameter block within the received packet.
     *
     * @return int
     */
    public final int getRxParameterBlock() {

        //  Get the offset to the parameter words
        return getParameter(10) + m_offset;
    }

    /**
     * Return the received transaction parameter block length.
     *
     * @return int
     */
    public final int getRxParameterBlockLength() {
        return getParameter(9);
    }

    /**
     * Return the received transaction setup parameter count.
     *
     * @return int
     */
    public final int getRxParameterCount() {
        return getParameterCount() - STD_PARAMS;
    }

    /**
     * Get the required transact parameter int value (32-bit).
     *
     * @param prmIdx int
     * @return int
     */
    public final int getRxParameterInt(int prmIdx) {

        //  Get the parameter block offset
        int pos = getRxParameterBlock();

        //  Get the required transact parameter word.
        pos += prmIdx * 2; // 16 bit words
        return DataPacker.getIntelInt(getBuffer(), pos);
    }

    /**
     * Get the required transact parameter string.
     *
     * @param pos Offset to the string within the parameter block.
     * @return int
     */
    public final String getRxParameterString(int pos) {

        //  Get the parameter block offset
        pos += getRxParameterBlock();

        //  Get the transact parameter string
        byte[] buf = getBuffer();
        int len = (buf[pos++] & 0x00FF);
        return DataPacker.getString(buf, pos, len);
    }

    /**
     * Get the required transact parameter string.
     *
     * @param pos Offset to the string within the parameter block.
     * @param len Length of the string.
     * @return int
     */
    public final String getRxParameterString(int pos, int len) {

        //  Get the parameter block offset
        pos += getRxParameterBlock();

        //  Get the transact parameter string
        byte[] buf = getBuffer();
        return DataPacker.getString(buf, pos, len);
    }

    /**
     * Return the received transaction name.
     *
     * @return String
     */
    public final String getRxTransactName() {

        //  Check if the transaction has a name
        if (getCommand() == Transaction2)
            return "";

        //  Unpack the transaction name string
        int pos = getByteOffset();
        return DataPacker.getString(getBuffer(), pos, getByteCount());
    }

    /**
     * Return the specified transaction setup parameter.
     *
     * @param idx Setup parameter index.
     * @return int
     * @exception ArrayIndexOutOfBoundsException Index out of range
     */
    public final int getSetupParameter(int idx)
            throws java.lang.ArrayIndexOutOfBoundsException {

        //  Check if the setup parameter index is valid
        if (idx >= getRxParameterCount())
            throw new java.lang.ArrayIndexOutOfBoundsException();

        //  Get the setup parameter
        return getParameter(idx + STD_PARAMS);
    }

    /**
     * Return the mailslot opcode
     *
     * @return int
     */
    public final int getMailslotOpcode() {
        try {
            return getSetupParameter(0);
        }
        catch (ArrayIndexOutOfBoundsException ex) {
        }
        return -1;
    }

    /**
     * Return the mailslot priority
     *
     * @return int
     */
    public final int getMailslotPriority() {
        try {
            return getSetupParameter(1);
        }
        catch (ArrayIndexOutOfBoundsException ex) {
        }
        return -1;
    }

    /**
     * Return the mailslot class of service
     *
     * @return int
     */
    public final int getMailslotClass() {
        try {
            return getSetupParameter(2);
        }
        catch (ArrayIndexOutOfBoundsException ex) {
        }
        return -1;
    }

    /**
     * Return the mailslot sub-opcode, the first byte from the mailslot data
     *
     * @return int
     */
    public final int getMailslotSubOpcode() {
        return (int) (m_smbbuf[getMailslotDataOffset()] & 0xFF);
    }

    /**
     * Return the mailslot data offset
     *
     * @return int
     */
    public final int getMailslotDataOffset() {
        return getRxDataBlock();
    }

    /**
     * Initialize a mailslot SMB
     *
     * @param name Mailslot name
     * @param data Request data bytes
     * @param dlen Data length
     */
    public final void initializeMailslotSMB(String name, byte[] data, int dlen) {

        //	Initialize the SMB packet header
        initializeBuffer();

        //	Clear header values
        setFlags(0);
        setFlags2(0);
        setUserId(0);
        setMultiplexId(0);
        setTreeId(0);
        setProcessId(0);

        //	Initialize the transaction
        initializeTransact(name, 17, null, 0, data, dlen);

        //	Initialize the transactin setup parameters for a mailslot write
        setSetupParameter(0, MailSlot.WRITE);
        setSetupParameter(1, 1);
        setSetupParameter(2, MailSlot.UNRELIABLE);
    }

    /**
     * Initialize the transact SMB packet
     *
     * @param name     Transaction name
     * @param pcnt     Total parameter count for this transaction
     * @param paramblk Parameter block data bytes
     * @param plen     Parameter block data length
     * @param datablk  Data block data bytes
     * @param dlen     Data block data length
     */
    protected final void initializeTransact(String name, int pcnt, byte[] paramblk, int plen, byte[] datablk, int dlen) {

        //  Set the SMB command code
        if (name == null)
            setCommand(Transaction2);
        else
            setCommand(Transaction);

        //  Set the parameter count
        setParameterCount(pcnt);

        //  Initialize the parameters
        setParameter(0, plen);    //  total parameter bytes being sent
        setParameter(1, dlen);    //  total data bytes being sent

        for (int i = 2; i < 9; setParameter(i++, 0)) ;

        setParameter(6, 1000);    //	timeout 1 second
        setParameter(9, plen);    //  parameter bytes sent in this packet
        setParameter(11, dlen); //  data bytes sent in this packet

        setParameter(13, pcnt - STD_PARAMS); //  number of setup words

        //  Get the data byte offset
        int pos = getByteOffset();
        int startPos = pos;

        //  Check if this is a named transaction, if so then store the name
        int idx;
        byte[] buf = getBuffer();

        if (name != null) {

            //  Store the transaction name
            byte[] nam = name.getBytes();

            for (idx = 0; idx < nam.length; idx++)
                buf[pos++] = nam[idx];
        }

        //  Word align the buffer offset
        if ((pos % 2) > 0)
            pos++;

        //  Store the parameter block
        if (paramblk != null) {

            //	Set the parameter block offset
            setParameter(10, pos - m_offset);

            //  Store the parameter block
            for (idx = 0; idx < plen; idx++)
                buf[pos++] = paramblk[idx];
        } else {

            //	Clear the parameter block offset
            setParameter(10, 0);
        }

        //  Word align the data block
        if ((pos % 2) > 0)
            pos++;

        //  Store the data block
        if (datablk != null) {

            //	Set the data block offset
            setParameter(12, pos - m_offset);

            //  Store the data block
            for (idx = 0; idx < dlen; idx++)
                buf[pos++] = datablk[idx];
        } else {

            //	Zero the data block offset
            setParameter(12, 0);
        }

        //  Set the byte count for the SMB packet
        setByteCount(pos - startPos);
    }

    /**
     * Set the secondary SMB command
     *
     * @param cmd Secondary SMB command code.
     */
    public final void setAndXCommand(int cmd) {
        m_smbbuf[ANDXCOMMAND + m_offset] = (byte) cmd;
        m_smbbuf[ANDXRESERVED + m_offset] = (byte) 0;
    }

    /**
     * Set the data byte count for this SMB packet
     *
     * @param cnt Data byte count.
     */
    public final void setByteCount(int cnt) {
        int offset = getByteOffset() - 2;
        DataPacker.putIntelShort(cnt, m_smbbuf, offset);
    }

    /**
     * Set the data byte area in the SMB packet
     *
     * @param byts Byte array containing the data to be copied to the SMB packet.
     */
    public final void setBytes(byte[] byts) {
        int offset = getByteOffset() - 2;
        DataPacker.putIntelShort(byts.length, m_smbbuf, offset);

        offset += 2;

        for (int idx = 0; idx < byts.length; m_smbbuf[offset + idx] = byts[idx++]) ;
    }

    /**
     * Set the SMB command
     *
     * @param cmd SMB command code
     */
    public final void setCommand(int cmd) {
        m_smbbuf[COMMAND + m_offset] = (byte) cmd;
    }

    /**
     * Set the SMB error class.
     *
     * @param cl SMB error class.
     */
    public final void setErrorClass(int cl) {
        m_smbbuf[ERRORCLASS + m_offset] = (byte) (cl & 0xFF);
    }

    /**
     * Set the SMB error code
     *
     * @param sts SMB error code.
     */
    public final void setErrorCode(int sts) {
        m_smbbuf[ERROR + m_offset] = (byte) (sts & 0xFF);
    }

    /**
     * Set the SMB flags value.
     *
     * @param flg SMB flags value.
     */
    public final void setFlags(int flg) {
        m_smbbuf[FLAGS + m_offset] = (byte) flg;
    }

    /**
     * Set the SMB flags2 value.
     *
     * @param flg SMB flags2 value.
     */
    public final void setFlags2(int flg) {
        DataPacker.putIntelShort(flg, m_smbbuf, FLAGS2 + m_offset);
    }

    /**
     * Set the multiplex identifier.
     *
     * @param mid Multiplex identifier
     */
    public final void setMultiplexId(int mid) {
        DataPacker.putIntelShort(mid, m_smbbuf, MID + m_offset);
    }

    /**
     * Set the specified parameter word.
     *
     * @param idx Parameter index (zero based).
     * @param val Parameter value.
     */
    public final void setParameter(int idx, int val) {
        int pos = WORDCNT + (2 * idx) + 1 + m_offset;
        DataPacker.putIntelShort(val, m_smbbuf, pos);
    }

    /**
     * Set the parameter count
     *
     * @param cnt Parameter word count.
     */
    public final void setParameterCount(int cnt) {
        m_smbbuf[WORDCNT + m_offset] = (byte) cnt;
    }

    /**
     * Set the process identifier value (PID).
     *
     * @param pid Process identifier value.
     */
    public final void setProcessId(int pid) {
        DataPacker.putIntelShort(pid, m_smbbuf, PID + m_offset);
    }

    /**
     * Set the packet sequence number, for connectionless commands.
     *
     * @param seq Sequence number.
     */
    public final void setSeqNo(int seq) {
        DataPacker.putIntelShort(seq, m_smbbuf, SEQNO + m_offset);
    }

    /**
     * Set the session id.
     *
     * @param sid Session id.
     */
    public final void setSID(int sid) {
        DataPacker.putIntelShort(sid, m_smbbuf, SID + m_offset);
    }

    /**
     * Set the tree identifier (TID)
     *
     * @param tid Tree identifier value.
     */
    public final void setTreeId(int tid) {
        DataPacker.putIntelShort(tid, m_smbbuf, TID + m_offset);
    }

    /**
     * Set the user identifier (UID)
     *
     * @param uid User identifier value.
     */
    public final void setUserId(int uid) {
        DataPacker.putIntelShort(uid, m_smbbuf, UID + m_offset);
    }

    /**
     * Set the specifiec setup parameter within the SMB packet.
     *
     * @param idx Setup parameter index.
     * @param val Setup parameter value.
     */
    public final void setSetupParameter(int idx, int val) {
        setParameter(STD_PARAMS + idx, val);
    }

    /**
     * Initialize the SMB packet buffer.
     */
    private final void initializeBuffer() {

        //	Set the packet signature
        m_smbbuf[SIGNATURE + m_offset] = (byte) 0xFF;
        m_smbbuf[SIGNATURE + 1 + m_offset] = (byte) 'S';
        m_smbbuf[SIGNATURE + 2 + m_offset] = (byte) 'M';
        m_smbbuf[SIGNATURE + 3 + m_offset] = (byte) 'B';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy