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 boolean needsFill() throws IOException
44 {
45 return AbstractEndPoint.this.needsFill();
46 }
47 };
48
49 private final WriteFlusher _writeFlusher = new WriteFlusher(this)
50 {
51 @Override
52 protected void onIncompleteFlushed()
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 void onOpen()
97 {
98 if (LOG.isDebugEnabled())
99 LOG.debug("onOpen {}",this);
100 super.onOpen();
101 }
102
103 @Override
104 public void onClose()
105 {
106 super.onClose();
107 if (LOG.isDebugEnabled())
108 LOG.debug("onClose {}",this);
109 _writeFlusher.onClose();
110 _fillInterest.onClose();
111 }
112
113 @Override
114 public void close()
115 {
116 onClose();
117 }
118
119 @Override
120 public void fillInterested(Callback callback) throws IllegalStateException
121 {
122 notIdle();
123 _fillInterest.register(callback);
124 }
125
126 @Override
127 public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateException
128 {
129 _writeFlusher.write(callback, buffers);
130 }
131
132 protected abstract void onIncompleteFlush();
133
134 protected abstract boolean needsFill() throws IOException;
135
136 protected FillInterest getFillInterest()
137 {
138 return _fillInterest;
139 }
140
141 protected WriteFlusher getWriteFlusher()
142 {
143 return _writeFlusher;
144 }
145
146 @Override
147 protected void onIdleExpired(TimeoutException timeout)
148 {
149 boolean output_shutdown=isOutputShutdown();
150 boolean input_shutdown=isInputShutdown();
151 boolean fillFailed = _fillInterest.onFail(timeout);
152 boolean writeFailed = _writeFlusher.onFail(timeout);
153
154
155
156
157
158
159
160
161 if (isOpen() && (output_shutdown || input_shutdown) && !(fillFailed || writeFailed))
162 close();
163 else
164 LOG.debug("Ignored idle endpoint {}",this);
165 }
166
167 @Override
168 public void upgrade(Connection newConnection)
169 {
170 Connection old_connection = getConnection();
171
172 if (LOG.isDebugEnabled())
173 LOG.debug("{} upgradeing from {} to {}", this, old_connection, newConnection);
174
175 ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
176 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
177 old_connection.onClose();
178 old_connection.getEndPoint().setConnection(newConnection);
179
180 if (newConnection instanceof Connection.UpgradeTo)
181 ((Connection.UpgradeTo)newConnection).onUpgradeTo(prefilled);
182 else if (BufferUtil.hasContent(prefilled))
183 throw new IllegalStateException();
184
185 newConnection.onOpen();
186 }
187
188 @Override
189 public String toString()
190 {
191 return String.format("%s@%x{%s<->%d,%s,%s,%s,%s,%s,%d/%d,%s}",
192 getClass().getSimpleName(),
193 hashCode(),
194 getRemoteAddress(),
195 getLocalAddress().getPort(),
196 isOpen()?"Open":"CLOSED",
197 isInputShutdown()?"ISHUT":"in",
198 isOutputShutdown()?"OSHUT":"out",
199 _fillInterest.isInterested()?"R":"-",
200 _writeFlusher.isInProgress()?"W":"-",
201 getIdleFor(),
202 getIdleTimeout(),
203 getConnection()==null?null:getConnection().getClass().getSimpleName());
204 }
205 }