package org.kne.cloud.network.srv6; import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.klalb.KLALBPacket; public class IPv6SegmentRoutingTLV extends NetworkPacket { public static final int PAD1=0; public static final int PADN=4; public static final int HMAC=5; public static final int SEQS=7; public static final int ACKSEQS=8; private int headerLength=2; public int getHeaderLength() { return headerLength; } private boolean isDefault; protected volatile ByteBuffer header; private ByteBuffer data; public IPv6SegmentRoutingTLV(ByteBuffer header ) { this(header,true); } public ByteBuffer getData() { return data; } public IPv6SegmentRoutingTLV(ByteBuffer header ,boolean isDefault ) { super(); this.header = header; this.isDefault=isDefault; if(getType()==PAD1) headerLength=1; if(isDefault&&(headerLength>1)) { data=ByteBuffer.allocate(512); } } public IPv6SegmentRoutingTLV(int type) { this(type,true); } public IPv6SegmentRoutingTLV(int type,boolean isDefault) { super(); this.header=ByteBuffer.allocate(2); this.isDefault=isDefault; header.put((byte) type); if(type==PAD1) { headerLength=1; } if(isDefault&&(headerLength>1)) { data=ByteBuffer.allocate(512); } } @Override public long getLength() { return headerLength+(isDefault?data.limit():0); } public static IPv6SegmentRoutingTLV readIPv6SegmentRoutingTLVFromChannel(ReadableByteChannel din) throws IOException { ByteBuffer bbf= ByteBuffer.allocate(2); bbf.limit(1); while (bbf.hasRemaining()) { if (din.read(bbf) == -1) { return null; } } int type=bbf.get(0)&0xff; IPv6SegmentRoutingTLV rtlv; switch(type) { case PAD1: rtlv=new PAD1SegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; case PADN: rtlv=new PADNSegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; case SEQS: rtlv=new SEQSSegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; case ACKSEQS: rtlv=new ACKSEQSSegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; default: rtlv=new IPv6SegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; } } public static void writeIPv6SegmentRoutingTLVToChannel(WritableByteChannel dto,IPv6SegmentRoutingTLV tlv) throws IOException { tlv.writeToChannel(dto); } @Override public void writeToChannel(WritableByteChannel dto) throws IOException { if(isDefault&&(headerLength>1)) { setDataLength(data.limit()); } header.limit(headerLength); dto.write(header.slice(0,header.limit())); if(isDefault&&(headerLength>1)) { dto.write(data.slice(0, data.limit())); } } @Override public void readFromChannel(ReadableByteChannel din, long length) throws IOException { header.limit(1); while (header.hasRemaining()) { if (din.read(header) == -1) { throw new EOFException(); } } if(headerLength>1) { header.limit(2); while (header.hasRemaining()) { if (din.read(header) == -1) { throw new EOFException(); } } } header.flip(); if(isDefault&&(headerLength>1)) { data.clear(); data.limit(getDataLength()); while(data.hasRemaining()){ if(din.read(data)==-1) { throw new EOFException(); } } data.flip(); } } @Override protected boolean needEndPosition() { return false; } public int getType() { return header.get(0)&0xff; } public void setType(int type) { header.put(0,(byte) type); } public int getDataLength() { return header.get(1)&0xff; } public void setDataLength(int dataLength) { header.put(1,(byte) dataLength); } }