1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.thrift.transport; 21 22 import org.slf4j.Logger; 23 import org.slf4j.LoggerFactory; 24 25 import java.io.IOException; 26 import java.net.InetSocketAddress; 27 import java.net.ServerSocket; 28 import java.net.Socket; 29 import java.net.SocketException; 30 31 /** 32 * Wrapper around ServerSocket for Thrift. 33 * 34 */ 35 public class TServerSocket extends TServerTransport { 36 37 private static final Logger LOGGER = LoggerFactory.getLogger(TServerSocket.class.getName()); 38 39 /** 40 * Underlying ServerSocket object 41 */ 42 private ServerSocket serverSocket_ = null; 43 44 /** 45 * Timeout for client sockets from accept 46 */ 47 private int clientTimeout_ = 0; 48 49 public static class ServerSocketTransportArgs extends AbstractServerTransportArgs<ServerSocketTransportArgs> { 50 ServerSocket serverSocket; 51 serverSocket(ServerSocket serverSocket)52 public ServerSocketTransportArgs serverSocket(ServerSocket serverSocket) { 53 this.serverSocket = serverSocket; 54 return this; 55 } 56 } 57 58 /** 59 * Creates a server socket from underlying socket object 60 */ TServerSocket(ServerSocket serverSocket)61 public TServerSocket(ServerSocket serverSocket) throws TTransportException { 62 this(serverSocket, 0); 63 } 64 65 /** 66 * Creates a server socket from underlying socket object 67 */ TServerSocket(ServerSocket serverSocket, int clientTimeout)68 public TServerSocket(ServerSocket serverSocket, int clientTimeout) throws TTransportException { 69 this(new ServerSocketTransportArgs().serverSocket(serverSocket).clientTimeout(clientTimeout)); 70 } 71 72 /** 73 * Creates just a port listening server socket 74 */ TServerSocket(int port)75 public TServerSocket(int port) throws TTransportException { 76 this(port, 0); 77 } 78 79 /** 80 * Creates just a port listening server socket 81 */ TServerSocket(int port, int clientTimeout)82 public TServerSocket(int port, int clientTimeout) throws TTransportException { 83 this(new InetSocketAddress(port), clientTimeout); 84 } 85 TServerSocket(InetSocketAddress bindAddr)86 public TServerSocket(InetSocketAddress bindAddr) throws TTransportException { 87 this(bindAddr, 0); 88 } 89 TServerSocket(InetSocketAddress bindAddr, int clientTimeout)90 public TServerSocket(InetSocketAddress bindAddr, int clientTimeout) throws TTransportException { 91 this(new ServerSocketTransportArgs().bindAddr(bindAddr).clientTimeout(clientTimeout)); 92 } 93 TServerSocket(ServerSocketTransportArgs args)94 public TServerSocket(ServerSocketTransportArgs args) throws TTransportException { 95 clientTimeout_ = args.clientTimeout; 96 if (args.serverSocket != null) { 97 this.serverSocket_ = args.serverSocket; 98 return; 99 } 100 try { 101 // Make server socket 102 serverSocket_ = new ServerSocket(); 103 // Prevent 2MSL delay problem on server restarts 104 serverSocket_.setReuseAddress(true); 105 // Bind to listening port 106 serverSocket_.bind(args.bindAddr, args.backlog); 107 } catch (IOException ioe) { 108 close(); 109 throw new TTransportException("Could not create ServerSocket on address " + args.bindAddr.toString() + ".", ioe); 110 } 111 } 112 listen()113 public void listen() throws TTransportException { 114 // Make sure to block on accept 115 if (serverSocket_ != null) { 116 try { 117 serverSocket_.setSoTimeout(0); 118 } catch (SocketException sx) { 119 LOGGER.error("Could not set socket timeout.", sx); 120 } 121 } 122 } 123 124 @Override accept()125 public TSocket accept() throws TTransportException { 126 if (serverSocket_ == null) { 127 throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); 128 } 129 Socket result; 130 try { 131 result = serverSocket_.accept(); 132 } catch (Exception e) { 133 throw new TTransportException(e); 134 } 135 if (result == null) { 136 throw new TTransportException("Blocking server's accept() may not return NULL"); 137 } 138 TSocket socket = new TSocket(result); 139 socket.setTimeout(clientTimeout_); 140 return socket; 141 } 142 close()143 public void close() { 144 if (serverSocket_ != null) { 145 try { 146 serverSocket_.close(); 147 } catch (IOException iox) { 148 LOGGER.warn("Could not close server socket.", iox); 149 } 150 serverSocket_ = null; 151 } 152 } 153 interrupt()154 public void interrupt() { 155 // The thread-safeness of this is dubious, but Java documentation suggests 156 // that it is safe to do this from a different thread context 157 close(); 158 } 159 getServerSocket()160 public ServerSocket getServerSocket() { 161 return serverSocket_; 162 } 163 } 164