src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DNSDatagramSocketFactory.java
author mgronlun
Wed, 30 Oct 2019 19:43:52 +0100
changeset 58863 c16ac7a2eba4
parent 48568 0255315ac8d4
permissions -rw-r--r--
8226511: Implement JFR Event Streaming Reviewed-by: egahlin, mseledtsov, mgronlun Contributed-by: erik.gahlin@oracle.com, mikhailo.seledtsov@oracle.com, markus.gronlund@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
48568
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     1
/*
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     2
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     4
 *
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    10
 *
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    15
 * accompanied this code).
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    16
 *
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    20
 *
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    23
 * questions.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    24
 */
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    25
package com.sun.jndi.dns;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    26
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    27
import java.io.IOException;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    28
import java.net.DatagramSocket;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    29
import java.net.ProtocolFamily;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    30
import java.net.SocketException;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    31
import java.net.InetSocketAddress;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    32
import java.nio.channels.DatagramChannel;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    33
import java.util.Objects;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    34
import java.util.Random;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    35
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    36
class DNSDatagramSocketFactory {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    37
    static final int DEVIATION = 3;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    38
    static final int THRESHOLD = 6;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    39
    static final int BIT_DEVIATION = 2;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    40
    static final int HISTORY = 32;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    41
    static final int MAX_RANDOM_TRIES = 5;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    42
    /**
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    43
     * The dynamic allocation port range (aka ephemeral ports), as configured
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    44
     * on the system. Use nested class for lazy evaluation.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    45
     */
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    46
    static final class EphemeralPortRange {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    47
        private EphemeralPortRange() {}
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    48
        static final int LOWER = sun.net.PortConfig.getLower();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    49
        static final int UPPER = sun.net.PortConfig.getUpper();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    50
        static final int RANGE = UPPER - LOWER + 1;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    51
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    52
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    53
    // Records a subset of max {@code capacity} previously used ports
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    54
    static final class PortHistory {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    55
        final int capacity;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    56
        final int[] ports;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    57
        final Random random;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    58
        int index;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    59
        PortHistory(int capacity, Random random) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    60
            this.random = random;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    61
            this.capacity = capacity;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    62
            this.ports = new int[capacity];
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    63
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    64
        // returns true if the history contains the specified port.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    65
        public boolean contains(int port) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    66
            int p = 0;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    67
            for (int i=0; i<capacity; i++) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    68
                if ((p = ports[i]) == 0 || p == port) break;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    69
            }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    70
            return p == port;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    71
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    72
        // Adds the port to the history - doesn't check whether the port
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    73
        // is already present. Always adds the port and always return true.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    74
        public boolean add(int port) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    75
            if (ports[index] != 0) { // at max capacity
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    76
                // remove one port at random and store the new port there
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    77
                ports[random.nextInt(capacity)] = port;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    78
            } else { // there's a free slot
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    79
                ports[index] = port;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    80
            }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    81
            if (++index == capacity) index = 0;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    82
            return true;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    83
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    84
        // Adds the port to the history if not already present.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    85
        // Return true if the port was added, false if the port was already
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    86
        // present.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    87
        public boolean offer(int port) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    88
            if (contains(port)) return false;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    89
            else return add(port);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    90
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    91
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    92
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    93
    int lastport = 0;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    94
    int suitablePortCount;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    95
    int unsuitablePortCount;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    96
    final ProtocolFamily family; // null (default) means dual stack
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    97
    final int thresholdCount; // decision point
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    98
    final int deviation;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
    99
    final Random random;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   100
    final PortHistory history;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   101
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   102
    DNSDatagramSocketFactory() {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   103
        this(new Random());
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   104
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   105
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   106
    DNSDatagramSocketFactory(Random random) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   107
        this(Objects.requireNonNull(random), null, DEVIATION, THRESHOLD);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   108
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   109
    DNSDatagramSocketFactory(Random random,
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   110
                             ProtocolFamily family,
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   111
                             int deviation,
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   112
                             int threshold) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   113
        this.random = Objects.requireNonNull(random);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   114
        this.history = new PortHistory(HISTORY, random);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   115
        this.family = family;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   116
        this.deviation = Math.max(1, deviation);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   117
        this.thresholdCount = Math.max(2, threshold);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   118
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   119
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   120
    /**
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   121
     * Opens a datagram socket listening to the wildcard address on a
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   122
     * random port. If the underlying OS supports UDP port randomization
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   123
     * out of the box (if binding a socket to port 0 binds it to a random
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   124
     * port) then the underlying OS implementation is used. Otherwise, this
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   125
     * method will allocate and bind a socket on a randomly selected ephemeral
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   126
     * port in the dynamic range.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   127
     * @return A new DatagramSocket bound to a random port.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   128
     * @throws SocketException if the socket cannot be created.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   129
     */
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   130
    public synchronized DatagramSocket open() throws SocketException {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   131
        int lastseen = lastport;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   132
        DatagramSocket s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   133
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   134
        boolean thresholdCrossed = unsuitablePortCount > thresholdCount;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   135
        if (thresholdCrossed) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   136
            // Underlying stack does not support random UDP port out of the box.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   137
            // Use our own algorithm to allocate a random UDP port
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   138
            s = openRandom();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   139
            if (s != null) return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   140
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   141
            // couldn't allocate a random port: reset all counters and fall
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   142
            // through.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   143
            unsuitablePortCount = 0; suitablePortCount = 0; lastseen = 0;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   144
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   145
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   146
        // Allocate an ephemeral port (port 0)
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   147
        s = openDefault();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   148
        lastport = s.getLocalPort();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   149
        if (lastseen == 0) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   150
            history.offer(lastport);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   151
            return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   152
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   153
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   154
        thresholdCrossed = suitablePortCount > thresholdCount;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   155
        boolean farEnough = Integer.bitCount(lastseen ^ lastport) > BIT_DEVIATION
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   156
                            && Math.abs(lastport - lastseen) > deviation;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   157
        boolean recycled = history.contains(lastport);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   158
        boolean suitable = (thresholdCrossed || farEnough && !recycled);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   159
        if (suitable && !recycled) history.add(lastport);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   160
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   161
        if (suitable) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   162
            if (!thresholdCrossed) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   163
                suitablePortCount++;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   164
            } else if (!farEnough || recycled) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   165
                unsuitablePortCount = 1;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   166
                suitablePortCount = thresholdCount/2;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   167
            }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   168
            // Either the underlying stack supports random UDP port allocation,
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   169
            // or the new port is sufficiently distant from last port to make
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   170
            // it look like it is. Let's use it.
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   171
            return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   172
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   173
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   174
        // Undecided... the new port was too close. Let's allocate a random
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   175
        // port using our own algorithm
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   176
        assert !thresholdCrossed;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   177
        DatagramSocket ss = openRandom();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   178
        if (ss == null) return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   179
        unsuitablePortCount++;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   180
        s.close();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   181
        return ss;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   182
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   183
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   184
    private DatagramSocket openDefault() throws SocketException {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   185
        if (family != null) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   186
            try {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   187
                DatagramChannel c = DatagramChannel.open(family);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   188
                try {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   189
                    DatagramSocket s = c.socket();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   190
                    s.bind(null);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   191
                    return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   192
                } catch (Throwable x) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   193
                    c.close();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   194
                    throw x;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   195
                }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   196
            } catch (SocketException x) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   197
                throw x;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   198
            } catch (IOException x) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   199
                SocketException e = new SocketException(x.getMessage());
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   200
                e.initCause(x);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   201
                throw e;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   202
            }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   203
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   204
        return new DatagramSocket();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   205
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   206
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   207
    synchronized boolean isUsingNativePortRandomization() {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   208
        return  unsuitablePortCount <= thresholdCount
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   209
                && suitablePortCount > thresholdCount;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   210
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   211
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   212
    synchronized boolean isUsingJavaPortRandomization() {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   213
        return unsuitablePortCount > thresholdCount ;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   214
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   215
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   216
    synchronized boolean isUndecided() {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   217
        return !isUsingJavaPortRandomization()
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   218
                && !isUsingNativePortRandomization();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   219
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   220
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   221
    private DatagramSocket openRandom() {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   222
        int maxtries = MAX_RANDOM_TRIES;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   223
        while (maxtries-- > 0) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   224
            int port = EphemeralPortRange.LOWER
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   225
                    + random.nextInt(EphemeralPortRange.RANGE);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   226
            try {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   227
                if (family != null) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   228
                    DatagramChannel c = DatagramChannel.open(family);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   229
                    try {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   230
                        DatagramSocket s = c.socket();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   231
                        s.bind(new InetSocketAddress(port));
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   232
                        return s;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   233
                    } catch (Throwable x) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   234
                        c.close();
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   235
                        throw x;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   236
                    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   237
                }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   238
                return new DatagramSocket(port);
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   239
            } catch (IOException x) {
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   240
                // try again until maxtries == 0;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   241
            }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   242
        }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   243
        return null;
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   244
    }
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   245
0255315ac8d4 8182125: Improve reliability of DNS lookups
vtewari
parents:
diff changeset
   246
}