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