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