package com.limegroup.gnutella.messages; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Allows multiple GGEP blocks to be parsed, storing * the 'secure GGEP' block separately. Can store * the position where the secure block began & ended, * so that the rest of the data can be properly verified. */ public class GGEPParser { private static final Log LOG = LogFactory.getLog(GGEPParser.class); private GGEP normal = null; private GGEP secure = null; private int secureStart = -1; private int secureEnd = -1; /** * Scans through the data, starting at idx, looking for the first * spot that has GGEP_PREFIX_MAGIC_NUMBER, and parses GGEP blocks * from there. * Once a secure block is found, no other GGEPs are parsed. */ public void scanForGGEPs(byte[] data, int idx) { // Find the beginning of the GGEP block. for (; idx < data.length && data[idx] != GGEP.GGEP_PREFIX_MAGIC_NUMBER; idx++); if(idx >= data.length) { LOG.debug("No GGEP in data"); return; // nothing to parse. } int[] storage = new int[1]; GGEP normal = null; GGEP secure = null; int secureStart = -1; int secureEnd = -1; try { while(secure == null && idx < data.length) { // optimization: don't bother constructing (and throwing exception) // if it clearly isn't a GGEP block. if(data[idx] != GGEP.GGEP_PREFIX_MAGIC_NUMBER) break; GGEP ggep = new GGEP(data, idx, storage); if(ggep.hasKey(GGEP.GGEP_HEADER_SECURE_BLOCK)) { secure = ggep; secureStart = idx; secureEnd = storage[0]; break; } else { if(normal == null) normal = ggep; else normal.merge(ggep); idx = storage[0]; storage[0] = -1; } } } catch (BadGGEPBlockException ignored) { LOG.debug("Unable to create ggep", ignored); } this.normal = normal; this.secure = secure; this.secureStart = secureStart; this.secureEnd = secureEnd; } public GGEP getNormalGGEP() { return normal; } public GGEP getSecureGGEP() { return secure; } public int getSecureStartIndex() { return secureStart; } public int getSecureEndIndex() { return secureEnd; } }