mirror of
https://github.com/openjdk/jdk19u.git
synced 2025-12-11 00:58:35 -06:00
Merge
This commit is contained in:
commit
bc946a4450
@ -45,6 +45,7 @@ endif
|
||||
|
||||
LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher
|
||||
LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \
|
||||
-I$(TOPDIR)/src/java.desktop/share/native/include \
|
||||
-I$(TOPDIR)/src/java.base/share/native/libjli \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \
|
||||
|
||||
@ -368,6 +368,7 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
common/awt/debug \
|
||||
common/font \
|
||||
common/java2d/opengl \
|
||||
include \
|
||||
#
|
||||
|
||||
LIBAWT_HEADLESS_CFLAGS := $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) $(X_CFLAGS) \
|
||||
@ -477,6 +478,7 @@ LIBFONTMANAGER_EXTRA_HEADER_DIRS := \
|
||||
libawt/java2d \
|
||||
libawt/java2d/pipe \
|
||||
libawt/java2d/loops \
|
||||
include \
|
||||
#
|
||||
|
||||
LIBFONTMANAGER_CFLAGS += $(LIBFREETYPE_CFLAGS)
|
||||
@ -656,6 +658,8 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
common/awt/systemscale \
|
||||
#
|
||||
|
||||
LIBSPLASHSCREEN_HEADER_DIRS += include
|
||||
|
||||
ifeq ($(USE_EXTERNAL_LIBGIF), false)
|
||||
LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/giflib
|
||||
else
|
||||
|
||||
@ -657,6 +657,11 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
|
||||
|
||||
const size_t outer_size = size + MemTracker::overhead_per_malloc();
|
||||
|
||||
// Check for overflow.
|
||||
if (outer_size < size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* const outer_ptr = ::malloc(outer_size);
|
||||
if (outer_ptr == NULL) {
|
||||
return NULL;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -117,9 +117,10 @@ public final class Client extends NTLM {
|
||||
* {@code nonce} is null for NTLM v1.
|
||||
*/
|
||||
public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
|
||||
if (type2 == null || (v != Version.NTLM && nonce == null)) {
|
||||
if (type2 == null || (v != Version.NTLM && nonce == null) ||
|
||||
(nonce != null && nonce.length != 8)) {
|
||||
throw new NTLMException(NTLMException.PROTOCOL,
|
||||
"type2 and nonce cannot be null");
|
||||
"type2 cannot be null, and nonce must be 8-byte long");
|
||||
}
|
||||
debug("NTLM Client: Type 2 received\n");
|
||||
debug(type2);
|
||||
|
||||
@ -224,23 +224,27 @@ class NTLM {
|
||||
System.arraycopy(data, 0, internal, offset, data.length);
|
||||
}
|
||||
|
||||
void writeSecurityBuffer(int offset, byte[] data) {
|
||||
void writeSecurityBuffer(int offset, byte[] data) throws NTLMException {
|
||||
if (data == null) {
|
||||
writeShort(offset+4, current);
|
||||
writeInt(offset+4, current);
|
||||
} else {
|
||||
int len = data.length;
|
||||
if (len > 65535) {
|
||||
throw new NTLMException(NTLMException.INVALID_INPUT,
|
||||
"Invalid data length " + len);
|
||||
}
|
||||
if (current + len > internal.length) {
|
||||
internal = Arrays.copyOf(internal, current + len + 256);
|
||||
}
|
||||
writeShort(offset, len);
|
||||
writeShort(offset+2, len);
|
||||
writeShort(offset+4, current);
|
||||
writeInt(offset+4, current);
|
||||
System.arraycopy(data, 0, internal, current, len);
|
||||
current += len;
|
||||
}
|
||||
}
|
||||
|
||||
void writeSecurityBuffer(int offset, String str, boolean unicode) {
|
||||
void writeSecurityBuffer(int offset, String str, boolean unicode) throws NTLMException {
|
||||
writeSecurityBuffer(offset, str == null ? null : str.getBytes(
|
||||
unicode ? StandardCharsets.UTF_16LE
|
||||
: StandardCharsets.ISO_8859_1));
|
||||
|
||||
@ -65,6 +65,11 @@ public final class NTLMException extends GeneralSecurityException {
|
||||
*/
|
||||
public static final int PROTOCOL = 6;
|
||||
|
||||
/**
|
||||
* If an invalid input is provided.
|
||||
*/
|
||||
public static final int INVALID_INPUT = 7;
|
||||
|
||||
private int errorCode;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -85,9 +85,9 @@ public abstract class Server extends NTLM {
|
||||
* {@code nonce} is null.
|
||||
*/
|
||||
public byte[] type2(byte[] type1, byte[] nonce) throws NTLMException {
|
||||
if (nonce == null) {
|
||||
if (nonce == null || nonce.length != 8) {
|
||||
throw new NTLMException(NTLMException.PROTOCOL,
|
||||
"nonce cannot be null");
|
||||
"nonce must be 8-byte long");
|
||||
}
|
||||
debug("NTLM Server: Type 1 received\n");
|
||||
if (type1 != null) debug(type1);
|
||||
|
||||
@ -31,6 +31,10 @@ package java.math;
|
||||
|
||||
import static java.math.BigInteger.LONG_MASK;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -1047,6 +1051,15 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
this.precision = prec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept no subclasses.
|
||||
*/
|
||||
private static BigInteger toStrictBigInteger(BigInteger val) {
|
||||
return (val.getClass() == BigInteger.class) ?
|
||||
val :
|
||||
new BigInteger(val.toByteArray().clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a {@code BigInteger} into a {@code BigDecimal}.
|
||||
* The scale of the {@code BigDecimal} is zero.
|
||||
@ -1056,8 +1069,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
*/
|
||||
public BigDecimal(BigInteger val) {
|
||||
scale = 0;
|
||||
intVal = val;
|
||||
intCompact = compactValFor(val);
|
||||
intVal = toStrictBigInteger(val);
|
||||
intCompact = compactValFor(intVal);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1071,7 +1084,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* @since 1.5
|
||||
*/
|
||||
public BigDecimal(BigInteger val, MathContext mc) {
|
||||
this(val,0,mc);
|
||||
this(toStrictBigInteger(val), 0, mc);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1085,8 +1098,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
*/
|
||||
public BigDecimal(BigInteger unscaledVal, int scale) {
|
||||
// Negative scales are now allowed
|
||||
this.intVal = unscaledVal;
|
||||
this.intCompact = compactValFor(unscaledVal);
|
||||
this.intVal = toStrictBigInteger(unscaledVal);
|
||||
this.intCompact = compactValFor(this.intVal);
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@ -1104,6 +1117,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* @since 1.5
|
||||
*/
|
||||
public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
|
||||
unscaledVal = toStrictBigInteger(unscaledVal);
|
||||
long compactVal = compactValFor(unscaledVal);
|
||||
int mcp = mc.precision;
|
||||
int prec = 0;
|
||||
@ -4246,9 +4260,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
= unsafe.objectFieldOffset(BigDecimal.class, "intCompact");
|
||||
private static final long intValOffset
|
||||
= unsafe.objectFieldOffset(BigDecimal.class, "intVal");
|
||||
private static final long scaleOffset
|
||||
= unsafe.objectFieldOffset(BigDecimal.class, "scale");
|
||||
|
||||
static void setIntCompact(BigDecimal bd, long val) {
|
||||
unsafe.putLong(bd, intCompactOffset, val);
|
||||
static void setIntValAndScale(BigDecimal bd, BigInteger intVal, int scale) {
|
||||
unsafe.putReference(bd, intValOffset, intVal);
|
||||
unsafe.putInt(bd, scaleOffset, scale);
|
||||
unsafe.putLong(bd, intCompactOffset, compactValFor(intVal));
|
||||
}
|
||||
|
||||
static void setIntValVolatile(BigDecimal bd, BigInteger val) {
|
||||
@ -4267,15 +4285,30 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
@java.io.Serial
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException {
|
||||
// Read in all fields
|
||||
s.defaultReadObject();
|
||||
// validate possibly bad fields
|
||||
if (intVal == null) {
|
||||
String message = "BigDecimal: null intVal in stream";
|
||||
throw new java.io.StreamCorruptedException(message);
|
||||
// [all values of scale are now allowed]
|
||||
// prepare to read the fields
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
BigInteger serialIntVal = (BigInteger) fields.get("intVal", null);
|
||||
|
||||
// Validate field data
|
||||
if (serialIntVal == null) {
|
||||
throw new StreamCorruptedException("Null or missing intVal in BigDecimal stream");
|
||||
}
|
||||
UnsafeHolder.setIntCompact(this, compactValFor(intVal));
|
||||
// Validate provenance of serialIntVal object
|
||||
serialIntVal = toStrictBigInteger(serialIntVal);
|
||||
|
||||
// Any integer value is valid for scale
|
||||
int serialScale = fields.get("scale", 0);
|
||||
|
||||
UnsafeHolder.setIntValAndScale(this, serialIntVal, serialScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization without data not supported for this class.
|
||||
*/
|
||||
@java.io.Serial
|
||||
private void readObjectNoData()
|
||||
throws ObjectStreamException {
|
||||
throw new InvalidObjectException("Deserialized BigDecimal objects need data");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,9 +30,11 @@
|
||||
package java.math;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamField;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
@ -4824,17 +4826,21 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
||||
// prepare to read the alternate persistent fields
|
||||
ObjectInputStream.GetField fields = s.readFields();
|
||||
|
||||
// Read the alternate persistent fields that we care about
|
||||
int sign = fields.get("signum", -2);
|
||||
byte[] magnitude = (byte[])fields.get("magnitude", null);
|
||||
// Read and validate the alternate persistent fields that we
|
||||
// care about, signum and magnitude
|
||||
|
||||
// Validate signum
|
||||
// Read and validate signum
|
||||
int sign = fields.get("signum", -2);
|
||||
if (sign < -1 || sign > 1) {
|
||||
String message = "BigInteger: Invalid signum value";
|
||||
if (fields.defaulted("signum"))
|
||||
message = "BigInteger: Signum not present in stream";
|
||||
throw new java.io.StreamCorruptedException(message);
|
||||
}
|
||||
|
||||
// Read and validate magnitude
|
||||
byte[] magnitude = (byte[])fields.get("magnitude", null);
|
||||
magnitude = magnitude.clone(); // defensive copy
|
||||
int[] mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
|
||||
if ((mag.length == 0) != (sign == 0)) {
|
||||
String message = "BigInteger: signum-magnitude mismatch";
|
||||
@ -4843,18 +4849,24 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
||||
throw new java.io.StreamCorruptedException(message);
|
||||
}
|
||||
|
||||
// Commit final fields via Unsafe
|
||||
UnsafeHolder.putSign(this, sign);
|
||||
|
||||
// Calculate mag field from magnitude and discard magnitude
|
||||
UnsafeHolder.putMag(this, mag);
|
||||
if (mag.length >= MAX_MAG_LENGTH) {
|
||||
try {
|
||||
checkRange();
|
||||
} catch (ArithmeticException e) {
|
||||
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
|
||||
}
|
||||
// Equivalent to checkRange() on mag local without assigning
|
||||
// this.mag field
|
||||
if (mag.length > MAX_MAG_LENGTH ||
|
||||
(mag.length == MAX_MAG_LENGTH && mag[0] < 0)) {
|
||||
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
|
||||
}
|
||||
|
||||
// Commit final fields via Unsafe
|
||||
UnsafeHolder.putSignAndMag(this, sign, mag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization without data not supported for this class.
|
||||
*/
|
||||
@java.io.Serial
|
||||
private void readObjectNoData()
|
||||
throws ObjectStreamException {
|
||||
throw new InvalidObjectException("Deserialized BigInteger objects need data");
|
||||
}
|
||||
|
||||
// Support for resetting final fields while deserializing
|
||||
@ -4866,11 +4878,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
||||
private static final long magOffset
|
||||
= unsafe.objectFieldOffset(BigInteger.class, "mag");
|
||||
|
||||
static void putSign(BigInteger bi, int sign) {
|
||||
static void putSignAndMag(BigInteger bi, int sign, int[] magnitude) {
|
||||
unsafe.putInt(bi, signumOffset, sign);
|
||||
}
|
||||
|
||||
static void putMag(BigInteger bi, int[] magnitude) {
|
||||
unsafe.putReference(bi, magOffset, magnitude);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -153,7 +153,7 @@ implements java.io.Serializable
|
||||
* Each chain is ordered bottom-to-top (i.e., with the signer certificate
|
||||
* first and the (root) certificate authority last). The signer
|
||||
* certificates are copied from the array. Subsequent changes to
|
||||
* the array will not affect this UnsolvedPermission.
|
||||
* the array will not affect this UnresolvedPermission.
|
||||
*/
|
||||
public UnresolvedPermission(String type,
|
||||
String name,
|
||||
@ -165,59 +165,63 @@ implements java.io.Serializable
|
||||
if (type == null)
|
||||
throw new NullPointerException("type can't be null");
|
||||
|
||||
// Perform a defensive copy and reassign certs if we have a non-null
|
||||
// reference
|
||||
if (certs != null) {
|
||||
certs = certs.clone();
|
||||
}
|
||||
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.actions = actions;
|
||||
|
||||
if (certs != null) {
|
||||
// Extract the signer certs from the list of certificates.
|
||||
for (int i=0; i<certs.length; i++) {
|
||||
for (int i = 0; i < certs.length; i++) {
|
||||
if (!(certs[i] instanceof X509Certificate)) {
|
||||
// there is no concept of signer certs, so we store the
|
||||
// entire cert array
|
||||
this.certs = certs.clone();
|
||||
break;
|
||||
// entire cert array. No further processing is necessary.
|
||||
this.certs = certs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.certs == null) {
|
||||
// Go through the list of certs and see if all the certs are
|
||||
// signer certs.
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
while (i < certs.length) {
|
||||
count++;
|
||||
while (((i+1) < certs.length) &&
|
||||
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
|
||||
((X509Certificate)certs[i+1]).getSubjectX500Principal())) {
|
||||
i++;
|
||||
}
|
||||
// Go through the list of certs and see if all the certs are
|
||||
// signer certs.
|
||||
int i = 0;
|
||||
int count = 0;
|
||||
while (i < certs.length) {
|
||||
count++;
|
||||
while (((i + 1) < certs.length) &&
|
||||
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
|
||||
((X509Certificate)certs[i + 1]).getSubjectX500Principal())) {
|
||||
i++;
|
||||
}
|
||||
if (count == certs.length) {
|
||||
// All the certs are signer certs, so we store the entire
|
||||
// array
|
||||
this.certs = certs.clone();
|
||||
}
|
||||
|
||||
if (this.certs == null) {
|
||||
// extract the signer certs
|
||||
ArrayList<java.security.cert.Certificate> signerCerts =
|
||||
new ArrayList<>();
|
||||
i = 0;
|
||||
while (i < certs.length) {
|
||||
signerCerts.add(certs[i]);
|
||||
while (((i+1) < certs.length) &&
|
||||
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
|
||||
((X509Certificate)certs[i+1]).getSubjectX500Principal())) {
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
this.certs =
|
||||
new java.security.cert.Certificate[signerCerts.size()];
|
||||
signerCerts.toArray(this.certs);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (count == certs.length) {
|
||||
// All the certs are signer certs, so we store the entire
|
||||
// array. No further processing is needed.
|
||||
this.certs = certs;
|
||||
return;
|
||||
}
|
||||
|
||||
// extract the signer certs
|
||||
ArrayList<java.security.cert.Certificate> signerCerts =
|
||||
new ArrayList<>();
|
||||
i = 0;
|
||||
while (i < certs.length) {
|
||||
signerCerts.add(certs[i]);
|
||||
while (((i + 1) < certs.length) &&
|
||||
((X509Certificate)certs[i]).getIssuerX500Principal().equals(
|
||||
((X509Certificate)certs[i + 1]).getSubjectX500Principal())) {
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
this.certs =
|
||||
new java.security.cert.Certificate[signerCerts.size()];
|
||||
signerCerts.toArray(this.certs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,6 +314,7 @@ implements java.io.Serializable
|
||||
*
|
||||
* @return false.
|
||||
*/
|
||||
@Override
|
||||
public boolean implies(Permission p) {
|
||||
return false;
|
||||
}
|
||||
@ -330,6 +335,7 @@ implements java.io.Serializable
|
||||
* type (class) name, permission name, actions, and
|
||||
* certificates as this object.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this)
|
||||
return true;
|
||||
@ -402,7 +408,7 @@ implements java.io.Serializable
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = type.hashCode();
|
||||
if (name != null)
|
||||
@ -422,6 +428,7 @@ implements java.io.Serializable
|
||||
*
|
||||
* @return the empty string "".
|
||||
*/
|
||||
@Override
|
||||
public String getActions()
|
||||
{
|
||||
return "";
|
||||
@ -489,6 +496,7 @@ implements java.io.Serializable
|
||||
*
|
||||
* @return information about this UnresolvedPermission.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(unresolved " + type + " " + name + " " + actions + ")";
|
||||
}
|
||||
@ -500,7 +508,7 @@ implements java.io.Serializable
|
||||
* @return a new PermissionCollection object suitable for
|
||||
* storing UnresolvedPermissions.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public PermissionCollection newPermissionCollection() {
|
||||
return new UnresolvedPermissionCollection();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -347,5 +347,40 @@ public final class ECUtil {
|
||||
return prv;
|
||||
}
|
||||
|
||||
// Partial Public key validation as described in NIST SP 800-186 Appendix D.1.1.1.
|
||||
// The extra step in the full validation (described in Appendix D.1.1.2) is implemented
|
||||
// as sun.security.ec.ECOperations#checkOrder inside the jdk.crypto.ec module.
|
||||
public static void validatePublicKey(ECPoint point, ECParameterSpec spec)
|
||||
throws InvalidKeyException {
|
||||
BigInteger p;
|
||||
if (spec.getCurve().getField() instanceof ECFieldFp f) {
|
||||
p = f.getP();
|
||||
} else {
|
||||
throw new InvalidKeyException("Only curves over prime fields are supported");
|
||||
}
|
||||
|
||||
// 1. If Q is the point at infinity, output REJECT
|
||||
if (point.equals(ECPoint.POINT_INFINITY)) {
|
||||
throw new InvalidKeyException("Public point is at infinity");
|
||||
}
|
||||
// 2. Verify that x and y are integers in the interval [0, p-1]. Output REJECT if verification fails.
|
||||
BigInteger x = point.getAffineX();
|
||||
if (x.signum() < 0 || x.compareTo(p) >= 0) {
|
||||
throw new InvalidKeyException("Public point x is not in the interval [0, p-1]");
|
||||
}
|
||||
BigInteger y = point.getAffineY();
|
||||
if (y.signum() < 0 || y.compareTo(p) >= 0) {
|
||||
throw new InvalidKeyException("Public point y is not in the interval [0, p-1]");
|
||||
}
|
||||
// 3. Verify that (x, y) is a point on the W_a,b by checking that (x, y) satisfies the defining
|
||||
// equation y^2 = x^3 + a x + b where computations are carried out in GF(p). Output REJECT
|
||||
// if verification fails.
|
||||
BigInteger left = y.modPow(BigInteger.TWO, p);
|
||||
BigInteger right = x.pow(3).add(spec.getCurve().getA().multiply(x)).add(spec.getCurve().getB()).mod(p);
|
||||
if (!left.equals(right)) {
|
||||
throw new InvalidKeyException("Public point is not on the curve");
|
||||
}
|
||||
}
|
||||
|
||||
private ECUtil() {}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,8 +46,13 @@
|
||||
|
||||
#define IS_SAFE_SIZE_T(x) ((x) >= 0 && (unsigned long long)(x) <= SIZE_MAX)
|
||||
|
||||
#define IS_MUL_OVERFLOW(m, n) \
|
||||
((m) != 0 && (n) != 0 && (((size_t)((m)*(n))) != (((size_t)(m)) * ((size_t)(n)))))
|
||||
|
||||
#define IS_SAFE_SIZE_MUL(m, n) \
|
||||
(IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && ((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m))))
|
||||
(IS_SAFE_SIZE_T(m) && IS_SAFE_SIZE_T(n) && \
|
||||
((m) == 0 || (n) == 0 || (size_t)(n) <= (SIZE_MAX / (size_t)(m))) && \
|
||||
!IS_MUL_OVERFLOW(m, n))
|
||||
|
||||
#define IS_SAFE_SIZE_ADD(a, b) \
|
||||
(IS_SAFE_SIZE_T(a) && IS_SAFE_SIZE_T(b) && (size_t)(b) <= (SIZE_MAX - (size_t)(a)))
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1043,7 +1043,7 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits
|
||||
// limit iconSize to MAX_ICON_SIZE, so that the colorBits and maskBits
|
||||
// arrays are big enough.
|
||||
// (logic: rather show bad icons than overrun the array size)
|
||||
iconSize = iconSize > MAX_ICON_SIZE ? MAX_ICON_SIZE : iconSize;
|
||||
iconSize = (iconSize <= 0 || iconSize > MAX_ICON_SIZE) ? MAX_ICON_SIZE : iconSize;
|
||||
|
||||
// Set up BITMAPINFO
|
||||
BITMAPINFO bmi;
|
||||
|
||||
@ -103,7 +103,7 @@ class AsyncSSLConnection extends AbstractAsyncSSLConnection {
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return ConnectionPool.cacheKey(address, null);
|
||||
return ConnectionPool.cacheKey(true, address, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -28,7 +28,6 @@ package jdk.internal.net.http;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.util.function.Function;
|
||||
import jdk.internal.net.http.common.MinimalFuture;
|
||||
import jdk.internal.net.http.common.SSLTube;
|
||||
@ -106,7 +105,7 @@ class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection {
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return ConnectionPool.cacheKey(address, plainConnection.proxyAddr);
|
||||
return ConnectionPool.cacheKey(true, address, plainConnection.proxyAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
package jdk.internal.net.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Instant;
|
||||
@ -68,18 +67,21 @@ final class ConnectionPool {
|
||||
/**
|
||||
* Entries in connection pool are keyed by destination address and/or
|
||||
* proxy address:
|
||||
* case 1: plain TCP not via proxy (destination only)
|
||||
* case 1: plain TCP not via proxy (destination IP only)
|
||||
* case 2: plain TCP via proxy (proxy only)
|
||||
* case 3: SSL not via proxy (destination only)
|
||||
* case 4: SSL over tunnel (destination and proxy)
|
||||
* case 3: SSL not via proxy (destination IP+hostname only)
|
||||
* case 4: SSL over tunnel (destination IP+hostname and proxy)
|
||||
*/
|
||||
static class CacheKey {
|
||||
final InetSocketAddress proxy;
|
||||
final InetSocketAddress destination;
|
||||
final boolean secure;
|
||||
|
||||
CacheKey(InetSocketAddress destination, InetSocketAddress proxy) {
|
||||
private CacheKey(boolean secure, InetSocketAddress destination,
|
||||
InetSocketAddress proxy) {
|
||||
this.proxy = proxy;
|
||||
this.destination = destination;
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,12 +93,26 @@ final class ConnectionPool {
|
||||
return false;
|
||||
}
|
||||
final CacheKey other = (CacheKey) obj;
|
||||
if (this.secure != other.secure) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.proxy, other.proxy)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.destination, other.destination)) {
|
||||
return false;
|
||||
}
|
||||
if (secure && destination != null) {
|
||||
if (destination.getHostName() != null) {
|
||||
if (!destination.getHostName().equalsIgnoreCase(
|
||||
other.destination.getHostName())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (other.destination.getHostName() != null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -128,10 +144,10 @@ final class ConnectionPool {
|
||||
assert !stopped : "Already stopped";
|
||||
}
|
||||
|
||||
static CacheKey cacheKey(InetSocketAddress destination,
|
||||
static CacheKey cacheKey(boolean secure, InetSocketAddress destination,
|
||||
InetSocketAddress proxy)
|
||||
{
|
||||
return new CacheKey(destination, proxy);
|
||||
return new CacheKey(secure, destination, proxy);
|
||||
}
|
||||
|
||||
synchronized HttpConnection getConnection(boolean secure,
|
||||
@ -140,7 +156,7 @@ final class ConnectionPool {
|
||||
if (stopped) return null;
|
||||
// for plain (unsecure) proxy connection the destination address is irrelevant.
|
||||
addr = secure || proxy == null ? addr : null;
|
||||
CacheKey key = new CacheKey(addr, proxy);
|
||||
CacheKey key = new CacheKey(secure, addr, proxy);
|
||||
HttpConnection c = secure ? findConnection(key, sslPool)
|
||||
: findConnection(key, plainPool);
|
||||
//System.out.println ("getConnection returning: " + c);
|
||||
|
||||
@ -414,7 +414,7 @@ class PlainHttpConnection extends HttpConnection {
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return new ConnectionPool.CacheKey(address, null);
|
||||
return ConnectionPool.cacheKey(false, address, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -35,7 +35,7 @@ class PlainProxyConnection extends PlainHttpConnection {
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return new ConnectionPool.CacheKey(null, address);
|
||||
return ConnectionPool.cacheKey(false, null, address);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -30,11 +30,10 @@ import java.net.InetSocketAddress;
|
||||
import java.net.http.HttpTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.function.Function;
|
||||
import java.net.http.HttpHeaders;
|
||||
|
||||
import jdk.internal.net.http.common.FlowTube;
|
||||
import jdk.internal.net.http.common.MinimalFuture;
|
||||
import static java.net.http.HttpResponse.BodyHandlers.discarding;
|
||||
@ -153,7 +152,7 @@ final class PlainTunnelingConnection extends HttpConnection {
|
||||
|
||||
@Override
|
||||
ConnectionPool.CacheKey cacheKey() {
|
||||
return new ConnectionPool.CacheKey(null, proxyAddr);
|
||||
return ConnectionPool.cacheKey(false, null, proxyAddr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -897,7 +897,7 @@ gss_init_sec_context(OM_uint32 *minor_status,
|
||||
gss_buffer_desc tn;
|
||||
gss_display_name(&minor, target_name, &tn, NULL);
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)tn.value, (int)tn.length,
|
||||
outName, sizeof(outName) - 1);
|
||||
outName, (sizeof(outName) / sizeof(outName[0])) - 1);
|
||||
if (len == 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -463,8 +463,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
Optional<ECDSAOperations> opsOpt =
|
||||
ECDSAOperations.forParameters(params);
|
||||
if (opsOpt.isEmpty()) {
|
||||
throw new SignatureException("Curve not supported: " +
|
||||
params.toString());
|
||||
throw new SignatureException("Curve not supported: " + params);
|
||||
}
|
||||
byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest, privateKey,
|
||||
random);
|
||||
@ -480,22 +479,33 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
@Override
|
||||
protected boolean engineVerify(byte[] signature) throws SignatureException {
|
||||
|
||||
ECPoint w = publicKey.getW();
|
||||
ECParameterSpec params = publicKey.getParams();
|
||||
|
||||
// Partial public key validation
|
||||
try {
|
||||
ECUtil.validatePublicKey(w, params);
|
||||
} catch (InvalidKeyException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ECDSAOperations ops = ECDSAOperations.forParameters(params)
|
||||
.orElseThrow(() -> new SignatureException("Curve not supported: " + params));
|
||||
|
||||
// Full public key validation, only necessary when h != 1.
|
||||
if (params.getCofactor() != 1) {
|
||||
if (!ops.getEcOperations().checkOrder(w)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] sig;
|
||||
if (p1363Format) {
|
||||
sig = signature;
|
||||
} else {
|
||||
sig = ECUtil.decodeSignature(signature);
|
||||
}
|
||||
|
||||
byte[] digest = getDigestValue();
|
||||
|
||||
Optional<ECDSAOperations> opsOpt =
|
||||
ECDSAOperations.forParameters(publicKey.getParams());
|
||||
if (opsOpt.isEmpty()) {
|
||||
throw new SignatureException("Curve not supported: " +
|
||||
publicKey.getParams().toString());
|
||||
}
|
||||
return opsOpt.get().verifySignedDigest(digest, sig, publicKey.getW());
|
||||
return ops.verifySignedDigest(getDigestValue(), sig, w);
|
||||
}
|
||||
|
||||
// set parameter, not supported. See JCA doc
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
package sun.security.ec;
|
||||
|
||||
import sun.security.ec.point.*;
|
||||
import sun.security.util.ArrayUtil;
|
||||
import sun.security.util.math.*;
|
||||
import sun.security.util.math.intpoly.*;
|
||||
|
||||
@ -33,6 +34,7 @@ import java.math.BigInteger;
|
||||
import java.security.ProviderException;
|
||||
import java.security.spec.ECFieldFp;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.security.spec.EllipticCurve;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -489,5 +491,19 @@ public class ECOperations {
|
||||
p.getZ().setSum(t1);
|
||||
|
||||
}
|
||||
|
||||
// The extra step in the Full Public key validation as described in
|
||||
// NIST SP 800-186 Appendix D.1.1.2
|
||||
public boolean checkOrder(ECPoint point) {
|
||||
BigInteger x = point.getAffineX();
|
||||
BigInteger y = point.getAffineY();
|
||||
|
||||
// Verify that n Q = INFINITY. Output REJECT if verification fails.
|
||||
IntegerFieldModuloP field = this.getField();
|
||||
AffinePoint ap = new AffinePoint(field.getElement(x), field.getElement(y));
|
||||
byte[] scalar = this.orderField.getSize().toByteArray();
|
||||
ArrayUtil.reverse(scalar);
|
||||
return isNeutral(this.multiply(ap, scalar));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,8 +30,6 @@ import javax.net.ssl.*;
|
||||
import java.nio.channels.*;
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.System.Logger.Level;
|
||||
import com.sun.net.httpserver.*;
|
||||
import com.sun.net.httpserver.spi.*;
|
||||
|
||||
/**
|
||||
* encapsulates all the connection specific state for a HTTP/S connection
|
||||
@ -55,14 +53,14 @@ class HttpConnection {
|
||||
SocketChannel chan;
|
||||
SelectionKey selectionKey;
|
||||
String protocol;
|
||||
long time;
|
||||
volatile long creationTime; // time this connection was created
|
||||
long idleStartTime; // absolute time in milli seconds, starting when the connection was marked idle
|
||||
volatile long reqStartedTime; // time when the request was initiated
|
||||
volatile long rspStartedTime; // time we started writing the response
|
||||
int remaining;
|
||||
boolean closed = false;
|
||||
Logger logger;
|
||||
|
||||
public enum State {IDLE, REQUEST, RESPONSE};
|
||||
public enum State {IDLE, REQUEST, RESPONSE, NEWLY_ACCEPTED};
|
||||
volatile State state;
|
||||
|
||||
public String toString() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,7 +44,6 @@ class SSLStreams {
|
||||
|
||||
SSLContext sslctx;
|
||||
SocketChannel chan;
|
||||
TimeSource time;
|
||||
ServerImpl server;
|
||||
SSLEngine engine;
|
||||
EngineWrapper wrapper;
|
||||
@ -56,7 +55,6 @@ class SSLStreams {
|
||||
|
||||
SSLStreams (ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException {
|
||||
this.server = server;
|
||||
this.time= (TimeSource)server;
|
||||
this.sslctx= sslctx;
|
||||
this.chan= chan;
|
||||
InetSocketAddress addr =
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,29 +37,35 @@ import java.security.PrivilegedAction;
|
||||
@SuppressWarnings("removal")
|
||||
class ServerConfig {
|
||||
|
||||
private static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec.
|
||||
private static final int DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS = 10000 ; // 10 sec.
|
||||
|
||||
/* These values must be a reasonable multiple of clockTick */
|
||||
private static final long DEFAULT_IDLE_INTERVAL = 30 ; // 5 min
|
||||
private static final long DEFAULT_IDLE_INTERVAL_IN_SECS = 30;
|
||||
private static final int DEFAULT_MAX_CONNECTIONS = -1 ; // no limit on maximum connections
|
||||
private static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ;
|
||||
|
||||
private static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever
|
||||
private static final long DEFAULT_MAX_RSP_TIME = -1; // default: forever
|
||||
private static final long DEFAULT_TIMER_MILLIS = 1000;
|
||||
// default timer schedule, in milli seconds, for the timer task that's responsible for
|
||||
// timing out request/response if max request/response time is configured
|
||||
private static final long DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS = 1000;
|
||||
private static final int DEFAULT_MAX_REQ_HEADERS = 200;
|
||||
private static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024;
|
||||
|
||||
private static int clockTick;
|
||||
private static long idleInterval;
|
||||
private static long idleTimerScheduleMillis;
|
||||
private static long idleIntervalMillis;
|
||||
// The maximum number of bytes to drain from an inputstream
|
||||
private static long drainAmount;
|
||||
// the maximum number of connections that the server will allow to be open
|
||||
// after which it will no longer "accept()" any new connections, till the
|
||||
// current connection count goes down due to completion of processing the requests
|
||||
private static int maxConnections;
|
||||
private static int maxIdleConnections;
|
||||
// The maximum number of request headers allowable
|
||||
private static int maxReqHeaders;
|
||||
// max time a request or response is allowed to take
|
||||
private static long maxReqTime;
|
||||
private static long maxRspTime;
|
||||
private static long timerMillis;
|
||||
private static long reqRspTimerScheduleMillis;
|
||||
private static boolean debug;
|
||||
|
||||
// the value of the TCP_NODELAY socket-level option
|
||||
@ -70,11 +76,22 @@ class ServerConfig {
|
||||
new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run () {
|
||||
idleInterval = Long.getLong("sun.net.httpserver.idleInterval",
|
||||
DEFAULT_IDLE_INTERVAL) * 1000;
|
||||
idleIntervalMillis = Long.getLong("sun.net.httpserver.idleInterval",
|
||||
DEFAULT_IDLE_INTERVAL_IN_SECS) * 1000;
|
||||
if (idleIntervalMillis <= 0) {
|
||||
idleIntervalMillis = DEFAULT_IDLE_INTERVAL_IN_SECS * 1000;
|
||||
}
|
||||
|
||||
clockTick = Integer.getInteger("sun.net.httpserver.clockTick",
|
||||
DEFAULT_CLOCK_TICK);
|
||||
idleTimerScheduleMillis = Long.getLong("sun.net.httpserver.clockTick",
|
||||
DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS);
|
||||
if (idleTimerScheduleMillis <= 0) {
|
||||
// ignore zero or negative value and use the default schedule
|
||||
idleTimerScheduleMillis = DEFAULT_IDLE_TIMER_SCHEDULE_MILLIS;
|
||||
}
|
||||
|
||||
maxConnections = Integer.getInteger(
|
||||
"jdk.httpserver.maxConnections",
|
||||
DEFAULT_MAX_CONNECTIONS);
|
||||
|
||||
maxIdleConnections = Integer.getInteger(
|
||||
"sun.net.httpserver.maxIdleConnections",
|
||||
@ -93,8 +110,13 @@ class ServerConfig {
|
||||
maxRspTime = Long.getLong("sun.net.httpserver.maxRspTime",
|
||||
DEFAULT_MAX_RSP_TIME);
|
||||
|
||||
timerMillis = Long.getLong("sun.net.httpserver.timerMillis",
|
||||
DEFAULT_TIMER_MILLIS);
|
||||
reqRspTimerScheduleMillis = Long.getLong("sun.net.httpserver.timerMillis",
|
||||
DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS);
|
||||
if (reqRspTimerScheduleMillis <= 0) {
|
||||
// ignore any negative or zero value for this configuration and reset
|
||||
// to default schedule
|
||||
reqRspTimerScheduleMillis = DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS;
|
||||
}
|
||||
|
||||
debug = Boolean.getBoolean("sun.net.httpserver.debug");
|
||||
|
||||
@ -150,14 +172,34 @@ class ServerConfig {
|
||||
return debug;
|
||||
}
|
||||
|
||||
static long getIdleInterval() {
|
||||
return idleInterval;
|
||||
/**
|
||||
* {@return Returns the maximum duration, in milli seconds, a connection can be idle}
|
||||
*/
|
||||
static long getIdleIntervalMillis() {
|
||||
return idleIntervalMillis;
|
||||
}
|
||||
|
||||
static int getClockTick() {
|
||||
return clockTick;
|
||||
/**
|
||||
* {@return Returns the schedule, in milli seconds, for the timer task that is responsible
|
||||
* for managing the idle connections}
|
||||
*/
|
||||
static long getIdleTimerScheduleMillis() {
|
||||
return idleTimerScheduleMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maximum number of connections that can be open at any given time.
|
||||
* This method can return a value of 0 or negative to represent that the limit hasn't
|
||||
* been configured.
|
||||
*/
|
||||
static int getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maximum number of connections that can be idle. This method
|
||||
* can return a value of 0 or negative.
|
||||
*/
|
||||
static int getMaxIdleConnections() {
|
||||
return maxIdleConnections;
|
||||
}
|
||||
@ -170,16 +212,30 @@ class ServerConfig {
|
||||
return maxReqHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maximum amount of time the server will wait for the request to be read
|
||||
* completely. This method can return a value of 0 or negative to imply no maximum limit has
|
||||
* been configured.
|
||||
*/
|
||||
static long getMaxReqTime() {
|
||||
return maxReqTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maximum amount of time the server will wait for the response to be generated
|
||||
* for a request that is being processed. This method can return a value of 0 or negative to
|
||||
* imply no maximum limit has been configured.
|
||||
*/
|
||||
static long getMaxRspTime() {
|
||||
return maxRspTime;
|
||||
}
|
||||
|
||||
static long getTimerMillis() {
|
||||
return timerMillis;
|
||||
/**
|
||||
* {@return Returns the timer schedule of the task that's responsible for timing out
|
||||
* request/response that have been running longer than any configured timeout}
|
||||
*/
|
||||
static long getReqRspTimerScheduleMillis() {
|
||||
return reqRspTimerScheduleMillis;
|
||||
}
|
||||
|
||||
static boolean noDelay() {
|
||||
|
||||
@ -25,26 +25,52 @@
|
||||
|
||||
package sun.net.httpserver;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.System.Logger.Level;
|
||||
import javax.net.ssl.*;
|
||||
import com.sun.net.httpserver.*;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import com.sun.net.httpserver.Filter;
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpContext;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import com.sun.net.httpserver.HttpsConfigurator;
|
||||
import sun.net.httpserver.HttpConnection.State;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.System.Logger.Level;
|
||||
import java.net.BindException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||
import static sun.net.httpserver.Utils.*;
|
||||
import static sun.net.httpserver.Utils.isValidName;
|
||||
|
||||
/**
|
||||
* Provides implementation for both HTTP and HTTPS
|
||||
*/
|
||||
class ServerImpl implements TimeSource {
|
||||
class ServerImpl {
|
||||
|
||||
private String protocol;
|
||||
private boolean https;
|
||||
@ -56,32 +82,47 @@ class ServerImpl implements TimeSource {
|
||||
private ServerSocketChannel schan;
|
||||
private Selector selector;
|
||||
private SelectionKey listenerKey;
|
||||
private Set<HttpConnection> idleConnections;
|
||||
private Set<HttpConnection> allConnections;
|
||||
private final Set<HttpConnection> idleConnections;
|
||||
// connections which have been accepted() by the server but which haven't
|
||||
// yet sent any byte on the connection yet
|
||||
private final Set<HttpConnection> newlyAcceptedConnections;
|
||||
private final Set<HttpConnection> allConnections;
|
||||
/* following two are used to keep track of the times
|
||||
* when a connection/request is first received
|
||||
* and when we start to send the response
|
||||
*/
|
||||
private Set<HttpConnection> reqConnections;
|
||||
private Set<HttpConnection> rspConnections;
|
||||
private final Set<HttpConnection> reqConnections;
|
||||
private final Set<HttpConnection> rspConnections;
|
||||
private List<Event> events;
|
||||
private Object lolock = new Object();
|
||||
private final Object lolock = new Object();
|
||||
private volatile boolean finished = false;
|
||||
private volatile boolean terminating = false;
|
||||
private boolean bound = false;
|
||||
private boolean started = false;
|
||||
private volatile long time; /* current time */
|
||||
private volatile long subticks = 0;
|
||||
private volatile long ticks; /* number of clock ticks since server started */
|
||||
private HttpServer wrapper;
|
||||
|
||||
static final int CLOCK_TICK = ServerConfig.getClockTick();
|
||||
static final long IDLE_INTERVAL = ServerConfig.getIdleInterval();
|
||||
// schedule for the timer task that's responsible for idle connection management
|
||||
static final long IDLE_TIMER_TASK_SCHEDULE = ServerConfig.getIdleTimerScheduleMillis();
|
||||
static final int MAX_CONNECTIONS = ServerConfig.getMaxConnections();
|
||||
static final int MAX_IDLE_CONNECTIONS = ServerConfig.getMaxIdleConnections();
|
||||
static final long TIMER_MILLIS = ServerConfig.getTimerMillis ();
|
||||
static final long MAX_REQ_TIME=getTimeMillis(ServerConfig.getMaxReqTime());
|
||||
static final long MAX_RSP_TIME=getTimeMillis(ServerConfig.getMaxRspTime());
|
||||
static final boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
|
||||
// schedule for the timer task that's responsible for request/response timeout management
|
||||
static final long REQ_RSP_TIMER_SCHEDULE = ServerConfig.getReqRspTimerScheduleMillis();
|
||||
static final long MAX_REQ_TIME = getTimeMillis(ServerConfig.getMaxReqTime());
|
||||
static final long MAX_RSP_TIME = getTimeMillis(ServerConfig.getMaxRspTime());
|
||||
static final boolean reqRspTimeoutEnabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
|
||||
// the maximum idle duration for a connection which is currently idle but has served
|
||||
// some request in the past
|
||||
static final long IDLE_INTERVAL = ServerConfig.getIdleIntervalMillis();
|
||||
// the maximum idle duration for a newly accepted connection which hasn't yet received
|
||||
// the first byte of data on that connection
|
||||
static final long NEWLY_ACCEPTED_CONN_IDLE_INTERVAL;
|
||||
static {
|
||||
// the idle duration of a newly accepted connection is considered to be the least of the
|
||||
// configured idle interval and the configured max request time (if any).
|
||||
NEWLY_ACCEPTED_CONN_IDLE_INTERVAL = MAX_REQ_TIME > 0
|
||||
? Math.min(IDLE_INTERVAL, MAX_REQ_TIME)
|
||||
: IDLE_INTERVAL;
|
||||
}
|
||||
|
||||
private Timer timer, timer1;
|
||||
private final Logger logger;
|
||||
@ -112,13 +153,14 @@ class ServerImpl implements TimeSource {
|
||||
allConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
|
||||
reqConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
|
||||
rspConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
|
||||
time = System.currentTimeMillis();
|
||||
timer = new Timer ("server-timer", true);
|
||||
timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK);
|
||||
if (timer1Enabled) {
|
||||
timer1 = new Timer ("server-timer1", true);
|
||||
timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS);
|
||||
logger.log (Level.DEBUG, "HttpServer timer1 enabled period in ms: ", TIMER_MILLIS);
|
||||
newlyAcceptedConnections = Collections.synchronizedSet(new HashSet<>());
|
||||
timer = new Timer ("idle-timeout-task", true);
|
||||
timer.schedule (new IdleTimeoutTask(), IDLE_TIMER_TASK_SCHEDULE, IDLE_TIMER_TASK_SCHEDULE);
|
||||
if (reqRspTimeoutEnabled) {
|
||||
timer1 = new Timer ("req-rsp-timeout-task", true);
|
||||
timer1.schedule (new ReqRspTimeoutTask(), REQ_RSP_TIMER_SCHEDULE, REQ_RSP_TIMER_SCHEDULE);
|
||||
logger.log(Level.DEBUG, "HttpServer request/response timeout task schedule ms: ",
|
||||
REQ_RSP_TIMER_SCHEDULE);
|
||||
logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME);
|
||||
logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME);
|
||||
}
|
||||
@ -209,8 +251,9 @@ class ServerImpl implements TimeSource {
|
||||
}
|
||||
allConnections.clear();
|
||||
idleConnections.clear();
|
||||
newlyAcceptedConnections.clear();
|
||||
timer.cancel();
|
||||
if (timer1Enabled) {
|
||||
if (reqRspTimeoutEnabled) {
|
||||
timer1.cancel();
|
||||
}
|
||||
if (dispatcherThread != null && dispatcherThread != Thread.currentThread()) {
|
||||
@ -273,10 +316,6 @@ class ServerImpl implements TimeSource {
|
||||
});
|
||||
}
|
||||
|
||||
Selector getSelector () {
|
||||
return selector;
|
||||
}
|
||||
|
||||
void addEvent (Event r) {
|
||||
synchronized (lolock) {
|
||||
events.add (r);
|
||||
@ -286,6 +325,70 @@ class ServerImpl implements TimeSource {
|
||||
|
||||
/* main server listener task */
|
||||
|
||||
/**
|
||||
* The Dispatcher is responsible for accepting any connections and then using those connections
|
||||
* to processing any incoming requests. A connection is represented as an instance of
|
||||
* sun.net.httpserver.HttpConnection.
|
||||
*
|
||||
* Connection states:
|
||||
* An instance of HttpConnection goes through the following states:
|
||||
*
|
||||
* - NEWLY_ACCEPTED: A connection is marked as newly accepted as soon as the Dispatcher
|
||||
* accept()s a connection. A newly accepted connection is added to a newlyAcceptedConnections
|
||||
* collection. A newly accepted connection also gets added to the allConnections collection.
|
||||
* The newlyAcceptedConnections isn't checked for any size limits, however, if the server is
|
||||
* configured with a maximum connection limit, then the elements in the
|
||||
* newlyAcceptedConnections will never exceed that configured limit (no explicit size checks
|
||||
* are done on the newlyAcceptedConnections collection, since the maximum connection limit
|
||||
* applies to connections across different connection states). A connection in NEWLY_ACCEPTED
|
||||
* state is considered idle and is eligible for idle connection management.
|
||||
*
|
||||
* - REQUEST: A connection is marked to be in REQUEST state when the request processing starts
|
||||
* on that connection. This typically happens when the first byte of data is received on a
|
||||
* NEWLY_ACCEPTED connection or when new data arrives on a connection which was previously
|
||||
* in IDLE state. When a connection is in REQUEST state, it implies that the connection is
|
||||
* active and thus isn't eligible for idle connection management. If the server is configured
|
||||
* with a maximum request timeout, then connections in REQUEST state are eligible
|
||||
* for Request/Response timeout management.
|
||||
*
|
||||
* - RESPONSE: A connection is marked to be in RESPONSE state when the server has finished
|
||||
* reading the request. A connection is RESPONSE state is considered active and isn't eligible
|
||||
* for idle connection management. If the server is configured with a maximum response timeout,
|
||||
* then connections in RESPONSE state are eligible for Request/Response timeout management.
|
||||
*
|
||||
* - IDLE: A connection is marked as IDLE when a request/response cycle (successfully) completes
|
||||
* on that particular connection. Idle connections are held in a idleConnections collection.
|
||||
* The idleConnections collection is limited in size and the size is decided by a server
|
||||
* configuration. Connections in IDLE state get added to the idleConnections collection only
|
||||
* if that collection hasn't reached the configured limit. If a connection has reached IDLE
|
||||
* state and there's no more room in the idleConnections collection, then such a connection
|
||||
* gets closed. Connections in idleConnections collection are eligible for idle connection
|
||||
* management.
|
||||
*
|
||||
* Idle connection management:
|
||||
* A timer task is responsible for closing idle connections. Each connection that is in a state
|
||||
* which is eligible for idle timeout management (see above section on connection states)
|
||||
* will have a corresponding idle expiration time associated with it. The idle timeout management
|
||||
* task will check the expiration time of each such connection against the current time and will
|
||||
* close the connection if the current time is either equal to or past the expiration time.
|
||||
*
|
||||
* Request/Response timeout management:
|
||||
* The server can be optionally configured with a maximum request timeout and/or maximum response
|
||||
* timeout. If either of these timeouts have been configured, then an additional timer task is
|
||||
* run by the server. This timer task is then responsible for closing connections which have
|
||||
* been in REQUEST or RESPONSE state for a period of time that exceeds the respective configured
|
||||
* timeouts.
|
||||
*
|
||||
* Maximum connection limit management:
|
||||
* The server can be optionally configured with a maximum connection limit. A value of 0 or
|
||||
* negative integer is ignored and considered to represent no connection limit. In case of a
|
||||
* positive integer value, any newly accepted connections will be first checked against the
|
||||
* current count of established connections (held by the allConnections collection) and if the
|
||||
* configured limit has reached, then the newly accepted connection will be closed immediately
|
||||
* (even before setting its state to NEWLY_ACCEPTED or adding it to the newlyAcceptedConnections
|
||||
* collection).
|
||||
*
|
||||
*/
|
||||
class Dispatcher implements Runnable {
|
||||
|
||||
private void handleEvent (Event r) {
|
||||
@ -339,8 +442,7 @@ class ServerImpl implements TimeSource {
|
||||
SelectionKey key = chan.register (selector, SelectionKey.OP_READ);
|
||||
key.attach (c);
|
||||
c.selectionKey = key;
|
||||
c.time = getTime() + IDLE_INTERVAL;
|
||||
idleConnections.add (c);
|
||||
markIdle(c);
|
||||
} catch (IOException e) {
|
||||
dprint(e);
|
||||
logger.log (Level.TRACE, "Dispatcher(8)", e);
|
||||
@ -387,9 +489,19 @@ class ServerImpl implements TimeSource {
|
||||
continue;
|
||||
}
|
||||
SocketChannel chan = schan.accept();
|
||||
|
||||
// optimist there's a channel
|
||||
if (chan != null) {
|
||||
if (MAX_CONNECTIONS > 0 && allConnections.size() >= MAX_CONNECTIONS) {
|
||||
// we've hit max limit of current open connections, so we go
|
||||
// ahead and close this connection without processing it
|
||||
try {
|
||||
chan.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
// move on to next selected key
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set TCP_NODELAY, if appropriate
|
||||
if (ServerConfig.noDelay()) {
|
||||
chan.socket().setTcpNoDelay(true);
|
||||
@ -401,7 +513,7 @@ class ServerImpl implements TimeSource {
|
||||
c.selectionKey = newkey;
|
||||
c.setChannel (chan);
|
||||
newkey.attach (c);
|
||||
requestStarted (c);
|
||||
markNewlyAccepted(c);
|
||||
allConnections.add (c);
|
||||
}
|
||||
} else {
|
||||
@ -412,10 +524,12 @@ class ServerImpl implements TimeSource {
|
||||
|
||||
key.cancel();
|
||||
chan.configureBlocking (true);
|
||||
if (idleConnections.remove(conn)) {
|
||||
// was an idle connection so add it
|
||||
// to reqConnections set.
|
||||
requestStarted (conn);
|
||||
if (newlyAcceptedConnections.remove(conn)
|
||||
|| idleConnections.remove(conn)) {
|
||||
// was either a newly accepted connection or an idle
|
||||
// connection. In either case, we mark that the request
|
||||
// has now started on this connection.
|
||||
requestStarted(conn);
|
||||
}
|
||||
handle (chan, conn);
|
||||
} else {
|
||||
@ -497,10 +611,14 @@ class ServerImpl implements TimeSource {
|
||||
case IDLE:
|
||||
idleConnections.remove(conn);
|
||||
break;
|
||||
case NEWLY_ACCEPTED:
|
||||
newlyAcceptedConnections.remove(conn);
|
||||
break;
|
||||
}
|
||||
assert !reqConnections.remove(conn);
|
||||
assert !rspConnections.remove(conn);
|
||||
assert !idleConnections.remove(conn);
|
||||
assert !newlyAcceptedConnections.remove(conn);
|
||||
}
|
||||
|
||||
/* per exchange task */
|
||||
@ -672,9 +790,9 @@ class ServerImpl implements TimeSource {
|
||||
rheaders.set ("Connection", "close");
|
||||
} else if (chdr.equalsIgnoreCase ("keep-alive")) {
|
||||
rheaders.set ("Connection", "keep-alive");
|
||||
int idle=(int)(ServerConfig.getIdleInterval()/1000);
|
||||
int idleSeconds = (int) (ServerConfig.getIdleIntervalMillis() / 1000);
|
||||
int max=ServerConfig.getMaxIdleConnections();
|
||||
String val = "timeout="+idle+", max="+max;
|
||||
String val = "timeout="+idleSeconds+", max="+max;
|
||||
rheaders.set ("Keep-Alive", val);
|
||||
}
|
||||
}
|
||||
@ -815,14 +933,6 @@ class ServerImpl implements TimeSource {
|
||||
logger.log (Level.DEBUG, message);
|
||||
}
|
||||
|
||||
long getTicks() {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
void delay () {
|
||||
Thread.yield();
|
||||
try {
|
||||
@ -847,11 +957,23 @@ class ServerImpl implements TimeSource {
|
||||
}
|
||||
|
||||
void requestStarted (HttpConnection c) {
|
||||
c.creationTime = getTime();
|
||||
c.reqStartedTime = System.currentTimeMillis();
|
||||
c.setState (State.REQUEST);
|
||||
reqConnections.add (c);
|
||||
}
|
||||
|
||||
void markIdle(HttpConnection c) {
|
||||
c.idleStartTime = System.currentTimeMillis();
|
||||
c.setState(State.IDLE);
|
||||
idleConnections.add(c);
|
||||
}
|
||||
|
||||
void markNewlyAccepted(HttpConnection c) {
|
||||
c.idleStartTime = System.currentTimeMillis();
|
||||
c.setState(State.NEWLY_ACCEPTED);
|
||||
newlyAcceptedConnections.add(c);
|
||||
}
|
||||
|
||||
// called after a request has been completely read
|
||||
// by the server. This stops the timer which would
|
||||
// close the connection if the request doesn't arrive
|
||||
@ -863,7 +985,7 @@ class ServerImpl implements TimeSource {
|
||||
State s = c.getState();
|
||||
assert s == State.REQUEST : "State is not REQUEST ("+s+")";
|
||||
reqConnections.remove (c);
|
||||
c.rspStartedTime = getTime();
|
||||
c.rspStartedTime = System.currentTimeMillis();
|
||||
rspConnections.add (c);
|
||||
c.setState (State.RESPONSE);
|
||||
}
|
||||
@ -877,38 +999,58 @@ class ServerImpl implements TimeSource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for closing connections that have been idle.
|
||||
* TimerTask run every CLOCK_TICK ms
|
||||
*/
|
||||
class ServerTimerTask extends TimerTask {
|
||||
class IdleTimeoutTask extends TimerTask {
|
||||
public void run () {
|
||||
LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
|
||||
time = System.currentTimeMillis();
|
||||
ticks ++;
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
synchronized (idleConnections) {
|
||||
for (HttpConnection c : idleConnections) {
|
||||
if (c.time <= time) {
|
||||
toClose.add (c);
|
||||
final Iterator<HttpConnection> it = idleConnections.iterator();
|
||||
while (it.hasNext()) {
|
||||
final HttpConnection c = it.next();
|
||||
if (currentTime - c.idleStartTime >= IDLE_INTERVAL) {
|
||||
toClose.add(c);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (HttpConnection c : toClose) {
|
||||
idleConnections.remove (c);
|
||||
allConnections.remove (c);
|
||||
c.close();
|
||||
}
|
||||
// if any newly accepted connection has been idle (i.e. no byte has been sent on that
|
||||
// connection during the configured idle timeout period) then close it as well
|
||||
synchronized (newlyAcceptedConnections) {
|
||||
final Iterator<HttpConnection> it = newlyAcceptedConnections.iterator();
|
||||
while (it.hasNext()) {
|
||||
final HttpConnection c = it.next();
|
||||
if (currentTime - c.idleStartTime >= NEWLY_ACCEPTED_CONN_IDLE_INTERVAL) {
|
||||
toClose.add(c);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (HttpConnection c : toClose) {
|
||||
allConnections.remove(c);
|
||||
c.close();
|
||||
if (logger.isLoggable(Level.TRACE)) {
|
||||
logger.log(Level.TRACE, "Closed idle connection " + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ServerTimerTask1 extends TimerTask {
|
||||
/**
|
||||
* Responsible for closing connections which have timed out while in REQUEST or RESPONSE state
|
||||
*/
|
||||
class ReqRspTimeoutTask extends TimerTask {
|
||||
|
||||
// runs every TIMER_MILLIS
|
||||
public void run () {
|
||||
LinkedList<HttpConnection> toClose = new LinkedList<HttpConnection>();
|
||||
time = System.currentTimeMillis();
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
synchronized (reqConnections) {
|
||||
if (MAX_REQ_TIME != -1) {
|
||||
for (HttpConnection c : reqConnections) {
|
||||
if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) {
|
||||
if (currentTime - c.reqStartedTime >= MAX_REQ_TIME) {
|
||||
toClose.add (c);
|
||||
}
|
||||
}
|
||||
@ -924,7 +1066,7 @@ class ServerImpl implements TimeSource {
|
||||
synchronized (rspConnections) {
|
||||
if (MAX_RSP_TIME != -1) {
|
||||
for (HttpConnection c : rspConnections) {
|
||||
if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) {
|
||||
if (currentTime - c.rspStartedTime >= MAX_RSP_TIME) {
|
||||
toClose.add (c);
|
||||
}
|
||||
}
|
||||
@ -939,21 +1081,17 @@ class ServerImpl implements TimeSource {
|
||||
}
|
||||
}
|
||||
|
||||
void logStackTrace (String s) {
|
||||
logger.log (Level.TRACE, s);
|
||||
StringBuilder b = new StringBuilder ();
|
||||
StackTraceElement[] e = Thread.currentThread().getStackTrace();
|
||||
for (int i=0; i<e.length; i++) {
|
||||
b.append (e[i].toString()).append("\n");
|
||||
}
|
||||
logger.log (Level.TRACE, b.toString());
|
||||
}
|
||||
|
||||
static long getTimeMillis(long secs) {
|
||||
if (secs == -1) {
|
||||
/**
|
||||
* Converts and returns the passed {@code secs} as milli seconds. If the passed {@code secs}
|
||||
* is negative or zero or if the conversion from seconds to milli seconds results in a negative
|
||||
* number, then this method returns -1.
|
||||
*/
|
||||
private static long getTimeMillis(long secs) {
|
||||
if (secs <= 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return secs * 1000;
|
||||
}
|
||||
final long milli = secs * 1000;
|
||||
// this handles potential numeric overflow that may have happened during conversion
|
||||
return milli > 0 ? milli : -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.net.httpserver;
|
||||
|
||||
interface TimeSource {
|
||||
public long getTime();
|
||||
}
|
||||
@ -26,6 +26,9 @@
|
||||
package sun.net.httpserver.simpleserver;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
@ -33,6 +36,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
*/
|
||||
public class JWebServer {
|
||||
|
||||
private static final String SYS_PROP_MAX_CONNECTIONS = "jdk.httpserver.maxConnections";
|
||||
private static final String DEFAULT_JWEBSERVER_MAX_CONNECTIONS = "200";
|
||||
|
||||
/**
|
||||
* This constructor should never be called.
|
||||
*/
|
||||
@ -59,6 +65,7 @@ public class JWebServer {
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
setMaxReqTime();
|
||||
setMaxConnectionsIfNotSet();
|
||||
|
||||
int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "jwebserver", args);
|
||||
if (ec != 0) {
|
||||
@ -76,4 +83,16 @@ public class JWebServer {
|
||||
System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
static void setMaxConnectionsIfNotSet() {
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
if (System.getProperty(SYS_PROP_MAX_CONNECTIONS) != null) {
|
||||
// an explicit value has already been set, so we don't override it
|
||||
return null;
|
||||
}
|
||||
System.setProperty(SYS_PROP_MAX_CONNECTIONS, DEFAULT_JWEBSERVER_MAX_CONNECTIONS);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ public class Main {
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
setMaxReqTime();
|
||||
JWebServer.setMaxConnectionsIfNotSet();
|
||||
|
||||
int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "java", args);
|
||||
if (ec != 0) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,8 @@ import java.net.ProtocolFamily;
|
||||
import java.net.SocketException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
@ -50,6 +52,21 @@ class DNSDatagramSocketFactory {
|
||||
static final int RANGE = UPPER - LOWER + 1;
|
||||
}
|
||||
|
||||
private static int findFirstFreePort() {
|
||||
PrivilegedExceptionAction<DatagramSocket> action = () -> new DatagramSocket(0);
|
||||
int port;
|
||||
try {
|
||||
@SuppressWarnings({"deprecated", "removal"})
|
||||
DatagramSocket ds = AccessController.doPrivileged(action);
|
||||
try (DatagramSocket ds1 = ds) {
|
||||
port = ds1.getLocalPort();
|
||||
}
|
||||
} catch (Exception x) {
|
||||
port = 0;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
// Records a subset of max {@code capacity} previously used ports
|
||||
static final class PortHistory {
|
||||
final int capacity;
|
||||
@ -74,7 +91,10 @@ class DNSDatagramSocketFactory {
|
||||
public boolean add(int port) {
|
||||
if (ports[index] != 0) { // at max capacity
|
||||
// remove one port at random and store the new port there
|
||||
ports[random.nextInt(capacity)] = port;
|
||||
// don't remove the last port
|
||||
int remove = random.nextInt(capacity);
|
||||
if ((remove +1) % capacity == index) remove = index;
|
||||
ports[index = remove] = port;
|
||||
} else { // there's a free slot
|
||||
ports[index] = port;
|
||||
}
|
||||
@ -90,7 +110,8 @@ class DNSDatagramSocketFactory {
|
||||
}
|
||||
}
|
||||
|
||||
int lastport = 0;
|
||||
int lastport = findFirstFreePort();
|
||||
int lastSystemAllocated = lastport;
|
||||
int suitablePortCount;
|
||||
int unsuitablePortCount;
|
||||
final ProtocolFamily family; // null (default) means dual stack
|
||||
@ -147,13 +168,16 @@ class DNSDatagramSocketFactory {
|
||||
s = openDefault();
|
||||
lastport = s.getLocalPort();
|
||||
if (lastseen == 0) {
|
||||
lastSystemAllocated = lastport;
|
||||
history.offer(lastport);
|
||||
return s;
|
||||
}
|
||||
|
||||
thresholdCrossed = suitablePortCount > thresholdCount;
|
||||
boolean farEnough = Integer.bitCount(lastseen ^ lastport) > BIT_DEVIATION
|
||||
&& Math.abs(lastport - lastseen) > deviation;
|
||||
boolean farEnough = farEnough(lastseen);
|
||||
if (farEnough && lastSystemAllocated > 0) {
|
||||
farEnough = farEnough(lastSystemAllocated);
|
||||
}
|
||||
boolean recycled = history.contains(lastport);
|
||||
boolean suitable = (thresholdCrossed || farEnough && !recycled);
|
||||
if (suitable && !recycled) history.add(lastport);
|
||||
@ -168,6 +192,7 @@ class DNSDatagramSocketFactory {
|
||||
// Either the underlying stack supports random UDP port allocation,
|
||||
// or the new port is sufficiently distant from last port to make
|
||||
// it look like it is. Let's use it.
|
||||
lastSystemAllocated = lastport;
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -196,9 +221,7 @@ class DNSDatagramSocketFactory {
|
||||
} catch (SocketException x) {
|
||||
throw x;
|
||||
} catch (IOException x) {
|
||||
SocketException e = new SocketException(x.getMessage());
|
||||
e.initCause(x);
|
||||
throw e;
|
||||
throw new SocketException(x.getMessage(), x);
|
||||
}
|
||||
}
|
||||
return new DatagramSocket();
|
||||
@ -218,24 +241,48 @@ class DNSDatagramSocketFactory {
|
||||
&& !isUsingNativePortRandomization();
|
||||
}
|
||||
|
||||
private boolean farEnough(int port) {
|
||||
return Integer.bitCount(port ^ lastport) > BIT_DEVIATION
|
||||
&& Math.abs(port - lastport) > deviation;
|
||||
}
|
||||
|
||||
private DatagramSocket openRandom() {
|
||||
int maxtries = MAX_RANDOM_TRIES;
|
||||
while (maxtries-- > 0) {
|
||||
int port = EphemeralPortRange.LOWER
|
||||
+ random.nextInt(EphemeralPortRange.RANGE);
|
||||
int port;
|
||||
boolean suitable;
|
||||
boolean recycled;
|
||||
int maxrandom = MAX_RANDOM_TRIES;
|
||||
do {
|
||||
port = EphemeralPortRange.LOWER
|
||||
+ random.nextInt(EphemeralPortRange.RANGE);
|
||||
recycled = history.contains(port);
|
||||
suitable = lastport == 0 || (farEnough(port) && !recycled);
|
||||
} while (maxrandom-- > 0 && !suitable);
|
||||
|
||||
// if no suitable port was found, try again
|
||||
// this means we might call random MAX_RANDOM_TRIES x MAX_RANDOM_TRIES
|
||||
// times - but that should be OK with MAX_RANDOM_TRIES = 5.
|
||||
if (!suitable) continue;
|
||||
|
||||
try {
|
||||
if (family != null) {
|
||||
DatagramChannel c = DatagramChannel.open(family);
|
||||
try {
|
||||
DatagramSocket s = c.socket();
|
||||
s.bind(new InetSocketAddress(port));
|
||||
lastport = s.getLocalPort();
|
||||
if (!recycled) history.add(port);
|
||||
return s;
|
||||
} catch (Throwable x) {
|
||||
c.close();
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
return new DatagramSocket(port);
|
||||
DatagramSocket s = new DatagramSocket(port);
|
||||
lastport = s.getLocalPort();
|
||||
if (!recycled) history.add(port);
|
||||
return s;
|
||||
} catch (IOException x) {
|
||||
// try again until maxtries == 0;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,21 +34,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test tests the actual swap size on linux and solaris.
|
||||
* The correct value should be checked manually:
|
||||
* Solaris:
|
||||
* 1. In a shell, enter the command: "swap -l"
|
||||
* 2. The value (reported in blocks) is in the "blocks" column.
|
||||
* Linux:
|
||||
* 1. In a shell, enter the command: "cat /proc/meminfo"
|
||||
* 2. The value (reported in bytes) is in "Swap" entry, "total" column.
|
||||
* Windows NT/XP/2000:
|
||||
* 1. Run Start->Accessories->System Tools->System Information.
|
||||
* 2. The value (reported in Kbytes) is in the "Page File Space" entry
|
||||
* Windows 98/ME:
|
||||
* Unknown.
|
||||
*
|
||||
* Usage: GetTotalSwapSpaceSize <expected swap size | "sanity-only"> [trace]
|
||||
* This test tests the actual swap size on Linux and MacOS only.
|
||||
*/
|
||||
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
@ -71,19 +57,31 @@ public class TestTotalSwap {
|
||||
private static final long MAX_SIZE_FOR_PASS = Long.MAX_VALUE;
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
|
||||
// yocto might ignore the request to report swap size in bytes
|
||||
boolean swapInKB = mbean.getVersion().contains("yocto");
|
||||
|
||||
long expected_swap_size = getSwapSizeFromOs();
|
||||
|
||||
long min_size = mbean.getFreeSwapSpaceSize();
|
||||
if (min_size > 0) {
|
||||
min_size_for_pass = min_size;
|
||||
}
|
||||
|
||||
long expected_swap_size = getSwapSizeFromOs();
|
||||
long size = mbean.getTotalSwapSpaceSize();
|
||||
|
||||
System.out.println("Total swap space size in bytes: " + size);
|
||||
System.out.println("Total swap space size from OS in bytes: " + expected_swap_size);
|
||||
System.out.println("Total swap space size in MBean bytes: " + size);
|
||||
|
||||
// if swap data from OS chnaged re-read OS and MBean data
|
||||
while (expected_swap_size != getSwapSizeFromOs()) {
|
||||
System.out.println("Total swap space reported by OS changed form " + expected_swap_size
|
||||
+ " current value = " + getSwapSizeFromOs());
|
||||
expected_swap_size = getSwapSizeFromOs();
|
||||
size = mbean.getTotalSwapSpaceSize();
|
||||
|
||||
System.out.println("Re-read total swap space size from OS in bytes: " + expected_swap_size);
|
||||
System.out.println("Total swap space size in MBean bytes: " + size);
|
||||
}
|
||||
|
||||
if (expected_swap_size > -1) {
|
||||
if (size != expected_swap_size) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,8 +25,8 @@
|
||||
* @test
|
||||
* @bug 6725892
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dsun.net.httpserver.maxReqTime=2 Test
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true -Dsun.net.httpserver.maxReqTime=2 Test
|
||||
* @run main/othervm -Dsun.net.httpserver.maxReqTime=2 -Dsun.net.httpserver.clockTick=2000 Test
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true -Dsun.net.httpserver.maxReqTime=2 -Dsun.net.httpserver.clockTick=2000 Test
|
||||
* @summary
|
||||
*/
|
||||
|
||||
|
||||
64
test/jdk/java/math/BigDecimal/ConstructorUnscaledValue.java
Normal file
64
test/jdk/java/math/BigDecimal/ConstructorUnscaledValue.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8282252
|
||||
* @summary Test constructors of BigDecimal to replace BigInteger subclasses
|
||||
*/
|
||||
|
||||
import java.math.*;
|
||||
|
||||
public class ConstructorUnscaledValue {
|
||||
public static void main(String... args) {
|
||||
TestBigInteger tbi = new TestBigInteger(BigInteger.ONE);
|
||||
// Create BigDecimal's using each of the three constructors
|
||||
// with guards on the class of unscaledValue
|
||||
BigDecimal[] values = {
|
||||
new BigDecimal(tbi),
|
||||
new BigDecimal(tbi, 2),
|
||||
new BigDecimal(tbi, 3, MathContext.DECIMAL32),
|
||||
};
|
||||
|
||||
for (var bd : values) {
|
||||
BigInteger unscaledValue = bd.unscaledValue();
|
||||
if (unscaledValue.getClass() != BigInteger.class) {
|
||||
throw new RuntimeException("Bad class for unscaledValue");
|
||||
}
|
||||
if (!unscaledValue.equals(BigInteger.ONE)) {
|
||||
throw new RuntimeException("Bad value for unscaledValue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestBigInteger extends BigInteger {
|
||||
public TestBigInteger(BigInteger bi) {
|
||||
super(bi.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return java.util.Arrays.toString(toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,54 +23,128 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6177836
|
||||
* @bug 6177836 8282252
|
||||
* @summary Verify BigDecimal objects with collapsed values are serialized properly.
|
||||
* @author Joseph D. Darcy
|
||||
*/
|
||||
|
||||
import java.math.*;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
public class SerializationTests {
|
||||
|
||||
static void checkSerialForm(BigDecimal bd) throws Exception {
|
||||
public static void main(String... args) throws Exception {
|
||||
checkBigDecimalSerialRoundTrip();
|
||||
checkBigDecimalSubSerialRoundTrip();
|
||||
}
|
||||
|
||||
private static void checkSerialForm(BigDecimal bd) throws Exception {
|
||||
checkSerialForm0(bd);
|
||||
checkSerialForm0(bd.negate());
|
||||
}
|
||||
|
||||
private static void checkSerialForm0(BigDecimal bd) throws Exception {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(bd);
|
||||
oos.flush();
|
||||
oos.close();
|
||||
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
|
||||
oos.writeObject(bd);
|
||||
oos.flush();
|
||||
}
|
||||
|
||||
ObjectInputStream ois = new
|
||||
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
||||
BigDecimal tmp = (BigDecimal)ois.readObject();
|
||||
|
||||
if (!bd.equals(tmp) ||
|
||||
bd.hashCode() != tmp.hashCode()) {
|
||||
bd.hashCode() != tmp.hashCode() ||
|
||||
bd.getClass() != tmp.getClass() ||
|
||||
// Directly test equality of components
|
||||
bd.scale() != tmp.scale() ||
|
||||
!bd.unscaledValue().equals(tmp.unscaledValue())) {
|
||||
System.err.print(" original : " + bd);
|
||||
System.err.println(" (hash: 0x" + Integer.toHexString(bd.hashCode()) + ")");
|
||||
System.err.print("serialized : " + tmp);
|
||||
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
|
||||
throw new RuntimeException("Bad serial roundtrip");
|
||||
}
|
||||
|
||||
// If the class of the deserialized number is BigDecimal,
|
||||
// verify the implementation constraint on the unscaled value
|
||||
// having BigInteger class
|
||||
if (tmp.getClass() == BigDecimal.class) {
|
||||
if (tmp.unscaledValue().getClass() != BigInteger.class) {
|
||||
throw new RuntimeException("Not using genuine BigInteger as an unscaled value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
BigDecimal values[] = {
|
||||
BigDecimal.ZERO,
|
||||
BigDecimal.ONE,
|
||||
BigDecimal.TEN,
|
||||
new BigDecimal(0),
|
||||
new BigDecimal(1),
|
||||
new BigDecimal(10),
|
||||
new BigDecimal(Integer.MAX_VALUE),
|
||||
new BigDecimal(Long.MAX_VALUE-1),
|
||||
new BigDecimal(BigInteger.valueOf(1), 1),
|
||||
new BigDecimal(BigInteger.valueOf(100), 50),
|
||||
};
|
||||
private static class BigIntegerSub extends BigInteger {
|
||||
public BigIntegerSub(BigInteger bi) {
|
||||
super(bi.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return java.util.Arrays.toString(toByteArray());
|
||||
}
|
||||
}
|
||||
private static void checkBigDecimalSerialRoundTrip() throws Exception {
|
||||
var values =
|
||||
List.of(BigDecimal.ZERO,
|
||||
BigDecimal.ONE,
|
||||
BigDecimal.TEN,
|
||||
new BigDecimal(0),
|
||||
new BigDecimal(1),
|
||||
new BigDecimal(10),
|
||||
new BigDecimal(Integer.MAX_VALUE),
|
||||
new BigDecimal(Long.MAX_VALUE-1),
|
||||
new BigDecimal(BigInteger.valueOf(1), 1),
|
||||
new BigDecimal(BigInteger.valueOf(100), 50),
|
||||
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
|
||||
Integer.MAX_VALUE),
|
||||
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
|
||||
Integer.MIN_VALUE),
|
||||
new BigDecimal(new BigIntegerSub(BigInteger.ONE), 2));
|
||||
|
||||
for(BigDecimal value : values) {
|
||||
checkSerialForm(value);
|
||||
checkSerialForm(value.negate());
|
||||
}
|
||||
}
|
||||
|
||||
private static class BigDecimalSub extends BigDecimal {
|
||||
public BigDecimalSub(BigDecimal bd) {
|
||||
super(bd.unscaledValue(), bd.scale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return unscaledValue() + "x10^" + (-scale());
|
||||
}
|
||||
}
|
||||
|
||||
// Subclass defining a serialVersionUID
|
||||
private static class BigDecimalSubSVUID extends BigDecimal {
|
||||
@java.io.Serial
|
||||
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
|
||||
|
||||
public BigDecimalSubSVUID(BigDecimal bd) {
|
||||
super(bd.unscaledValue(), bd.scale());
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkBigDecimalSubSerialRoundTrip() throws Exception {
|
||||
var values =
|
||||
List.of(BigDecimal.ZERO,
|
||||
BigDecimal.ONE,
|
||||
BigDecimal.TEN,
|
||||
new BigDecimal(BigInteger.TEN, 1234),
|
||||
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
|
||||
Integer.MAX_VALUE),
|
||||
new BigDecimal(new BigInteger("9223372036854775808"), // Long.MAX_VALUE + 1
|
||||
Integer.MIN_VALUE));
|
||||
|
||||
for(var value : values) {
|
||||
checkSerialForm(new BigDecimalSub(value));
|
||||
checkSerialForm(new BigDecimalSubSVUID(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
141
test/jdk/java/math/BigInteger/SerializationTests.java
Normal file
141
test/jdk/java/math/BigInteger/SerializationTests.java
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8282252
|
||||
* @summary Verify BigInteger objects are serialized properly.
|
||||
*/
|
||||
|
||||
import java.math.*;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SerializationTests {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
checkBigIntegerSerialRoundTrip();
|
||||
checkBigIntegerSubSerialRoundTrip();
|
||||
}
|
||||
|
||||
private static void checkSerialForm(BigInteger bi) throws Exception {
|
||||
checkSerialForm0(bi);
|
||||
checkSerialForm0(bi.negate());
|
||||
}
|
||||
|
||||
private static void checkSerialForm0(BigInteger bi) throws Exception {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try(ObjectOutputStream oos = new ObjectOutputStream(bos)) {
|
||||
oos.writeObject(bi);
|
||||
oos.flush();
|
||||
}
|
||||
|
||||
ObjectInputStream ois = new
|
||||
ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
||||
BigInteger tmp = (BigInteger)ois.readObject();
|
||||
|
||||
if (!bi.equals(tmp) ||
|
||||
bi.hashCode() != tmp.hashCode() ||
|
||||
bi.getClass() != tmp.getClass() ||
|
||||
// For extra measure, directly test equality of components
|
||||
bi.signum() != tmp.signum() ||
|
||||
!Arrays.equals(bi.toByteArray(), (tmp.toByteArray())) ) {
|
||||
System.err.print(" original : " + bi);
|
||||
System.err.println(" (hash: 0x" + Integer.toHexString(bi.hashCode()) + ")");
|
||||
System.err.print("serialized : " + tmp);
|
||||
System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
|
||||
throw new RuntimeException("Bad serial roundtrip");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkBigIntegerSerialRoundTrip() throws Exception {
|
||||
var values =
|
||||
List.of(BigInteger.ZERO,
|
||||
BigInteger.ONE,
|
||||
BigInteger.TWO,
|
||||
BigInteger.TEN,
|
||||
BigInteger.valueOf(100),
|
||||
BigInteger.valueOf(Integer.MAX_VALUE),
|
||||
BigInteger.valueOf(Long.MAX_VALUE-1),
|
||||
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
|
||||
|
||||
for(BigInteger value : values) {
|
||||
checkSerialForm(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Subclass with specialized toString output
|
||||
private static class BigIntegerSub extends BigInteger {
|
||||
public BigIntegerSub(BigInteger bi) {
|
||||
super(bi.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
// Subclass defining a serialVersionUID
|
||||
private static class BigIntegerSubSVUID extends BigInteger {
|
||||
@java.io.Serial
|
||||
private static long serialVesionUID = 0x0123_4567_89ab_cdefL;
|
||||
|
||||
public BigIntegerSubSVUID(BigInteger bi) {
|
||||
super(bi.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
// Subclass defining writeReplace
|
||||
private static class BigIntegerSubWR extends BigInteger {
|
||||
public BigIntegerSubWR(BigInteger bi) {
|
||||
super(bi.toByteArray());
|
||||
}
|
||||
|
||||
// Just return this; could use a serial proxy instead
|
||||
@java.io.Serial
|
||||
private Object writeReplace() throws ObjectStreamException {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void checkBigIntegerSubSerialRoundTrip() throws Exception {
|
||||
var values = List.of(BigInteger.ZERO,
|
||||
BigInteger.ONE,
|
||||
BigInteger.TEN,
|
||||
new BigInteger("9223372036854775808")); // Long.MAX_VALUE + 1
|
||||
|
||||
for(var value : values) {
|
||||
checkSerialForm(new BigIntegerSub(value));
|
||||
checkSerialForm(new BigIntegerSubSVUID(value));
|
||||
checkSerialForm(new BigIntegerSubWR(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -457,7 +457,7 @@ public class ConnectionPoolTest {
|
||||
InetSocketAddress proxy,
|
||||
boolean secured) {
|
||||
super(address, impl);
|
||||
this.key = ConnectionPool.cacheKey(address, proxy);
|
||||
this.key = ConnectionPool.cacheKey(secured, address, proxy);
|
||||
this.address = address;
|
||||
this.proxy = proxy;
|
||||
this.secured = secured;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8151788
|
||||
* @bug 8151788 8286526
|
||||
* @summary NullPointerException from ntlm.Client.type3
|
||||
* @modules java.base/com.sun.security.ntlm
|
||||
* @run main NULLTargetInfoTest
|
||||
@ -42,7 +42,7 @@ public class NULLTargetInfoTest {
|
||||
"4E 54 4C 4D 53 53 50 00 02 00 00 00 00 00 00 00"
|
||||
+ "00 00 00 00 05 82 89 00 0B 87 81 B6 2D 6E 8B C1"
|
||||
+ "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
|
||||
byte[] nonce = new byte[10];
|
||||
byte[] nonce = new byte[8];
|
||||
c.type3(type2, nonce);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user