@Override protected void startInternal() throws Exception { c_logger.info(StrUtil.join("Starting ", this, "...")); m_stopped = false; final Configuration conf = m_conf; InetAddress bindAddr = null; final String host = conf.bindAddr(); if (host != null) bindAddr = InetAddress.getByName(host); final ServerSocketChannel ssc = ServerSocketChannel.open(); try { final ServerSocket socket = ssc.socket(); initSocket(socket, conf); final SocketAddress ep = new InetSocketAddress(bindAddr, conf.port()); final Integer backlog = conf.backlog(); if (backlog == null) socket.bind(ep); else socket.bind(ep, backlog); m_ssc = ssc; m_acceptor.doAccept(this); c_logger.info(StrUtil.join(this, " started, listening on ", socket.getLocalSocketAddress())); } catch (Exception e) { try { ssc.close(); } catch (Throwable t) { } c_logger.error(StrUtil.join(this, " failed to start"), e); m_ssc = null; throw e; } }
private void updateFilters(Configuration newConf) { final String[] newNames = newConf == null ? StrUtil.getEmptyStringArray() : newConf.filters(); String[] oldNames = StrUtil.getEmptyStringArray(); final IFilterManager fm = m_fm; if (m_conf == null) m_filters = fm.getFilters(oldNames); else oldNames = m_conf.filters(); if (Arrays.equals(newNames, oldNames)) return; m_filters = fm.getFilters(newNames); fm.ungetFilters(oldNames); }
@Override public void onSessionConnectTimedOut(ISession session) { Object msg = session.detach(); c_logger.warn(StrUtil.join(session, ": CONNECT_TIMEOUT, ", StrUtil.getLineSeparator(), msg)); if (msg instanceof Closeable) { try { ((Closeable) msg).close(); } catch (Throwable t) { c_logger.error(StrUtil.join(session, "Failed to close message: ", msg), t); } } }
@Override public void onSessionReadTimedOut(ISession session) { Object msg = session.withdraw(IoConstants.FID_TCPCLIENT); c_logger.warn(StrUtil.join(session, ": READ_TIMEOUT, ", StrUtil.getLineSeparator(), msg)); if (msg instanceof Closeable) { try { ((Closeable) msg).close(); } catch (Throwable t) { c_logger.error( StrUtil.join(session, "Failed to close message: ", StrUtil.getLineSeparator(), msg), t); } } }
@Override public void onChannelException(IChannel channel, Throwable t) { try { c_logger.error( StrUtil.join(channel, "(remoteAddr=", channel.remoteAddress(), ") got an error"), t); final ISessionListener<I, O> listener = m_listener; if (listener != null) listener.onSessionException(channel, t); } catch (Throwable e) { c_logger.error( StrUtil.join(channel, "(remoteAddr=", channel.remoteAddress(), ") Unexpected Error: "), e); } finally { channel.close(); } }
@Override protected void stopInternal(int options) { c_logger.info(StrUtil.join("Stopping ", this, "...")); m_stopped = true; try { m_ssc.close(); } catch (Throwable t) { c_logger.error(StrUtil.join(this, " failed to close ServerSocketChannel"), t); } m_ssc = null; if (options == 0) { closeChannels(); } c_logger.info(StrUtil.join(this, " stopped")); }
@Override public void onSessionException(ISession session, Throwable t) { Object msg = session.withdraw(IoConstants.FID_TCPCLIENT); if (msg == null) msg = session.detach(); if (msg == null) c_logger.error(StrUtil.join(session, " got an error"), t); else { c_logger.error(StrUtil.join(session, " got an error: ", StrUtil.getLineSeparator(), msg), t); if (msg instanceof Closeable) { try { ((Closeable) msg).close(); } catch (Throwable e) { c_logger.error( StrUtil.join(session, "Failed to close: ", StrUtil.getLineSeparator(), msg), e); } } } }
@Override public void onMessage(IMessage message) { Object attachment = message.attachment(); if (attachment == null) { c_logger.warn(StrUtil.join(this, " consumes a null message: ", message)); message.close(); return; } m_ss.write(null, message); }
@Override public void write(ISession session, O msg) { final ConcurrentHashMap<Long, IChannel> channels = m_channels; if (channels == null) return; final IChannel channel = channels.get(session.id()); if (channel != null) { channel.write(msg); return; } final Object remoteAddr = session.remoteAddress(); c_logger.warn( StrUtil.join( session, "(remoteAddr=", remoteAddr, ") failed to send(channel closed): ", StrUtil.getLineSeparator(), msg)); if (msg instanceof AutoCloseable) { try { ((AutoCloseable) msg).close(); } catch (Throwable t) { c_logger.error( StrUtil.join( session, "(remoteAddr=", remoteAddr, ") failed to close message: ", StrUtil.getLineSeparator(), msg), t); } } }
@Override public void onChannelClosed(IChannel channel) { c_logger.debug("{}(remoteAddr={}): CLOSED", channel, channel.remoteAddress()); final ConcurrentHashMap<Long, IChannel> channels = m_channels; if (channels != null) channels.remove(channel.id()); final ISessionListener<I, O> listener = m_listener; if (listener != null) { try { listener.onSessionClosed(channel); } catch (Throwable t) { c_logger.error( StrUtil.join(channel, "(remoteAddr=", channel.remoteAddress(), ") Unexpected Error: "), t); } } }
@Override protected boolean updateInternal(Map<String, ?> properties) throws Exception { final String id = (String) properties.get(IoConstants.SERVICE_ID); m_caption = StrUtil.join("TcpServer[", id, "]"); final Configuration newConf = new Configuration(); newConf.initialize(properties); final Configuration oldConf = m_conf; updateFilters(newConf); final boolean changed = oldConf.isMandatoryChanged(newConf); if (!changed) { final int timeout = newConf.sessionIdleTimeoutInSeconds(); if (timeout == 0) closeChannels(); } m_conf = newConf; return changed; }