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