Mercurial Hosting > luan
comparison src/org/eclipse/jetty/io/nio/ChannelEndPoint.java @ 802:3428c60d7cfc
replace jetty jars with source
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Wed, 07 Sep 2016 21:15:48 -0600 |
| parents | |
| children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
| 801:6a21393191c1 | 802:3428c60d7cfc |
|---|---|
| 1 // | |
| 2 // ======================================================================== | |
| 3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
| 4 // ------------------------------------------------------------------------ | |
| 5 // All rights reserved. This program and the accompanying materials | |
| 6 // are made available under the terms of the Eclipse Public License v1.0 | |
| 7 // and Apache License v2.0 which accompanies this distribution. | |
| 8 // | |
| 9 // The Eclipse Public License is available at | |
| 10 // http://www.eclipse.org/legal/epl-v10.html | |
| 11 // | |
| 12 // The Apache License v2.0 is available at | |
| 13 // http://www.opensource.org/licenses/apache2.0.php | |
| 14 // | |
| 15 // You may elect to redistribute this code under either of these licenses. | |
| 16 // ======================================================================== | |
| 17 // | |
| 18 | |
| 19 package org.eclipse.jetty.io.nio; | |
| 20 | |
| 21 import java.io.IOException; | |
| 22 import java.net.InetSocketAddress; | |
| 23 import java.net.Socket; | |
| 24 import java.net.SocketException; | |
| 25 import java.nio.ByteBuffer; | |
| 26 import java.nio.channels.ByteChannel; | |
| 27 import java.nio.channels.GatheringByteChannel; | |
| 28 import java.nio.channels.SelectableChannel; | |
| 29 import java.nio.channels.SocketChannel; | |
| 30 | |
| 31 import org.eclipse.jetty.io.Buffer; | |
| 32 import org.eclipse.jetty.io.EndPoint; | |
| 33 import org.eclipse.jetty.util.StringUtil; | |
| 34 import org.eclipse.jetty.util.log.Log; | |
| 35 import org.eclipse.jetty.util.log.Logger; | |
| 36 | |
| 37 /** | |
| 38 * Channel End Point. | |
| 39 * <p>Holds the channel and socket for an NIO endpoint. | |
| 40 * | |
| 41 */ | |
| 42 public class ChannelEndPoint implements EndPoint | |
| 43 { | |
| 44 private static final Logger LOG = Log.getLogger(ChannelEndPoint.class); | |
| 45 | |
| 46 protected final ByteChannel _channel; | |
| 47 protected final ByteBuffer[] _gather2=new ByteBuffer[2]; | |
| 48 protected final Socket _socket; | |
| 49 protected final InetSocketAddress _local; | |
| 50 protected final InetSocketAddress _remote; | |
| 51 protected volatile int _maxIdleTime; | |
| 52 private volatile boolean _ishut; | |
| 53 private volatile boolean _oshut; | |
| 54 | |
| 55 public ChannelEndPoint(ByteChannel channel) throws IOException | |
| 56 { | |
| 57 super(); | |
| 58 this._channel = channel; | |
| 59 _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null; | |
| 60 if (_socket!=null) | |
| 61 { | |
| 62 _local=(InetSocketAddress)_socket.getLocalSocketAddress(); | |
| 63 _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); | |
| 64 _maxIdleTime=_socket.getSoTimeout(); | |
| 65 } | |
| 66 else | |
| 67 { | |
| 68 _local=_remote=null; | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 protected ChannelEndPoint(ByteChannel channel, int maxIdleTime) throws IOException | |
| 73 { | |
| 74 this._channel = channel; | |
| 75 _maxIdleTime=maxIdleTime; | |
| 76 _socket=(channel instanceof SocketChannel)?((SocketChannel)channel).socket():null; | |
| 77 if (_socket!=null) | |
| 78 { | |
| 79 _local=(InetSocketAddress)_socket.getLocalSocketAddress(); | |
| 80 _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); | |
| 81 _socket.setSoTimeout(_maxIdleTime); | |
| 82 } | |
| 83 else | |
| 84 { | |
| 85 _local=_remote=null; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 public boolean isBlocking() | |
| 90 { | |
| 91 return !(_channel instanceof SelectableChannel) || ((SelectableChannel)_channel).isBlocking(); | |
| 92 } | |
| 93 | |
| 94 public boolean blockReadable(long millisecs) throws IOException | |
| 95 { | |
| 96 return true; | |
| 97 } | |
| 98 | |
| 99 public boolean blockWritable(long millisecs) throws IOException | |
| 100 { | |
| 101 return true; | |
| 102 } | |
| 103 | |
| 104 /* | |
| 105 * @see org.eclipse.io.EndPoint#isOpen() | |
| 106 */ | |
| 107 public boolean isOpen() | |
| 108 { | |
| 109 return _channel.isOpen(); | |
| 110 } | |
| 111 | |
| 112 /** Shutdown the channel Input. | |
| 113 * Cannot be overridden. To override, see {@link #shutdownInput()} | |
| 114 * @throws IOException | |
| 115 */ | |
| 116 protected final void shutdownChannelInput() throws IOException | |
| 117 { | |
| 118 LOG.debug("ishut {}", this); | |
| 119 _ishut = true; | |
| 120 if (_channel.isOpen()) | |
| 121 { | |
| 122 if (_socket != null) | |
| 123 { | |
| 124 try | |
| 125 { | |
| 126 if (!_socket.isInputShutdown()) | |
| 127 { | |
| 128 _socket.shutdownInput(); | |
| 129 } | |
| 130 } | |
| 131 catch (SocketException e) | |
| 132 { | |
| 133 LOG.debug(e.toString()); | |
| 134 LOG.ignore(e); | |
| 135 } | |
| 136 finally | |
| 137 { | |
| 138 if (_oshut) | |
| 139 { | |
| 140 close(); | |
| 141 } | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 /* (non-Javadoc) | |
| 148 * @see org.eclipse.io.EndPoint#close() | |
| 149 */ | |
| 150 public void shutdownInput() throws IOException | |
| 151 { | |
| 152 shutdownChannelInput(); | |
| 153 } | |
| 154 | |
| 155 protected final void shutdownChannelOutput() throws IOException | |
| 156 { | |
| 157 LOG.debug("oshut {}",this); | |
| 158 _oshut = true; | |
| 159 if (_channel.isOpen()) | |
| 160 { | |
| 161 if (_socket != null) | |
| 162 { | |
| 163 try | |
| 164 { | |
| 165 if (!_socket.isOutputShutdown()) | |
| 166 { | |
| 167 _socket.shutdownOutput(); | |
| 168 } | |
| 169 } | |
| 170 catch (SocketException e) | |
| 171 { | |
| 172 LOG.debug(e.toString()); | |
| 173 LOG.ignore(e); | |
| 174 } | |
| 175 finally | |
| 176 { | |
| 177 if (_ishut) | |
| 178 { | |
| 179 close(); | |
| 180 } | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 /* (non-Javadoc) | |
| 187 * @see org.eclipse.io.EndPoint#close() | |
| 188 */ | |
| 189 public void shutdownOutput() throws IOException | |
| 190 { | |
| 191 shutdownChannelOutput(); | |
| 192 } | |
| 193 | |
| 194 public boolean isOutputShutdown() | |
| 195 { | |
| 196 return _oshut || !_channel.isOpen() || _socket != null && _socket.isOutputShutdown(); | |
| 197 } | |
| 198 | |
| 199 public boolean isInputShutdown() | |
| 200 { | |
| 201 return _ishut || !_channel.isOpen() || _socket != null && _socket.isInputShutdown(); | |
| 202 } | |
| 203 | |
| 204 /* (non-Javadoc) | |
| 205 * @see org.eclipse.io.EndPoint#close() | |
| 206 */ | |
| 207 public void close() throws IOException | |
| 208 { | |
| 209 LOG.debug("close {}",this); | |
| 210 _channel.close(); | |
| 211 } | |
| 212 | |
| 213 /* (non-Javadoc) | |
| 214 * @see org.eclipse.io.EndPoint#fill(org.eclipse.io.Buffer) | |
| 215 */ | |
| 216 public int fill(Buffer buffer) throws IOException | |
| 217 { | |
| 218 if (_ishut) | |
| 219 return -1; | |
| 220 Buffer buf = buffer.buffer(); | |
| 221 int len=0; | |
| 222 if (buf instanceof NIOBuffer) | |
| 223 { | |
| 224 final NIOBuffer nbuf = (NIOBuffer)buf; | |
| 225 final ByteBuffer bbuf=nbuf.getByteBuffer(); | |
| 226 | |
| 227 //noinspection SynchronizationOnLocalVariableOrMethodParameter | |
| 228 try | |
| 229 { | |
| 230 synchronized(bbuf) | |
| 231 { | |
| 232 try | |
| 233 { | |
| 234 bbuf.position(buffer.putIndex()); | |
| 235 len=_channel.read(bbuf); | |
| 236 } | |
| 237 finally | |
| 238 { | |
| 239 buffer.setPutIndex(bbuf.position()); | |
| 240 bbuf.position(0); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 if (len<0 && isOpen()) | |
| 245 { | |
| 246 if (!isInputShutdown()) | |
| 247 shutdownInput(); | |
| 248 if (isOutputShutdown()) | |
| 249 _channel.close(); | |
| 250 } | |
| 251 } | |
| 252 catch (IOException x) | |
| 253 { | |
| 254 LOG.debug("Exception while filling", x); | |
| 255 try | |
| 256 { | |
| 257 if (_channel.isOpen()) | |
| 258 _channel.close(); | |
| 259 } | |
| 260 catch (Exception xx) | |
| 261 { | |
| 262 LOG.ignore(xx); | |
| 263 } | |
| 264 | |
| 265 if (len>0) | |
| 266 throw x; | |
| 267 len=-1; | |
| 268 } | |
| 269 } | |
| 270 else | |
| 271 { | |
| 272 throw new IOException("Not Implemented"); | |
| 273 } | |
| 274 | |
| 275 return len; | |
| 276 } | |
| 277 | |
| 278 /* (non-Javadoc) | |
| 279 * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer) | |
| 280 */ | |
| 281 public int flush(Buffer buffer) throws IOException | |
| 282 { | |
| 283 Buffer buf = buffer.buffer(); | |
| 284 int len=0; | |
| 285 if (buf instanceof NIOBuffer) | |
| 286 { | |
| 287 final NIOBuffer nbuf = (NIOBuffer)buf; | |
| 288 final ByteBuffer bbuf=nbuf.getByteBuffer().asReadOnlyBuffer(); | |
| 289 try | |
| 290 { | |
| 291 bbuf.position(buffer.getIndex()); | |
| 292 bbuf.limit(buffer.putIndex()); | |
| 293 len=_channel.write(bbuf); | |
| 294 } | |
| 295 finally | |
| 296 { | |
| 297 if (len>0) | |
| 298 buffer.skip(len); | |
| 299 } | |
| 300 } | |
| 301 else if (buf instanceof RandomAccessFileBuffer) | |
| 302 { | |
| 303 len = ((RandomAccessFileBuffer)buf).writeTo(_channel,buffer.getIndex(),buffer.length()); | |
| 304 if (len>0) | |
| 305 buffer.skip(len); | |
| 306 } | |
| 307 else if (buffer.array()!=null) | |
| 308 { | |
| 309 ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length()); | |
| 310 len=_channel.write(b); | |
| 311 if (len>0) | |
| 312 buffer.skip(len); | |
| 313 } | |
| 314 else | |
| 315 { | |
| 316 throw new IOException("Not Implemented"); | |
| 317 } | |
| 318 return len; | |
| 319 } | |
| 320 | |
| 321 /* (non-Javadoc) | |
| 322 * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer) | |
| 323 */ | |
| 324 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException | |
| 325 { | |
| 326 int length=0; | |
| 327 | |
| 328 Buffer buf0 = header==null?null:header.buffer(); | |
| 329 Buffer buf1 = buffer==null?null:buffer.buffer(); | |
| 330 | |
| 331 if (_channel instanceof GatheringByteChannel && | |
| 332 header!=null && header.length()!=0 && buf0 instanceof NIOBuffer && | |
| 333 buffer!=null && buffer.length()!=0 && buf1 instanceof NIOBuffer) | |
| 334 { | |
| 335 length = gatheringFlush(header,((NIOBuffer)buf0).getByteBuffer(),buffer,((NIOBuffer)buf1).getByteBuffer()); | |
| 336 } | |
| 337 else | |
| 338 { | |
| 339 // flush header | |
| 340 if (header!=null && header.length()>0) | |
| 341 length=flush(header); | |
| 342 | |
| 343 // flush buffer | |
| 344 if ((header==null || header.length()==0) && | |
| 345 buffer!=null && buffer.length()>0) | |
| 346 length+=flush(buffer); | |
| 347 | |
| 348 // flush trailer | |
| 349 if ((header==null || header.length()==0) && | |
| 350 (buffer==null || buffer.length()==0) && | |
| 351 trailer!=null && trailer.length()>0) | |
| 352 length+=flush(trailer); | |
| 353 } | |
| 354 | |
| 355 return length; | |
| 356 } | |
| 357 | |
| 358 protected int gatheringFlush(Buffer header, ByteBuffer bbuf0, Buffer buffer, ByteBuffer bbuf1) throws IOException | |
| 359 { | |
| 360 int length; | |
| 361 | |
| 362 synchronized(this) | |
| 363 { | |
| 364 // Adjust position indexs of buf0 and buf1 | |
| 365 bbuf0=bbuf0.asReadOnlyBuffer(); | |
| 366 bbuf0.position(header.getIndex()); | |
| 367 bbuf0.limit(header.putIndex()); | |
| 368 bbuf1=bbuf1.asReadOnlyBuffer(); | |
| 369 bbuf1.position(buffer.getIndex()); | |
| 370 bbuf1.limit(buffer.putIndex()); | |
| 371 | |
| 372 _gather2[0]=bbuf0; | |
| 373 _gather2[1]=bbuf1; | |
| 374 | |
| 375 // do the gathering write. | |
| 376 length=(int)((GatheringByteChannel)_channel).write(_gather2); | |
| 377 | |
| 378 int hl=header.length(); | |
| 379 if (length>hl) | |
| 380 { | |
| 381 header.clear(); | |
| 382 buffer.skip(length-hl); | |
| 383 } | |
| 384 else if (length>0) | |
| 385 { | |
| 386 header.skip(length); | |
| 387 } | |
| 388 } | |
| 389 return length; | |
| 390 } | |
| 391 | |
| 392 /* ------------------------------------------------------------ */ | |
| 393 /** | |
| 394 * @return Returns the channel. | |
| 395 */ | |
| 396 public ByteChannel getChannel() | |
| 397 { | |
| 398 return _channel; | |
| 399 } | |
| 400 | |
| 401 | |
| 402 /* ------------------------------------------------------------ */ | |
| 403 /* | |
| 404 * @see org.eclipse.io.EndPoint#getLocalAddr() | |
| 405 */ | |
| 406 public String getLocalAddr() | |
| 407 { | |
| 408 if (_socket==null) | |
| 409 return null; | |
| 410 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) | |
| 411 return StringUtil.ALL_INTERFACES; | |
| 412 return _local.getAddress().getHostAddress(); | |
| 413 } | |
| 414 | |
| 415 /* ------------------------------------------------------------ */ | |
| 416 /* | |
| 417 * @see org.eclipse.io.EndPoint#getLocalHost() | |
| 418 */ | |
| 419 public String getLocalHost() | |
| 420 { | |
| 421 if (_socket==null) | |
| 422 return null; | |
| 423 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) | |
| 424 return StringUtil.ALL_INTERFACES; | |
| 425 return _local.getAddress().getCanonicalHostName(); | |
| 426 } | |
| 427 | |
| 428 /* ------------------------------------------------------------ */ | |
| 429 /* | |
| 430 * @see org.eclipse.io.EndPoint#getLocalPort() | |
| 431 */ | |
| 432 public int getLocalPort() | |
| 433 { | |
| 434 if (_socket==null) | |
| 435 return 0; | |
| 436 if (_local==null) | |
| 437 return -1; | |
| 438 return _local.getPort(); | |
| 439 } | |
| 440 | |
| 441 /* ------------------------------------------------------------ */ | |
| 442 /* | |
| 443 * @see org.eclipse.io.EndPoint#getRemoteAddr() | |
| 444 */ | |
| 445 public String getRemoteAddr() | |
| 446 { | |
| 447 if (_socket==null) | |
| 448 return null; | |
| 449 if (_remote==null) | |
| 450 return null; | |
| 451 return _remote.getAddress().getHostAddress(); | |
| 452 } | |
| 453 | |
| 454 /* ------------------------------------------------------------ */ | |
| 455 /* | |
| 456 * @see org.eclipse.io.EndPoint#getRemoteHost() | |
| 457 */ | |
| 458 public String getRemoteHost() | |
| 459 { | |
| 460 if (_socket==null) | |
| 461 return null; | |
| 462 if (_remote==null) | |
| 463 return null; | |
| 464 return _remote.getAddress().getCanonicalHostName(); | |
| 465 } | |
| 466 | |
| 467 /* ------------------------------------------------------------ */ | |
| 468 /* | |
| 469 * @see org.eclipse.io.EndPoint#getRemotePort() | |
| 470 */ | |
| 471 public int getRemotePort() | |
| 472 { | |
| 473 if (_socket==null) | |
| 474 return 0; | |
| 475 return _remote==null?-1:_remote.getPort(); | |
| 476 } | |
| 477 | |
| 478 /* ------------------------------------------------------------ */ | |
| 479 /* | |
| 480 * @see org.eclipse.io.EndPoint#getConnection() | |
| 481 */ | |
| 482 public Object getTransport() | |
| 483 { | |
| 484 return _channel; | |
| 485 } | |
| 486 | |
| 487 /* ------------------------------------------------------------ */ | |
| 488 public void flush() | |
| 489 throws IOException | |
| 490 { | |
| 491 } | |
| 492 | |
| 493 /* ------------------------------------------------------------ */ | |
| 494 public int getMaxIdleTime() | |
| 495 { | |
| 496 return _maxIdleTime; | |
| 497 } | |
| 498 | |
| 499 /* ------------------------------------------------------------ */ | |
| 500 /** | |
| 501 * @see org.eclipse.jetty.io.bio.StreamEndPoint#setMaxIdleTime(int) | |
| 502 */ | |
| 503 public void setMaxIdleTime(int timeMs) throws IOException | |
| 504 { | |
| 505 if (_socket!=null && timeMs!=_maxIdleTime) | |
| 506 _socket.setSoTimeout(timeMs>0?timeMs:0); | |
| 507 _maxIdleTime=timeMs; | |
| 508 } | |
| 509 } |
