com.addc.commons.slp.messages.SLPMessageHeader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of addc-slp Show documentation
Show all versions of addc-slp Show documentation
The addc-slp library supplies client classes for registering objects with a Service Location Protocol Daemon and
for looking theses objects up later.
package com.addc.commons.slp.messages;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.addc.commons.slp.SLPConstants;
import com.addc.commons.slp.ServiceLocationException;
/**
* The SLPMessageHeader abstracts the SLP message header information.
*/
public class SLPMessageHeader {
private static final Logger LOGGER= LoggerFactory.getLogger(SLPMessageHeader.class);
private static final int OVERFLOW= 0x80;
private static final int FRESH= 0x40;
private static final int MCAST= 0x20;
private int version;
private int functionId;
private int xid;
private boolean fresh;
private boolean multicast;
private boolean overflow;
private int size;
private Locale locale;
private boolean tcp;
private final int mtu;
/**
* Create a new SLPMessageHeader for reading from data input stream
*
* @param mtu
* The MTU size
*/
public SLPMessageHeader(int mtu) {
this.mtu= mtu;
}
/**
* Create a new SLPMessageHeader.
*
* @param version
* the version number (1 or 2).
* @param functionId
* The function ID.
* @param xid
* The XID.
* @param size
* The size of the message
* @param fresh
* true if the request is fresh.
* @param multicast
* true if the request is multicast.
* @param locale
* The locale to use
* @param tcp
* true
if connection is over TCP
* @param mtu
* The MTU size
*/
public SLPMessageHeader(int version, int functionId, int xid, int size, boolean fresh, boolean multicast,
Locale locale, boolean tcp, int mtu) {
this.version= version;
this.functionId= functionId;
this.xid= xid;
this.fresh= fresh;
this.multicast= multicast;
this.size= size;
this.locale= locale;
this.mtu= mtu;
this.tcp= tcp;
}
/**
* Get the version
*
* @return the version
*/
public int getVersion() {
return version;
}
/**
* Set the version (for testing only)
*
* @param version
* the version to set
*/
void setVersion(int version) {
this.version= version;
}
/**
* Get the functionId
*
* @return the functionId
*/
public int getFunctionId() {
return functionId;
}
/**
* Get the xid
*
* @return the xid
*/
public int getXid() {
return xid;
}
/**
* Get the fresh
*
* @return the fresh
*/
public boolean isFresh() {
return fresh;
}
/**
* Get the multicast
*
* @return the multicast
*/
public boolean isMulticast() {
return multicast;
}
/**
* Get the overflow
*
* @return the overflow
*/
public boolean isOverflow() {
return overflow;
}
/**
* Get the size
*
* @return the size
*/
public int getSize() {
return size;
}
/**
* Get the Locale
*
* @return the Locale
*/
public Locale getLocale() {
return locale;
}
/**
* Get the tcp
*
* @return the tcp
*/
public boolean isTcp() {
return tcp;
}
/**
* Get the mtu
*
* @return the mtu
*/
public int getMTU() {
return mtu;
}
/**
* Write the Message Header to the given output stream
*
* @param dos
* The data output to write to
* @throws IOException
* If there was an error writing to the output
*/
public void write(DataOutput dos) throws IOException {
int flags= 0;
if (functionId == SLPConstants.SRVREG) {
flags|= FRESH;
}
if (multicast) {
flags|= MCAST;
}
if (!tcp && size > mtu) {
flags|= OVERFLOW;
}
dos.writeByte(version);
// Function id (1)
dos.writeByte(functionId);
// length (2 - 4)
dos.write((byte) (size >> 16));
dos.write((byte) ((size >> 8) & 0xFF));
dos.write((byte) (size & 0xFF));
// flags (5)
dos.writeByte(flags);
// reserved and extensions (6-9)
dos.writeByte(0);
dos.writeByte(0);
dos.writeByte(0);
dos.writeByte(0);
// xid (10 - 11)
dos.writeShort(xid);
dos.writeUTF(locale.getLanguage());
}
/**
* Read the fields of the header from the given input
*
* @param dis
* The data input to read from
* @throws IOException
* If there was an I/O error
* @throws ServiceLocationException
* If the header has version 1
*/
public void read(DataInputStream dis) throws IOException, ServiceLocationException {
version= dis.readByte();
if (1 == version) {
dis.readByte(); // funcID
int length= dis.readShort();
byte[] drop= new byte[length - 4];
dis.readFully(drop);
LOGGER.warn("Dropped SLPv1 message");
throw new ServiceLocationException("Invalid SLP version " + version, SLPConstants.PARSE_ERROR);
}
functionId= dis.readByte();
size= readInt(dis, 3);
int flags= dis.readByte();
if (!tcp && (flags & OVERFLOW) != 0) {
throw new IOException("Not tcp and everflow flag set, cannot read");
}
overflow= (flags & OVERFLOW) == OVERFLOW;
multicast= (flags & MCAST) == MCAST;
fresh= (flags & FRESH) == FRESH;
dis.readByte();
dis.readByte();
dis.readByte();
dis.readByte();
xid= dis.readShort();
locale= new Locale(dis.readUTF(), "");
}
/**
* parse a numerical value that can be spanned over multiple bytes.
*
* @param input
* the data input stream.
* @param len
* the number of bytes to read.
* @return the int value.
* @throws IOException
* in case of IO errors.
*/
private int readInt(final DataInputStream input, final int len) throws IOException {
int value= 0;
for (int i= 0; i < len; i++) {
value<<= 8;
value+= input.readByte() & 0xff;
}
return value;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy