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 bbuf0.position(0);
362 bbuf1.position(0);
363 bbuf0.limit(bbuf0.capacity());
364 bbuf1.limit(bbuf1.capacity());
365 }
366 }
367 }
368 }
369 return length;
370 }
371
372
373
374
375
376 public ByteChannel getChannel()
377 {
378 return _channel;
379 }
380
381
382
383
384
385
386 public String getLocalAddr()
387 {
388 if (_socket==null)
389 return null;
390 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
391 return StringUtil.ALL_INTERFACES;
392 return _local.getAddress().getHostAddress();
393 }
394
395
396
397
398
399 public String getLocalHost()
400 {
401 if (_socket==null)
402 return null;
403 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
404 return StringUtil.ALL_INTERFACES;
405 return _local.getAddress().getCanonicalHostName();
406 }
407
408
409
410
411
412 public int getLocalPort()
413 {
414 if (_socket==null)
415 return 0;
416 if (_local==null)
417 return -1;
418 return _local.getPort();
419 }
420
421
422
423
424
425 public String getRemoteAddr()
426 {
427 if (_socket==null)
428 return null;
429 if (_remote==null)
430 return null;
431 return _remote.getAddress().getHostAddress();
432 }
433
434
435
436
437
438 public String getRemoteHost()
439 {
440 if (_socket==null)
441 return null;
442 if (_remote==null)
443 return null;
444 return _remote.getAddress().getCanonicalHostName();
445 }
446
447
448
449
450
451 public int getRemotePort()
452 {
453 if (_socket==null)
454 return 0;
455 return _remote==null?-1:_remote.getPort();
456 }
457
458
459
460
461
462 public Object getTransport()
463 {
464 return _channel;
465 }
466
467
468 public void flush()
469 throws IOException
470 {
471 }
472
473
474 public boolean isBufferingInput()
475 {
476 return false;
477 }
478
479
480 public boolean isBufferingOutput()
481 {
482 return false;
483 }
484
485
486 public boolean isBufferred()
487 {
488 return false;
489 }
490
491
492 public int getMaxIdleTime()
493 {
494 return _maxIdleTime;
495 }
496
497
498
499
500
501 public void setMaxIdleTime(int timeMs) throws IOException
502 {
503 if (_socket!=null && timeMs!=_maxIdleTime)
504 _socket.setSoTimeout(timeMs>0?timeMs:0);
505 _maxIdleTime=timeMs;
506 }
507 }