1/* 2 * Copyright (C) 2017 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 */ 16package android.net; 17 18import android.os.Parcel; 19import android.os.ParcelFileDescriptor; 20import android.os.Parcelable; 21import java.io.FileDescriptor; 22import java.io.IOException; 23 24/** 25 * This class is used to return a UDP Socket and corresponding status from the IpSecService to an 26 * IpSecManager.UdpEncapsulationSocket. 27 * 28 * @hide 29 */ 30public final class IpSecUdpEncapResponse implements Parcelable { 31 private static final String TAG = "IpSecUdpEncapResponse"; 32 33 public final int resourceId; 34 public final int port; 35 public final int status; 36 // There is a weird asymmetry with FileDescriptor: you can write a FileDescriptor 37 // but you read a ParcelFileDescriptor. To circumvent this, when we receive a FD 38 // from the user, we immediately create a ParcelFileDescriptor DUP, which we invalidate 39 // on writeParcel() by setting the flag to do close-on-write. 40 // TODO: tests to ensure this doesn't leak 41 public final ParcelFileDescriptor fileDescriptor; 42 43 // Parcelable Methods 44 45 @Override 46 public int describeContents() { 47 return (fileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; 48 } 49 50 @Override 51 public void writeToParcel(Parcel out, int flags) { 52 out.writeInt(status); 53 out.writeInt(resourceId); 54 out.writeInt(port); 55 out.writeParcelable(fileDescriptor, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 56 } 57 58 public IpSecUdpEncapResponse(int inStatus) { 59 if (inStatus == IpSecManager.Status.OK) { 60 throw new IllegalArgumentException("Valid status implies other args must be provided"); 61 } 62 status = inStatus; 63 resourceId = IpSecManager.INVALID_RESOURCE_ID; 64 port = -1; 65 fileDescriptor = null; // yes I know it's redundant, but readability 66 } 67 68 public IpSecUdpEncapResponse(int inStatus, int inResourceId, int inPort, FileDescriptor inFd) 69 throws IOException { 70 if (inStatus == IpSecManager.Status.OK && inFd == null) { 71 throw new IllegalArgumentException("Valid status implies FD must be non-null"); 72 } 73 status = inStatus; 74 resourceId = inResourceId; 75 port = inPort; 76 fileDescriptor = (status == IpSecManager.Status.OK) ? ParcelFileDescriptor.dup(inFd) : null; 77 } 78 79 private IpSecUdpEncapResponse(Parcel in) { 80 status = in.readInt(); 81 resourceId = in.readInt(); 82 port = in.readInt(); 83 fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); 84 } 85 86 public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR = 87 new Parcelable.Creator<IpSecUdpEncapResponse>() { 88 public IpSecUdpEncapResponse createFromParcel(Parcel in) { 89 return new IpSecUdpEncapResponse(in); 90 } 91 92 public IpSecUdpEncapResponse[] newArray(int size) { 93 return new IpSecUdpEncapResponse[size]; 94 } 95 }; 96} 97