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