001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.net; 019 020import java.io.IOException; 021import java.net.InetAddress; 022import java.net.InetSocketAddress; 023import java.net.Proxy; 024import java.net.Socket; 025import java.net.UnknownHostException; 026 027import javax.net.SocketFactory; 028 029import org.apache.hadoop.classification.InterfaceAudience; 030import org.apache.hadoop.classification.InterfaceStability; 031import org.apache.hadoop.conf.Configurable; 032import org.apache.hadoop.conf.Configuration; 033 034import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SOCKS_SERVER_KEY; 035 036/** 037 * Specialized SocketFactory to create sockets with a SOCKS proxy 038 */ 039@InterfaceAudience.Public 040@InterfaceStability.Evolving 041public class SocksSocketFactory extends SocketFactory implements 042 Configurable { 043 044 private Configuration conf; 045 046 private Proxy proxy; 047 048 /** 049 * Default empty constructor (for use with the reflection API). 050 */ 051 public SocksSocketFactory() { 052 this.proxy = Proxy.NO_PROXY; 053 } 054 055 /** 056 * Constructor with a supplied Proxy 057 * 058 * @param proxy the proxy to use to create sockets 059 */ 060 public SocksSocketFactory(Proxy proxy) { 061 this.proxy = proxy; 062 } 063 064 @Override 065 public Socket createSocket() throws IOException { 066 067 return new Socket(proxy); 068 } 069 070 @Override 071 public Socket createSocket(InetAddress addr, int port) throws IOException { 072 073 Socket socket = createSocket(); 074 socket.connect(new InetSocketAddress(addr, port)); 075 return socket; 076 } 077 078 @Override 079 public Socket createSocket(InetAddress addr, int port, 080 InetAddress localHostAddr, int localPort) throws IOException { 081 082 Socket socket = createSocket(); 083 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 084 socket.connect(new InetSocketAddress(addr, port)); 085 return socket; 086 } 087 088 @Override 089 public Socket createSocket(String host, int port) throws IOException, 090 UnknownHostException { 091 092 Socket socket = createSocket(); 093 socket.connect(new InetSocketAddress(host, port)); 094 return socket; 095 } 096 097 @Override 098 public Socket createSocket(String host, int port, 099 InetAddress localHostAddr, int localPort) throws IOException, 100 UnknownHostException { 101 102 Socket socket = createSocket(); 103 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 104 socket.connect(new InetSocketAddress(host, port)); 105 return socket; 106 } 107 108 @Override 109 public int hashCode() { 110 return proxy.hashCode(); 111 } 112 113 @Override 114 public boolean equals(Object obj) { 115 if (this == obj) 116 return true; 117 if (obj == null) 118 return false; 119 if (!(obj instanceof SocksSocketFactory)) 120 return false; 121 final SocksSocketFactory other = (SocksSocketFactory) obj; 122 if (proxy == null) { 123 if (other.proxy != null) 124 return false; 125 } else if (!proxy.equals(other.proxy)) 126 return false; 127 return true; 128 } 129 130 @Override 131 public Configuration getConf() { 132 return this.conf; 133 } 134 135 @Override 136 public void setConf(Configuration conf) { 137 this.conf = conf; 138 String proxyStr = conf.get(HADOOP_SOCKS_SERVER_KEY); 139 if ((proxyStr != null) && (proxyStr.length() > 0)) { 140 setProxy(proxyStr); 141 } 142 } 143 144 /** 145 * Set the proxy of this socket factory as described in the string 146 * parameter 147 * 148 * @param proxyStr the proxy address using the format "host:port" 149 */ 150 private void setProxy(String proxyStr) { 151 String[] strs = proxyStr.split(":", 2); 152 if (strs.length != 2) 153 throw new RuntimeException("Bad SOCKS proxy parameter: " + proxyStr); 154 String host = strs[0]; 155 int port = Integer.parseInt(strs[1]); 156 this.proxy = 157 new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(host, 158 port)); 159 } 160}