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 void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
134 {
135 _writeFlusher.write(callback, buffers);
136 }
137
138 protected abstract void onIncompleteFlush();
139
140 protected abstract void needsFillInterest() throws IOException;
141
142 public FillInterest getFillInterest()
143 {
144 return _fillInterest;
145 }
146
147 protected WriteFlusher getWriteFlusher()
148 {
149 return _writeFlusher;
150 }
151
152 @Override
153 protected void onIdleExpired(TimeoutException timeout)
154 {
155 boolean output_shutdown=isOutputShutdown();
156 boolean input_shutdown=isInputShutdown();
157 boolean fillFailed = _fillInterest.onFail(timeout);
158 boolean writeFailed = _writeFlusher.onFail(timeout);
159
160
161
162
163
164
165
166
167 if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
168 close();
169 else
170 LOG.debug("Ignored idle endpoint {}",this);
171 }
172
173 @Override
174 public void upgrade(Connection newConnection)
175 {
176 Connection old_connection = getConnection();
177
178 if (LOG.isDebugEnabled())
179 LOG.debug("{} upgradeing from {} to {}", this, old_connection, newConnection);
180
181 ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
182 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
183 old_connection.onClose();
184 old_connection.getEndPoint().setConnection(newConnection);
185
186 if (newConnection instanceof Connection.UpgradeTo)
187 ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
188 else if (BufferUtil.hasContent(prefilled))
189 throw new IllegalStateException();
190
191 newConnection.onOpen();
192 }
193
194 @Override
195 public String toString()
196 {
197 Class<?> c=getClass();
198 String name=c.getSimpleName();
199 while (name.length()==0 && c.getSuperclass()!=null)
200 {
201 c=c.getSuperclass();
202 name=c.getSimpleName();
203 }
204
205 return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s}",
206 name,
207 hashCode(),
208 getRemoteAddress(),
209 getLocalAddress().getPort(),
210 isOpen()?"Open":"CLOSED",
211 isInputShutdown()?"ISHUT":"in",
212 isOutputShutdown()?"OSHUT":"out",
213 _fillInterest.isInterested()?"R":"-",
214 _writeFlusher.isInProgress()?"W":"-",
215 getIdleFor(),
216 getIdleTimeout(),
217 getConnection()==null?null:getConnection().getClass().getSimpleName());
218 }
219 }