package com.limegroup.gnutella.messages; import java.io.IOException; import java.io.InputStream; import java.net.SocketAddress; import com.limegroup.gnutella.messages.Message.Network; /** * A factory for creating Gnutella messages. * <p> * MessageFactory delegates the parsing of specific messages to a MessageParser. * MessageParsers can be installed using * {@link #setParser(byte, com.limegroup.gnutella.messages.MessageFactory.MessageParser)}. * When reading a message from a stream, various optional parameters can be * provided. In all cases, a {@link Network} is required to know which Network * the Message was read from. Optional parameters are <code>softMax</code>, * which can be used to limit the maximum number of hops a message should * travel, <code>headerBuf</code> which can be used as an optimization to * reduce byte[] allocations, and <code>addr</code> which can be used to know * what host this message was read from. * */ public interface MessageFactory { /** * Registers a MessageParser under the provided functionId. * * @param functionId the ID of the function (MessageParser) * @param parser the MessageParser */ public void setParser(byte functionId, MessageParser parser); /** * Returns a MessageParser for the provided functionId or null * if no such MessageParser is registered. */ public MessageParser getParser(byte functionId); /** * @modifies in * @effects reads a packet from the network and returns it as an instance of * a subclass of Message, unless one of the following happens: * <ul> * <li>No data is available: returns null * <li>A bad packet is read: BadPacketException. The client should * be able to recover from this. * <li>A major problem occurs: IOException. This includes reading * packets that are ridiculously long and half-completed messages. * The client is not expected to recover from this. * </ul> * @param network the network the message was read from. */ public Message read(InputStream in, Network network, byte softMax) throws BadPacketException, IOException; /** * @modifies in * @effects reads a packet from the network and returns it as an instance of * a subclass of Message, unless one of the following happens: * <ul> * <li>No data is available: returns null * <li>A bad packet is read: BadPacketException. The client should * be able to recover from this. * <li>A major problem occurs: IOException. This includes reading * packets that are ridiculously long and half-completed messages. * The client is not expected to recover from this. * </ul> */ public Message read(InputStream in, Network network) throws BadPacketException, IOException; /** * @requires buf.length==23 * @effects exactly like Message.read(in), but buf is used as scratch for * reading the header. This is an optimization that lets you avoid * repeatedly allocating 23-byte arrays. buf may be used when this * returns, but the contents are not guaranteed to contain any * useful data. * @param network the network the message was read from. */ public Message read(InputStream in, Network network, byte[] headerBuf, byte softMax) throws BadPacketException, IOException; /** * Reads a message using the specified buffer & network and the default soft * max. */ public Message read(InputStream in, Network network, byte[] headerBuf, SocketAddress addr) throws BadPacketException, IOException; /** * @param network * the network this was received from. * @requires buf.length==23 * @effects exactly like Message.read(in), but buf is used as scratch for * reading the header. This is an optimization that lets you avoid * repeatedly allocating 23-byte arrays. buf may be used when this * returns, but the contents are not guaranteed to contain any * useful data. */ public Message read(InputStream in, Network network, byte[] headerBuf, byte softMax, SocketAddress addr) throws BadPacketException, IOException; /** * Creates a message based on the header & payload. The header, starting at * headerOffset, MUST be >= 19 bytes. Additional headers bytes will be * ignored and the byte[] will be discarded. (Note that the header is * normally 23 bytes, but we don't need the last 4 here.) The payload MUST * be a unique byte[] of that payload. Nothing can write into or change the * byte[]. */ public Message createMessage(byte[] header, byte[] payload, Network network, byte softMax, SocketAddress addr) throws BadPacketException, IOException; /** * The interface for custom MessageParser(s). */ public interface MessageParser { public Message parse(byte[] header, byte[] payload, Network network, byte softMax, SocketAddress addr) throws BadPacketException, IOException; } }