10ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller/*
22550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller * Copyright (C) 2015 The Android Open Source Project
30ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller *
40ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
50ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * you may not use this file except in compliance with the License.
60ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * You may obtain a copy of the License at
70ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller *
80ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
90ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller *
100ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * Unless required by applicable law or agreed to in writing, software
110ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
120ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * See the License for the specific language governing permissions and
140ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * limitations under the License.
150ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller */
160ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
170ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerpackage android.system;
180ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
190ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerimport java.net.SocketAddress;
200ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerimport java.nio.charset.StandardCharsets;
210ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerimport java.util.Arrays;
220ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
230ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller/**
240ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * A UNIX-domain (AF_UNIX / AF_LOCAL) socket address.
250ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller *
260ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller * @hide
270ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller */
280ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerpublic final class UnixSocketAddress extends SocketAddress {
290ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
300ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    private static final int NAMED_PATH_LENGTH = OsConstants.UNIX_PATH_MAX;
310ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    private static final byte[] UNNAMED_PATH = new byte[0];
320ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
330ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    // See unix(7): Three types of UnixSocketAddress:
342550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // 1) pathname: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] != 0.
350ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    // 2) unnamed: sun_path = [].
362550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // 3) abstract: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] == 0.
370ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    private byte[] sun_path;
380ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
390ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    /** This constructor is also used from JNI. */
400ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    private UnixSocketAddress(byte[] sun_path) {
410ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (sun_path == null) {
420ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            throw new IllegalArgumentException("sun_path must not be null");
430ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
440ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (sun_path.length > NAMED_PATH_LENGTH) {
450ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            throw new IllegalArgumentException("sun_path exceeds the maximum length");
460ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
470ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
480ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (sun_path.length == 0) {
490ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            this.sun_path = UNNAMED_PATH;
500ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        } else {
512550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller            this.sun_path = new byte[sun_path.length];
520ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            System.arraycopy(sun_path, 0, this.sun_path, 0, sun_path.length);
530ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
540ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
550ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
560ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    /**
570ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     * Creates a named, abstract AF_UNIX socket address.
580ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     */
590ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public static UnixSocketAddress createAbstract(String name) {
600ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
610ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        // Abstract sockets have a path that starts with (byte) 0.
620ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        byte[] path = new byte[nameBytes.length + 1];
630ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        System.arraycopy(nameBytes, 0, path, 1, nameBytes.length);
640ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return new UnixSocketAddress(path);
650ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
660ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
670ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    /**
680ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     * Creates a named, filesystem AF_UNIX socket address.
690ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     */
702550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    public static UnixSocketAddress createFileSystem(String pathName) {
712550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        byte[] pathNameBytes = pathName.getBytes(StandardCharsets.UTF_8);
722550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        // File system sockets have a path that ends with (byte) 0.
732550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        byte[] path = new byte[pathNameBytes.length + 1];
742550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        System.arraycopy(pathNameBytes, 0, path, 0, pathNameBytes.length);
752550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return new UnixSocketAddress(path);
760ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
770ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
780ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    /**
790ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     * Creates an unnamed, filesystem AF_UNIX socket address.
800ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller     */
810ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public static UnixSocketAddress createUnnamed() {
820ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return new UnixSocketAddress(UNNAMED_PATH);
830ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
840ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
850ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    /** Used for testing. */
860ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public byte[] getSunPath() {
870ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (sun_path.length == 0) {
880ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            return sun_path;
890ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
900ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        byte[] sunPathCopy = new byte[sun_path.length];
910ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        System.arraycopy(sun_path, 0, sunPathCopy, 0, sun_path.length);
920ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return sunPathCopy;
930ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
940ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
950ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    @Override
960ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public boolean equals(Object o) {
970ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (this == o) {
980ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            return true;
990ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
1000ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        if (o == null || getClass() != o.getClass()) {
1010ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            return false;
1020ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
1030ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
1040ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        UnixSocketAddress that = (UnixSocketAddress) o;
1050ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return Arrays.equals(sun_path, that.sun_path);
1060ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
1070ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
1080ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    @Override
1090ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public int hashCode() {
1100ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return Arrays.hashCode(sun_path);
1110ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
1120ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
1130ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    @Override
1140ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    public String toString() {
1152550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return "UnixSocketAddress[" +
1160ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller                "sun_path=" + Arrays.toString(sun_path) +
1172550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller                ']';
1180ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
1190ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller}
120