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