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 034/** 035 * Specialized SocketFactory to create sockets with a SOCKS proxy 036 */ 037@InterfaceAudience.Public 038@InterfaceStability.Evolving 039public 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 /* @inheritDoc */ 063 @Override 064 public Socket createSocket() throws IOException { 065 066 return new Socket(proxy); 067 } 068 069 /* @inheritDoc */ 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 /* @inheritDoc */ 079 @Override 080 public Socket createSocket(InetAddress addr, int port, 081 InetAddress localHostAddr, int localPort) throws IOException { 082 083 Socket socket = createSocket(); 084 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 085 socket.connect(new InetSocketAddress(addr, port)); 086 return socket; 087 } 088 089 /* @inheritDoc */ 090 @Override 091 public Socket createSocket(String host, int port) throws IOException, 092 UnknownHostException { 093 094 Socket socket = createSocket(); 095 socket.connect(new InetSocketAddress(host, port)); 096 return socket; 097 } 098 099 /* @inheritDoc */ 100 @Override 101 public Socket createSocket(String host, int port, 102 InetAddress localHostAddr, int localPort) throws IOException, 103 UnknownHostException { 104 105 Socket socket = createSocket(); 106 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 107 socket.connect(new InetSocketAddress(host, port)); 108 return socket; 109 } 110 111 /* @inheritDoc */ 112 @Override 113 public int hashCode() { 114 return proxy.hashCode(); 115 } 116 117 /* @inheritDoc */ 118 @Override 119 public boolean equals(Object obj) { 120 if (this == obj) 121 return true; 122 if (obj == null) 123 return false; 124 if (!(obj instanceof SocksSocketFactory)) 125 return false; 126 final SocksSocketFactory other = (SocksSocketFactory) obj; 127 if (proxy == null) { 128 if (other.proxy != null) 129 return false; 130 } else if (!proxy.equals(other.proxy)) 131 return false; 132 return true; 133 } 134 135 /* @inheritDoc */ 136 public Configuration getConf() { 137 return this.conf; 138 } 139 140 /* @inheritDoc */ 141 public void setConf(Configuration conf) { 142 this.conf = conf; 143 String proxyStr = conf.get("hadoop.socks.server"); 144 if ((proxyStr != null) && (proxyStr.length() > 0)) { 145 setProxy(proxyStr); 146 } 147 } 148 149 /** 150 * Set the proxy of this socket factory as described in the string 151 * parameter 152 * 153 * @param proxyStr the proxy address using the format "host:port" 154 */ 155 private void setProxy(String proxyStr) { 156 String[] strs = proxyStr.split(":", 2); 157 if (strs.length != 2) 158 throw new RuntimeException("Bad SOCKS proxy parameter: " + proxyStr); 159 String host = strs[0]; 160 int port = Integer.parseInt(strs[1]); 161 this.proxy = 162 new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(host, 163 port)); 164 } 165}