1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel;
17
18 import java.net.SocketAddress;
19 import java.util.concurrent.ConcurrentMap;
20
21 import org.jboss.netty.util.internal.ConcurrentHashMap;
22
23
24
25
26 public abstract class AbstractChannel implements Channel {
27
28 static final ConcurrentMap<Integer, Channel> allChannels = new ConcurrentHashMap<Integer, Channel>();
29
30 private static Integer allocateId(Channel channel) {
31 Integer id = System.identityHashCode(channel);
32 for (;;) {
33
34
35 if (allChannels.putIfAbsent(id, channel) == null) {
36
37 return id;
38 } else {
39
40 id = id.intValue() + 1;
41 }
42 }
43 }
44
45 private final Integer id;
46 private final Channel parent;
47 private final ChannelFactory factory;
48 private final ChannelPipeline pipeline;
49 private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
50 private final ChannelCloseFuture closeFuture = new ChannelCloseFuture();
51 private volatile int interestOps = OP_READ;
52
53
54 private boolean strValConnected;
55 private String strVal;
56 private volatile Object attachment;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 protected AbstractChannel(
72 Channel parent, ChannelFactory factory,
73 ChannelPipeline pipeline, ChannelSink sink) {
74
75 this.parent = parent;
76 this.factory = factory;
77 this.pipeline = pipeline;
78
79 id = allocateId(this);
80
81 pipeline.attach(this, sink);
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 protected AbstractChannel(
99 Integer id,
100 Channel parent, ChannelFactory factory,
101 ChannelPipeline pipeline, ChannelSink sink) {
102
103 this.id = id;
104 this.parent = parent;
105 this.factory = factory;
106 this.pipeline = pipeline;
107 pipeline.attach(this, sink);
108 }
109
110 public final Integer getId() {
111 return id;
112 }
113
114 public Channel getParent() {
115 return parent;
116 }
117
118 public ChannelFactory getFactory() {
119 return factory;
120 }
121
122 public ChannelPipeline getPipeline() {
123 return pipeline;
124 }
125
126
127
128
129 protected ChannelFuture getSucceededFuture() {
130 return succeededFuture;
131 }
132
133
134
135
136
137 protected ChannelFuture getUnsupportedOperationFuture() {
138 return new FailedChannelFuture(this, new UnsupportedOperationException());
139 }
140
141
142
143
144
145 @Override
146 public final int hashCode() {
147 return System.identityHashCode(this);
148 }
149
150
151
152
153
154 @Override
155 public final boolean equals(Object o) {
156 return this == o;
157 }
158
159
160
161
162 public final int compareTo(Channel o) {
163 return getId().compareTo(o.getId());
164 }
165
166 public boolean isOpen() {
167 return !closeFuture.isDone();
168 }
169
170
171
172
173
174
175
176
177
178 protected boolean setClosed() {
179
180
181 allChannels.remove(id);
182
183 return closeFuture.setClosed();
184 }
185
186 public ChannelFuture bind(SocketAddress localAddress) {
187 return Channels.bind(this, localAddress);
188 }
189
190 public ChannelFuture unbind() {
191 return Channels.unbind(this);
192 }
193
194 public ChannelFuture close() {
195 ChannelFuture returnedCloseFuture = Channels.close(this);
196 assert closeFuture == returnedCloseFuture;
197 return closeFuture;
198 }
199
200 public ChannelFuture getCloseFuture() {
201 return closeFuture;
202 }
203
204 public ChannelFuture connect(SocketAddress remoteAddress) {
205 return Channels.connect(this, remoteAddress);
206 }
207
208 public ChannelFuture disconnect() {
209 return Channels.disconnect(this);
210 }
211
212 public int getInterestOps() {
213 return interestOps;
214 }
215
216 public ChannelFuture setInterestOps(int interestOps) {
217 return Channels.setInterestOps(this, interestOps);
218 }
219
220
221
222
223
224
225 protected void setInterestOpsNow(int interestOps) {
226 this.interestOps = interestOps;
227 }
228
229 public boolean isReadable() {
230 return (getInterestOps() & OP_READ) != 0;
231 }
232
233 public boolean isWritable() {
234 return (getInterestOps() & OP_WRITE) == 0;
235 }
236
237 public ChannelFuture setReadable(boolean readable) {
238 if (readable) {
239 return setInterestOps(getInterestOps() | OP_READ);
240 } else {
241 return setInterestOps(getInterestOps() & ~OP_READ);
242 }
243 }
244
245 public ChannelFuture write(Object message) {
246 return Channels.write(this, message);
247 }
248
249 public ChannelFuture write(Object message, SocketAddress remoteAddress) {
250 return Channels.write(this, message, remoteAddress);
251 }
252
253 public Object getAttachment() {
254 return attachment;
255 }
256
257 public void setAttachment(Object attachment) {
258 this.attachment = attachment;
259 }
260
261
262
263
264
265
266 @Override
267 public String toString() {
268 boolean connected = isConnected();
269 if (strValConnected == connected && strVal != null) {
270 return strVal;
271 }
272
273 StringBuilder buf = new StringBuilder(128);
274 buf.append("[id: 0x");
275 buf.append(getIdString());
276
277 SocketAddress localAddress = getLocalAddress();
278 SocketAddress remoteAddress = getRemoteAddress();
279 if (remoteAddress != null) {
280 buf.append(", ");
281 if (getParent() == null) {
282 buf.append(localAddress);
283 buf.append(connected? " => " : " :> ");
284 buf.append(remoteAddress);
285 } else {
286 buf.append(remoteAddress);
287 buf.append(connected? " => " : " :> ");
288 buf.append(localAddress);
289 }
290 } else if (localAddress != null) {
291 buf.append(", ");
292 buf.append(localAddress);
293 }
294
295 buf.append(']');
296
297 String strVal = buf.toString();
298 this.strVal = strVal;
299 strValConnected = connected;
300 return strVal;
301 }
302
303 private String getIdString() {
304 String answer = Integer.toHexString(id.intValue());
305 switch (answer.length()) {
306 case 0:
307 answer = "00000000";
308 break;
309 case 1:
310 answer = "0000000" + answer;
311 break;
312 case 2:
313 answer = "000000" + answer;
314 break;
315 case 3:
316 answer = "00000" + answer;
317 break;
318 case 4:
319 answer = "0000" + answer;
320 break;
321 case 5:
322 answer = "000" + answer;
323 break;
324 case 6:
325 answer = "00" + answer;
326 break;
327 case 7:
328 answer = "0" + answer;
329 break;
330 }
331 return answer;
332 }
333
334 private final class ChannelCloseFuture extends DefaultChannelFuture {
335
336 public ChannelCloseFuture() {
337 super(AbstractChannel.this, false);
338 }
339
340 @Override
341 public boolean setSuccess() {
342
343 return false;
344 }
345
346 @Override
347 public boolean setFailure(Throwable cause) {
348
349 return false;
350 }
351
352 boolean setClosed() {
353 return super.setSuccess();
354 }
355 }
356 }