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(x.toString());
250 LOG.ignore(x);
251 try
252 {
253 if (_channel.isOpen())
254 _channel.close();
255 }
256 catch (Exception xx)
257 {
258 LOG.ignore(xx);
259 }
260
261 if (len>0)
262 throw x;
263 len=-1;
264 }
265 }
266 else
267 {
268 throw new IOException("Not Implemented");
269 }
270
271 return len;
272 }
273
274
275
276
277 public int flush(Buffer buffer) throws IOException
278 {
279 Buffer buf = buffer.buffer();
280 int len=0;
281 if (buf instanceof NIOBuffer)
282 {
283 final NIOBuffer nbuf = (NIOBuffer)buf;
284 final ByteBuffer bbuf=nbuf.getByteBuffer();
285
286
287 synchronized(bbuf)
288 {
289 try
290 {
291 bbuf.position(buffer.getIndex());
292 bbuf.limit(buffer.putIndex());
293 len=_channel.write(bbuf);
294 }
295 finally
296 {
297 if (len>0)
298 buffer.skip(len);
299 bbuf.position(0);
300 bbuf.limit(bbuf.capacity());
301 }
302 }
303 }
304 else if (buf instanceof RandomAccessFileBuffer)
305 {
306 len = ((RandomAccessFileBuffer)buf).writeTo(_channel,buffer.getIndex(),buffer.length());
307 if (len>0)
308 buffer.skip(len);
309 }
310 else if (buffer.array()!=null)
311 {
312 ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
313 len=_channel.write(b);
314 if (len>0)
315 buffer.skip(len);
316 }
317 else
318 {
319 throw new IOException("Not Implemented");
320 }
321 return len;
322 }
323
324
325
326
327 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
328 {
329 int length=0;
330
331 Buffer buf0 = header==null?null:header.buffer();
332 Buffer buf1 = buffer==null?null:buffer.buffer();
333
334 if (_channel instanceof GatheringByteChannel &&
335 header!=null && header.length()!=0 && buf0 instanceof NIOBuffer &&
336 buffer!=null && buffer.length()!=0 && buf1 instanceof NIOBuffer)
337 {
338 length = gatheringFlush(header,((NIOBuffer)buf0).getByteBuffer(),buffer,((NIOBuffer)buf1).getByteBuffer());
339 }
340 else
341 {
342
343 if (header!=null && header.length()>0)
344 length=flush(header);
345
346
347 if ((header==null || header.length()==0) &&
348 buffer!=null && buffer.length()>0)
349 length+=flush(buffer);
350
351
352 if ((header==null || header.length()==0) &&
353 (buffer==null || buffer.length()==0) &&
354 trailer!=null && trailer.length()>0)
355 length+=flush(trailer);
356 }
357
358 return length;
359 }
360
361 protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException
362 {
363 int length;
364
365 synchronized(this)
366 {
367
368
369 synchronized(bbuf0)
370 {
371
372 synchronized(bbuf1)
373 {
374 try
375 {
376
377 bbuf0.position(header.getIndex());
378 bbuf0.limit(header.putIndex());
379 bbuf1.position(buffer.getIndex());
380 bbuf1.limit(buffer.putIndex());
381
382 _gather2[0]=bbuf0;
383 _gather2[1]=bbuf1;
384
385
386 length=(int)((GatheringByteChannel)_channel).write(_gather2);
387
388 int hl=header.length();
389 if (length>hl)
390 {
391 header.clear();
392 buffer.skip(length-hl);
393 }
394 else if (length>0)
395 {
396 header.skip(length);
397 }
398 }
399 finally
400 {
401 bbuf0.position(0);
402 bbuf1.position(0);
403 bbuf0.limit(bbuf0.capacity());
404 bbuf1.limit(bbuf1.capacity());
405 }
406 }
407 }
408 }
409 return length;
410 }
411
412
413
414
415
416 public ByteChannel getChannel()
417 {
418 return _channel;
419 }
420
421
422
423
424
425
426 public String getLocalAddr()
427 {
428 if (_socket==null)
429 return null;
430 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
431 return StringUtil.ALL_INTERFACES;
432 return _local.getAddress().getHostAddress();
433 }
434
435
436
437
438
439 public String getLocalHost()
440 {
441 if (_socket==null)
442 return null;
443 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
444 return StringUtil.ALL_INTERFACES;
445 return _local.getAddress().getCanonicalHostName();
446 }
447
448
449
450
451
452 public int getLocalPort()
453 {
454 if (_socket==null)
455 return 0;
456 if (_local==null)
457 return -1;
458 return _local.getPort();
459 }
460
461
462
463
464
465 public String getRemoteAddr()
466 {
467 if (_socket==null)
468 return null;
469 if (_remote==null)
470 return null;
471 return _remote.getAddress().getHostAddress();
472 }
473
474
475
476
477
478 public String getRemoteHost()
479 {
480 if (_socket==null)
481 return null;
482 if (_remote==null)
483 return null;
484 return _remote.getAddress().getCanonicalHostName();
485 }
486
487
488
489
490
491 public int getRemotePort()
492 {
493 if (_socket==null)
494 return 0;
495 return _remote==null?-1:_remote.getPort();
496 }
497
498
499
500
501
502 public Object getTransport()
503 {
504 return _channel;
505 }
506
507
508 public void flush()
509 throws IOException
510 {
511 }
512
513
514 public int getMaxIdleTime()
515 {
516 return _maxIdleTime;
517 }
518
519
520
521
522
523 public void setMaxIdleTime(int timeMs) throws IOException
524 {
525 if (_socket!=null && timeMs!=_maxIdleTime)
526 _socket.setSoTimeout(timeMs>0?timeMs:0);
527 _maxIdleTime=timeMs;
528 }
529 }