1 22 package org.xsocket.stream.io.impl; 23 24 25 import java.io.IOException ; 26 import java.net.BindException ; 27 import java.net.InetSocketAddress ; 28 import java.nio.channels.ServerSocketChannel ; 29 import java.nio.channels.SocketChannel ; 30 import java.util.ArrayList ; 31 import java.util.Collections ; 32 import java.util.HashMap ; 33 import java.util.List ; 34 import java.util.Map ; 35 import java.util.logging.Level ; 36 import java.util.logging.Logger ; 37 38 import javax.net.ssl.SSLContext; 39 40 41 42 import org.xsocket.IDispatcher; 43 import org.xsocket.stream.io.spi.IAcceptor; 44 import org.xsocket.stream.io.spi.IAcceptorCallback; 45 import org.xsocket.stream.io.spi.IIoHandler; 46 import org.xsocket.stream.io.spi.IIoHandlerContext; 47 48 49 50 59 final class Acceptor implements IAcceptor { 60 61 private static final Logger LOG = Logger.getLogger(Acceptor.class.getName()); 62 63 private static final Map <String ,Class > SUPPORTED_OPTIONS = new HashMap <String , Class >(); 64 65 static { 66 SUPPORTED_OPTIONS.put(SO_RCVBUF, Integer .class); 67 SUPPORTED_OPTIONS.put(SO_REUSEADDR, Boolean .class); 68 } 69 70 71 private static final IoProvider IO_PROVIDER = new IoProvider(); 73 private IAcceptorCallback callback = null; 74 private IIoHandlerContext handlerContext = null; 75 76 private boolean isRunning = true; 78 79 80 private InetSocketAddress address = null; 82 private ServerSocketChannel serverChannel = null; 83 private int backlog = 0; 84 85 86 private boolean sslOn = false; 88 private SSLContext sslContext = null; 89 90 91 private final IoSocketDispatcherPool dispatcherPool = new IoSocketDispatcherPool(IoProvider.getReadBufferPreallocationsizeServer(), IoProvider.isUseDirectReadBufferServer()); 93 94 private long handledConnections = 0; 96 97 98 public Acceptor(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress address, int backlog) throws IOException { 99 this(callback, handlerContext, address, backlog, null, false); 100 } 101 102 103 104 public Acceptor(IAcceptorCallback callback, IIoHandlerContext handlerContext, InetSocketAddress address, int backlog, SSLContext sslContext, boolean sslOn) throws IOException { 105 this.callback = callback; 106 this.address = address; 107 this.handlerContext = handlerContext; 108 this.backlog = backlog; 109 this.sslContext = sslContext; 110 this.sslOn = sslOn; 111 112 113 LOG.fine("try to bind server on " + address); 114 115 serverChannel = ServerSocketChannel.open(); 117 serverChannel.configureBlocking(true); 118 119 serverChannel.socket().setReuseAddress(true); } 121 122 123 124 127 public InetSocketAddress getLocalAddress() { 128 return new InetSocketAddress (serverChannel.socket().getInetAddress(), serverChannel.socket().getLocalPort()); 129 } 130 131 132 void setOption(String name, Object value) throws IOException { 133 134 if (name.equals(IAcceptor.SO_RCVBUF)) { 135 serverChannel.socket().setReceiveBufferSize((Integer ) value); 136 137 } else if (name.equals(IAcceptor.SO_REUSEADDR)) { 138 serverChannel.socket().setReuseAddress((Boolean ) value); 139 140 } else { 141 LOG.warning("option " + name + " is not supproted for " + this.getClass().getName()); 142 } 143 } 144 145 146 149 public Object getOption(String name) throws IOException { 150 151 if (name.equals(IAcceptor.SO_RCVBUF)) { 152 return serverChannel.socket().getReceiveBufferSize(); 153 154 } else if (name.equals(IAcceptor.SO_REUSEADDR)) { 155 return serverChannel.socket().getReuseAddress(); 156 157 } else { 158 LOG.warning("option " + name + " is not supproted for " + this.getClass().getName()); 159 return null; 160 } 161 } 162 163 164 public Map <String , Class > getOptions() { 165 return Collections.unmodifiableMap(SUPPORTED_OPTIONS); 166 } 167 168 169 172 public void listen() throws IOException { 173 174 try { 175 setDispatcherPoolSize(Runtime.getRuntime().availableProcessors() + 1); 176 177 serverChannel.socket().bind(address, backlog); 179 180 callback.onConnected(); 181 182 accept(); 184 185 } catch (BindException be) { 186 if (serverChannel != null) { 187 serverChannel.close(); 188 } 189 LOG.info("error occured while binding server on on " + address + ". Reason: " + be.toString()); 190 throw be; 191 } 192 } 193 194 195 private void accept() { 196 dispatcherPool.run(); 197 198 while (isRunning) { 200 try { 201 202 SocketChannel channel = serverChannel.accept(); 204 205 IoSocketDispatcher dispatcher = dispatcherPool.nextDispatcher(); 207 IIoHandler ioHandler = IO_PROVIDER.createIoHandler(handlerContext, false, dispatcher, channel, sslContext, sslOn); 208 209 callback.onConnectionAccepted(ioHandler); 211 handledConnections++; 212 213 } catch (Throwable t) { 214 if (LOG.isLoggable(Level.FINE)) { 215 if (serverChannel.isOpen()) { 218 LOG.fine("error occured while accepting connection: " + t.toString()); 219 } 220 } 221 } 222 223 } } 225 226 227 public void setDispatcherPoolSize(int size) { 228 dispatcherPool.setSize(size); 229 } 230 231 232 public int getDispatcherPoolSize() { 233 return dispatcherPool.getDispatchers().size(); 234 } 235 236 237 public int getReceiveBufferPreallocationSize() { 238 return dispatcherPool.getReceiveBufferPreallocationSize(); 239 } 240 241 242 243 public void setReceiveBufferPreallocationSize(int size) { 244 dispatcherPool.setReceiveBufferPreallocationSize(size); 245 } 246 247 248 public List <String > getOpenConnections() { 249 List <String > result = new ArrayList <String >(); 250 251 for (IDispatcher<IoSocketHandler> dispatcher : dispatcherPool.getDispatchers()) { 252 for (IoSocketHandler handler : dispatcher.getRegistered()) { 253 result.add(handler.toString()); 254 } 255 } 256 257 return result; 258 } 259 260 261 List <IDispatcher<IoSocketHandler>> getDispatchers() { 262 return dispatcherPool.getDispatchers(); 263 } 264 265 266 269 public int getNumberOfOpenConnections() { 270 return getOpenConnections().size(); 271 } 272 273 IoSocketDispatcherPool getDispatcherPool() { 274 return dispatcherPool; 275 } 276 277 280 public long getNumberOfHandledConnections() { 281 return handledConnections; 282 } 283 284 285 public long getNumberOfConnectionTimeouts() { 286 return dispatcherPool.getNumberOfConnectionTimeouts(); 287 } 288 289 public long getNumberOfIdleTimeouts() { 290 return dispatcherPool.getNumberOfIdleTimeouts(); 291 } 292 293 294 297 public void close() throws IOException { 298 if (isRunning) { 299 isRunning = false; 300 301 if (LOG.isLoggable(Level.FINE)) { 302 LOG.fine("closing acceptor"); 303 } 304 305 try { 306 serverChannel.close(); 308 } catch (Exception ignore) { } 309 310 try { 311 dispatcherPool.shutdown(); 312 } catch (Exception ignore) { } 313 314 callback.onDisconnected(); 315 } 316 } 317 } 318 | Popular Tags |