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