/*
* SSHTools - Java SSH2 API
*
* Copyright (C) 2002-2003 Lee David Painter and Contributors.
*
* Contributions made by:
*
* Brett Smith
* Richard Pernavas
* Erwin Bolwidt
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package com.sshtools.j2ssh.transport;
import com.sshtools.j2ssh.io.ByteArrayReader;
import com.sshtools.j2ssh.io.ByteArrayWriter;
/**
* <p>
* This class implements the payload portion each message sent by the transport
* protocol. Each message consists of an integer message id followed by a
* variable byte array containing message data.
* </p>
*
* @author Lee David Painter
* @version $Revision: 1.21 $
*
* @since 0.2.0
*/
public abstract class SshMessage {
// The message Id of the message
private int messageId;
/**
* <p>
* Contructs the message.
* </p>
*
* @param messageId the id of the message
*
* @since 0.2.0
*/
public SshMessage(int messageId) {
// Save the message id
this.messageId = messageId;
}
/**
* <p>
* Returns the id of the message
* </p>
*
* @return an integer message id
*
* @since 0.2.0
*/
public final int getMessageId() {
return messageId;
}
/**
* <p>
* Returns the name of the message implementation for debugging purposes.
* </p>
*
* @return the name of the message e.g. "SSH_MSG_DISCONNECT"
*
* @since 0.2.0
*/
public abstract String getMessageName();
/**
* <p>
* Format the message into the payload array for sending by the transport
* protocol. This implementation creates a byte array, writes the message
* id and calls the abstract <code>constructByteArray</code>.
* </p>
*
* @return the payload portion of a transport protocol message
*
* @throws InvalidMessageException if the message is invalid
*
* @since 0.2.0
*/
public final byte[] toByteArray() throws InvalidMessageException {
// Create a writer object to construct the array
ByteArrayWriter baw = new ByteArrayWriter();
// Write the message id
baw.write(messageId);
// Call the abstract method so subclasses classes can add their data
constructByteArray(baw);
// Return the array
return baw.toByteArray();
}
/**
* <p>
* Initializes the message from a byte array.
* </p>
*
* @param data the byte array being read.
*
* @throws InvalidMessageException if the message is invalid
*
* @since 0.2.0
*/
protected final void fromByteArray(ByteArrayReader data)
throws InvalidMessageException {
// Skip the first 5 bytes as this contains the packet length and payload
// length fields
data.skip(5);
int id = data.read();
if (id != messageId) {
throw new InvalidMessageException("The message id " +
String.valueOf(id) +
" is not the same as the message implementation id " +
String.valueOf(messageId));
}
// Call abstract method for subclasses to extract the message specific data
constructMessage(data);
}
/**
* <p>
* Helper method to extract the message id from the complete message data
* recieved by the transport protocol.
* </p>
*
* @param msgdata the transport protocol message
*
* @return the id of the message
*
* @since 0.2.0
*/
public static Integer getMessageId(byte[] msgdata) {
return new Integer(msgdata[5]);
}
/**
* <p>
* Message implementations should implement this method, writing the data
* as exected in the transport protocol message format.
* </p>
*
* @param baw the byte array being written to
*
* @throws InvalidMessageException if the message is invalid
*
* @since 0.2.0
*/
protected abstract void constructByteArray(ByteArrayWriter baw)
throws InvalidMessageException;
/**
* <p>
* Message implementation should implement this method, reading the data as
* expected in the transport protocol message format.
* </p>
*
* @param bar the byte array being read
*
* @throws InvalidMessageException if the message is invalid
*
* @since 0.2.0
*/
protected abstract void constructMessage(ByteArrayReader bar)
throws InvalidMessageException;
}