1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.hdfs.net;
19 
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.channels.ReadableByteChannel;
24 
25 import org.apache.hadoop.net.unix.DomainSocket;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 
28 /**
29  * Represents a peer that we communicate with by using blocking I/O
30  * on a UNIX domain socket.
31  */
32 @InterfaceAudience.Private
33 public class DomainPeer implements Peer {
34   private final DomainSocket socket;
35   private final OutputStream out;
36   private final InputStream in;
37   private final ReadableByteChannel channel;
38 
DomainPeer(DomainSocket socket)39   public DomainPeer(DomainSocket socket) {
40     this.socket = socket;
41     this.out = socket.getOutputStream();
42     this.in = socket.getInputStream();
43     this.channel = socket.getChannel();
44   }
45 
46   @Override
getInputStreamChannel()47   public ReadableByteChannel getInputStreamChannel() {
48     return channel;
49   }
50 
51   @Override
setReadTimeout(int timeoutMs)52   public void setReadTimeout(int timeoutMs) throws IOException {
53     socket.setAttribute(DomainSocket.RECEIVE_TIMEOUT, timeoutMs);
54   }
55 
56   @Override
getReceiveBufferSize()57   public int getReceiveBufferSize() throws IOException {
58     return socket.getAttribute(DomainSocket.RECEIVE_BUFFER_SIZE);
59   }
60 
61   @Override
getTcpNoDelay()62   public boolean getTcpNoDelay() throws IOException {
63     /* No TCP, no TCP_NODELAY. */
64     return false;
65   }
66 
67   @Override
setWriteTimeout(int timeoutMs)68   public void setWriteTimeout(int timeoutMs) throws IOException {
69     socket.setAttribute(DomainSocket.SEND_TIMEOUT, timeoutMs);
70   }
71 
72   @Override
isClosed()73   public boolean isClosed() {
74     return !socket.isOpen();
75   }
76 
77   @Override
close()78   public void close() throws IOException {
79     socket.close();
80   }
81 
82   @Override
getRemoteAddressString()83   public String getRemoteAddressString() {
84     return "unix:" + socket.getPath();
85   }
86 
87   @Override
getLocalAddressString()88   public String getLocalAddressString() {
89     return "<local>";
90   }
91 
92   @Override
getInputStream()93   public InputStream getInputStream() throws IOException {
94     return in;
95   }
96 
97   @Override
getOutputStream()98   public OutputStream getOutputStream() throws IOException {
99     return out;
100   }
101 
102   @Override
isLocal()103   public boolean isLocal() {
104     /* UNIX domain sockets can only be used for local communication. */
105     return true;
106   }
107 
108   @Override
toString()109   public String toString() {
110     return "DomainPeer(" + getRemoteAddressString() + ")";
111   }
112 
113   @Override
getDomainSocket()114   public DomainSocket getDomainSocket() {
115     return socket;
116   }
117 
118   @Override
hasSecureChannel()119   public boolean hasSecureChannel() {
120     //
121     // Communication over domain sockets is assumed to be secure, since it
122     // doesn't pass over any network.  We also carefully control the privileges
123     // that can be used on the domain socket inode and its parent directories.
124     // See #{java.org.apache.hadoop.net.unix.DomainSocket#validateSocketPathSecurity0}
125     // for details.
126     //
127     // So unless you are running as root or the hdfs superuser, you cannot
128     // launch a man-in-the-middle attach on UNIX domain socket traffic.
129     //
130     return true;
131   }
132 }
133