001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.internal; 028 029 030 031 import java.io.IOException; 032 import java.net.InetAddress; 033 import java.net.InetSocketAddress; 034 import java.net.Socket; 035 import java.net.SocketAddress; 036 import java.nio.channels.SocketChannel; 037 038 import org.opends.server.types.DN; 039 040 041 042 /** 043 * This class provides an implementation of a {@code java.net.Socket} 044 * object that can be used to facilitate internal communication with 045 * the Directory Server through third-party LDAP APIs that provide the 046 * ability to use a custom socket factory when creating connections. 047 * Whenever data is written over the socket, it is decoded as LDAP 048 * communication and converted to an appropriate internal operation, 049 * which the server then processes and converts the response back to 050 * an LDAP encoding. 051 * <BR><BR> 052 * Note that this implementation only supports those operations which 053 * can be performed in the Directory Server via internal operations. 054 * This includes add, compare, delete, modify, modify DN, and search 055 * operations, and some types of extended operations. Special support 056 * has been added for simple bind operations to function properly, but 057 * SASL binds are not supported. Abandon and unbind operations are 058 * not supported, nor are the cancel or StartTLS extended operations. 059 * Only clear-text LDAP communication may be used. 060 */ 061 @org.opends.server.types.PublicAPI( 062 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 063 mayInstantiate=true, 064 mayExtend=false, 065 mayInvoke=true) 066 public final class InternalLDAPSocket 067 extends Socket 068 { 069 // Indicates whether this socket is closed. 070 private boolean closed; 071 072 // The value that the client has requested for SO_KEEPALIVE. 073 private boolean keepAlive; 074 075 // The value that the client has requested for OOBINLINE. 076 private boolean oobInline; 077 078 // The value that the client has requested for SO_REUSEADDR. 079 private boolean reuseAddress; 080 081 // The value that the client has requested for TCP_NODELAY. 082 private boolean tcpNoDelay; 083 084 // The value that the client has requested for SO_LINGER. 085 private int lingerDuration; 086 087 // The value that the client has requested for SO_RCVBUF. 088 private int receiveBufferSize; 089 090 // The value that the client has requested for SO_SNDBUF. 091 private int sendBufferSize; 092 093 // The value that the client has requested for SO_TIMEOUT. 094 private int timeout; 095 096 // The value that the client has requested for the traffic class. 097 private int trafficClass; 098 099 // The internal client connection used to perform the internal 100 // operations. It will be null until it is first used. 101 private InternalClientConnection conn; 102 103 // The input stream associated with this internal LDAP socket. 104 private InternalLDAPInputStream inputStream; 105 106 // The output stream associated with this internal LDAP socket. 107 private InternalLDAPOutputStream outputStream; 108 109 110 111 /** 112 * Creates a new internal LDAP socket. 113 */ 114 public InternalLDAPSocket() 115 { 116 closed = false; 117 keepAlive = true; 118 oobInline = true; 119 reuseAddress = true; 120 tcpNoDelay = true; 121 lingerDuration = 0; 122 receiveBufferSize = 1024; 123 sendBufferSize = 1024; 124 timeout = 0; 125 trafficClass = 0; 126 conn = null; 127 inputStream = new InternalLDAPInputStream(this); 128 outputStream = new InternalLDAPOutputStream(this); 129 } 130 131 132 133 /** 134 * Retrieves the internal client connection used to back this 135 * internal LDAP socket. 136 * 137 * @return The internal client connection used to back this 138 * internal LDAP socket. 139 * 140 * @throws IOException If there is a problem obtaining the 141 * connection. 142 */ 143 @org.opends.server.types.PublicAPI( 144 stability=org.opends.server.types.StabilityLevel.PRIVATE, 145 mayInstantiate=false, 146 mayExtend=false, 147 mayInvoke=false) 148 synchronized InternalClientConnection getConnection() 149 throws IOException 150 { 151 if (conn == null) 152 { 153 try 154 { 155 conn = new InternalClientConnection(DN.nullDN()); 156 } 157 catch (Exception e) 158 { 159 // This should never happen. 160 throw new IOException(e.getMessage()); 161 } 162 } 163 164 return conn; 165 } 166 167 168 169 /** 170 * Sets the internal client connection used to back this internal 171 * LDAP socket. 172 * 173 * @param conn The internal client connection used to back this 174 * internal LDAP socket. 175 */ 176 @org.opends.server.types.PublicAPI( 177 stability=org.opends.server.types.StabilityLevel.PRIVATE, 178 mayInstantiate=false, 179 mayExtend=false, 180 mayInvoke=false) 181 synchronized void setConnection(InternalClientConnection conn) 182 { 183 this.conn = conn; 184 } 185 186 187 188 /** 189 * Binds the socket to a local address. This does nothing, since 190 * there is no actual network communication performed by this 191 * socket implementation. 192 * 193 * @param bindpoint The socket address to which to bind. 194 */ 195 @Override() 196 public void bind(SocketAddress bindpoint) 197 { 198 // No implementation is required. 199 } 200 201 202 203 /** 204 * Closes this socket. This will make it unavailable for use. 205 */ 206 @Override() 207 public synchronized void close() 208 { 209 try 210 { 211 inputStream.closeInternal(); 212 } catch (Exception e) {} 213 214 try 215 { 216 outputStream.closeInternal(); 217 } catch (Exception e) {} 218 219 closed = true; 220 inputStream = null; 221 outputStream = null; 222 } 223 224 225 226 /** 227 * Connects this socket to the specified remote endpoint. This will 228 * make the connection available again if it has been previously 229 * closed. The provided address is irrelevant, as it will always be 230 * an internal connection. 231 * 232 * @param endpoint The address of the remote endpoint. 233 */ 234 @Override() 235 public synchronized void connect(SocketAddress endpoint) 236 { 237 closed = false; 238 inputStream = new InternalLDAPInputStream(this); 239 outputStream = new InternalLDAPOutputStream(this); 240 } 241 242 243 244 /** 245 * Connects this socket to the specified remote endpoint. This does 246 * nothing, since there is no actual network communication performed 247 * by this socket implementation. 248 * 249 * @param endpoint The address of the remote endpoint. 250 * @param timeout The maximum length of time in milliseconds to 251 * wait for the connection to be established. 252 */ 253 @Override() 254 public void connect(SocketAddress endpoint, int timeout) 255 { 256 closed = false; 257 inputStream = new InternalLDAPInputStream(this); 258 outputStream = new InternalLDAPOutputStream(this); 259 } 260 261 262 263 /** 264 * Retrieves the socket channel associated with this socket. This 265 * method always returns {@code null} since this implementation does 266 * not support use with NIO channels. 267 * 268 * @return {@code null} because this implementation does not 269 * support use with NIO channels. 270 */ 271 @Override() 272 public SocketChannel getChannel() 273 { 274 // This implementation does not support use with NIO channels. 275 return null; 276 } 277 278 279 280 /** 281 * Retrieves the address to which this socket is connected. The 282 * address returned is meaningless, since there is no actual network 283 * communication performed by this socket implementation. 284 * 285 * @return The address to which this socket is connected. 286 */ 287 @Override() 288 public InetAddress getInetAddress() 289 { 290 try 291 { 292 return InetAddress.getLocalHost(); 293 } 294 catch (Exception e) 295 { 296 // This should not happen. 297 return null; 298 } 299 } 300 301 302 303 /** 304 * Retrieves the input stream for this socket. 305 * 306 * @return The input stream for this socket. 307 */ 308 @Override() 309 public InternalLDAPInputStream getInputStream() 310 { 311 return inputStream; 312 } 313 314 315 316 /** 317 * Indicates whether SO_KEEPALIVE is enabled. This implementation 318 * will return {@code true} by default, but if its value is changed 319 * using {@code setKeepalive} then that value will be returned. 320 * This setting has no effect in this socket implementation. 321 * 322 * @return {@code true} if SO_KEEPALIVE is enabled, or 323 * {@code false} if not. 324 */ 325 @Override() 326 public boolean getKeepAlive() 327 { 328 return keepAlive; 329 } 330 331 332 333 /** 334 * Retrieves the local address to which this socket is bound. The 335 * address returned is meaningless, since there is no actual network 336 * communication performed by this socket implementation. 337 * 338 * @return The local address to which this socket is bound. 339 */ 340 @Override() 341 public InetAddress getLocalAddress() 342 { 343 try 344 { 345 return InetAddress.getLocalHost(); 346 } 347 catch (Exception e) 348 { 349 // This should not happen. 350 return null; 351 } 352 } 353 354 355 356 /** 357 * Retrieves the local port to which this socket is bound. The 358 * value returned is meaningless, since there is no actual network 359 * communication performed by this socket implementation. 360 * 361 * @return The local port to which this socket is bound. 362 */ 363 @Override() 364 public int getLocalPort() 365 { 366 return 389; 367 } 368 369 370 371 /** 372 * Retrieves the local socket address to which this socket is bound. 373 * The value returned is meaningless, since there is no actual 374 * network communication performed by this socket implementation. 375 * 376 * @return The local socket address to which this socket is bound. 377 */ 378 @Override() 379 public SocketAddress getLocalSocketAddress() 380 { 381 try 382 { 383 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 384 } 385 catch (Exception e) 386 { 387 // This should not happen. 388 return null; 389 } 390 } 391 392 393 394 /** 395 * Indicates whether OOBINLINE is enabled. This implementation will 396 * return {@code true} by default, but if its value is changed 397 * using {@code setOOBInline} then that value will be returned. 398 * This setting has no effect in this socket implementation. 399 * 400 * @return {@code true} if OOBINLINE is enabled, or {@code false} 401 * if it is not. 402 */ 403 @Override() 404 public boolean getOOBInline() 405 { 406 return oobInline; 407 } 408 409 410 411 /** 412 * Retrieves the output stream for this socket. 413 * 414 * @return The output stream for this socket. 415 */ 416 @Override() 417 public InternalLDAPOutputStream getOutputStream() 418 { 419 return outputStream; 420 } 421 422 423 424 /** 425 * Retrieves the remote port to which this socket is connected. The 426 * value returned is meaningless, since there is no actual network 427 * communication performed by this socket implementation. 428 * 429 * @return The remote port to which this socket is connected. 430 */ 431 @Override() 432 public int getPort() 433 { 434 return 389; 435 } 436 437 438 439 /** 440 * Retrieves the value of the SO_RCVBUF option for this socket. The 441 * value returned is meaningless, since there is no actual network 442 * communication performed by this socket implementation. 443 * 444 * @return The value of the SO_RCVBUF option for this socket. 445 */ 446 @Override() 447 public int getReceiveBufferSize() 448 { 449 return receiveBufferSize; 450 } 451 452 453 454 /** 455 * Retrieves the remote socket address to which this socket is 456 * connected. The value returned is meaningless, since there is no 457 * actual network communication performed by this socket 458 * implementation. 459 * 460 * @return The remote socket address to which this socket is 461 * connected. 462 */ 463 @Override() 464 public SocketAddress getRemoteSocketAddress() 465 { 466 try 467 { 468 return new InetSocketAddress(getInetAddress(), getPort()); 469 } 470 catch (Exception e) 471 { 472 // This should not happen. 473 return null; 474 } 475 } 476 477 478 479 /** 480 * Indicates whether SO_REUSEADDR is enabled. This implementation 481 * will return {@code true} by default, but if its value is changed 482 * using {@code setReuseAddress} then that value will be returned. 483 * This setting has no effect in this socket implementation. 484 * 485 * @return {@code true} if SO_REUSEADDR is enabled, or 486 * {@code false} if it is not. 487 */ 488 @Override() 489 public boolean getReuseAddress() 490 { 491 return reuseAddress; 492 } 493 494 495 496 /** 497 * Retrieves the value of the SO_SNDBUF option for this socket. The 498 * value returned is meaningless, since there is no actual network 499 * communication performed by this socket implementation. 500 * 501 * @return The value of the SO_SNDBUF option for this socket. 502 */ 503 @Override() 504 public int getSendBufferSize() 505 { 506 return sendBufferSize; 507 } 508 509 510 511 /** 512 * Retrieves the value of the SO_LINGER option for this socket. The 513 * value returned is meaningless, since there is no actual network 514 * communication performed by this socket implementation. 515 * 516 * @return The value of the SO_LINGER option for this socket. 517 */ 518 @Override() 519 public int getSoLinger() 520 { 521 return lingerDuration; 522 } 523 524 525 526 /** 527 * Retrieves the value of the SO_TIMEOUT option for this socket. 528 * The value returned is meaningless, since there is no actual 529 * network communication performed by this socket implementation. 530 * 531 * @return The value of the SO_TIMEOUT option for this socket. 532 */ 533 @Override() 534 public int getSoTimeout() 535 { 536 return timeout; 537 } 538 539 540 541 /** 542 * Indicates whether TCP_NODELAY is enabled. This implementation 543 * will return {@code true} by default, but if its value is changed 544 * using {@code setTcpNoDelay} then that value will be returned. 545 * This setting has no effect in this socket implementation. 546 * 547 * @return {@code true} if TCP_NODELAY is enabled, or {@code false} 548 * if it is not. 549 */ 550 @Override() 551 public boolean getTcpNoDelay() 552 { 553 return tcpNoDelay; 554 } 555 556 557 558 /** 559 * Retrieves the traffic class for this socket. The value returned 560 * will be meaningless, since there is no actual network 561 * communication performed by this socket. 562 * 563 * @return The traffic class for this socket. 564 */ 565 @Override() 566 public int getTrafficClass() 567 { 568 return trafficClass; 569 } 570 571 572 573 /** 574 * Indicates whether this socket is bound to a local address. This 575 * method will always return {@code true} to indicate that it is 576 * bound. 577 * 578 * @return {@code true} to indicate that the socket is bound to a 579 * local address. 580 */ 581 @Override() 582 public boolean isBound() 583 { 584 return true; 585 } 586 587 588 589 /** 590 * Indicates whether this socket is closed. This method will always 591 * return {@code false} to indicate that it is not closed. 592 * 593 * @return {@code false} to indicate that the socket is not closed. 594 */ 595 @Override() 596 public boolean isClosed() 597 { 598 return closed; 599 } 600 601 602 603 /** 604 * Indicates whether this socket is connected to both local and 605 * remote endpoints. This method will always return {@code true} to 606 * indicate that it is connected. 607 * 608 * @return {@code true} to indicate that the socket is connected. 609 */ 610 @Override() 611 public boolean isConnected() 612 { 613 return (! closed); 614 } 615 616 617 618 /** 619 * Indicates whether the input side of this socket has been closed. 620 * This method will always return {@code false} to indicate that it 621 * is not closed. 622 * 623 * @return {@code false} to indicate that the input side of this 624 * socket is not closed. 625 */ 626 @Override() 627 public boolean isInputShutdown() 628 { 629 return closed; 630 } 631 632 633 634 /** 635 * Indicates whether the output side of this socket has been closed. 636 * This method will always return {@code false} to indicate that it 637 * is not closed. 638 * 639 * @return {@code false} to indicate that the output side of this 640 * socket is not closed. 641 */ 642 @Override() 643 public boolean isOutputShutdown() 644 { 645 return closed; 646 } 647 648 649 650 /** 651 * Sends a single byte of urgent data over this socket. 652 * 653 * @param data The data to be sent. 654 * 655 * @throws IOException If a problem occurs while trying to write 656 * the provided data over this socket. 657 */ 658 @Override() 659 public void sendUrgentData(int data) 660 throws IOException 661 { 662 getOutputStream().write(data); 663 } 664 665 666 667 /** 668 * Sets the value of SO_KEEPALIVE for this socket. This will not 669 * affect anything, since there is no actual network communication 670 * performed by this socket. 671 * 672 * @param on The value to use for the SO_KEEPALIVE option. 673 */ 674 @Override() 675 public void setKeepAlive(boolean on) 676 { 677 keepAlive = on; 678 } 679 680 681 682 /** 683 * Sets the value of OOBINLINE for this socket. This will not 684 * affect anything, since there is no actual network communication 685 * performed by this socket. 686 * 687 * @param on The value to use for the OOBINLINE option. 688 */ 689 @Override() 690 public void setOOBInline(boolean on) 691 { 692 oobInline = on; 693 } 694 695 696 697 /** 698 * Sets the provided performance preferences for this socket. This 699 * will not affect anything, since there is no actual network 700 * communication performed by this socket. 701 * 702 * @param connectionTime An {@code int} expressing the relative 703 * importance of a short connection time. 704 * @param latency An {@code int} expressing the relative 705 * importance of low latency. 706 * @param bandwidth An {@code int} expressing the relative 707 * importance of high bandwidth. 708 */ 709 @Override() 710 public void setPerformancePreferences(int connectionTime, 711 int latency, int bandwidth) 712 { 713 // No implementation is required. 714 } 715 716 717 718 /** 719 * Sets the value of SO_RCVBUF for this socket. This will not 720 * affect anything, since there is no actual network communication 721 * performed by this socket. 722 * 723 * @param size The value to use for the SO_RCVBUF option. 724 */ 725 @Override() 726 public void setReceiveBufferSize(int size) 727 { 728 receiveBufferSize = size; 729 } 730 731 732 733 /** 734 * Sets the value of SO_REUSEADDR for this socket. This will not 735 * affect anything, since there is no actual network communication 736 * performed by this socket. 737 * 738 * @param on The value to use for the SO_REUSEADDR option. 739 */ 740 @Override() 741 public void setReuseAddress(boolean on) 742 { 743 reuseAddress = on; 744 } 745 746 747 748 /** 749 * Sets the value of SO_SNDBUF for this socket. This will not 750 * affect anything, since there is no actual network communication 751 * performed by this socket. 752 * 753 * @param size The value to use for the SO_SNDBUF option. 754 */ 755 @Override() 756 public void setSendBufferSize(int size) 757 { 758 sendBufferSize = size; 759 } 760 761 762 763 /** 764 * Sets the value of SO_LINGER for this socket. This will not 765 * affect anything, since there is no actual network communication 766 * performed by this socket. 767 * 768 * @param on Indicates whether to enable the linger option. 769 * @param linger The length of time in milliseconds to allow the 770 * connection to linger. 771 */ 772 @Override() 773 public void setSoLinger(boolean on, int linger) 774 { 775 lingerDuration = linger; 776 } 777 778 779 780 /** 781 * Sets the value of SO_TIMEOUT for this socket. This will not 782 * affect anything, since there is no actual network communication 783 * performed by this socket. 784 * 785 * @param timeout The value to use for the SO_TIMEOUT option. 786 */ 787 @Override() 788 public void setSoTimeout(int timeout) 789 { 790 this.timeout = timeout; 791 } 792 793 794 795 /** 796 * Sets the value of TCP_NODELAY for this socket. This will not 797 * affect anything, since there is no actual network communication 798 * performed by this socket. 799 * 800 * @param on The value to use for the TCP_NODELAY option. 801 */ 802 @Override() 803 public void setTcpNoDelay(boolean on) 804 { 805 tcpNoDelay = on; 806 } 807 808 809 810 /** 811 * Sets the traffic class for this socket. This will not affect 812 * anything, since there is no actual network communication 813 * performed by this socket. 814 * 815 * @param tc The value to use for the traffic class. 816 */ 817 @Override() 818 public void setTrafficClass(int tc) 819 { 820 trafficClass = tc; 821 } 822 823 824 825 /** 826 * Shuts down the input side of this socket. This will have the 827 * effect of closing the entire socket. 828 */ 829 @Override() 830 public void shutdownInput() 831 { 832 close(); 833 } 834 835 836 837 /** 838 * Shuts down the output side of this socket. This will have the 839 * effect of closing the entire socket. 840 */ 841 @Override() 842 public void shutdownOutput() 843 { 844 close(); 845 } 846 847 848 849 /** 850 * Retrieves a string representation of this internal LDAP socket. 851 * 852 * @return A string representation of this internal LDAP socket. 853 */ 854 @Override() 855 public String toString() 856 { 857 return "InternalLDAPSocket"; 858 } 859 } 860