]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/io/AbstractEndPoint.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / io / AbstractEndPoint.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.io;
20
21 import java.io.IOException;
22 import java.net.InetSocketAddress;
23 import java.nio.ByteBuffer;
24 import java.util.concurrent.TimeoutException;
25
26 import org.eclipse.jetty.util.BufferUtil;
27 import org.eclipse.jetty.util.Callback;
28 import org.eclipse.jetty.util.log.Log;
29 import org.eclipse.jetty.util.log.Logger;
30 import org.eclipse.jetty.util.thread.Scheduler;
31
32 public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
33 {
34     private static final Logger LOG = Log.getLogger(AbstractEndPoint.class);
35     private final long _created=System.currentTimeMillis();
36     private final InetSocketAddress _local;
37     private final InetSocketAddress _remote;
38     private volatile Connection _connection;
39
40     private final FillInterest _fillInterest = new FillInterest()
41     {
42         @Override
43         protected boolean needsFill() throws IOException
44         {
45             return AbstractEndPoint.this.needsFill();
46         }
47     };
48
49     private final WriteFlusher _writeFlusher = new WriteFlusher(this)
50     {
51         @Override
52         protected void onIncompleteFlushed()
53         {
54             AbstractEndPoint.this.onIncompleteFlush();
55         }
56     };
57
58     protected AbstractEndPoint(Scheduler scheduler,InetSocketAddress local,InetSocketAddress remote)
59     {
60         super(scheduler);
61         _local=local;
62         _remote=remote;
63     }
64
65     @Override
66     public long getCreatedTimeStamp()
67     {
68         return _created;
69     }
70
71     @Override
72     public InetSocketAddress getLocalAddress()
73     {
74         return _local;
75     }
76
77     @Override
78     public InetSocketAddress getRemoteAddress()
79     {
80         return _remote;
81     }
82
83     @Override
84     public Connection getConnection()
85     {
86         return _connection;
87     }
88
89     @Override
90     public void setConnection(Connection connection)
91     {
92         _connection = connection;
93     }
94
95     @Override
96     public void onOpen()
97     {
98         if (LOG.isDebugEnabled())
99             LOG.debug("onOpen {}",this);
100         super.onOpen();
101     }
102
103     @Override
104     public void onClose()
105     {
106         super.onClose();
107         if (LOG.isDebugEnabled())
108             LOG.debug("onClose {}",this);
109         _writeFlusher.onClose();
110         _fillInterest.onClose();
111     }
112
113     @Override
114     public void close()
115     {
116         onClose();
117     }
118
119     @Override
120     public void fillInterested(Callback callback) throws IllegalStateException
121     {
122         notIdle();
123         _fillInterest.register(callback);
124     }
125
126     @Override
127     public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
128     {
129         _writeFlusher.write(callback, buffers);
130     }
131
132     protected abstract void onIncompleteFlush();
133
134     protected abstract boolean needsFill() throws IOException;
135
136     protected FillInterest getFillInterest()
137     {
138         return _fillInterest;
139     }
140
141     protected WriteFlusher getWriteFlusher()
142     {
143         return _writeFlusher;
144     }
145
146     @Override
147     protected void onIdleExpired(TimeoutException timeout)
148     {
149         boolean output_shutdown=isOutputShutdown();
150         boolean input_shutdown=isInputShutdown();
151         boolean fillFailed = _fillInterest.onFail(timeout);
152         boolean writeFailed = _writeFlusher.onFail(timeout);
153
154         // If the endpoint is half closed and there was no fill/write handling, then close here.
155         // This handles the situation where the connection has completed its close handling
156         // and the endpoint is half closed, but the other party does not complete the close.
157         // This perhaps should not check for half closed, however the servlet spec case allows
158         // for a dispatched servlet or suspended request to extend beyond the connections idle
159         // time.  So if this test would always close an idle endpoint that is not handled, then
160         // we would need a mode to ignore timeouts for some HTTP states
161         if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
162             close();
163         else
164             LOG.debug("Ignored idle endpoint {}",this);
165     }
166
167     @Override
168     public void upgrade(Connection newConnection)
169     {
170         Connection old_connection = getConnection();
171
172         if (LOG.isDebugEnabled())
173             LOG.debug("{} upgrading from {} to {}", this, old_connection, newConnection);
174
175         ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
176                 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
177         old_connection.onClose();
178         old_connection.getEndPoint().setConnection(newConnection);
179
180         if (newConnection instanceof Connection.UpgradeTo)
181             ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
182         else if (BufferUtil.hasContent(prefilled))
183             throw new IllegalStateException();
184
185         newConnection.onOpen();
186     }
187
188     @Override
189     public String toString()
190     {
191         return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s}",
192                 getClass().getSimpleName(),
193                 hashCode(),
194                 getRemoteAddress(),
195                 getLocalAddress().getPort(),
196                 isOpen()?"Open":"CLOSED",
197                 isInputShutdown()?"ISHUT":"in",
198                 isOutputShutdown()?"OSHUT":"out",
199                 _fillInterest.isInterested()?"R":"-",
200                 _writeFlusher.isInProgress()?"W":"-",
201                 getIdleFor(),
202                 getIdleTimeout(),
203                 getConnection()==null?null:getConnection().getClass().getSimpleName());
204     }
205 }