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