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 boolean output_shutdown=isOutputShutdown();
162 boolean input_shutdown=isInputShutdown();
163 boolean fillFailed = _fillInterest.onFail(timeout);
164 boolean writeFailed = _writeFlusher.onFail(timeout);
165
166
167
168
169
170
171
172
173 if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
174 close();
175 else
176 LOG.debug("Ignored idle endpoint {}",this);
177 }
178
179 @Override
180 public void upgrade(Connection newConnection)
181 {
182 Connection old_connection = getConnection();
183
184 if (LOG.isDebugEnabled())
185 LOG.debug("{} upgradeing from {} to {}", this, old_connection, newConnection);
186
187 ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
188 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
189 old_connection.onClose();
190 old_connection.getEndPoint().setConnection(newConnection);
191
192 if (newConnection instanceof Connection.UpgradeTo)
193 ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
194 else if (BufferUtil.hasContent(prefilled))
195 throw new IllegalStateException();
196
197 newConnection.onOpen();
198 }
199
200 @Override
201 public String toString()
202 {
203 Class<?> c=getClass();
204 String name=c.getSimpleName();
205 while (name.length()==0 && c.getSuperclass()!=null)
206 {
207 c=c.getSuperclass();
208 name=c.getSimpleName();
209 }
210
211 return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s}",
212 name,
213 hashCode(),
214 getRemoteAddress(),
215 getLocalAddress().getPort(),
216 isOpen()?"Open":"CLOSED",
217 isInputShutdown()?"ISHUT":"in",
218 isOutputShutdown()?"OSHUT":"out",
219 _fillInterest.toStateString(),
220 _writeFlusher.toStateString(),
221 getIdleFor(),
222 getIdleTimeout(),
223 getConnection()==null?null:getConnection().getClass().getSimpleName());
224 }
225 }