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 /* @inheritDoc */ 046 @Override 047 public Socket createSocket() throws IOException { 048 /* 049 * NOTE: This returns an NIO socket so that it has an associated 050 * SocketChannel. As of now, this unfortunately makes streams returned 051 * by Socket.getInputStream() and Socket.getOutputStream() unusable 052 * (because a blocking read on input stream blocks write on output stream 053 * and vice versa). 054 * 055 * So users of these socket factories should use 056 * NetUtils.getInputStream(socket) and 057 * NetUtils.getOutputStream(socket) instead. 058 * 059 * A solution for hiding from this from user is to write a 060 * 'FilterSocket' on the lines of FilterInputStream and extend it by 061 * overriding getInputStream() and getOutputStream(). 062 */ 063 return SocketChannel.open().socket(); 064 } 065 066 /* @inheritDoc */ 067 @Override 068 public Socket createSocket(InetAddress addr, int port) throws IOException { 069 070 Socket socket = createSocket(); 071 socket.connect(new InetSocketAddress(addr, port)); 072 return socket; 073 } 074 075 /* @inheritDoc */ 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 /* @inheritDoc */ 087 @Override 088 public Socket createSocket(String host, int port) throws IOException, 089 UnknownHostException { 090 091 Socket socket = createSocket(); 092 socket.connect(new InetSocketAddress(host, port)); 093 return socket; 094 } 095 096 /* @inheritDoc */ 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 /* @inheritDoc */ 109 @Override 110 public boolean equals(Object obj) { 111 if (this == obj) 112 return true; 113 if (obj == null) 114 return false; 115 return obj.getClass().equals(this.getClass()); 116 } 117 118 /* @inheritDoc */ 119 @Override 120 public int hashCode() { 121 return this.getClass().hashCode(); 122 } 123 124}