package com.robonobo.eon; /* * Eye-Of-Needle * Copyright (C) 2008 Will Morton (macavity@well.com) & Ray Hilton (ray@wirestorm.net) * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import java.nio.ByteBuffer; public abstract class EONPacket { public static final int EON_PROTOCOL_DEON = 1; public static final int EON_PROTOCOL_SEON = 2; // Note: this won't set the IP Endpoints - do that externally public static EONPacket parse(ByteBuffer buf) { int numBytes = buf.remaining(); int sourcePort, destPort, protocol; EonSocketAddress sourceEP, destEP; // All EON packets are at least 40 bits long if (numBytes < 5) return null; // Source Port is bytes 0-1 byte b0 = buf.get(); byte b1 = buf.get(); sourcePort = (b0 << 8) + b1; sourceEP = new EonSocketAddress(null, sourcePort); // Dest Port is bytes 2-3 byte b2 = buf.get(); byte b3 = buf.get(); destPort = (b2 << 8) + b3; destEP = new EonSocketAddress(null, destPort); // Protocol is byte 4 protocol = buf.get(); if (protocol == 1) { // D-EON packet ByteBuffer payload = buf.slice(); DEONPacket thisPacket = new DEONPacket(sourceEP, destEP, payload); return thisPacket; } else if (protocol == 2) { // S-EON packet - must be at least 128 bits long if (numBytes < 14) return null; boolean ack, rst, syn, fin; long seqNum, ackNum; // Flags are the first 4 bits of byte 5 byte b5 = buf.get(); ack = (b5 & 0x80) > 0 ? true : false; rst = (b5 & 0x40) > 0 ? true : false; syn = (b5 & 0x20) > 0 ? true : false; fin = (b5 & 0x10) > 0 ? true : false; // Number of SACK regions is bits 4-5 of byte 5 int numSackRegions = (b5 & 0xC) >> 2; // Sequence number is bytes 6-9 seqNum = 0l; seqNum |= buf.get() & 0xFF; seqNum <<= 8; seqNum |= buf.get() & 0xFF; seqNum <<= 8; seqNum |= buf.get() & 0xFF; seqNum <<= 8; seqNum |= buf.get() & 0xFF; // Acknowledgement number is bytes 10-13 ackNum = 0l; ackNum |= buf.get() & 0xFF; ackNum <<= 8; ackNum |= buf.get() & 0xFF; ackNum <<= 8; ackNum |= buf.get() & 0xFF; ackNum <<= 8; ackNum |= buf.get() & 0xFF; // Up to 3 Sack regions long[] begins = null, ends = null; if (numSackRegions > 0) { begins = new long[numSackRegions]; ends = new long[numSackRegions]; for (int i = 0; i < numSackRegions; i++) { long begin = 0l; begin |= buf.get() & 0xFF; begin <<= 8; begin |= buf.get() & 0xFF; begin <<= 8; begin |= buf.get() & 0xFF; begin <<= 8; begin |= buf.get() & 0xFF; long end = 0l; end |= buf.get() & 0xFF; end <<= 8; end |= buf.get() & 0xFF; end <<= 8; end |= buf.get() & 0xFF; end <<= 8; end |= buf.get() & 0xFF; begins[i] = begin; ends[i] = end; } } ByteBuffer payload = buf.slice(); SEONPacket thisPacket = new SEONPacket(sourceEP, destEP, payload); thisPacket.setACK(ack); thisPacket.setRST(rst); thisPacket.setSYN(syn); thisPacket.setFIN(fin); if (numSackRegions > 0) thisPacket.setSackBlocks(begins, ends); thisPacket.setSequenceNumber(seqNum); thisPacket.setAckNumber(ackNum); return thisPacket; } else { // Unknown protocol return null; } } public abstract EonSocketAddress getDestSocketAddress(); public abstract EonSocketAddress getSourceSocketAddress(); public abstract void setDestSocketAddress(EonSocketAddress endPoint); public abstract void setSourceSocketAddress(EonSocketAddress endPoint); public abstract void toByteBuffer(ByteBuffer buf); public abstract int getProtocol(); public abstract ByteBuffer getPayload(); public abstract int getPayloadSize(); }