1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 void needsFillInterest() throws IOException
44 {
45 AbstractEndPoint.this.needsFillInterest();
46 }
47 };
48
49 private final WriteFlusher _writeFlusher = new WriteFlusher(this)
50 {
51 @Override
52 protected void onIncompleteFlush()
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 boolean isOptimizedForDirectBuffers()
97 {
98 return false;
99 }
100
101 @Override
102 public void onOpen()
103 {
104 if (LOG.isDebugEnabled())
105 LOG.debug("onOpen {}",this);
106 super.onOpen();
107 }
108
109 @Override
110 public void close()
111 {
112 onClose();
113 _writeFlusher.onClose();
114 _fillInterest.onClose();
115 }
116
117 protected void close(Throwable failure)
118 {
119 onClose();
120 _writeFlusher.onFail(failure);
121 _fillInterest.onFail(failure);
122 }
123
124 @Override
125 public void fillInterested(Callback callback) throws IllegalStateException
126 {
127 notIdle();
128 _fillInterest.register(callback);
129 }
130
131 @Override
132 public boolean isFillInterested()
133 {
134 return _fillInterest.isInterested();
135 }
136
137 @Override
138 public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
139 {
140 _writeFlusher.write(callback, buffers);
141 }
142
143 protected abstract void onIncompleteFlush();
144
145 protected abstract void needsFillInterest() throws IOException;
146
147 public FillInterest getFillInterest()
148 {
149 return _fillInterest;
150 }
151
152 protected WriteFlusher getWriteFlusher()
153 {
154 return _writeFlusher;
155 }
156
157 @Override
158 protected void onIdleExpired(TimeoutException timeout)
159 {
160 Connection connection = _connection;
161 if (connection != null && !connection.onIdleExpired())
162 return;
163
164 boolean output_shutdown=isOutputShutdown();
165 boolean input_shutdown=isInputShutdown();
166 boolean fillFailed = _fillInterest.onFail(timeout);
167 boolean writeFailed = _writeFlusher.onFail(timeout);
168
169
170
171
172
173
174
175
176 if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
177 close();
178 else
179 LOG.debug("Ignored idle endpoint {}",this);
180 }
181
182 @Override
183 public void upgrade(Connection newConnection)
184 {
185 Connection old_connection = getConnection();
186
187 if (LOG.isDebugEnabled())
188 LOG.debug("{} upgrading from {} to {}", this, old_connection, newConnection);
189
190 ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
191 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
192 old_connection.onClose();
193 old_connection.getEndPoint().setConnection(newConnection);
194
195 if (newConnection instanceof Connection.UpgradeTo)
196 ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
197 else if (BufferUtil.hasContent(prefilled))
198 throw new IllegalStateException();
199
200 newConnection.onOpen();
201 }
202
203 @Override
204 public String toString()
205 {
206 Class<?> c=getClass();
207 String name=c.getSimpleName();
208 while (name.length()==0 && c.getSuperclass()!=null)
209 {
210 c=c.getSuperclass();
211 name=c.getSimpleName();
212 }
213
214 Connection connection = getConnection();
215 return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s@%x}",
216 name,
217 hashCode(),
218 getRemoteAddress(),
219 getLocalAddress().getPort(),
220 isOpen()?"Open":"CLOSED",
221 isInputShutdown()?"ISHUT":"in",
222 isOutputShutdown()?"OSHUT":"out",
223 _fillInterest.toStateString(),
224 _writeFlusher.toStateString(),
225 getIdleFor(),
226 getIdleTimeout(),
227 connection == null ? null : connection.getClass().getSimpleName(),
228 connection == null ? 0 : connection.hashCode());
229 }
230 }