1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.io.nio;
15
16 import java.io.IOException;
17 import java.net.InetSocketAddress;
18 import java.net.Socket;
19 import java.net.SocketException;
20 import java.nio.ByteBuffer;
21 import java.nio.channels.ByteChannel;
22 import java.nio.channels.GatheringByteChannel;
23 import java.nio.channels.SelectableChannel;
24 import java.nio.channels.SocketChannel;
25
26 import org.eclipse.jetty.io.Buffer;
27 import org.eclipse.jetty.io.EndPoint;
28 import org.eclipse.jetty.util.StringUtil;
29 import org.eclipse.jetty.util.log.Log;
30 import org.eclipse.jetty.util.log.Logger;
31
32
33
34
35
36
37 public class ChannelEndPoint implements EndPoint
38 {
39 private static final Logger LOG = Log.getLogger(ChannelEndPoint.class);
40
41 protected final ByteChannel _channel;
42 protected final ByteBuffer[] _gather2=new ByteBuffer[2];
43 protected final Socket _socket;
44 protected final InetSocketAddress _local;
45 protected final InetSocketAddress _remote;
46 protected volatile int _maxIdleTime;
47 private volatile boolean _ishut;
48 private volatile boolean _oshut;
49
50 public ChannelEndPoint(ByteChannel channel) throws IOException
51 {
52 super();
53 this._channel = channel;
54 _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null;
55 if (_socket!=null)
56 {
57 _local=(InetSocketAddress)_socket.getLocalSocketAddress();
58 _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
59 _maxIdleTime=_socket.getSoTimeout();
60 }
61 else
62 {
63 _local=_remote=null;
64 }
65 }
66
67 protected ChannelEndPoint(ByteChannel channel, int maxIdleTime) throws IOException
68 {
69 this._channel = channel;
70 _maxIdleTime=maxIdleTime;
71 _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null;
72 if (_socket!=null)
73 {
74 _local=(InetSocketAddress)_socket.getLocalSocketAddress();
75 _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
76 _socket.setSoTimeout(_maxIdleTime);
77 }
78 else
79 {
80 _local=_remote=null;
81 }
82 }
83
84 public boolean isBlocking()
85 {
86 return !(_channel instanceof SelectableChannel) || ((SelectableChannel)_channel).isBlocking();
87 }
88
89 public boolean blockReadable(long millisecs) throws IOException
90 {
91 return true;
92 }
93
94 public boolean blockWritable(long millisecs) throws IOException
95 {
96 return true;
97 }
98
99
100
101
102 public boolean isOpen()
103 {
104 return _channel.isOpen();
105 }
106
107
108
109
110
111 protected final void shutdownChannelInput() throws IOException
112 {
113 LOG.debug("ishut {}", this);
114 _ishut = true;
115 if (_channel.isOpen())
116 {
117 if (_socket != null)
118 {
119 try
120 {
121 if (!_socket.isInputShutdown())
122 {
123 _socket.shutdownInput();
124 }
125 }
126 catch (SocketException e)
127 {
128 LOG.debug(e.toString());
129 LOG.ignore(e);
130 }
131 finally
132 {
133 if (_oshut)
134 {
135 close();
136 }
137 }
138 }
139 }
140 }
141
142
143
144
145 public void shutdownInput() throws IOException
146 {
147 shutdownChannelInput();
148 }
149
150 protected final void shutdownChannelOutput() throws IOException
151 {
152 LOG.debug("oshut {}",this);
153 _oshut = true;
154 if (_channel.isOpen())
155 {
156 if (_socket != null)
157 {
158 try
159 {
160 if (!_socket.isOutputShutdown())
161 {
162 _socket.shutdownOutput();
163 }
164 }
165 catch (SocketException e)
166 {
167 LOG.debug(e.toString());
168 LOG.ignore(e);
169 }
170 finally
171 {
172 if (_ishut)
173 {
174 close();
175 }
176 }
177 }
178 }
179 }
180
181
182
183
184 public void shutdownOutput() throws IOException
185 {
186 shutdownChannelOutput();
187 }
188
189 public boolean isOutputShutdown()
190 {
191 return _oshut || !_channel.isOpen() || _socket != null && _socket.isOutputShutdown();
192 }
193
194 public boolean isInputShutdown()
195 {
196 return _ishut || !_channel.isOpen() || _socket != null && _socket.isInputShutdown();
197 }
198
199
200
201
202 public void close() throws IOException
203 {
204 LOG.debug("close {}",this);
205 _channel.close();
206 }
207
208
209
210
211 public int fill(Buffer buffer) throws IOException
212 {
213 if (_ishut)
214 return -1;
215 Buffer buf = buffer.buffer();
216 int len=0;
217 if (buf instanceof NIOBuffer)
218 {
219 final NIOBuffer nbuf = (NIOBuffer)buf;
220 final ByteBuffer bbuf=nbuf.getByteBuffer();
221
222
223 try
224 {
225 synchronized(bbuf)
226 {
227 try
228 {
229 bbuf.position(buffer.putIndex());
230 len=_channel.read(bbuf);
231 }
232 finally
233 {
234 buffer.setPutIndex(bbuf.position());
235 bbuf.position(0);
236 }
237 }
238
239 if (len<0 && isOpen())
240 {
241 if (!isInputShutdown())
242 shutdownInput();
243 if (isOutputShutdown())
244 _channel.close();
245 }
246 }
247 catch (IOException x)
248 {
249 LOG.debug("Exception while filling", x);
250 try
251 {
252 if (_channel.isOpen())
253 _channel.close();
254 }
255 catch (Exception xx)
256 {
257 LOG.ignore(xx);
258 }
259
260 if (len>0)
261 throw x;
262 len=-1;
263 }
264 }
265 else
266 {
267 throw new IOException("Not Implemented");
268 }
269
270 return len;
271 }
272
273
274
275
276 public int flush(Buffer buffer) throws IOException
277 {
278 Buffer buf = buffer.buffer();
279 int len=0;
280 if (buf instanceof NIOBuffer)
281 {
282 final NIOBuffer nbuf = (NIOBuffer)buf;
283 final ByteBuffer bbuf=nbuf.getByteBuffer().asReadOnlyBuffer();
284 try
285 {
286 bbuf.position(buffer.getIndex());
287 bbuf.limit(buffer.putIndex());
288 len=_channel.write(bbuf);
289 }
290 finally
291 {
292 if (len>0)
293 buffer.skip(len);
294 }
295 }
296 else if (buf instanceof RandomAccessFileBuffer)
297 {
298 len = ((RandomAccessFileBuffer)buf).writeTo(_channel,buffer.getIndex(),buffer.length());
299 if (len>0)
300 buffer.skip(len);
301 }
302 else if (buffer.array()!=null)
303 {
304 ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
305 len=_channel.write(b);
306 if (len>0)
307 buffer.skip(len);
308 }
309 else
310 {
311 throw new IOException("Not Implemented");
312 }
313 return len;
314 }
315
316
317
318
319 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
320 {
321 int length=0;
322
323 Buffer buf0 = header==null?null:header.buffer();
324 Buffer buf1 = buffer==null?null:buffer.buffer();
325
326 if (_channel instanceof GatheringByteChannel &&
327 header!=null && header.length()!=0 && buf0 instanceof NIOBuffer &&
328 buffer!=null && buffer.length()!=0 && buf1 instanceof NIOBuffer)
329 {
330 length = gatheringFlush(header,((NIOBuffer)buf0).getByteBuffer(),buffer,((NIOBuffer)buf1).getByteBuffer());
331 }
332 else
333 {
334
335 if (header!=null && header.length()>0)
336 length=flush(header);
337
338
339 if ((header==null || header.length()==0) &&
340 buffer!=null && buffer.length()>0)
341 length+=flush(buffer);
342
343
344 if ((header==null || header.length()==0) &&
345 (buffer==null || buffer.length()==0) &&
346 trailer!=null && trailer.length()>0)
347 length+=flush(trailer);
348 }
349
350 return length;
351 }
352
353 protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException
354 {
355 int length;
356
357 synchronized(this)
358 {
359
360 bbuf0=bbuf0.asReadOnlyBuffer();
361 bbuf0.position(header.getIndex());
362 bbuf0.limit(header.putIndex());
363 bbuf1=bbuf1.asReadOnlyBuffer();
364 bbuf1.position(buffer.getIndex());
365 bbuf1.limit(buffer.putIndex());
366
367 _gather2[0]=bbuf0;
368 _gather2[1]=bbuf1;
369
370
371 length=(int)((GatheringByteChannel)_channel).write(_gather2);
372
373 int hl=header.length();
374 if (length>hl)
375 {
376 header.clear();
377 buffer.skip(length-hl);
378 }
379 else if (length>0)
380 {
381 header.skip(length);
382 }
383 }
384 return length;
385 }
386
387
388
389
390
391 public ByteChannel getChannel()
392 {
393 return _channel;
394 }
395
396
397
398
399
400
401 public String getLocalAddr()
402 {
403 if (_socket==null)
404 return null;
405 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
406 return StringUtil.ALL_INTERFACES;
407 return _local.getAddress().getHostAddress();
408 }
409
410
411
412
413
414 public String getLocalHost()
415 {
416 if (_socket==null)
417 return null;
418 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
419 return StringUtil.ALL_INTERFACES;
420 return _local.getAddress().getCanonicalHostName();
421 }
422
423
424
425
426
427 public int getLocalPort()
428 {
429 if (_socket==null)
430 return 0;
431 if (_local==null)
432 return -1;
433 return _local.getPort();
434 }
435
436
437
438
439
440 public String getRemoteAddr()
441 {
442 if (_socket==null)
443 return null;
444 if (_remote==null)
445 return null;
446 return _remote.getAddress().getHostAddress();
447 }
448
449
450
451
452
453 public String getRemoteHost()
454 {
455 if (_socket==null)
456 return null;
457 if (_remote==null)
458 return null;
459 return _remote.getAddress().getCanonicalHostName();
460 }
461
462
463
464
465
466 public int getRemotePort()
467 {
468 if (_socket==null)
469 return 0;
470 return _remote==null?-1:_remote.getPort();
471 }
472
473
474
475
476
477 public Object getTransport()
478 {
479 return _channel;
480 }
481
482
483 public void flush()
484 throws IOException
485 {
486 }
487
488
489 public int getMaxIdleTime()
490 {
491 return _maxIdleTime;
492 }
493
494
495
496
497
498 public void setMaxIdleTime(int timeMs) throws IOException
499 {
500 if (_socket!=null && timeMs!=_maxIdleTime)
501 _socket.setSoTimeout(timeMs>0?timeMs:0);
502 _maxIdleTime=timeMs;
503 }
504 }