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 }