jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPChannel.java
author robm
Wed, 24 May 2017 22:07:07 +0100
changeset 45336 2be29f802d94
parent 45333 fd3fdfe96bb4
child 47032 98e444a1b204
permissions -rw-r--r--
8180949: Correctly handle exception in TCPChannel.createConnection Reviewed-by: rriggs
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
23010
6dadb192ad81 8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents: 21278
diff changeset
     2
 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package sun.rmi.transport.tcp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.io.DataInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.DataOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.lang.ref.Reference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.lang.ref.SoftReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.net.Socket;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.rmi.ConnectIOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.rmi.RemoteException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.security.AccessControlContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.security.AccessController;
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    37
import java.security.PrivilegedAction;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.util.ListIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.util.WeakHashMap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.util.concurrent.Future;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.util.concurrent.ScheduledExecutorService;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.concurrent.TimeUnit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import sun.rmi.runtime.Log;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import sun.rmi.runtime.NewThreadAction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import sun.rmi.runtime.RuntimeUtil;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import sun.rmi.transport.Channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
import sun.rmi.transport.Connection;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
import sun.rmi.transport.Endpoint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
import sun.rmi.transport.TransportConstants;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * TCPChannel is the socket-based implementation of the RMI Channel
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * abstraction.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * @author Ann Wollrath
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
public class TCPChannel implements Channel {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    /** endpoint for this channel */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    private final TCPEndpoint ep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    /** transport for this channel */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    private final TCPTransport tr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    /** list of cached connections */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    private final List<TCPConnection> freeList =
12040
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 5506
diff changeset
    66
        new ArrayList<>();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    /** frees cached connections that have expired (guarded by freeList) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    private Future<?> reaper = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    /** using multiplexer (for bi-directional applet communication */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    private boolean usingMultiplexer = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    /** connection multiplexer, if used */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    private ConnectionMultiplexer multiplexer = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    /** connection acceptor (should be in TCPTransport) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    private ConnectionAcceptor acceptor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /** most recently authorized AccessControlContext */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    private AccessControlContext okContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /** cache of authorized AccessControlContexts */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    private WeakHashMap<AccessControlContext,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
                        Reference<AccessControlContext>> authcache;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    /** the SecurityManager which authorized okContext and authcache */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    private SecurityManager cacheSecurityManager = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    /** client-side connection idle usage timeout */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    private static final long idleTimeout =             // default 15 seconds
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    89
        AccessController.doPrivileged((PrivilegedAction<Long>) () ->
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    90
            Long.getLong("sun.rmi.transport.connectionTimeout", 15000));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    /** client-side connection handshake read timeout */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    private static final int handshakeTimeout =         // default 1 minute
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    94
        AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    95
            Integer.getInteger("sun.rmi.transport.tcp.handshakeTimeout", 60000));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /** client-side connection response read timeout (after handshake) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    private static final int responseTimeout =          // default infinity
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
    99
        AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 23010
diff changeset
   100
            Integer.getInteger("sun.rmi.transport.tcp.responseTimeout", 0));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /** thread pool for scheduling delayed tasks */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    private static final ScheduledExecutorService scheduler =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
            new RuntimeUtil.GetInstanceAction()).getScheduler();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     * Create channel for endpoint.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    TCPChannel(TCPTransport tr, TCPEndpoint ep) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        this.tr = tr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        this.ep = ep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * Return the endpoint for this channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    public Endpoint getEndpoint() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        return ep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * Checks if the current caller has sufficient privilege to make
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * a connection to the remote endpoint.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * @exception SecurityException if caller is not allowed to use this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * Channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    private void checkConnectPermission() throws SecurityException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        SecurityManager security = System.getSecurityManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        if (security == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        if (security != cacheSecurityManager) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
            // The security manager changed: flush the cache
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            okContext = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            authcache = new WeakHashMap<AccessControlContext,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                                        Reference<AccessControlContext>>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            cacheSecurityManager = security;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        AccessControlContext ctx = AccessController.getContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        // If ctx is the same context as last time, or if it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        // appears in the cache, bypass the checkConnect.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        if (okContext == null ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
            !(okContext.equals(ctx) || authcache.containsKey(ctx)))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
            security.checkConnect(ep.getHost(), ep.getPort());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            authcache.put(ctx, new SoftReference<AccessControlContext>(ctx));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            // A WeakHashMap is transformed into a SoftHashSet by making
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            // each value softly refer to its own key (Peter's idea).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        okContext = ctx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
     * Supplies a connection to the endpoint of the address space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
     * for which this is a channel.  The returned connection may
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     * be one retrieved from a cache of idle connections.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    public Connection newConnection() throws RemoteException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        TCPConnection conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        // loop until we find a free live connection (in which case
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        // we return) or until we run out of freelist (in which case
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        // the loop exits)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
            conn = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
            // try to get a free connection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            synchronized (freeList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                int elementPos = freeList.size()-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
                if (elementPos >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
                    // If there is a security manager, make sure
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                    // the caller is allowed to connect to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                    // requested endpoint.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                    checkConnectPermission();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                    conn = freeList.get(elementPos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                    freeList.remove(elementPos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            // at this point, conn is null iff the freelist is empty,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            // and nonnull if a free connection of uncertain vitality
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            // has been found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            if (conn != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                // check to see if the connection has closed since last use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                if (!conn.isDead()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                    TCPTransport.tcpLog.log(Log.BRIEF, "reuse connection");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                    return conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                // conn is dead, and cannot be reused (reuse => false)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                this.free(conn, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        } while (conn != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        // none free, so create a new connection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        return (createConnection());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     * Create a new connection to the remote endpoint of this channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * The returned connection is new.  The caller must already have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * passed a security checkConnect or equivalent.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
    private Connection createConnection() throws RemoteException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        Connection conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        TCPTransport.tcpLog.log(Log.BRIEF, "create connection");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        if (!usingMultiplexer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            Socket sock = ep.newSocket();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            conn = new TCPConnection(this, sock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                DataOutputStream out =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                    new DataOutputStream(conn.getOutputStream());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                writeTransportHeader(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                // choose protocol (single op if not reusable socket)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                if (!conn.isReusable()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                    out.writeByte(TransportConstants.SingleOpProtocol);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                    out.writeByte(TransportConstants.StreamProtocol);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                    out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                     * Set socket read timeout to configured value for JRMP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                     * connection handshake; this also serves to guard against
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                     * non-JRMP servers that do not respond (see 4322806).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                    int originalSoTimeout = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                        originalSoTimeout = sock.getSoTimeout();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                        sock.setSoTimeout(handshakeTimeout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                    } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                        // if we fail to set this, ignore and proceed anyway
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                    DataInputStream in =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                        new DataInputStream(conn.getInputStream());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                    byte ack = in.readByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                    if (ack != TransportConstants.ProtocolAck) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                        throw new ConnectIOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                            ack == TransportConstants.ProtocolNack ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                            "JRMP StreamProtocol not supported by server" :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                            "non-JRMP server at remote endpoint");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                    String suggestedHost = in.readUTF();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                    int    suggestedPort = in.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                    if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                        TCPTransport.tcpLog.log(Log.VERBOSE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                            "server suggested " + suggestedHost + ":" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                            suggestedPort);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                    // set local host name, if unknown
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
                    TCPEndpoint.setLocalHost(suggestedHost);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                    // do NOT set the default port, because we don't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                    // know if we can't listen YET...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                    // write out default endpoint to match protocol
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                    // (but it serves no purpose)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                    TCPEndpoint localEp =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                        TCPEndpoint.getLocalEndpoint(0, null, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                    out.writeUTF(localEp.getHost());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                    out.writeInt(localEp.getPort());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                    if (TCPTransport.tcpLog.isLoggable(Log.VERBOSE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                        TCPTransport.tcpLog.log(Log.VERBOSE, "using " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                            localEp.getHost() + ":" + localEp.getPort());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                     * After JRMP handshake, set socket read timeout to value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                     * configured for the rest of the lifetime of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
                     * connection.  NOTE: this timeout, if configured to a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
                     * finite duration, places an upper bound on the time
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
                     * that a remote method call is permitted to execute.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
                         * If socket factory had set a non-zero timeout on its
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
                         * own, then restore it instead of using the property-
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                         * configured value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                        sock.setSoTimeout((originalSoTimeout != 0 ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
                                           originalSoTimeout :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                                           responseTimeout));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
                    } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                        // if we fail to set this, ignore and proceed anyway
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                    out.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            } catch (IOException e) {
45336
2be29f802d94 8180949: Correctly handle exception in TCPChannel.createConnection
robm
parents: 45333
diff changeset
   299
                try {
2be29f802d94 8180949: Correctly handle exception in TCPChannel.createConnection
robm
parents: 45333
diff changeset
   300
                    conn.close();
2be29f802d94 8180949: Correctly handle exception in TCPChannel.createConnection
robm
parents: 45333
diff changeset
   301
                } catch (Exception ex) {}
45333
fd3fdfe96bb4 8175131: sun.rmi.transport.tcp.TCPChannel.createConnection close connection on timeout
robm
parents: 25859
diff changeset
   302
                if (e instanceof RemoteException) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
                    throw (RemoteException) e;
45333
fd3fdfe96bb4 8175131: sun.rmi.transport.tcp.TCPChannel.createConnection close connection on timeout
robm
parents: 25859
diff changeset
   304
                } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                    throw new ConnectIOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                        "error during JRMP connection establishment", e);
45333
fd3fdfe96bb4 8175131: sun.rmi.transport.tcp.TCPChannel.createConnection close connection on timeout
robm
parents: 25859
diff changeset
   307
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                conn = multiplexer.openConnection();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                synchronized (this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
                    usingMultiplexer = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                    multiplexer = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                throw new ConnectIOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                    "error opening virtual connection " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                    "over multiplexed connection", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        return conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * Free the connection generated by this channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * @param conn The connection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     * @param reuse If true, the connection is in a state in which it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
     *        can be reused for another method call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    public void free(Connection conn, boolean reuse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        if (conn == null) return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        if (reuse && conn.isReusable()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            long lastuse = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            TCPConnection tcpConnection = (TCPConnection) conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            TCPTransport.tcpLog.log(Log.BRIEF, "reuse connection");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
             * Cache connection; if reaper task for expired
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
             * connections isn't scheduled, then schedule it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            synchronized (freeList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                freeList.add(tcpConnection);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                if (reaper == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                    TCPTransport.tcpLog.log(Log.BRIEF, "create reaper");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                    reaper = scheduler.scheduleWithFixedDelay(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                        new Runnable() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                            public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                                TCPTransport.tcpLog.log(Log.VERBOSE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                                                        "wake up");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                                freeCachedConnections();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                        }, idleTimeout, idleTimeout, TimeUnit.MILLISECONDS);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
            tcpConnection.setLastUseTime(lastuse);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            tcpConnection.setExpiration(lastuse + idleTimeout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            TCPTransport.tcpLog.log(Log.BRIEF, "close connection");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                conn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            } catch (IOException ignored) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     * Send transport header over stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
    private void writeTransportHeader(DataOutputStream out)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        throws RemoteException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            // write out transport header
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            DataOutputStream dataOut =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                new DataOutputStream(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            dataOut.writeInt(TransportConstants.Magic);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            dataOut.writeShort(TransportConstants.Version);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            throw new ConnectIOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                "error writing JRMP transport header", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
     * Use given connection multiplexer object to obtain new connections
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
     * through this channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
    synchronized void useMultiplexer(ConnectionMultiplexer newMultiplexer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        // for now, always just use the last one given
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        multiplexer = newMultiplexer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        usingMultiplexer = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
     * Accept a connection provided over a multiplexed channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
    void acceptMultiplexConnection(Connection conn) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        if (acceptor == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            acceptor = new ConnectionAcceptor(tr);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            acceptor.startNewAcceptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        acceptor.accept(conn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
     * Closes all the connections in the cache, whether timed out or not.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
    public void shedCache() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        // Build a list of connections, to avoid holding the freeList
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        // lock during (potentially long-running) close() calls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        Connection[] conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        synchronized (freeList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
            conn = freeList.toArray(new Connection[freeList.size()]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
            freeList.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        // Close all the connections that were free
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        for (int i = conn.length; --i >= 0; ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            Connection c = conn[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
            conn[i] = null; // help gc
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                c.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
            } catch (java.io.IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                // eat exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    private void freeCachedConnections() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
         * Remove each connection whose time out has expired.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        synchronized (freeList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            int size = freeList.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            if (size > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                long time = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                ListIterator<TCPConnection> iter = freeList.listIterator(size);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                while (iter.hasPrevious()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                    TCPConnection conn = iter.previous();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                    if (conn.expired(time)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                        TCPTransport.tcpLog.log(Log.VERBOSE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                            "connection timeout expired");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                            conn.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                        } catch (java.io.IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                            // eat exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                        iter.remove();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            if (freeList.isEmpty()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                reaper.cancel(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                reaper = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
 * ConnectionAcceptor manages accepting new connections and giving them
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
 * to TCPTransport's message handler on new threads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
 * Since this object only needs to know which transport to give new
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
 * connections to, it doesn't need to be per-channel as currently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
 * implemented.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
class ConnectionAcceptor implements Runnable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    /** transport that will handle message on accepted connections */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
    private TCPTransport transport;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
    /** queue of connections to be accepted */
12040
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 5506
diff changeset
   485
    private List<Connection> queue = new ArrayList<>();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
    /** thread ID counter */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    private static int threadNum = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
     * Create a new ConnectionAcceptor that will give connections
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
     * to the specified transport on a new thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
    public ConnectionAcceptor(TCPTransport transport) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        this.transport = transport;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
     * Start a new thread to accept connections.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    public void startNewAcceptor() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        Thread t = AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            new NewThreadAction(ConnectionAcceptor.this,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                                "Multiplex Accept-" + ++ threadNum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                                true));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        t.start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
     * Add connection to queue of connections to be accepted.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
    public void accept(Connection conn) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        synchronized (queue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            queue.add(conn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            queue.notify();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
    /**
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 14342
diff changeset
   520
     * Give transport next accepted connection, when available.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        Connection conn;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        synchronized (queue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            while (queue.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                    queue.wait();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
            startNewAcceptor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            conn = queue.remove(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        transport.handleMessages(conn, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
}