package protocolP2P; import protocolP2P.Payload; import tools.HostItem; import tools.BytesArrayTools; import localException.SizeError; import localException.InternalError; import localException.TransmissionError; import localException.ProtocolError; /** Representation of payload for ratio response. * @author Louis Royer * @author Flavien Haas * @author JS Auge * @version 1.0 */ public class RatioResponse extends Payload { private HostItem hostItem; private long totalUp; private long totalDown; private static final int TOTAL_UP_START_POSITION = PAYLOAD_START_POSITION; private static final int TOTAL_DOWN_START_POSITION = TOTAL_UP_START_POSITION + 8; private static final int PORT_START_POSITION = TOTAL_DOWN_START_POSITION + 8; private static final int HOSTNAME_START_POSITION = PORT_START_POSITION + 2; /** Constructor with hostItem (typically used by tracker) * @param hostItem Host to get ratio of. * @param totalUp total bytes uploaded * @param totalDown total bytes downloaded * @throws InternalError */ public RatioResponse(HostItem hostItem, long totalUp, long totalDown) throws InternalError { super(RequestResponseCode.RATIO_RESPONSE); this.hostItem = hostItem; this.totalUp = totalUp; this.totalDown = totalDown; } /** Constructor (typically used by client/server) with a byte[] parameter containing the Packet received. * @param packet the full Packet received * @throws SizeError * @throws InternalError * @throws ProtocolError * @throws TransmissionError */ protected RatioResponse(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError { super(packet); int size = getPayloadSize(packet); totalUp = BytesArrayTools.readLong(packet, TOTAL_UP_START_POSITION); totalDown = BytesArrayTools.readLong(packet, TOTAL_DOWN_START_POSITION); int port = BytesArrayTools.readInt16Bits(packet, PORT_START_POSITION); String hostname = BytesArrayTools.readString(packet, HOSTNAME_START_POSITION, size - HOSTNAME_START_POSITION + PAYLOAD_START_POSITION); hostItem = new HostItem(hostname, port); } /** Returns a byte[] containing Packet with padding. * This Packet is still incomplete and should not be send directly. * ProtocolP2PPacket will use this method to generate the complete Packet. * @return Packet with padding * @throws InternalError */ protected byte[] toPacket() throws InternalError { String hostname = hostItem.getHostname(); // compute total size int size = HOSTNAME_START_POSITION + hostname.length(); byte[] packet = new byte[size]; // java initialize all to zero // set request/response code packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue; // set Payload size setPayloadSize(size - PAYLOAD_START_POSITION, packet); // write totalUp BytesArrayTools.write(packet, TOTAL_UP_START_POSITION, totalUp); // write totalDown BytesArrayTools.write(packet, TOTAL_DOWN_START_POSITION, totalDown); // write port to Packet try { BytesArrayTools.write16Bits(packet, PORT_START_POSITION, hostItem.getPort()); } catch (SizeError e) { throw new InternalError(); } // write hostname to Packet BytesArrayTools.write(packet, hostname, HOSTNAME_START_POSITION); return packet; } /** HostItem getter. * @return hostItem */ public HostItem getHostItem() { return hostItem; } /** totalUp getter. * @return totalUp */ public long getTotalUp() { return totalUp; } /** totalDown getter. * @return totalDown */ public long getTotalDown() { return totalDown; } }