package org.voovan.network.aio;

import org.voovan.network.EventTrigger;
import org.voovan.network.HeartBeat;
import org.voovan.network.MessageLoader;
import org.voovan.tools.ByteBufferChannel;

import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.CompletionHandler;

/**
 * Aio 读取事件
 * 
 * @author helyho
 *
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class ReadCompletionHandler implements CompletionHandler<Integer,  ByteBuffer>{
	private AioSocket aioSocket;
	private ByteBufferChannel netByteBufferChannel;
	private ByteBufferChannel appByteBufferChannel;
	private AioSession session;
	private Method readSSLMethod;
	
	public ReadCompletionHandler(AioSocket aioSocket, ByteBufferChannel byteBufferChannel){
		this.aioSocket = aioSocket;
		this.appByteBufferChannel = byteBufferChannel;
		this.session = aioSocket.getSession();
	}

	@Override
	public void completed(Integer length, ByteBuffer buffer) {
		try {

			if(netByteBufferChannel== null && session.getSSLParser()!=null) {
				netByteBufferChannel = new ByteBufferChannel(session.socketContext().getBufferSize());
			}

			// 如果对端连接关闭,或者 session 关闭,则直接调用 session 的关闭
			if (MessageLoader.isRemoteClosed(buffer, length) || !session.isConnected()) {
				session.getMessageLoader().setStopType(MessageLoader.StopType.STREAM_END);
				session.close();
			} else {
				buffer.flip();

				if (length > 0) {

					// 接收数据
					if(session.getSSLParser()!=null && session.getSSLParser().isHandShakeDone()){
						netByteBufferChannel.writeEnd(buffer);
						buffer = session.getSSLParser().unWarpByteBufferChannel(session, netByteBufferChannel);
					}

					//检查心跳
					HeartBeat.interceptHeartBeat(session, buffer);

					appByteBufferChannel.writeEnd(buffer);

					// 触发 onReceive 事件
					EventTrigger.fireReceiveThread(session);
					
					// 接收完成后重置buffer对象
					buffer.clear();

					// 继续接收 Read 请求
					if(aioSocket.isConnected()) {
						aioSocket.catchRead(buffer);
					}
				}
			}
		} catch (IOException e) {
			// 触发 onException 事件
			session.getMessageLoader().setStopType(MessageLoader.StopType.EXCEPTION);
			EventTrigger.fireExceptionThread(session, e);
		}
		
	}

	@Override
	public void failed(Throwable exc,  ByteBuffer buffer) {
		if((exc instanceof AsynchronousCloseException) ||
				(exc instanceof ClosedChannelException)){
			return;
		}

		if(exc instanceof Exception){

			Exception e = (Exception)exc;

			//兼容 windows 的 "java.io.IOException: 指定的网络名不再可用" 错误
            if(e.getStackTrace()[0].getClassName().contains("sun.nio.ch")){
            	session.close();
                return;
            }

			//触发 onException 事件
			EventTrigger.fireExceptionThread(session, (Exception)exc);
		}
	}

	public void release(){
		if(netByteBufferChannel!=null) {
			netByteBufferChannel.release();
		}
	}
}

@@ -1557,24 +1557,61 @@
 er.flip();%0A%0A
+%09%09%09%09ByteBuffer tempBuffer = buffer;%0A%0A
 %09%09%09%09if (leng
@@ -1764,25 +1764,29 @@
 fer);%0A%09%09%09%09%09%09
-b
+tempB
 uffer = sess
@@ -1923,17 +1923,21 @@
 ession, 
-b
+tempB
 uffer);%0A
@@ -1933,24 +1933,63 @@
 mpBuffer);%0A%0A
+%09%09%09%09%09if(tempBuffer.remaining() %3E 0) %7B%0A%09
 %09%09%09%09%09appByte
@@ -2003,33 +2003,37 @@
 hannel.writeEnd(
-b
+tempB
 uffer);%0A%0A%09%09%09%09%09//
@@ -2021,24 +2021,25 @@
 mpBuffer);%0A%0A
+%09
 %09%09%09%09%09// %E8%A7%A6%E5%8F%91 o
@@ -2055,16 +2055,17 @@
 %E4%BA%8B%E4%BB%B6%0A%09%09%09%09%09
+%09
 EventTri
@@ -2097,16 +2097,23 @@
 ssion);%0A
+%09%09%09%09%09%7D%0A
 %09%09%09%09%09%0A%09%09
@@ -2134,16 +2134,41 @@
 uffer%E5%AF%B9%E8%B1%A1%0A
+%09%09%09%09%09tempBuffer.clear();%0A
 %09%09%09%09%09buf

优化 Aio 的读取