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
26package com.sun.jdi.connect.spi;
27
28import java.io.IOException;
29import com.sun.jdi.connect.TransportTimeoutException;
30
31/**
32 * A transport service for connections between a debugger and
33 * a target VM.
34 *
35 * <p> A transport service is a concrete subclass of this class
36 * that has a zero-argument constructor and implements the abstract
37 * methods specified below. It is the underlying service
38 * used by a {@link com.sun.jdi.connect.Transport} for
39 * connections between a debugger and a target VM.
40 *
41 * <p> A transport service is used to establish a connection
42 * between a debugger and a target VM, and to transport Java
43 * Debug Wire Protocol (JDWP) packets over an underlying
44 * communication protocol. In essence a transport service
45 * implementation binds JDWP (as specified in the
46 * <a href="{@docRoot}/../specs/jdwp/jdwp-spec.html">
47 * JDWP specification</a>) to an underlying communication
48 * protocol. A transport service implementation provides
49 * a reliable JDWP packet transportation service. JDWP
50 * packets are sent to and from the target VM without duplication
51 * or data loss. A transport service implementation may be
52 * based on an underlying communication protocol that is
53 * reliable or unreliable. If the underlying communication
54 * protocol is reliable then the transport service implementation
55 * may be relatively simple and may only need to transport JDWP
56 * packets as payloads of the underlying communication
57 * protocol. In the case of an unreliable communication
58 * protocol the transport service implementation may include
59 * additional protocol support in order to ensure that packets
60 * are not duplicated and that there is no data loss. The
61 * details of such protocols are specific to the implementation
62 * but may involve techniques such as the <i>positive
63 * acknowledgment with retransmission</i> technique used in
64 * protocols such as the Transmission Control Protocol (TCP)
65 * (see <a href="http://www.ietf.org/rfc/rfc0793.txt"> RFC 793
66 * </a>).
67 *
68 * <p> A transport service can be used to initiate a connection
69 * to a target VM. This is done by invoking the {@link #attach}
70 * method. Alternatively, a transport service can listen and
71 * accept connections initiated by a target VM. This is done
72 * by invoking the {@link #startListening(String)} method to
73 * put the transport into listen mode. Then the {@link #accept}
74 * method is used to accept a connection initiated by a
75 * target VM.
76 *
77 * @since 1.5
78 */
79
80public 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        /**
113         * Tell whether or not this transport service supports a timeout
114         * when attaching to a target VM.
115         *
116         * @return      {@code true} if, and only if, this transport
117         *              service supports attaching with a timeout.
118         *
119         * @see #attach(String,long,long)
120         */
121        public abstract boolean supportsAttachTimeout();
122
123        /**
124         * Tell whether or not this transport service supports a
125         * timeout while waiting for a target VM to connect.
126         *
127         * @return  {@code true} if, and only if, this transport
128         *          service supports timeout while waiting for
129         *          a target VM to connect.
130         *
131         * @see #accept(TransportService.ListenKey,long,long)
132         */
133        public abstract boolean supportsAcceptTimeout();
134
135        /**
136         * Tells whether or not this transport service supports a
137         * timeout when handshaking with the target VM.
138         *
139         * @return  {@code true} if, and only if, this transport
140         *          service supports a timeout while handshaking
141         *          with the target VM.
142         *
143         * @see #attach(String,long,long)
144         * @see #accept(TransportService.ListenKey,long,long)
145         */
146        public abstract boolean supportsHandshakeTimeout();
147
148    }
149
150    /**
151     * Returns the capabilities of the transport service.
152     *
153     * @return  the transport service capabilities
154     */
155    public abstract Capabilities capabilities();
156
157    /**
158     * Attaches to the specified address.
159     *
160     * <p> Attaches to the specified address and returns a connection
161     * representing the bi-directional communication channel to the
162     * target VM.
163     *
164     * <p> Attaching to the target VM involves two steps:
165     * First, a connection is established to specified address. This
166     * is followed by a handshake to ensure that the connection is
167     * to a target VM. The handshake involves the exchange
168     * of a string <i>JDWP-Handshake</i> as specified in the <a
169     * href="{@docRoot}/../specs/jdwp/jdwp-spec.html">
170     * Java Debug Wire Protocol</a> specification.
171     *
172     * @param   address
173     *          The address of the target VM.
174     *
175     * @param   attachTimeout
176     *          If this transport service supports an attach timeout,
177     *          and if {@code attachTimeout} is positive, then it specifies
178     *          the timeout, in milliseconds (more or less), to use
179     *          when attaching to the target VM.  If the transport service
180     *          does not support an attach timeout, or if {@code attachTimeout}
181     *          is specified as zero then attach without any timeout.
182     *
183     * @param   handshakeTimeout
184     *          If this transport service supports a handshake timeout,
185     *          and if {@code handshakeTimeout} is positive, then it
186     *          specifies the timeout, in milliseconds (more or less), to
187     *          use when handshaking with the target VM. The exact
188     *          usage of the timeout are specific to the transport service.
189     *          A transport service may, for example, use the handshake
190     *          timeout as the inter-character timeout while waiting for
191     *          the <i>JDWP-Handshake</i> message from the target VM.
192     *          Alternatively, a transport service may, for example,
193     *          use the handshakeTimeout as a timeout for the duration of the
194     *          handshake exchange.
195     *          If the transport service does not support a handshake
196     *          timeout, or if {@code handshakeTimeout} is specified
197     *          as zero then the handshake does not timeout if there
198     *          isn't a response from the target VM.
199     *
200     * @return  The Connection representing the bi-directional
201     *          communication channel to the target VM.
202     *
203     * @throws  TransportTimeoutException
204     *          If a timeout occurs while establishing the connection.
205     *
206     * @throws  IOException
207     *          If an I/O error occurs (including a timeout when
208     *          handshaking).
209     *
210     * @throws  IllegalArgumentException
211     *          If the address is invalid or the value of the
212     *          attach timeout or handshake timeout is negative.
213     *
214     * @see TransportService.Capabilities#supportsAttachTimeout()
215     */
216    public abstract Connection attach(String address, long attachTimeout,
217        long handshakeTimeout) throws IOException;
218
219    /**
220     * A <i>listen key</i>.
221     *
222     * <p> A {@code TransportService} may listen on multiple, yet
223     * different, addresses at the same time. To uniquely identify
224     * each {@code listener} a listen key is created each time that
225     * {@link #startListening startListening} is called. The listen
226     * key is used in calls to the {@link #accept accept} method
227     * to accept inbound connections to that listener. A listen
228     * key is valid until it is used as an argument to {@link
229     * #stopListening stopListening} to stop the transport
230     * service from listening on an address.
231     */
232    public static abstract class ListenKey {
233
234        /**
235         * Returns a string representation of the listen key.
236         */
237        public abstract String address();
238    }
239
240    /**
241     * Listens on the specified address for inbound connections.
242     *
243     * <p> This method starts the transport service listening on
244     * the specified address so that it can subsequently accept
245     * an inbound connection. It does not wait until an inbound
246     * connection is established.
247     *
248     * @param   address
249     *          The address to start listening for connections,
250     *          or {@code null} to listen on an address chosen
251     *          by the transport service.
252     *
253     * @return  a listen key to be used in subsequent calls to be
254     *          {@link #accept accept} or {@link #stopListening
255     *          stopListening} methods.
256     *
257     * @throws  IOException
258     *          If an I/O error occurs.
259     *
260     * @throws  IllegalArgumentException
261     *          If the specific address is invalid
262     */
263    public abstract ListenKey startListening(String address) throws IOException;
264
265    /**
266     * Listens on an address chosen by the transport service.
267     *
268     * <p> This convenience method works as if by invoking
269     * {@link #startListening(String) startListening(null)}.
270     *
271     * @return  a listen key to be used in subsequent calls to be
272     *          {@link #accept accept} or {@link #stopListening
273     *          stopListening} methods.
274     *
275     * @throws  IOException
276     *          If an I/O error occurs.
277     */
278    public abstract ListenKey startListening() throws IOException;
279
280    /**
281     * Stop listening for inbound connections.
282     *
283     * <p> Invoking this method while another thread is blocked
284     * in {@link #accept accept}, with the same listen key,
285     * waiting to accept a connection will cause that thread to
286     * throw an IOException. If the thread blocked in accept
287     * has already accepted a connection from a target VM and
288     * is in the process of handshaking with the target VM then
289     * invoking this method will not cause the thread to throw
290     * an exception.
291     *
292     * @param   listenKey
293     *          The listen key obtained from a previous call to {@link
294     *          #startListening(String)} or {@link #startListening()}.
295     *
296     * @throws  IllegalArgumentException
297     *          If the listen key is invalid
298     *
299     * @throws  IOException
300     *          If an I/O error occurs.
301     */
302    public abstract void stopListening(ListenKey listenKey) throws IOException;
303
304    /**
305     * Accept a connection from a target VM.
306     *
307     * <p> Waits (indefinitely or with timeout) to accept a connection
308     * from a target VM. Returns a connection representing the
309     * bi-directional communication channel to the target VM.
310     *
311     * <p> Accepting a connection from a target VM involves two
312     * steps. First, the transport service waits to accept
313     * the connection from the target VM. Once the connection is
314     * established a handshake is performed to ensure that the
315     * connection is indeed to a target VM. The handshake involves
316     * the exchange of a string <i>JDWP-Handshake</i> as specified
317     * in the <a
318     * href="{@docRoot}/../specs/jdwp/jdwp-spec.html">
319     * Java Debug Wire Protocol</a> specification.
320     *
321     * @param   listenKey
322     *          A listen key obtained from a previous call to {@link
323     *          #startListening(String)} or {@link #startListening()}.
324     *
325     * @param   acceptTimeout
326     *          if this transport service supports an accept timeout, and
327     *          if {@code acceptTimeout} is positive then block for up to
328     *          {@code acceptTimeout} milliseconds, more or less, while waiting
329     *          for the target VM to connect.
330     *          If the transport service does not support an accept timeout
331     *          or if {@code acceptTimeout} is zero then block indefinitely
332     *          for a target VM to connect.
333     *
334     * @param   handshakeTimeout
335     *          If this transport service supports a handshake timeout,
336     *          and if {@code handshakeTimeout} is positive, then it
337     *          specifies the timeout, in milliseconds (more or less), to
338     *          use when handshaking with the target VM. The exact
339     *          usage of the timeout is specific to the transport service.
340     *          A transport service may, for example, use the handshake
341     *          timeout as the inter-character timeout while waiting for
342     *          the <i>JDWP-Handshake</i> message from the target VM.
343     *          Alternatively, a transport service may, for example,
344     *          use the timeout as a timeout for the duration of the
345     *          handshake exchange.
346     *          If the transport service does not support a handshake
347     *          timeout, of if {@code handshakeTimeout} is specified
348     *          as zero then the handshake does not timeout if there
349     *          isn't a response from the target VM.
350     *
351     * @return  The Connection representing the bi-directional
352     *          communication channel to the target VM.
353     *
354     * @throws  TransportTimeoutException
355     *          If a timeout occurs while waiting for a target VM
356     *          to connect.
357     *
358     * @throws  IOException
359     *          If an I/O error occurs (including a timeout when
360     *          handshaking).
361     *
362     * @throws  IllegalArgumentException
363     *          If the value of the acceptTimeout argument, or
364     *          handshakeTimeout is negative, or an invalid listen key
365     *          is provided.
366     *
367     * @throws  IllegalStateException
368     *          If {@link #stopListening stopListening} has already been
369     *          called with this listen key and the transport service
370     *          is no longer listening for inbound connections.
371     *
372     * @see TransportService.Capabilities#supportsAcceptTimeout()
373     */
374    public abstract Connection accept(ListenKey listenKey, long acceptTimeout,
375        long handshakeTimeout) throws IOException;
376
377}
378