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 onClose()
111 {
112 super.onClose();
113 if (LOG.isDebugEnabled())
114 LOG.debug("onClose {}",this);
115 _writeFlusher.onClose();
116 _fillInterest.onClose();
117 }
118
119 @Override
120 public void close()
121 {
122 onClose();
123 }
124
125 @Override
126 public void fillInterested(Callback callback) throws IllegalStateException
127 {
128 notIdle();
129 _fillInterest.register(callback);
130 }
131
132 @Override
133 public boolean isFillInterested()
134 {
135 return _fillInterest.isInterested();
136 }
137
138 @Override
139 public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
140 {
141 _writeFlusher.write(callback, buffers);
142 }
143
144 protected abstract void onIncompleteFlush();
145
146 protected abstract void needsFillInterest() throws IOException;
147
148 public FillInterest getFillInterest()
149 {
150 return _fillInterest;
151 }
152
153 protected WriteFlusher getWriteFlusher()
154 {
155 return _writeFlusher;
156 }
157
158 @Override
159 protected void onIdleExpired(TimeoutException timeout)
160 {
161 Connection connection = _connection;
162 if (connection != null && !_connection.onIdleExpired())
163 return;
164
165 boolean output_shutdown=isOutputShutdown();
166 boolean input_shutdown=isInputShutdown();
167 boolean fillFailed = _fillInterest.onFail(timeout);
168 boolean writeFailed = _writeFlusher.onFail(timeout);
169
170
171
172
173
174
175
176
177 if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
178 close();
179 else
180 LOG.debug("Ignored idle endpoint {}",this);
181 }
182
183 @Override
184 public void upgrade(Connection newConnection)
185 {
186 Connection old_connection = getConnection();
187
188 if (LOG.isDebugEnabled())
189 LOG.debug("{} upgrading from {} to {}", this, old_connection, newConnection);
190
191 ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
192 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
193 old_connection.onClose();
194 old_connection.getEndPoint().setConnection(newConnection);
195
196 if (newConnection instanceof Connection.UpgradeTo)
197 ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
198 else if (BufferUtil.hasContent(prefilled))
199 throw new IllegalStateException();
200
201 newConnection.onOpen();
202 }
203
204 @Override
205 public String toString()
206 {
207 Class<?> c=getClass();
208 String name=c.getSimpleName();
209 while (name.length()==0 && c.getSuperclass()!=null)
210 {
211 c=c.getSuperclass();
212 name=c.getSimpleName();
213 }
214
215 return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s}",
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 getConnection()==null?null:getConnection().getClass().getSimpleName());
228 }
229 }