Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 68f795c9f21a040abd6dd36f4e5a3a60e641fea3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//
//  ========================================================================
//  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.io;

import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;

import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IteratingCallback;

/**
 *
 * A transport EndPoint
 *
 * <h3>Asynchronous Methods</h3>
 * <p>The asynchronous scheduling methods of {@link EndPoint}
 * has been influenced by NIO.2 Futures and Completion
 * handlers, but does not use those actual interfaces because they have
 * some inefficiencies.</p>
 * <p>This class will frequently be used in conjunction with some of the utility
 * implementations of {@link Callback}, such as {@link FutureCallback} and
 * {@link IteratingCallback}. Examples are:</p>
 *
 * <h3>Blocking Read</h3>
 * <p>A FutureCallback can be used to block until an endpoint is ready to be filled
 * from:</p>
 * <blockquote><pre>
 * FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
 * endpoint.fillInterested("ContextObj",future);
 * ...
 * String context = future.get(); // This blocks
 * int filled=endpoint.fill(mybuffer);
 * </pre></blockquote>
 *
 * <h3>Dispatched Read</h3>
 * <p>By using a different callback, the read can be done asynchronously in its own dispatched thread:</p>
 * <blockquote><pre>
 * endpoint.fillInterested("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
 * {
 *   public void onCompleted(String context)
 *   {
 *     int filled=endpoint.fill(mybuffer);
 *     ...
 *   }
 *   public void onFailed(String context,Throwable cause) {...}
 * });
 * </pre></blockquote>
 * <p>The executor callback can also be customized to not dispatch in some circumstances when
 * it knows it can use the callback thread and does not need to dispatch.</p>
 *
 * <h3>Blocking Write</h3>
 * <p>The write contract is that the callback complete is not called until all data has been
 * written or there is a failure.  For blocking this looks like:</p>
 * <blockquote><pre>
 * FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
 * endpoint.write("ContextObj",future,headerBuffer,contentBuffer);
 * String context = future.get(); // This blocks
 * </pre></blockquote>
 *
 * <h3>Dispatched Write</h3>
 * <p>Note also that multiple buffers may be passed in write so that gather writes
 * can be done:</p>
 * <blockquote><pre>
 * endpoint.write("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
 * {
 *   public void onCompleted(String context)
 *   {
 *     int filled=endpoint.fill(mybuffer);
 *     ...
 *   }
 *   public void onFailed(String context,Throwable cause) {...}
 * },headerBuffer,contentBuffer);
 * </pre></blockquote>
 */
public interface EndPoint extends Closeable
{    
    /* ------------------------------------------------------------ */
    /**
     * @return The local Inet address to which this <code>EndPoint</code> is bound, or <code>null</code>
     * if this <code>EndPoint</code> does not represent a network connection.
     */
    InetSocketAddress getLocalAddress();

    /* ------------------------------------------------------------ */
    /**
     * @return The remote Inet address to which this <code>EndPoint</code> is bound, or <code>null</code>
     * if this <code>EndPoint</code> does not represent a network connection.
     */
    InetSocketAddress getRemoteAddress();

    /* ------------------------------------------------------------ */
    boolean isOpen();

    /* ------------------------------------------------------------ */
    long getCreatedTimeStamp();

    /* ------------------------------------------------------------ */
    /** Shutdown the output.
     * <p>This call indicates that no more data will be sent on this endpoint that
     * that the remote end should read an EOF once all previously sent data has been
     * consumed. Shutdown may be done either at the TCP/IP level, as a protocol exchange (Eg
     * TLS close handshake) or both.
     * <p>
     * If the endpoint has {@link #isInputShutdown()} true, then this call has the same effect
     * as {@link #close()}.
     */
    void shutdownOutput();

    /* ------------------------------------------------------------ */
    /** Test if output is shutdown.
     * The output is shutdown by a call to {@link #shutdownOutput()}
     * or {@link #close()}.
     * @return true if the output is shutdown or the endpoint is closed.
     */
    boolean isOutputShutdown();

    /* ------------------------------------------------------------ */
    /** Test if the input is shutdown.
     * The input is shutdown if an EOF has been read while doing
     * a {@link #fill(ByteBuffer)}.   Once the input is shutdown, all calls to
     * {@link #fill(ByteBuffer)} will  return -1, until such time as the
     * end point is close, when they will return {@link EofException}.
     * @return True if the input is shutdown or the endpoint is closed.
     */
    boolean isInputShutdown();

    /**
     * Close any backing stream associated with the endpoint
     */
    @Override
    void close();

    /**
     * Fill the passed buffer with data from this endpoint.  The bytes are appended to any
     * data already in the buffer by writing from the buffers limit up to it's capacity.
     * The limit is updated to include the filled bytes.
     *
     * @param buffer The buffer to fill. The position and limit are modified during the fill. After the
     * operation, the position is unchanged and the limit is increased to reflect the new data filled.
     * @return an <code>int</code> value indicating the number of bytes
     * filled or -1 if EOF is read or the input is shutdown.
     * @throws IOException if the endpoint is closed.
     */
    int fill(ByteBuffer buffer) throws IOException;


    /**
     * Flush data from the passed header/buffer to this endpoint.  As many bytes as can be consumed
     * are taken from the header/buffer position up until the buffer limit.  The header/buffers position
     * is updated to indicate how many bytes have been consumed.
     * @param buffer the buffers to flush
     * @return True IFF all the buffers have been consumed and the endpoint has flushed the data to its
     * destination (ie is not buffering any data).
     * @throws IOException If the endpoint is closed or output is shutdown.
     */
    boolean flush(ByteBuffer... buffer) throws IOException;

    /* ------------------------------------------------------------ */
    /**
     * @return The underlying transport object (socket, channel, etc.)
     */
    Object getTransport();

    /* ------------------------------------------------------------ */
    /** Get the max idle time in ms.
     * <p>The max idle time is the time the endpoint can be idle before
     * extraordinary handling takes place.
     * @return the max idle time in ms or if ms &lt;= 0 implies an infinite timeout
     */
    long getIdleTimeout();

    /* ------------------------------------------------------------ */
    /** Set the idle timeout.
     * @param idleTimeout the idle timeout in MS. Timeout &lt;= 0 implies an infinite timeout
     */
    void setIdleTimeout(long idleTimeout);


    /**
     * <p>Requests callback methods to be invoked when a call to {@link #fill(ByteBuffer)} would return data or EOF.</p>
     *
     * @param callback the callback to call when an error occurs or we are readable.
     * @throws ReadPendingException if another read operation is concurrent.
     */
    void fillInterested(Callback callback) throws ReadPendingException;

    /**
     * @return whether {@link #fillInterested(Callback)} has been called, but {@link #fill(ByteBuffer)} has not yet
     * been called
     */
    boolean isFillInterested();

    /**
     * <p>Writes the given buffers via {@link #flush(ByteBuffer...)} and invokes callback methods when either
     * all the data has been flushed or an error occurs.</p>
     *
     * @param callback the callback to call when an error occurs or the write completed.
     * @param buffers one or more {@link ByteBuffer}s that will be flushed.
     * @throws WritePendingException if another write operation is concurrent.
     */
    void write(Callback callback, ByteBuffer... buffers) throws WritePendingException;

    /**
     * @return the {@link Connection} associated with this {@link EndPoint}
     * @see #setConnection(Connection)
     */
    Connection getConnection();

    /**
     * @param connection the {@link Connection} associated with this {@link EndPoint}
     * @see #getConnection()
     * @see #upgrade(Connection)
     */
    void setConnection(Connection connection);

    /**
     * <p>Callback method invoked when this {@link EndPoint} is opened.</p>
     * @see #onClose()
     */
    void onOpen();

    /**
     * <p>Callback method invoked when this {@link EndPoint} is close.</p>
     * @see #onOpen()
     */
    void onClose();

    /** Is the endpoint optimized for DirectBuffer usage
     * @return True if direct buffers can be used optimally.
     */
    boolean isOptimizedForDirectBuffers();


    /** Upgrade connections.
     * Close the old connection, update the endpoint and open the new connection.
     * If the oldConnection is an instance of {@link Connection.UpgradeFrom} then
     * a prefilled buffer is requested and passed to the newConnection if it is an instance
     * of {@link Connection.UpgradeTo}
     * @param newConnection The connection to upgrade to
     */
    public void upgrade(Connection newConnection);
}

Back to the top