package com.limegroup.gnutella.messages.vendor; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.limewire.io.BadGGEPBlockException; import org.limewire.io.BadGGEPPropertyException; import org.limewire.io.GGEP; import org.limewire.service.ErrorService; import com.limegroup.gnutella.messages.BadPacketException; public final class UpdateResponse extends AbstractVendorMessage implements VendorMessage.ControlMessage { private static final int NON_GGEP_VERSION = 1; private static final int OLD_KEY_VERSION = 2; private static final int NEW_KEY_VERSION = 3; public static final int VERSION = 3; private byte [] update; /** * Constructs a new UpdateResponse message from the network. */ UpdateResponse(byte[] guid, byte ttl, byte hops, int version, byte[] payload, Network network) throws BadPacketException { super(guid, ttl, hops, F_LIME_VENDOR_ID, F_UPDATE_RESP, version, payload, network); if (version == NON_GGEP_VERSION) update = payload; else { // try to parse a GGEP block try { GGEP ggep = new GGEP(payload,0,null); if (ggep.hasKey(UpdateRequest.UNCOMPRESSED_UPDATE_KEY)) update = ggep.getBytes(UpdateRequest.UNCOMPRESSED_UPDATE_KEY); else if (ggep.hasKey(UpdateRequest.COMPRESSED_UPDATE_KEY)) update = ggep.getBytes(UpdateRequest.COMPRESSED_UPDATE_KEY); else throw new BadPacketException("no update in GGEP?"); } catch (BadGGEPPropertyException bad) { throw new BadPacketException("bad ggep property"); } catch (BadGGEPBlockException notSoBad) { update = payload; } } } /** * Constructs an outgoing message with the payload being the signed parameter body. */ private UpdateResponse(byte[] body, int version) { super(F_LIME_VENDOR_ID, F_UPDATE_RESP, version, body); } public static UpdateResponse createUpdateResponse(byte [] update, UpdateRequest request) { if(!request.isOldRequest()) { // If it's not an old request, just always toss it in a GGEP. byte[] ggep = createGGEP(request, update); return new UpdateResponse(ggep, VERSION); } else if (!request.hasGGEP()) { // If it's an old request w/o ggep, don't put in GGEP return new UpdateResponse(update, NON_GGEP_VERSION); } else { // Old request w/ ggep, toss in the old GGEP. byte[] ggep = createGGEP(request, update); return new UpdateResponse(ggep, OLD_KEY_VERSION); } } public boolean isNewVersion() { return getVersion() >= NEW_KEY_VERSION; } private static byte[] createGGEP(UpdateRequest request, byte[] update) { GGEP ggep = new GGEP(); if (request.requestsCompressed()) { ggep.putCompressed(UpdateRequest.COMPRESSED_UPDATE_KEY, update); } else { ggep.put(UpdateRequest.UNCOMPRESSED_UPDATE_KEY, update); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { ggep.write(baos); } catch (IOException bad) { ErrorService.error(bad); } return baos.toByteArray(); } public byte[] getUpdate() { return update; } }