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.Socket; 024import java.net.UnknownHostException; 025import java.nio.channels.SocketChannel; 026 027import javax.net.SocketFactory; 028 029import org.apache.hadoop.classification.InterfaceAudience; 030import org.apache.hadoop.classification.InterfaceStability; 031 032/** 033 * Specialized SocketFactory to create sockets with a SOCKS proxy 034 */ 035@InterfaceAudience.Public 036@InterfaceStability.Evolving 037public class StandardSocketFactory extends SocketFactory { 038 039 /** 040 * Default empty constructor (for use with the reflection API). 041 */ 042 public StandardSocketFactory() { 043 } 044 045 @Override 046 public Socket createSocket() throws IOException { 047 /* 048 * NOTE: This returns an NIO socket so that it has an associated 049 * SocketChannel. As of now, this unfortunately makes streams returned 050 * by Socket.getInputStream() and Socket.getOutputStream() unusable 051 * (because a blocking read on input stream blocks write on output stream 052 * and vice versa). 053 * 054 * So users of these socket factories should use 055 * NetUtils.getInputStream(socket) and 056 * NetUtils.getOutputStream(socket) instead. 057 * 058 * A solution for hiding from this from user is to write a 059 * 'FilterSocket' on the lines of FilterInputStream and extend it by 060 * overriding getInputStream() and getOutputStream(). 061 */ 062 return SocketChannel.open().socket(); 063 } 064 065 @Override 066 public Socket createSocket(InetAddress addr, int port) throws IOException { 067 068 Socket socket = createSocket(); 069 socket.connect(new InetSocketAddress(addr, port)); 070 return socket; 071 } 072 073 @Override 074 public Socket createSocket(InetAddress addr, int port, 075 InetAddress localHostAddr, int localPort) throws IOException { 076 077 Socket socket = createSocket(); 078 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 079 socket.connect(new InetSocketAddress(addr, port)); 080 return socket; 081 } 082 083 @Override 084 public Socket createSocket(String host, int port) throws IOException, 085 UnknownHostException { 086 087 Socket socket = createSocket(); 088 socket.connect(new InetSocketAddress(host, port)); 089 return socket; 090 } 091 092 @Override 093 public Socket createSocket(String host, int port, 094 InetAddress localHostAddr, int localPort) throws IOException, 095 UnknownHostException { 096 097 Socket socket = createSocket(); 098 socket.bind(new InetSocketAddress(localHostAddr, localPort)); 099 socket.connect(new InetSocketAddress(host, port)); 100 return socket; 101 } 102 103 @Override 104 public boolean equals(Object obj) { 105 if (this == obj) 106 return true; 107 if (obj == null) 108 return false; 109 return obj.getClass().equals(this.getClass()); 110 } 111 112 @Override 113 public int hashCode() { 114 return this.getClass().hashCode(); 115 } 116 117}