package com.quickserverlab.quickcached.binary; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.logging.Level; import java.util.logging.Logger; import com.quickserverlab.quickcached.HexUtil; import com.quickserverlab.quickcached.QuickCached; import com.quickserverlab.quickcached.Util; /** * * @author akshath */ public class BinaryPacket { private static final Logger logger = Logger.getLogger(BinaryPacket.class.getName()); private Header header; private Extras extras; private String key; private String encodedKey; private byte[] value; /* Byte/ 0 | 1 | 2 | 3 | / | | | | |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7| +---------------+---------------+---------------+---------------+ 0/ HEADER / / / / / / / +---------------+---------------+---------------+---------------+ 24/ COMMAND-SPECIFIC EXTRAS (as needed) / +/ (note length in the extras length header field) / +---------------+---------------+---------------+---------------+ m/ Key (as needed) / +/ (note length in key length header field) / +---------------+---------------+---------------+---------------+ n/ Value (as needed) / +/ (note length is total body length header field, minus / +/ sum of the extras and key length body fields) / +---------------+---------------+---------------+---------------+ Total 24 bytes */ public byte[] toBinaryByte() throws IOException { try { StringBuilder sb = new StringBuilder(); sb.append(getHeader().encodedString()); if(getExtras()!=null) sb.append(getExtras().encodedString()); if(getKey()!=null) sb.append(getEncodedKey()); if(getValue()!=null) { sb.append(HexUtil.encode(getValue())); } String encodedValue = sb.toString(); if(QuickCached.DEBUG) logger.fine("encodedValue: "+encodedValue); return HexUtil.decodeToByte(encodedValue); } catch(Exception e) { logger.warning("Error: "+e); e.printStackTrace(); throw new IOException("Error: "+e); } } public static BinaryPacket parseRequest(RequestHeader header, byte[] bodyData) throws Exception { try { String hexData = HexUtil.encode(bodyData); if(hexData.length()!=header.getTotalBodyLength()*2) throw new IllegalArgumentException("Bad Body passed: "+hexData); BinaryPacket bp = new BinaryPacket(); bp.setHeader(header); int pos = 0; if(header.getExtrasLength()>0) { Extras extras = new Extras(); if(header.getOpcode().equals("05") || header.getOpcode().equals("06") || header.getOpcode().equals("15") || header.getOpcode().equals("16")) {//incr/decr if(header.getExtrasLength()>=8) {//Delta extras.setDelta(hexData.substring(0, 16)); pos = 16; } if(header.getExtrasLength()>=16) {//InitalValue extras.setInitalValue(hexData.substring(pos, pos+16)); pos = pos + 16; } if(header.getExtrasLength()>=20) {//Expiration extras.setExpiration(hexData.substring(pos, pos+8)); pos = pos + 8; } } else { if(header.getExtrasLength()>=4) {//flag extras.setFlags(hexData.substring(0, 8)); pos = 8; } if(header.getExtrasLength()>=8) {//Expiration extras.setExpiration(hexData.substring(pos, pos + 8)); pos = pos + 8; } } bp.setExtras(extras); } if(header.getKeyLength()>0) { int endPos = pos+(header.getKeyLength()*2); String hexKey = hexData.substring(pos, endPos); pos = endPos; bp.setEncodedKey(hexKey); } int len = header.getExtrasLength()+header.getKeyLength(); if(header.getTotalBodyLength() > len) { String value = hexData.substring(pos); bp.setValue(HexUtil.decodeToByte(value)); } return bp; } catch(Exception e) { logger.warning("Error: "+e); throw e; } } public Header getHeader() { return header; } public void setHeader(Header header) { this.header = header; } public Extras getExtras() { return extras; } public void setExtras(Extras extras) { this.extras = extras; } public String getKey() { return key; } public String getEncodedKey() throws UnsupportedEncodingException { return HexUtil.encode(key); } public void setEncodedKey(String encodedKey) throws UnsupportedEncodingException { this.encodedKey = encodedKey; if(encodedKey!=null) key = HexUtil.decodeToString(encodedKey); } public void setKey(String key) throws UnsupportedEncodingException { this.key = key; if(key!=null) encodedKey = HexUtil.encode(key); } public byte[] getValue() { return value; } public void setValue(byte[] value) { this.value = value; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[BinaryPacket {"); sb.append(getHeader()); if(getExtras()!=null) sb.append(getExtras()); sb.append(", Key:"); if(getKey()!=null) sb.append(getKey()); sb.append(", Value:"); if(getValue()!=null) { try { sb.append(new String(getValue(), HexUtil.getCharset())); } catch (UnsupportedEncodingException ex) { Logger.getLogger(BinaryPacket.class.getName()).log(Level.SEVERE, null, ex); } } sb.append("}]"); return sb.toString(); } }