1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jdi.connect.spi;
  27 
  28 import java.io.IOException;
  29 
  30 import com.sun.jdi.connect.TransportTimeoutException;
  31 
  32 /**
  33  * A transport service for connections between a debugger and
  34  * a target VM.
  35  *
  36  * <p> A transport service is a concrete subclass of this class
  37  * that has a zero-argument constructor and implements the abstract
  38  * methods specified below. It is the underlying service
  39  * used by a {@link com.sun.jdi.connect.Transport} for
  40  * connections between a debugger and a target VM.
  41  *
  42  * <p> A transport service is used to establish a connection
  43  * between a debugger and a target VM, and to transport Java
  44  * Debug Wire Protocol (JDWP) packets over an underlying
  45  * communication protocol. In essence a transport service
  46  * implementation binds JDWP (as specified in the
  47  * <a href="../../../../../../../../../technotes/guides/jpda/jdwp-spec.html">
  48  * JDWP specification</a>) to an underlying communication
  49  * protocol. A transport service implementation provides
  50  * a reliable JDWP packet transportation service. JDWP
  51  * packets are sent to and from the target VM without duplication
  52  * or data loss. A transport service implementation may be
  53  * based on an underlying communication protocol that is
  54  * reliable or unreliable. If the underlying communication
  55  * protocol is reliable then the transport service implementation
  56  * may be relatively simple and may only need to transport JDWP
  57  * packets as payloads of the underlying communication
  58  * protocol. In the case of an unreliable communication
  59  * protocol the transport service implementation may include
  60  * additional protocol support in order to ensure that packets
  61  * are not duplicated and that there is no data loss. The
  62  * details of such protocols are specific to the implementation
  63  * but may involve techniques such as the <i>positive
  64  * acknowledgment with retransmission</i> technique used in
  65  * protocols such as the Transmission Control Protocol (TCP)
  66  * (see <a href="http://www.ietf.org/rfc/rfc0793.txt"> RFC 793
  67  * </a>).
  68  *
  69  * <p> A transport service can be used to initiate a connection
  70  * to a target VM. This is done by invoking the {@link #attach}
  71  * method. Alternatively, a transport service can listen and
  72  * accept connections initiated by a target VM. This is done
  73  * by invoking the {@link #startListening(String)} method to
  74  * put the transport into listen mode. Then the {@link #accept}
  75  * method is used to accept a connection initiated by a
  76  * target VM.
  77  *
  78  * @since 1.5
  79  */
  80 public abstract class TransportService {
  81 
  82     /**
  83      * Returns a name to identify the transport service.
  84      *
  85      * @return  The name of the transport service
  86      */
  87     public abstract String name();
  88 
  89     /**
  90      * Returns a description of the transport service.
  91      *
  92      * @return  The description of the transport service
  93      */
  94     public abstract String description();
  95 
  96     /**
  97      * The transport service capabilities.
  98      */
  99     public static abstract class Capabilities {
 100 
 101         /**
 102          * Tells whether or not this transport service can support
 103          * multiple concurrent connections to a single address that
 104          * it is listening on.
 105          *
 106          * @return  {@code true} if, and only if, this transport
 107          *          service supports multiple connections.
 108          */
 109         public abstract boolean supportsMultipleConnections();
 110 
 111         /**
 112          * Tell whether or not this transport service supports a timeout
 113          * when attaching to a target VM.
 114          *
 115          * @return      {@code true} if, and only if, this transport
 116          *              service supports attaching with a timeout.
 117          *
 118          * @see #attach(String,long,long)
 119          */
 120         public abstract boolean supportsAttachTimeout();
 121 
 122         /**
 123          * Tell whether or not this transport service supports a
 124          * timeout while waiting for a target VM to connect.
 125          *
 126          * @return  {@code true} if, and only if, this transport
 127          *          service supports timeout while waiting for
 128          *          a target VM to connect.
 129          *
 130          * @see #accept(TransportService.ListenKey,long,long)
 131          */
 132         public abstract boolean supportsAcceptTimeout();
 133 
 134         /**
 135          * Tells whether or not this transport service supports a
 136          * timeout when handshaking with the target VM.
 137          *
 138          * @return  {@code true} if, and only if, this transport
 139          *          service supports a timeout while handshaking
 140          *          with the target VM.
 141          *
 142          * @see #attach(String,long,long)
 143          * @see #accept(TransportService.ListenKey,long,long)
 144          */
 145         public abstract boolean supportsHandshakeTimeout();
 146     }
 147 
 148     /**
 149      * Returns the capabilities of the transport service.
 150      *
 151      * @return  the transport service capabilities
 152      */
 153     public abstract Capabilities capabilities();
 154 
 155     /**
 156      * Attaches to the specified address.
 157      *
 158      * <p> Attaches to the specified address and returns a connection
 159      * representing the bi-directional communication channel to the
 160      * target VM.
 161      *
 162      * <p> Attaching to the target VM involves two steps:
 163      * First, a connection is established to specified address. This
 164      * is followed by a handshake to ensure that the connection is
 165      * to a target VM. The handshake involves the exchange
 166      * of a string <i>JDWP-Handshake</i> as specified in the <a
 167      * href="../../../../../../../../../technotes/guides/jpda/jdwp-spec.html">
 168      * Java Debug Wire Protocol</a> specification.
 169      *
 170      * @param   address
 171      *          The address of the target VM.
 172      *
 173      * @param   attachTimeout
 174      *          If this transport service supports an attach timeout,
 175      *          and if {@code attachTimeout} is positive, then it specifies
 176      *          the timeout, in milliseconds (more or less), to use
 177      *          when attaching to the target VM.  If the transport service
 178      *          does not support an attach timeout, or if {@code attachTimeout}
 179      *          is specified as zero then attach without any timeout.
 180      *
 181      * @param   handshakeTimeout
 182      *          If this transport service supports a handshake timeout,
 183      *          and if {@code handshakeTimeout} is positive, then it
 184      *          specifies the timeout, in milliseconds (more or less), to
 185      *          use when handshaking with the target VM. The exact
 186      *          usage of the timeout are specific to the transport service.
 187      *          A transport service may, for example, use the handshake
 188      *          timeout as the inter-character timeout while waiting for
 189      *          the <i>JDWP-Handshake</i> message from the target VM.
 190      *          Alternatively, a transport service may, for example,
 191      *          use the handshakeTimeout as a timeout for the duration of the
 192      *          handshake exchange.
 193      *          If the transport service does not support a handshake
 194      *          timeout, or if {@code handshakeTimeout} is specified
 195      *          as zero then the handshake does not timeout if there
 196      *          isn't a response from the target VM.
 197      *
 198      * @return  The Connection representing the bi-directional
 199      *          communication channel to the target VM.
 200      *
 201      * @throws  TransportTimeoutException
 202      *          If a timeout occurs while establishing the connection.
 203      *
 204      * @throws  IOException
 205      *          If an I/O error occurs (including a timeout when
 206      *          handshaking).
 207      *
 208      * @throws  IllegalArgumentException
 209      *          If the address is invalid or the value of the
 210      *          attach timeout or handshake timeout is negative.
 211      *
 212      * @see TransportService.Capabilities#supportsAttachTimeout()
 213      */
 214     public abstract Connection attach(String address, long attachTimeout,
 215         long handshakeTimeout) throws IOException;
 216 
 217     /**
 218      * A <i>listen key</i>.
 219      *
 220      * <p> A {@code TransportService} may listen on multiple, yet
 221      * different, addresses at the same time. To uniquely identify
 222      * each {@code listener} a listen key is created each time that
 223      * {@link #startListening startListening} is called. The listen
 224      * key is used in calls to the {@link #accept accept} method
 225      * to accept inbound connections to that listener. A listen
 226      * key is valid until it is used as an argument to {@link
 227      * #stopListening stopListening} to stop the transport
 228      * service from listening on an address.
 229      */
 230     public static abstract class ListenKey {
 231 
 232         /**
 233          * Returns a string representation of the listen key.
 234          */
 235         public abstract String address();
 236     }
 237 
 238     /**
 239      * Listens on the specified address for inbound connections.
 240      *
 241      * <p> This method starts the transport service listening on
 242      * the specified address so that it can subsequently accept
 243      * an inbound connection. It does not wait until an inbound
 244      * connection is established.
 245      *
 246      * @param   address
 247      *          The address to start listening for connections,
 248      *          or {@code null} to listen on an address chosen
 249      *          by the transport service.
 250      *
 251      * @return  a listen key to be used in subsequent calls to be
 252      *          {@link #accept accept} or {@link #stopListening
 253      *          stopListening} methods.
 254      *
 255      * @throws  IOException
 256      *          If an I/O error occurs.
 257      *
 258      * @throws  IllegalArgumentException
 259      *          If the specific address is invalid
 260      */
 261     public abstract ListenKey startListening(String address) throws IOException;
 262 
 263     /**
 264      * Listens on an address chosen by the transport service.
 265      *
 266      * <p> This convenience method works as if by invoking
 267      * {@link #startListening(String) startListening(null)}.
 268      *
 269      * @return  a listen key to be used in subsequent calls to be
 270      *          {@link #accept accept} or {@link #stopListening
 271      *          stopListening} methods.
 272      *
 273      * @throws  IOException
 274      *          If an I/O error occurs.
 275      */
 276     public abstract ListenKey startListening() throws IOException;
 277 
 278     /**
 279      * Stop listening for inbound connections.
 280      *
 281      * <p> Invoking this method while another thread is blocked
 282      * in {@link #accept accept}, with the same listen key,
 283      * waiting to accept a connection will cause that thread to
 284      * throw an IOException. If the thread blocked in accept
 285      * has already accepted a connection from a target VM and
 286      * is in the process of handshaking with the target VM then
 287      * invoking this method will not cause the thread to throw
 288      * an exception.
 289      *
 290      * @param   listenKey
 291      *          The listen key obtained from a previous call to {@link
 292      *          #startListening(String)} or {@link #startListening()}.
 293      *
 294      * @throws  IllegalArgumentException
 295      *          If the listen key is invalid
 296      *
 297      * @throws  IOException
 298      *          If an I/O error occurs.
 299      */
 300     public abstract void stopListening(ListenKey listenKey) throws IOException;
 301 
 302     /**
 303      * Accept a connection from a target VM.
 304      *
 305      * <p> Waits (indefinitely or with timeout) to accept a connection
 306      * from a target VM. Returns a connection representing the
 307      * bi-directional communication channel to the target VM.
 308      *
 309      * <p> Accepting a connection from a target VM involves two
 310      * steps. First, the transport service waits to accept
 311      * the connection from the target VM. Once the connection is
 312      * established a handshake is performed to ensure that the
 313      * connection is indeed to a target VM. The handshake involves
 314      * the exchange of a string <i>JDWP-Handshake</i> as specified
 315      * in the <a
 316      * href="../../../../../../../../../technotes/guides/jpda/jdwp-spec.html">
 317      * Java Debug Wire Protocol</a> specification.
 318      *
 319      * @param   listenKey
 320      *          A listen key obtained from a previous call to {@link
 321      *          #startListening(String)} or {@link #startListening()}.
 322      *
 323      * @param   acceptTimeout
 324      *          if this transport service supports an accept timeout, and
 325      *          if {@code acceptTimeout} is positive then block for up to
 326      *          {@code acceptTimeout} milliseconds, more or less, while waiting
 327      *          for the target VM to connect.
 328      *          If the transport service does not support an accept timeout
 329      *          or if {@code acceptTimeout} is zero then block indefinitely
 330      *          for a target VM to connect.
 331      *
 332      * @param   handshakeTimeout
 333      *          If this transport service supports a handshake timeout,
 334      *          and if {@code handshakeTimeout} is positive, then it
 335      *          specifies the timeout, in milliseconds (more or less), to
 336      *          use when handshaking with the target VM. The exact
 337      *          usage of the timeout is specific to the transport service.
 338      *          A transport service may, for example, use the handshake
 339      *          timeout as the inter-character timeout while waiting for
 340      *          the <i>JDWP-Handshake</i> message from the target VM.
 341      *          Alternatively, a transport service may, for example,
 342      *          use the timeout as a timeout for the duration of the
 343      *          handshake exchange.
 344      *          If the transport service does not support a handshake
 345      *          timeout, of if {@code handshakeTimeout} is specified
 346      *          as zero then the handshake does not timeout if there
 347      *          isn't a response from the target VM.
 348      *
 349      * @return  The Connection representing the bi-directional
 350      *          communication channel to the target VM.
 351      *
 352      * @throws  TransportTimeoutException
 353      *          If a timeout occurs while waiting for a target VM
 354      *          to connect.
 355      *
 356      * @throws  IOException
 357      *          If an I/O error occurs (including a timeout when
 358      *          handshaking).
 359      *
 360      * @throws  IllegalArgumentException
 361      *          If the value of the acceptTimeout argument, or
 362      *          handshakeTimeout is negative, or an invalid listen key
 363      *          is provided.
 364      *
 365      * @throws  IllegalStateException
 366      *          If {@link #stopListening stopListening} has already been
 367      *          called with this listen key and the transport service
 368      *          is no longer listening for inbound connections.
 369      *
 370      * @see TransportService.Capabilities#supportsAcceptTimeout()
 371      */
 372     public abstract Connection accept(ListenKey listenKey, long acceptTimeout,
 373         long handshakeTimeout) throws IOException;
 374 }