blob: 5c9369deb5a84bbf706b85881cad7601a5f8d4ed [file] [log] [blame]
Neil Fuller0ab1a262015-07-07 17:03:25 +01001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.system;
18
19import java.net.SocketAddress;
20import java.nio.charset.StandardCharsets;
21import java.util.Arrays;
22
23/**
24 * A UNIX-domain (AF_UNIX / AF_LOCAL) socket address.
25 *
26 * @hide
27 */
28public final class UnixSocketAddress extends SocketAddress {
29
30 private static final int NAMED_PATH_LENGTH = OsConstants.UNIX_PATH_MAX;
31 private static final byte[] UNNAMED_PATH = new byte[0];
32
33 // See unix(7): Three types of UnixSocketAddress:
34 // 1) pathname: sun_path.length == NAMED_PATH_LENGTH, sun_path[0] != 0.
35 // 2) unnamed: sun_path = [].
36 // 3) abstract: sun_path.length == NAMED_PATH_LENGTH, sun_path[0] == 0.
37 private byte[] sun_path;
38
39 /** This constructor is also used from JNI. */
40 private UnixSocketAddress(byte[] sun_path) {
41 if (sun_path == null) {
42 throw new IllegalArgumentException("sun_path must not be null");
43 }
44 if (sun_path.length > NAMED_PATH_LENGTH) {
45 throw new IllegalArgumentException("sun_path exceeds the maximum length");
46 }
47
48 if (sun_path.length == 0) {
49 this.sun_path = UNNAMED_PATH;
50 } else {
51 this.sun_path = new byte[NAMED_PATH_LENGTH];
52 System.arraycopy(sun_path, 0, this.sun_path, 0, sun_path.length);
53 }
54 }
55
56 /**
57 * Creates a named, abstract AF_UNIX socket address.
58 */
59 public static UnixSocketAddress createAbstract(String name) {
60 byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
61 // Abstract sockets have a path that starts with (byte) 0.
62 byte[] path = new byte[nameBytes.length + 1];
63 System.arraycopy(nameBytes, 0, path, 1, nameBytes.length);
64 return new UnixSocketAddress(path);
65 }
66
67 /**
68 * Creates a named, filesystem AF_UNIX socket address.
69 */
70 public static UnixSocketAddress createFileSystem(String path) {
71 return new UnixSocketAddress(path.getBytes(StandardCharsets.UTF_8));
72 }
73
74 /**
75 * Creates an unnamed, filesystem AF_UNIX socket address.
76 */
77 public static UnixSocketAddress createUnnamed() {
78 return new UnixSocketAddress(UNNAMED_PATH);
79 }
80
81 /** Used for testing. */
82 public byte[] getSunPath() {
83 if (sun_path.length == 0) {
84 return sun_path;
85 }
86 byte[] sunPathCopy = new byte[sun_path.length];
87 System.arraycopy(sun_path, 0, sunPathCopy, 0, sun_path.length);
88 return sunPathCopy;
89 }
90
91 @Override
92 public boolean equals(Object o) {
93 if (this == o) {
94 return true;
95 }
96 if (o == null || getClass() != o.getClass()) {
97 return false;
98 }
99
100 UnixSocketAddress that = (UnixSocketAddress) o;
101 return Arrays.equals(sun_path, that.sun_path);
102 }
103
104 @Override
105 public int hashCode() {
106 return Arrays.hashCode(sun_path);
107 }
108
109 @Override
110 public String toString() {
111 return "UnixSocketAddress{" +
112 "sun_path=" + Arrays.toString(sun_path) +
113 '}';
114 }
115}