org.filesys.smb.mailslot.SMBMailslotPacket Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfileserver Show documentation
Show all versions of jfileserver Show documentation
Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems
/*
* 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';
}
}