1 /* 2 * Copyright (C) 2015 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 17 package android.system; 18 19 import java.net.SocketAddress; 20 import java.nio.charset.StandardCharsets; 21 import java.util.Arrays; 22 23 /** 24 * A UNIX-domain (AF_UNIX / AF_LOCAL) socket address. 25 * 26 * @hide 27 */ 28 @libcore.api.CorePlatformApi 29 public final class UnixSocketAddress extends SocketAddress { 30 31 private static final int NAMED_PATH_LENGTH = OsConstants.UNIX_PATH_MAX; 32 private static final byte[] UNNAMED_PATH = new byte[0]; 33 34 // See unix(7): Three types of UnixSocketAddress: 35 // 1) pathname: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] != 0. 36 // 2) unnamed: sun_path = []. 37 // 3) abstract: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] == 0. 38 private byte[] sun_path; 39 40 /** This constructor is also used from JNI. */ UnixSocketAddress(byte[] sun_path)41 private UnixSocketAddress(byte[] sun_path) { 42 if (sun_path == null) { 43 throw new IllegalArgumentException("sun_path must not be null"); 44 } 45 if (sun_path.length > NAMED_PATH_LENGTH) { 46 throw new IllegalArgumentException("sun_path exceeds the maximum length"); 47 } 48 49 if (sun_path.length == 0) { 50 this.sun_path = UNNAMED_PATH; 51 } else { 52 this.sun_path = new byte[sun_path.length]; 53 System.arraycopy(sun_path, 0, this.sun_path, 0, sun_path.length); 54 } 55 } 56 57 /** 58 * Creates a named, abstract AF_UNIX socket address. 59 */ createAbstract(String name)60 public static UnixSocketAddress createAbstract(String name) { 61 byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); 62 // Abstract sockets have a path that starts with (byte) 0. 63 byte[] path = new byte[nameBytes.length + 1]; 64 System.arraycopy(nameBytes, 0, path, 1, nameBytes.length); 65 return new UnixSocketAddress(path); 66 } 67 68 /** 69 * Creates a named, filesystem AF_UNIX socket address. 70 */ 71 @libcore.api.CorePlatformApi createFileSystem(String pathName)72 public static UnixSocketAddress createFileSystem(String pathName) { 73 byte[] pathNameBytes = pathName.getBytes(StandardCharsets.UTF_8); 74 // File system sockets have a path that ends with (byte) 0. 75 byte[] path = new byte[pathNameBytes.length + 1]; 76 System.arraycopy(pathNameBytes, 0, path, 0, pathNameBytes.length); 77 return new UnixSocketAddress(path); 78 } 79 80 /** 81 * Creates an unnamed, filesystem AF_UNIX socket address. 82 */ createUnnamed()83 public static UnixSocketAddress createUnnamed() { 84 return new UnixSocketAddress(UNNAMED_PATH); 85 } 86 87 /** Used for testing. */ getSunPath()88 public byte[] getSunPath() { 89 if (sun_path.length == 0) { 90 return sun_path; 91 } 92 byte[] sunPathCopy = new byte[sun_path.length]; 93 System.arraycopy(sun_path, 0, sunPathCopy, 0, sun_path.length); 94 return sunPathCopy; 95 } 96 97 @Override equals(Object o)98 public boolean equals(Object o) { 99 if (this == o) { 100 return true; 101 } 102 if (o == null || getClass() != o.getClass()) { 103 return false; 104 } 105 106 UnixSocketAddress that = (UnixSocketAddress) o; 107 return Arrays.equals(sun_path, that.sun_path); 108 } 109 110 @Override hashCode()111 public int hashCode() { 112 return Arrays.hashCode(sun_path); 113 } 114 115 @Override toString()116 public String toString() { 117 return "UnixSocketAddress[" + 118 "sun_path=" + Arrays.toString(sun_path) + 119 ']'; 120 } 121 } 122