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