package org.voovan.network; import org.voovan.network.exception.ReadMessageException; import org.voovan.network.exception.SendMessageException; import org.voovan.tools.ByteBufferChannel; import org.voovan.tools.TEnv; import org.voovan.tools.TObject; import org.voovan.tools.log.Logger; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 会话抽象类 * * @author helyho * * Voovan Framework. * WebSite: https://github.com/helyho/Voovan * Licence: Apache v2 License */ public abstract class IoSession<T extends SocketContext> { private Map<Object, Object> attributes; private SSLParser sslParser; private boolean receiving; private MessageLoader messageLoader; private ByteBufferChannel byteBufferChannel; private T socketContext; /** * 构造函数 * @param socketContext socketContext对象 */ public IoSession(T socketContext){ attributes = new ConcurrentHashMap<Object, Object>(); this.socketContext = socketContext; byteBufferChannel = new ByteBufferChannel(socketContext.getBufferSize()); messageLoader = new MessageLoader(this); } protected boolean isReceiving() { return receiving; } protected void setReceiving(boolean receiving) { this.receiving = receiving; } /** * 获取接收的输出流 * * @return 接收的输出流 */ public ByteBufferChannel getByteBufferChannel() { return byteBufferChannel; } /** * 获取 SSLParser * @return SSLParser对象 */ public SSLParser getSSLParser() { return sslParser; } /** * 获取 SSLParser * @param sslParser SSL解析对象 */ protected void setSSLParser(SSLParser sslParser) { if(this.sslParser==null){ this.sslParser = sslParser; } } /** * 获取会话参数 * @param key 参数名 * @return 参数对象 */ public Object getAttribute(Object key) { return attributes.get(key); } /** * 设置会话参数 * @param key 参数名 * @param value 参数对象 */ public void setAttribute(Object key, Object value) { this.attributes.put(key, value); } /** * 移除会话参数 * @param key 参数名 */ public void removeAttribute(Object key) { this.attributes.remove(key); } /** * 检查会话参数是否存在 * @param key 参数名 * @return 是否包含 */ public boolean containAttribute(Object key) { return this.attributes.containsKey(key); } /** * 获取本地 IP 地址 * @return 本地 IP 地址 */ public abstract String loaclAddress(); /** * 获取本地端口 * @return 返回-1为没有取到本地端口 */ public abstract int loaclPort(); /** * 获取对端 IP 地址 * @return 对端 ip 地址 */ public abstract String remoteAddress(); /** * 获取对端端口 * @return 返回-1为没有取到对端端口 */ public abstract int remotePort(); /** * 获取 socket 连接上下文 * @return socket 连接上下文, 连接断开时返回的是null */ public T socketContext() { return socketContext; }; /** * 读取消息到缓冲区 * @param buffer 接收数据的缓冲区 * @return 接收数据大小 * @throws IOException IO 异常 */ protected abstract int read0(ByteBuffer buffer) throws IOException; /** * 发送消息 * 注意直接调用不会出发 onSent 事件 * @param buffer 发送缓冲区 * @return 读取的字节数 * @throws IOException IO 异常 */ protected abstract int send0(ByteBuffer buffer) throws IOException; /** * 同步读取消息 * 消息会经过 filter 的 decoder 函数处理后再返回 * @return 读取出的对象 * @throws ReadMessageException 读取消息异常 */ public Object syncRead() throws ReadMessageException { Object readObject = null; while(true){ readObject = getAttribute("SocketResponse"); if(readObject!=null){ removeAttribute("SocketResponse"); break; }else { Exception exception = TObject.cast(getAttribute("SocketException")); if (exception != null) { removeAttribute("SocketException"); throw new ReadMessageException("Method syncRead error! Error by " + exception.getClass().getSimpleName() + ". " + exception.getMessage(), exception); } } if(!isConnected()){ break; } TEnv.sleep(1); } return readObject; } /** * 同步发送消息 * 消息会经过 filter 的 encoder 函数处理后再发送 * @param obj 要发送的对象 * @throws SendMessageException 消息发送异常 */ public void syncSend(Object obj) throws SendMessageException{ //等待 ssl 握手完成 while(sslParser!=null && !sslParser.handShakeDone){ TEnv.sleep(1); } if (obj != null) { try { obj = EventProcess.filterEncoder(this,obj); EventProcess.sendMessage(this, obj); }catch (Exception e){ throw new SendMessageException("Method syncSend error! Error by "+ e.getClass().getSimpleName() + ".",e); } } } /** * 设置是否使用分割器读取 * @param useSpliter true 使用分割器读取,false 不使用分割器读取,且不会出发 onRecive 事件 */ public void enabledMessageSpliter(boolean useSpliter) { messageLoader.setUseSpliter(useSpliter); } /** * 发送SSL消息 * 注意直接调用不会出发 onSent 事件 * @param buffer byte缓冲区 * @return 发送的数据大小 */ public int send(ByteBuffer buffer){ try { if(sslParser!=null && sslParser.isHandShakeDone()) { sslParser.warpData(buffer); return buffer.limit(); }else{ return send0(buffer); } } catch (IOException e) { Logger.error("Send data failed." + e.getMessage(),e); } return -1; } /** * 直接从缓冲区读取数据 * @param byteBuffer 字节缓冲对象ByteBuffer,读取 前需要使用 enabledMessageSpliter(false) 停止分割器的工作,除非有特殊的需求. * @return 读取的字节数 * @throws IOException IO异常 * */ public int read(ByteBuffer byteBuffer) throws IOException { int readSize = -1; readSize = this.read0(byteBuffer); if(!this.isConnected() && readSize <= 0){ readSize = -1; } return readSize; } /** * 获取消息处理类 * @return 消息处理类 */ public MessageLoader getMessageLoader() { return messageLoader; } /** * 获取消息分割处理类 * @return 消息分割处理类 */ protected abstract MessageSplitter getMessagePartition(); /** * 会话是否连接 * @return true: 连接,false: 关闭 */ public abstract boolean isConnected(); /** * 会话是否打开 * @return true: 打开,false: 关闭 */ public abstract boolean isOpen(); /** * 关闭会话 * @return 是否关闭 */ public abstract boolean close(); @Override public abstract String toString(); }