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 // Note that the array referenced by this field can be modified from JNI (libcore_io_Linux.cpp). 39 private final byte[] sun_path; 40 41 /** This constructor is also used from JNI. */ UnixSocketAddress(byte[] sun_path)42 private UnixSocketAddress(byte[] sun_path) { 43 if (sun_path == null) { 44 throw new IllegalArgumentException("sun_path must not be null"); 45 } 46 if (sun_path.length > NAMED_PATH_LENGTH) { 47 throw new IllegalArgumentException("sun_path exceeds the maximum length"); 48 } 49 50 if (sun_path.length == 0) { 51 this.sun_path = UNNAMED_PATH; 52 } else { 53 this.sun_path = new byte[sun_path.length]; 54 System.arraycopy(sun_path, 0, this.sun_path, 0, sun_path.length); 55 } 56 } 57 58 /** 59 * Creates a named, abstract AF_UNIX socket address. 60 * 61 * @throws NullPointerException if {@code name} is null 62 * @throws IllegalArgumentException if {@code name} is invalid, e.g. too long 63 */ createAbstract(String name)64 public static UnixSocketAddress createAbstract(String name) { 65 byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); 66 // Abstract sockets have a path that starts with (byte) 0. 67 byte[] path = new byte[nameBytes.length + 1]; 68 System.arraycopy(nameBytes, 0, path, 1, nameBytes.length); 69 return new UnixSocketAddress(path); 70 } 71 72 /** 73 * Creates a named, filesystem AF_UNIX socket address. 74 * 75 * @throws NullPointerException if {@code name} is null 76 * @throws IllegalArgumentException if {@code name} is invalid, e.g. too long 77 */ 78 @libcore.api.CorePlatformApi createFileSystem(String pathName)79 public static UnixSocketAddress createFileSystem(String pathName) { 80 byte[] pathNameBytes = pathName.getBytes(StandardCharsets.UTF_8); 81 // File system sockets have a path that ends with (byte) 0. 82 byte[] path = new byte[pathNameBytes.length + 1]; 83 System.arraycopy(pathNameBytes, 0, path, 0, pathNameBytes.length); 84 return new UnixSocketAddress(path); 85 } 86 87 /** 88 * Creates an unnamed, filesystem AF_UNIX socket address. 89 */ createUnnamed()90 public static UnixSocketAddress createUnnamed() { 91 return new UnixSocketAddress(UNNAMED_PATH); 92 } 93 94 /** Used for testing. */ getSunPath()95 public byte[] getSunPath() { 96 if (sun_path.length == 0) { 97 return sun_path; 98 } 99 byte[] sunPathCopy = new byte[sun_path.length]; 100 System.arraycopy(sun_path, 0, sunPathCopy, 0, sun_path.length); 101 return sunPathCopy; 102 } 103 104 @Override equals(Object o)105 public boolean equals(Object o) { 106 if (this == o) { 107 return true; 108 } 109 if (o == null || getClass() != o.getClass()) { 110 return false; 111 } 112 113 UnixSocketAddress that = (UnixSocketAddress) o; 114 return Arrays.equals(sun_path, that.sun_path); 115 } 116 117 @Override hashCode()118 public int hashCode() { 119 return Arrays.hashCode(sun_path); 120 } 121 122 @Override toString()123 public String toString() { 124 return "UnixSocketAddress[" + 125 "sun_path=" + Arrays.toString(sun_path) + 126 ']'; 127 } 128 } 129