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