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