1 /*
   2  * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  */
  28 
  29 package sun.nio.ch;
  30 
  31 import java.io.IOException;
  32 import java.net.InetAddress;
  33 import java.net.InetSocketAddress;
  34 import java.nio.*;
  35 import java.nio.channels.*;
  36 import java.nio.channels.spi.*;
  37 import java.security.AccessController;
  38 import java.security.PrivilegedExceptionAction;
  39 import java.security.PrivilegedActionException;
  40 import java.util.Random;
  41 
  42 
  43 /**
  44  * A simple Pipe implementation based on a socket connection.
  45  */
  46 
  47 class PipeImpl
  48     extends Pipe
  49 {
  50 
  51     // Source and sink channels
  52     private SourceChannel source;
  53     private SinkChannel sink;
  54 
  55     // Random object for handshake values
  56     private static final Random rnd;
  57 
  58     static {
  59         Util.load();
  60         byte[] someBytes = new byte[8];
  61         boolean resultOK = IOUtil.randomBytes(someBytes);
  62         if (resultOK) {
  63             rnd = new Random(ByteBuffer.wrap(someBytes).getLong());
  64         } else {
  65             rnd = new Random();
  66         }
  67     }
  68 
  69     private class Initializer
  70         implements PrivilegedExceptionAction<Void>
  71     {
  72 
  73         private final SelectorProvider sp;
  74 
  75         private Initializer(SelectorProvider sp) {
  76             this.sp = sp;
  77         }
  78 
  79         public Void run() throws IOException {
  80             ServerSocketChannel ssc = null;
  81             SocketChannel sc1 = null;
  82             SocketChannel sc2 = null;
  83 
  84             try {
  85                 // loopback address
  86                 InetAddress lb = InetAddress.getByName("127.0.0.1");
  87                 assert(lb.isLoopbackAddress());
  88 
  89                 // bind ServerSocketChannel to a port on the loopback address
  90                 ssc = ServerSocketChannel.open();
  91                 ssc.socket().bind(new InetSocketAddress(lb, 0));
  92 
  93                 // Establish connection (assumes connections are eagerly
  94                 // accepted)
  95                 InetSocketAddress sa
  96                     = new InetSocketAddress(lb, ssc.socket().getLocalPort());
  97                 sc1 = SocketChannel.open(sa);
  98 
  99                 ByteBuffer bb = ByteBuffer.allocate(8);
 100                 long secret = rnd.nextLong();
 101                 bb.putLong(secret).flip();
 102                 sc1.write(bb);
 103 
 104                 // Get a connection and verify it is legitimate
 105                 for (;;) {
 106                     sc2 = ssc.accept();
 107                     bb.clear();
 108                     sc2.read(bb);
 109                     bb.rewind();
 110                     if (bb.getLong() == secret)
 111                         break;
 112                     sc2.close();
 113                 }
 114 
 115                 // Create source and sink channels
 116                 source = new SourceChannelImpl(sp, sc1);
 117                 sink = new SinkChannelImpl(sp, sc2);
 118             } catch (IOException e) {
 119                 try {
 120                     if (sc1 != null)
 121                         sc1.close();
 122                     if (sc2 != null)
 123                         sc2.close();
 124                 } catch (IOException e2) { }
 125                 IOException x = new IOException("Unable to establish"
 126                                                 + " loopback connection");
 127                 x.initCause(e);
 128                 throw x;
 129             } finally {
 130                 try {
 131                     if (ssc != null)
 132                         ssc.close();
 133                 } catch (IOException e2) { }
 134             }
 135             return null;
 136         }
 137     }
 138 
 139     PipeImpl(final SelectorProvider sp) throws IOException {
 140         try {
 141             AccessController.doPrivileged(new Initializer(sp));
 142         } catch (PrivilegedActionException x) {
 143             throw (IOException)x.getCause();
 144         }
 145     }
 146 
 147 
 148     public SourceChannel source() {
 149         return source;
 150     }
 151 
 152     public SinkChannel sink() {
 153         return sink;
 154     }
 155 
 156 }