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