/*package org.kne.cloud.network.klalb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.SpeedLimiter;

public class DatagramKLALBPacketLink implements KLALBPacketLink {

	private static final int MTU=1500;
	
	private static final int HEAD=32;
	
	private int packSign=0;
	
	@Override
	public String toString() {
		return new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getLocalSocketAddress())+"←"+new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getRemoteSocketAddress());
	}

	private DatagramSocket ds;

	public DatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException {
		this.ds=connectDatagramSocket;
	}

		private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535);
		private DataOutputStream dos=new DataOutputStream(bos);
	@Override
	public void writePacket(KLALBPacket kp) throws IOException {
		//System.out.println("               TX:"+kp);
		KLALBOutputStream.writeKLALBPacketToStream(dos, kp);
		
	}

	private byte[]bc=new byte[65535];
	DataInputStream dis;
	@Override
	public KLALBPacket readPacket() throws IOException {
		KLALBPacket kp=null;
		do {
		if(dis==null) {
			
			byte[]data=new byte[65535];
		DatagramPacket dp=new DatagramPacket(data, data.length);
		ds.receive(dp);
		
		
		dis=new DataInputStream(new ByteArrayInputStream(bc, 0, dp.getLength()));
		}
		kp=KLALBInputStream.readKLALBPacketFromStream(dis);
		if(kp!=null) {
			break;
		}
		dis=null;
		//System.out.println("               RX:"+kp);
		}while(true);
		return kp;
	}

	@Override
	public void close() throws IOException {
		ds.close();
	}

	@Override
	public boolean isClosed() {
		return ds.isClosed();
	}

	@Override
	public void setSoTimeout(int val) throws SocketException  {
		ds.setSoTimeout(val);
	}

	@Override
	public int getSoTimeout() throws SocketException {
		return	ds.getSoTimeout();
	}

	@Override
	public void flush() throws IOException {
		byte[]bt=bos.toByteArray();
		bos.reset();
		int seq=0;
		int maxseq=(bt.length+MTU-HEAD-1)/(MTU-HEAD);
		int startptr=0;
		while(startptr<bt.length) {
			int copysize=Math.min(bt.length-startptr,MTU-HEAD);
			byte[]data=new byte[copysize+4];
			data[2]=(byte) (packSign>>8);
			data[3]=(byte) packSign;
			data[4]=(byte)seq;
			data[5]=(byte)maxseq;
			System.arraycopy(bt, startptr, data, 6, copysize);
			startptr+=copysize;
		DatagramPacket dp=new DatagramPacket(data,data.length);
		ds.send(dp);
		}
		packSign++;
		packSign=packSign&0xffff;
	}

	@Override
	public boolean isStream() {
		return false;
	}
}*/
package org.kne.cloud.network.klalb;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;

import org.kne.cloud.network.DatagramServerSocket;
import org.kne.cloud.network.MultiProtocolSocketAddress;
import org.kne.cloud.network.NetworkPacket;

public class DatagramKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {

	@Override
	public String toString() {
		return new MultiProtocolSocketAddress("UDP",(InetSocketAddress)ds.getLocalSocketAddress())+"←"+new MultiProtocolSocketAddress("UDP",(InetSocketAddress)ds.getRemoteSocketAddress());
	}

	private DatagramSocket ds;

	public DatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException {
		this.ds=connectDatagramSocket;
	}

		private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535);
		private DataOutputStream dos=new DataOutputStream(bos);
	/*@Override
	public void writeKLALBPacket(KLALBPacket kp) throws IOException {
		//System.out.println("               TX:"+kp);
		KLALBPacket.writeKLALBPacketToStream(dos, kp);
		byte[]bt=bos.toByteArray();
		DatagramPacket dp=new DatagramPacket(bt,bt.length);
		ds.send(dp);
		bos.reset();
	}

	private byte[]bc=new byte[65535];
	DataInputStream dis;
	@Override
	public KLALBPacket readKLALBPacket() throws IOException {
		KLALBPacket kp=null;
		do {
		if(dis==null) {
			if(ds instanceof DatagramServerSocket.SubDatagramSocket) {
				DatagramPacket dp=((DatagramServerSocket.SubDatagramSocket) ds).receive();
				dis=new DataInputStream(new ByteArrayInputStream(dp.getData(), 0, dp.getLength()));
			}else {
		DatagramPacket dp=new DatagramPacket(bc, bc.length);
		ds.receive(dp);
		dis=new DataInputStream(new ByteArrayInputStream(bc, 0, dp.getLength()));
			}
		}
		kp=KLALBPacket.readKLALBPacketFromStream(dis);
		if(kp!=null) {
			break;
		}
		dis=null;
		//System.out.println("               RX:"+kp);
		}while(true);
		return kp;
	}*/
	
	
		byte[]b=new byte[65536];
	@Override
	public void writePacket(ByteBuffer kp) throws IOException {
		int length=kp.remaining();
		kp.get(b,0,length);
		DatagramPacket dp=new DatagramPacket(b,length);
		ds.send(dp);
	}

	byte[]c=new byte[65536];
	@Override
	public ByteBuffer readPacket() throws IOException {
		DatagramPacket dp;
		if(ds instanceof DatagramServerSocket.SubDatagramSocket) {
			 dp=((DatagramServerSocket.SubDatagramSocket) ds).receive();
		}else {
			dp=new DatagramPacket(c, c.length);
			ds.receive(dp);
		}
		ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(dp.getLength());
		bbf.put(dp.getData(),0,dp.getLength());
		bbf.flip();
		return bbf;
	}
	

	@Override
	public void close() throws IOException {
		ds.close();
	}

	@Override
	public boolean isClosed() {
		return ds.isClosed();
	}

	@Override
	public void setSoTimeout(int val) throws SocketException  {
		ds.setSoTimeout(val);
	}

	@Override
	public int getSoTimeout() throws SocketException {
		return	ds.getSoTimeout();
	}

	@Override
	public void flush() throws IOException {
		
		
	}

	@Override
	public boolean isStream() {
		return false;
	}

	
}
