| 40 | import javax.net.ServerSocketFactory; |
| 41 | |
| 42 | final class OkHttpServer implements InternalServer { |
| 43 | private static final Logger log = Logger.getLogger(OkHttpServer.class.getName()); |
| 44 | |
| 45 | private final SocketAddress originalListenAddress; |
| 46 | private final ServerSocketFactory socketFactory; |
| 47 | private final ObjectPool<Executor> transportExecutorPool; |
| 48 | private final ObjectPool<ScheduledExecutorService> scheduledExecutorServicePool; |
| 49 | private final OkHttpServerTransport.Config transportConfig; |
| 50 | private final InternalChannelz channelz; |
| 51 | private ServerSocket serverSocket; |
| 52 | private SocketAddress actualListenAddress; |
| 53 | private InternalInstrumented<InternalChannelz.SocketStats> listenInstrumented; |
| 54 | private Executor transportExecutor; |
| 55 | private ScheduledExecutorService scheduledExecutorService; |
| 56 | private ServerListener listener; |
| 57 | private boolean shutdown; |
| 58 | |
| 59 | public OkHttpServer( |
| 60 | OkHttpServerBuilder builder, |
| 61 | List<? extends ServerStreamTracer.Factory> streamTracerFactories, |
| 62 | InternalChannelz channelz) { |
| 63 | this.originalListenAddress = Preconditions.checkNotNull(builder.listenAddress, "listenAddress"); |
| 64 | this.socketFactory = Preconditions.checkNotNull(builder.socketFactory, "socketFactory"); |
| 65 | this.transportExecutorPool = |
| 66 | Preconditions.checkNotNull(builder.transportExecutorPool, "transportExecutorPool"); |
| 67 | this.scheduledExecutorServicePool = |
| 68 | Preconditions.checkNotNull( |
| 69 | builder.scheduledExecutorServicePool, "scheduledExecutorServicePool"); |
| 70 | this.transportConfig = new OkHttpServerTransport.Config(builder, streamTracerFactories); |
| 71 | this.channelz = Preconditions.checkNotNull(channelz, "channelz"); |
| 72 | } |
| 73 | |
| 74 | @Override |
| 75 | public void start(ServerListener listener) throws IOException { |
| 76 | this.listener = Preconditions.checkNotNull(listener, "listener"); |
| 77 | ServerSocket serverSocket = socketFactory.createServerSocket(); |
| 78 | try { |
| 79 | serverSocket.bind(originalListenAddress); |
| 80 | } catch (IOException t) { |
| 81 | serverSocket.close(); |
| 82 | throw t; |
| 83 | } |
| 84 | |
| 85 | this.serverSocket = serverSocket; |
| 86 | this.actualListenAddress = serverSocket.getLocalSocketAddress(); |
| 87 | this.listenInstrumented = new ListenSocket(serverSocket); |
| 88 | this.transportExecutor = transportExecutorPool.getObject(); |
| 89 | // Keep reference alive to avoid frequent re-creation by server transports |
| 90 | this.scheduledExecutorService = scheduledExecutorServicePool.getObject(); |
| 91 | channelz.addListenSocket(this.listenInstrumented); |
| 92 | transportExecutor.execute(this::acceptConnections); |
| 93 | } |
| 94 | |
| 95 | private void acceptConnections() { |
| 96 | try { |
| 97 | while (true) { |
| 98 | Socket socket; |
| 99 | try { |