1/* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.net; 27 28import java.lang.annotation.Native; 29 30/** 31 * Represents the service level properties for the platform specific socket 32 * option {@link ExtendedSocketOptions#SO_FLOW_SLA}. 33 * <p> 34 * The priority and bandwidth parameters must be set before 35 * setting the socket option. 36 * <p> 37 * When the {@code SO_FLOW_SLA} option is set then it may not take effect 38 * immediately. If the value of the socket option is obtained with 39 * {@code getOption()} then the status may be returned as {@code INPROGRESS} 40 * until it takes effect. The priority and bandwidth values are only valid when 41 * the status is returned as OK. 42 * <p> 43 * When a security manager is installed, a {@link NetworkPermission} 44 * is required to set or get this option. 45 * 46 * @since 1.8 47 */ 48public class SocketFlow { 49 50 @Native public static final int UNSET = -1; 51 @Native public static final int NORMAL_PRIORITY = 1; 52 @Native public static final int HIGH_PRIORITY = 2; 53 54 @Native private static final int NO_STATUS_VALUE = 0; 55 @Native private static final int OK_VALUE = 1; 56 @Native private static final int NO_PERMISSION_VALUE = 2; 57 @Native private static final int NOT_CONNECTED_VALUE = 3; 58 @Native private static final int NOT_SUPPORTED_VALUE = 4; 59 @Native private static final int ALREADY_CREATED_VALUE = 5; 60 @Native private static final int IN_PROGRESS_VALUE = 6; 61 @Native private static final int OTHER_VALUE = 7; 62 63 /** 64 * Enumeration of the return values from the SO_FLOW_SLA 65 * socket option. Both setting and getting the option return 66 * one of these statuses, which reflect the state of socket's 67 * flow. 68 * 69 * @since 1.8 70 */ 71 public enum Status { 72 /** 73 * Set or get socket option has not been called yet. Status 74 * values can only be retrieved after calling set or get. 75 */ 76 NO_STATUS(NO_STATUS_VALUE), 77 /** 78 * Flow successfully created. 79 */ 80 OK(OK_VALUE), 81 /** 82 * Caller has no permission to create flow. 83 */ 84 NO_PERMISSION(NO_PERMISSION_VALUE), 85 /** 86 * Flow can not be created because socket is not connected. 87 */ 88 NOT_CONNECTED(NOT_CONNECTED_VALUE), 89 /** 90 * Flow creation not supported for this socket. 91 */ 92 NOT_SUPPORTED(NOT_SUPPORTED_VALUE), 93 /** 94 * A flow already exists with identical attributes. 95 */ 96 ALREADY_CREATED(ALREADY_CREATED_VALUE), 97 /** 98 * A flow is being created. 99 */ 100 IN_PROGRESS(IN_PROGRESS_VALUE), 101 /** 102 * Some other unspecified error. 103 */ 104 OTHER(OTHER_VALUE); 105 106 private final int value; 107 Status(int value) { this.value = value; } 108 109 static Status from(int value) { 110 if (value == NO_STATUS.value) return NO_STATUS; 111 else if (value == OK.value) return OK; 112 else if (value == NO_PERMISSION.value) return NO_PERMISSION; 113 else if (value == NOT_CONNECTED.value) return NOT_CONNECTED; 114 else if (value == NOT_SUPPORTED.value) return NOT_SUPPORTED; 115 else if (value == ALREADY_CREATED.value) return ALREADY_CREATED; 116 else if (value == IN_PROGRESS.value) return IN_PROGRESS; 117 else if (value == OTHER.value) return OTHER; 118 else throw new InternalError("Unknown value: " + value); 119 } 120 } 121 122 private int priority = NORMAL_PRIORITY; 123 private long bandwidth = UNSET; 124 private Status status = Status.NO_STATUS; 125 126 /** 127 * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA 128 * socket option and create a socket flow. 129 */ 130 public static SocketFlow create() { 131 return new SocketFlow(); 132 } 133 134 private SocketFlow() { } 135 136 /** 137 * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY 138 * HIGH_PRIORITY. If not set, a flow's priority is normal. 139 * 140 * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or 141 * HIGH_PRIORITY. 142 */ 143 public SocketFlow priority(int priority) { 144 if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) 145 throw new IllegalArgumentException("invalid priority :" + priority); 146 this.priority = priority; 147 return this; 148 } 149 150 /** 151 * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero. 152 * A value of zero drops all packets for the socket. 153 * 154 * @throws IllegalArgumentException if bandwidth is less than zero. 155 */ 156 public SocketFlow bandwidth(long bandwidth) { 157 if (bandwidth < 0) 158 throw new IllegalArgumentException("invalid bandwidth: " + bandwidth); 159 this.bandwidth = bandwidth; 160 return this; 161 } 162 163 /** 164 * Returns this SocketFlow's priority. 165 */ 166 public int priority() { 167 return priority; 168 } 169 170 /** 171 * Returns this SocketFlow's bandwidth. 172 * 173 * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK. 174 */ 175 public long bandwidth() { 176 return bandwidth; 177 } 178 179 /** 180 * Returns the Status value of this SocketFlow. NO_STATUS is returned 181 * if the object was not used in a call to set or get the option. 182 */ 183 public Status status() { 184 return status; 185 } 186 187 void status(int status) { 188 this.status = Status.from(status); 189 } 190 191 @Override 192 public String toString() { 193 StringBuilder sb = new StringBuilder(super.toString()); 194 sb.append(" [ priority=").append(priority()) 195 .append(", bandwidth=").append(bandwidth()) 196 .append(", status=").append(status()) 197 .append(" ]"); 198 return sb.toString(); 199 } 200} 201