View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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.Callback;
27  import org.eclipse.jetty.util.log.Log;
28  import org.eclipse.jetty.util.log.Logger;
29  import org.eclipse.jetty.util.thread.Scheduler;
30  
31  public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
32  {
33      private static final Logger LOG = Log.getLogger(AbstractEndPoint.class);
34      private final long _created=System.currentTimeMillis();
35      private final InetSocketAddress _local;
36      private final InetSocketAddress _remote;
37      private volatile Connection _connection;
38  
39      private final FillInterest _fillInterest = new FillInterest()
40      {
41          @Override
42          protected boolean needsFill() throws IOException
43          {
44              return AbstractEndPoint.this.needsFill();
45          }
46      };
47      
48      private final WriteFlusher _writeFlusher = new WriteFlusher(this)
49      {
50          @Override
51          protected void onIncompleteFlushed()
52          {
53              AbstractEndPoint.this.onIncompleteFlush();
54          }
55      };
56  
57      protected AbstractEndPoint(Scheduler scheduler,InetSocketAddress local,InetSocketAddress remote)
58      {
59          super(scheduler);
60          _local=local;
61          _remote=remote;
62      }
63  
64      @Override
65      public long getCreatedTimeStamp()
66      {
67          return _created;
68      }
69  
70      @Override
71      public InetSocketAddress getLocalAddress()
72      {
73          return _local;
74      }
75  
76      @Override
77      public InetSocketAddress getRemoteAddress()
78      {
79          return _remote;
80      }
81      
82      @Override
83      public Connection getConnection()
84      {
85          return _connection;
86      }
87  
88      @Override
89      public void setConnection(Connection connection)
90      {
91          _connection = connection;
92      }
93  
94      @Override
95      public void onOpen()
96      {
97          if (LOG.isDebugEnabled())
98              LOG.debug("onOpen {}",this);
99          super.onOpen();
100     }
101 
102     @Override
103     public void onClose()
104     {
105         super.onClose();
106         if (LOG.isDebugEnabled())
107             LOG.debug("onClose {}",this);
108         _writeFlusher.onClose();
109         _fillInterest.onClose();
110     }
111     
112     @Override
113     public void close()
114     {
115         onClose();
116     }
117 
118     @Override
119     public void fillInterested(Callback callback) throws IllegalStateException
120     {
121         notIdle();
122         _fillInterest.register(callback);
123     }
124 
125     @Override
126     public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
127     {
128         _writeFlusher.write(callback, buffers);
129     }
130 
131     protected abstract void onIncompleteFlush();
132 
133     protected abstract boolean needsFill() throws IOException;
134 
135     protected FillInterest getFillInterest()
136     {
137         return _fillInterest;
138     }
139 
140     protected WriteFlusher getWriteFlusher()
141     {
142         return _writeFlusher;
143     }
144 
145     @Override
146     protected void onIdleExpired(TimeoutException timeout)
147     {
148         boolean output_shutdown=isOutputShutdown();
149         boolean input_shutdown=isInputShutdown();
150         boolean fillFailed = _fillInterest.onFail(timeout);
151         boolean writeFailed = _writeFlusher.onFail(timeout);
152         
153         // If the endpoint is half closed and there was no onFail handling, the close here
154         // This handles the situation where the connection has completed its close handling 
155         // and the endpoint is half closed, but the other party does not complete the close.
156         // This perhaps should not check for half closed, however the servlet spec case allows
157         // for a dispatched servlet or suspended request to extend beyond the connections idle 
158         // time.  So if this test would always close an idle endpoint that is not handled, then 
159         // we would need a mode to ignore timeouts for some HTTP states
160         if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
161             close();
162         else 
163             LOG.debug("Ignored idle endpoint {}",this);
164     }
165 
166     @Override
167     public String toString()
168     {
169         return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d,%s}",
170                 getClass().getSimpleName(),
171                 hashCode(),
172                 getRemoteAddress(),
173                 getLocalAddress().getPort(),
174                 isOpen()?"Open":"CLOSED",
175                 isInputShutdown()?"ISHUT":"in",
176                 isOutputShutdown()?"OSHUT":"out",
177                 _fillInterest.isInterested()?"R":"-",
178                 _writeFlusher.isInProgress()?"W":"-",
179                 getIdleTimeout(),
180                 getConnection()==null?null:getConnection().getClass().getSimpleName());
181     }
182 }