/* * MyProtocolParser.java * * Created on 2008年05月08日 星期四, 下午9:06 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package grizzlyserver; import com.sun.grizzly.ProtocolParser; import com.sun.grizzly.util.ByteBufferFactory; import com.sun.grizzly.util.WorkerThread; import java.nio.ByteBuffer; /** * * @author kentsang */ public class MyProtocolParser implements ProtocolParser { // saved buffer private ByteBuffer savedBuffer = null; // saved buffer private ByteBuffer packetBuffer = null; public static final byte STX = 0x02; public static final byte ETX = 0x03; // array index of STX in data private int start = -1; // array index of ETX in data private int end = -1; // current position of savedBuffer private int pos = 0; // for debug private static boolean printArray = true; // for debug private static boolean debug = true; /** * Creates a new instance of MyProtocolParser */ public MyProtocolParser() { } public void startBuffer(ByteBuffer bb) { if (savedBuffer != null && savedBuffer != bb) System.out.println("WARNING: savedBuffer wasn't released!"); if (debug) System.out.println("startBuffer / bb = " + bb); if (savedBuffer != null) return; savedBuffer = bb; savedBuffer.flip(); if (debug) System.out.println("startBuffer / bb = " + savedBuffer); if (debug) printByteBuffer(); //partial = false; } public boolean hasMoreBytesToParse() { if (debug) System.out.println("hasMoreBytesToParse()"); if (savedBuffer == null) { if (debug) System.out.println("hasMoreBytesToParse() savedBuffer == null, return false"); return false; } boolean result = pos < savedBuffer.limit(); if (debug) System.out.println("hasMoreBytesToParse() pos / limit / return = " + pos + " / " + savedBuffer.limit() + " / " + result); return result; } public boolean isExpectingMoreData() { boolean isExpectingMore = (start > -1 && end == -1); if (debug) System.out.println(this.toString() + " | isExpectingMoreData() = " + isExpectingMore); return isExpectingMore; } public ByteBuffer getNextMessage() { System.out.print("\r\nGetMessage:printByteBuffer: "); printPacketBuffer(); System.out.println("\r\n"); return packetBuffer; } public boolean hasNextMessage() { if (debug) System.out.print("hasNextMessage() before savedBuffer = " + savedBuffer + " start: " + start + " pos: " + pos + " end: " + end); if (debug) printByteBuffer(); if (savedBuffer == null) return false; if (end != -1) { // If complete packet was just parsed but we have more bytes to parse start = -1; end = -1; } for(; pos -1) { if (debug) System.out.println("ETX !!!! pos = " + pos); end = pos; packetBuffer = createPacketBuffer(savedBuffer, start, end); if (debug) printPacketBuffer(); pos++; return true; } } if (debug) System.out.println("hasNextMessage() start = " + start + " position = " + pos + " end = " + end); return false; } public boolean releaseBuffer() { if (debug) System.out.println("releaseBuffer() pos / savedBuffer = " + savedBuffer.position() + " / " + savedBuffer); boolean saveCurrentParserState = false; if (isExpectingMoreData()) { if (start > 0) { // If we expect more data to come, but start is not aligned to position 0 - align it savedBuffer.position(start); savedBuffer.compact(); pos -= start; start = 0; } else if (savedBuffer.limit() == savedBuffer.capacity()) { // We expect more data, but buffer is full. Reallocate the buffer savedBuffer = reallocateByteBuffer(savedBuffer); } savedBuffer.position(pos); savedBuffer.limit(savedBuffer.capacity()); savedBuffer = null; saveCurrentParserState = true; if (debug) System.out.println("releaseBuffer() saveState. start: " + start + " pos: " + pos + " end: " + end); } else { start = end = -1; pos = 0; if (savedBuffer != null) { savedBuffer.clear(); } savedBuffer = null; if (debug) System.out.println("releaseBuffer() savedBuffer cleared! savedBuffer = null"); } return saveCurrentParserState; } public void printByteBuffer(){ if (!printArray) return; if (debug) System.out.print("PrintByteBuffer (savedBuffer) = " + savedBuffer); if (savedBuffer == null) return; for (int i = 0 ; i < savedBuffer.limit() && i < 100 ; i++) { System.out.print(Integer.toHexString((int)savedBuffer.get(i) & 0xff) + " "); } System.out.println(""); } public void printPacketBuffer(){ if (!printArray) return; if (debug) System.out.print("PrintPacketBuffer (packetBuffer) = " + packetBuffer); if (packetBuffer == null) return; for (int i = 0 ; i < packetBuffer.limit() && i < 100 ; i++) { System.out.print(Integer.toHexString((int)packetBuffer.get(i) & 0xff) + " "); } System.out.println(""); } private static ByteBuffer createPacketBuffer(ByteBuffer srcBuffer, int start, int end) { // Slice source ByteBuffer and get packet ByteBuffer, related to the single packet int currentPos = srcBuffer.position(); int currentLimit = srcBuffer.limit(); srcBuffer.position(start); srcBuffer.limit(end + 1); ByteBuffer packetByteBuffer = srcBuffer.slice(); // Restore saved ByteBuffer srcBuffer.limit(currentLimit); srcBuffer.position(currentPos); return packetByteBuffer; } private ByteBuffer reallocateByteBuffer(ByteBuffer savedBuffer) { savedBuffer.position(0); savedBuffer.limit(savedBuffer.capacity()); ByteBuffer newBuffer = ByteBufferFactory.allocateView(savedBuffer.capacity() * 2, savedBuffer.isDirect()); newBuffer.put(savedBuffer); WorkerThread workerThread = (WorkerThread) Thread.currentThread(); workerThread.setByteBuffer(newBuffer); return newBuffer; } }