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 */ 018 package org.apache.hadoop.net; 019 020 import java.io.IOException; 021 import java.net.InetAddress; 022 import java.net.InetSocketAddress; 023 import java.net.Proxy; 024 import java.net.Socket; 025 import java.net.UnknownHostException; 026 027 import javax.net.SocketFactory; 028 029 import org.apache.hadoop.classification.InterfaceAudience; 030 import org.apache.hadoop.classification.InterfaceStability; 031 import org.apache.hadoop.conf.Configurable; 032 import org.apache.hadoop.conf.Configuration; 033 034 /** 035 * Specialized SocketFactory to create sockets with a SOCKS proxy 036 */ 037 @InterfaceAudience.Public 038 @InterfaceStability.Evolving 039 public class SocksSocketFactory extends SocketFactory implements 040 Configurable { 041 042 private Configuration conf; 043 044 private Proxy proxy; 045 046 /** 047 * Default empty constructor (for use with the reflection API). 048 */ 049 public SocksSocketFactory() { 050 this.proxy = Proxy.NO_PROXY; 051 } 052 053 /** 054 * Constructor with a supplied Proxy 055 * 056 * @param proxy the proxy to use to create sockets 057 */ 058 public SocksSocketFactory(Proxy proxy) { 059 this.proxy = proxy; 060 } 061 062 @Override 063 public Socket createSocket() throws IOException { 064 065 return new Socket(proxy); 066 } 067 068 @Override 069 public Socket createSocket(InetAddress addr, int port) throws IOException { 070 071 Socket socket = createSocket(); 072 socket.connect(new InetSocketAddress(addr, port)); 073 return socket; 074 } 075 076 @Override 077 public Socket createSocket(InetAddress addr, int port, 078 InetAddress localHostAddr, int localPort) throws IOException { 079 080 Socket socket = createSocket(); 081 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 082 socket.connect(new InetSocketAddress(addr, port)); 083 return socket; 084 } 085 086 @Override 087 public Socket createSocket(String host, int port) throws IOException, 088 UnknownHostException { 089 090 Socket socket = createSocket(); 091 socket.connect(new InetSocketAddress(host, port)); 092 return socket; 093 } 094 095 @Override 096 public Socket createSocket(String host, int port, 097 InetAddress localHostAddr, int localPort) throws IOException, 098 UnknownHostException { 099 100 Socket socket = createSocket(); 101 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 102 socket.connect(new InetSocketAddress(host, port)); 103 return socket; 104 } 105 106 @Override 107 public int hashCode() { 108 return proxy.hashCode(); 109 } 110 111 @Override 112 public boolean equals(Object obj) { 113 if (this == obj) 114 return true; 115 if (obj == null) 116 return false; 117 if (!(obj instanceof SocksSocketFactory)) 118 return false; 119 final SocksSocketFactory other = (SocksSocketFactory) obj; 120 if (proxy == null) { 121 if (other.proxy != null) 122 return false; 123 } else if (!proxy.equals(other.proxy)) 124 return false; 125 return true; 126 } 127 128 @Override 129 public Configuration getConf() { 130 return this.conf; 131 } 132 133 @Override 134 public void setConf(Configuration conf) { 135 this.conf = conf; 136 String proxyStr = conf.get("hadoop.socks.server"); 137 if ((proxyStr != null) && (proxyStr.length() > 0)) { 138 setProxy(proxyStr); 139 } 140 } 141 142 /** 143 * Set the proxy of this socket factory as described in the string 144 * parameter 145 * 146 * @param proxyStr the proxy address using the format "host:port" 147 */ 148 private void setProxy(String proxyStr) { 149 String[] strs = proxyStr.split(":", 2); 150 if (strs.length != 2) 151 throw new RuntimeException("Bad SOCKS proxy parameter: " + proxyStr); 152 String host = strs[0]; 153 int port = Integer.parseInt(strs[1]); 154 this.proxy = 155 new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(host, 156 port)); 157 } 158 }