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()&&!socket.isInputShutdown())
113 {
114 socket.shutdownInput();
115 }
116 }
117 }
118
119
120
121
122 public void shutdownOutput() throws IOException
123 {
124 if (_channel.isOpen() && _channel instanceof SocketChannel)
125 {
126 Socket socket= ((SocketChannel)_channel).socket();
127 if (!socket.isClosed()&&!socket.isOutputShutdown())
128 {
129 socket.shutdownOutput();
130 }
131 }
132 }
133
134 public boolean isOutputShutdown()
135 {
136 return _channel.isOpen() && _socket!=null && _socket.isOutputShutdown();
137 }
138
139 public boolean isInputShutdown()
140 {
141 return _channel.isOpen() && _socket!=null && _socket.isInputShutdown();
142 }
143
144
145
146
147 public void close() throws IOException
148 {
149 _channel.close();
150 }
151
152
153
154
155 public int fill(Buffer buffer) throws IOException
156 {
157 Buffer buf = buffer.buffer();
158 int len=0;
159 if (buf instanceof NIOBuffer)
160 {
161 final NIOBuffer nbuf = (NIOBuffer)buf;
162 final ByteBuffer bbuf=nbuf.getByteBuffer();
163
164
165 try
166 {
167 synchronized(bbuf)
168 {
169 try
170 {
171 bbuf.position(buffer.putIndex());
172 len=_channel.read(bbuf);
173 }
174 finally
175 {
176 buffer.setPutIndex(bbuf.position());
177 bbuf.position(0);
178 }
179 }
180
181 if (len<0 && isOpen() && !isInputShutdown())
182 {
183 shutdownInput();
184 }
185 }
186 catch (IOException x)
187 {
188 try
189 {
190 close();
191 }
192 catch (IOException xx)
193 {
194 LOG.ignore(xx);
195 }
196
197 if (len>0)
198 throw x;
199 LOG.ignore(x);
200 len=-1;
201 }
202 }
203 else
204 {
205 throw new IOException("Not Implemented");
206 }
207
208 return len;
209 }
210
211
212
213
214 public int flush(Buffer buffer) throws IOException
215 {
216 Buffer buf = buffer.buffer();
217 int len=0;
218 if (buf instanceof NIOBuffer)
219 {
220 final NIOBuffer nbuf = (NIOBuffer)buf;
221 final ByteBuffer bbuf=nbuf.getByteBuffer();
222
223
224 synchronized(bbuf)
225 {
226 try
227 {
228 bbuf.position(buffer.getIndex());
229 bbuf.limit(buffer.putIndex());
230 len=_channel.write(bbuf);
231 }
232 finally
233 {
234 if (len>0)
235 buffer.skip(len);
236 bbuf.position(0);
237 bbuf.limit(bbuf.capacity());
238 }
239 }
240 }
241 else if (buf instanceof RandomAccessFileBuffer)
242 {
243 len = ((RandomAccessFileBuffer)buf).writeTo(_channel,buffer.getIndex(),buffer.length());
244 if (len>0)
245 buffer.skip(len);
246 }
247 else if (buffer.array()!=null)
248 {
249 ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
250 len=_channel.write(b);
251 if (len>0)
252 buffer.skip(len);
253 }
254 else
255 {
256 throw new IOException("Not Implemented");
257 }
258 return len;
259 }
260
261
262
263
264 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
265 {
266 int length=0;
267
268 Buffer buf0 = header==null?null:header.buffer();
269 Buffer buf1 = buffer==null?null:buffer.buffer();
270
271 if (_channel instanceof GatheringByteChannel &&
272 header!=null && header.length()!=0 && buf0 instanceof NIOBuffer &&
273 buffer!=null && buffer.length()!=0 && buf1 instanceof NIOBuffer)
274 {
275 length = gatheringFlush(header,((NIOBuffer)buf0).getByteBuffer(),buffer,((NIOBuffer)buf1).getByteBuffer());
276 }
277 else
278 {
279 if (header!=null)
280 {
281 if (buffer!=null && buffer.length()>0 && header.space()>buffer.length())
282 {
283 header.put(buffer);
284 buffer.clear();
285 }
286 if (trailer!=null && trailer.length()>0 && header.space()>trailer.length())
287 {
288 header.put(trailer);
289 trailer.clear();
290 }
291 }
292
293
294 if (header!=null && header.length()>0)
295 length=flush(header);
296
297
298 if ((header==null || header.length()==0) &&
299 buffer!=null && buffer.length()>0)
300 length+=flush(buffer);
301
302
303 if ((header==null || header.length()==0) &&
304 (buffer==null || buffer.length()==0) &&
305 trailer!=null && trailer.length()>0)
306 length+=flush(trailer);
307 }
308
309 return length;
310 }
311
312 protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException
313 {
314 int length;
315
316 synchronized(this)
317 {
318
319
320 synchronized(bbuf0)
321 {
322
323 synchronized(bbuf1)
324 {
325 try
326 {
327
328 bbuf0.position(header.getIndex());
329 bbuf0.limit(header.putIndex());
330 bbuf1.position(buffer.getIndex());
331 bbuf1.limit(buffer.putIndex());
332
333 _gather2[0]=bbuf0;
334 _gather2[1]=bbuf1;
335
336
337 length=(int)((GatheringByteChannel)_channel).write(_gather2);
338
339 int hl=header.length();
340 if (length>hl)
341 {
342 header.clear();
343 buffer.skip(length-hl);
344 }
345 else if (length>0)
346 {
347 header.skip(length);
348 }
349 }
350 finally
351 {
352
353 if (!header.isImmutable())
354 header.setGetIndex(bbuf0.position());
355 if (!buffer.isImmutable())
356 buffer.setGetIndex(bbuf1.position());
357
358 bbuf0.position(0);
359 bbuf1.position(0);
360 bbuf0.limit(bbuf0.capacity());
361 bbuf1.limit(bbuf1.capacity());
362 }
363 }
364 }
365 }
366 return length;
367 }
368
369
370
371
372
373 public ByteChannel getChannel()
374 {
375 return _channel;
376 }
377
378
379
380
381
382
383 public String getLocalAddr()
384 {
385 if (_socket==null)
386 return null;
387 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
388 return StringUtil.ALL_INTERFACES;
389 return _local.getAddress().getHostAddress();
390 }
391
392
393
394
395
396 public String getLocalHost()
397 {
398 if (_socket==null)
399 return null;
400 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
401 return StringUtil.ALL_INTERFACES;
402 return _local.getAddress().getCanonicalHostName();
403 }
404
405
406
407
408
409 public int getLocalPort()
410 {
411 if (_socket==null)
412 return 0;
413 if (_local==null)
414 return -1;
415 return _local.getPort();
416 }
417
418
419
420
421
422 public String getRemoteAddr()
423 {
424 if (_socket==null)
425 return null;
426 if (_remote==null)
427 return null;
428 return _remote.getAddress().getHostAddress();
429 }
430
431
432
433
434
435 public String getRemoteHost()
436 {
437 if (_socket==null)
438 return null;
439 if (_remote==null)
440 return null;
441 return _remote.getAddress().getCanonicalHostName();
442 }
443
444
445
446
447
448 public int getRemotePort()
449 {
450 if (_socket==null)
451 return 0;
452 return _remote==null?-1:_remote.getPort();
453 }
454
455
456
457
458
459 public Object getTransport()
460 {
461 return _channel;
462 }
463
464
465 public void flush()
466 throws IOException
467 {
468 }
469
470
471 public boolean isBufferingInput()
472 {
473 return false;
474 }
475
476
477 public boolean isBufferingOutput()
478 {
479 return false;
480 }
481
482
483 public boolean isBufferred()
484 {
485 return false;
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 }