package org.kne.cloud.network.klalb; import java.io.IOException; import java.net.BindException; import java.net.DatagramPacket; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; import java.util.function.BiConsumer; import java.util.function.Supplier; import org.kne.cloud.network.VirtualRawSocketImpl; import org.kne.cloud.network.ipv6.IPv6Packet; import org.kne.cloud.network.ipv6.IPv6Packet.IPv6DefaultPayload; import org.kne.cloud.network.ipv6.IPv6ProtocolRegister; import org.kne.cloud.network.ipv6.IPv6Address; import org.kne.cloud.network.ipv6.IPv6AddressGroup; import org.kne.cloud.network.ipv6.IPv6NetworkLink; import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink; import org.kne.io.KNEChannels; public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements IPv6ProtocolRegister{ private boolean ipHeaderInclude=false; private LoopbackIPv6NetworkLink link; protected volatile Inet6Address remoteaddr; protected volatile Inet6Address localaddr; private int bindProtocolNumber; private volatile int inputchachesize = 1024*1024; protected LoopbackIPv6NetworkLink getLoopbackLink() { return link; } public KLALBVirtualRawSocketImpl(LoopbackIPv6NetworkLink link) { super(); this.link = link; } @Override public void setOption(int optID, Object value) throws SocketException { // TODO 自动生成的方法存根 } @Override public Object getOption(int optID) throws SocketException { // TODO 自动生成的方法存根 return null; } @Override protected void create() throws IOException { } @Override protected void setIPHeaderInclude(boolean ipHeaderInclude) throws IOException { this.ipHeaderInclude=ipHeaderInclude; } @Override protected boolean getIPHeaderInclude() throws IOException { return ipHeaderInclude; } @Override protected void setUseSelectTimeout(boolean useSelect) throws IOException { // TODO 自动生成的方法存根 } @Override protected boolean getUseSelectTimeout() throws IOException { // TODO 自动生成的方法存根 return false; } @Override protected void setSendTimeout(int timeout) throws IOException { // TODO 自动生成的方法存根 } @Override protected int getSendTimeout() throws IOException { // TODO 自动生成的方法存根 return 0; } @Override protected void setReceiveTimeout(int timeout) throws IOException { // TODO 自动生成的方法存根 } @Override protected int getReceiveTimeout() throws IOException { // TODO 自动生成的方法存根 return 0; } @Override protected void close() { link.getProtocolNumberRegister()[bindProtocolNumber]=null; } @Override protected void bind(InetAddress address,int protocolNumber) throws SocketException{ if(protocolNumber<0) { throw new UnsupportedOperationException("unsupprted bind all protocols"); } try { if (address.equals(Inet4Address.getByName("0.0.0.0"))) { address = Inet6Address.getByName("::0"); } } catch (UnknownHostException e) { e.printStackTrace(); } if (!(address instanceof Inet6Address)) { throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address"); } if (!address.isAnyLocalAddress() ) { boolean contains=false; for(IPv6AddressGroup adg:link.getAddressGroups()) { if(adg.checkMatch(IPv6Address.valueOf( address))) { contains=true; break; } } if(!contains) { throw new BindException("must bind to self"); } } localaddr=(Inet6Address) address; this.bindProtocolNumber=protocolNumber; if(link.getProtocolNumberRegister()[protocolNumber]!=null) { throw new BindException("protocol number already bind"); }else { link.getProtocolNumberRegister()[protocolNumber]=this; } } @Override protected void join(InetAddress inetaddr) throws IOException { // TODO 自动生成的方法存根 } @Override protected void leave(InetAddress inetaddr) throws IOException { // TODO 自动生成的方法存根 } @Override protected void joinGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException { // TODO 自动生成的方法存根 } @Override protected void leaveGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException { // TODO 自动生成的方法存根 } @Override protected void send(DatagramPacket p) throws IOException { ByteBuffer buf= ByteBuffer.wrap(p.getData(), p.getOffset(), p.getLength()); if(ipHeaderInclude) { }else { IPv6DefaultPayload pl=new IPv6DefaultPayload(bindProtocolNumber); pl.getData().put(buf); pl.getData().flip(); BiConsumer>cons=link.getReceiveConsumer(); if(cons!=null) { cons.accept(link,() -> { IPv6Packet ipv=new IPv6Packet(); ipv.setVersion(6); ipv.setTrafficClass(0); ipv.setFlowLabel(0); ipv.setHopLimit(255); if(!localaddr.isAnyLocalAddress()) { ipv.setSourceAddress2(localaddr); }else { ipv.setSourceAddress(link.getRouter().getLocator().getAddress()); } InetAddress address= p.getAddress(); if (!(address instanceof Inet6Address)) { throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address"); } ipv.setDestinationAddress2((Inet6Address)address); //ipv.enableECN(); ipv.setPayload(pl); return ipv; }); } } } @Override protected InetAddress peek() throws IOException { return peekNextPacket().getSourceAddress2(); } @Override protected void peekData(DatagramPacket p) throws IOException { IPv6Packet pack=peekNextPacket(); copyTo(pack, p); } private void copyTo(IPv6Packet pack, DatagramPacket p) throws IOException { p.setAddress(pack.getSourceAddress2()); ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength()); if(ipHeaderInclude) { }else { try { pack.getPayload().writeToChannel(KNEChannels.newWritableChannel(buffer)); }catch(BufferOverflowException e) { } } buffer.flip(); p.setLength(buffer.limit()); } @Override protected void receive(DatagramPacket p) throws IOException { IPv6Packet pack=pollNextPacket(); copyTo(pack, p); } private volatile Thread parkThread; private IPv6Packet peekNextPacket() { IPv6Packet pol=null; while(true) { pol=recvQueue.peek(); if(pol!=null) { recvQueueUsed.addAndGet((int) -pol.getPayload().getTotalLength()); return pol; } parkThread=Thread.currentThread(); LockSupport.parkNanos(1000000L); } } private IPv6Packet pollNextPacket() { IPv6Packet pol=null; while(true) { pol=recvQueue.poll(); if(pol!=null) { recvQueueUsed.addAndGet((int) -pol.getPayload().getTotalLength()); return pol; } parkThread=Thread.currentThread(); LockSupport.parkNanos(1000000L); } } private Queue recvQueue = new ConcurrentLinkedQueue(); private AtomicInteger recvQueueUsed=new AtomicInteger(0); @Override public boolean onaccept(IPv6Packet packx) throws IOException { if(recvQueueUsed.get()<=inputchachesize) { if(recvQueue.offer(packx)) { recvQueueUsed.addAndGet((int) packx.getPayload().getTotalLength()); LockSupport.unpark(parkThread); } } return true; } }