1 /* 2 * Copyright (c) 2008, 2009, 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 package sun.nio.ch; 27 28 import java.nio.channels.*; 29 import java.net.InetAddress; 30 import java.net.NetworkInterface; 31 import java.io.IOException; 32 import java.util.HashSet; 33 34 /** 35 * MembershipKey implementation. 36 */ 37 38 class MembershipKeyImpl 39 extends MembershipKey 40 { 41 private final MulticastChannel ch; 42 private final InetAddress group; 43 private final NetworkInterface interf; 44 private final InetAddress source; 45 46 // true when key is valid 47 private volatile boolean valid = true; 48 49 // lock used when creating or accessing blockedSet 50 private Object stateLock = new Object(); 51 52 // set of source addresses that are blocked 53 private HashSet<InetAddress> blockedSet; 54 MembershipKeyImpl(MulticastChannel ch, InetAddress group, NetworkInterface interf, InetAddress source)55 private MembershipKeyImpl(MulticastChannel ch, 56 InetAddress group, 57 NetworkInterface interf, 58 InetAddress source) 59 { 60 this.ch = ch; 61 this.group = group; 62 this.interf = interf; 63 this.source = source; 64 } 65 66 /** 67 * MembershipKey will additional context for IPv4 membership 68 */ 69 static class Type4 extends MembershipKeyImpl { 70 private final int groupAddress; 71 private final int interfAddress; 72 private final int sourceAddress; 73 Type4(MulticastChannel ch, InetAddress group, NetworkInterface interf, InetAddress source, int groupAddress, int interfAddress, int sourceAddress)74 Type4(MulticastChannel ch, 75 InetAddress group, 76 NetworkInterface interf, 77 InetAddress source, 78 int groupAddress, 79 int interfAddress, 80 int sourceAddress) 81 { 82 super(ch, group, interf, source); 83 this.groupAddress = groupAddress; 84 this.interfAddress = interfAddress; 85 this.sourceAddress = sourceAddress; 86 } 87 groupAddress()88 int groupAddress() { 89 return groupAddress; 90 } 91 interfaceAddress()92 int interfaceAddress() { 93 return interfAddress; 94 } 95 source()96 int source() { 97 return sourceAddress; 98 } 99 } 100 101 /** 102 * MembershipKey will additional context for IPv6 membership 103 */ 104 static class Type6 extends MembershipKeyImpl { 105 private final byte[] groupAddress; 106 private final int index; 107 private final byte[] sourceAddress; 108 Type6(MulticastChannel ch, InetAddress group, NetworkInterface interf, InetAddress source, byte[] groupAddress, int index, byte[] sourceAddress)109 Type6(MulticastChannel ch, 110 InetAddress group, 111 NetworkInterface interf, 112 InetAddress source, 113 byte[] groupAddress, 114 int index, 115 byte[] sourceAddress) 116 { 117 super(ch, group, interf, source); 118 this.groupAddress = groupAddress; 119 this.index = index; 120 this.sourceAddress = sourceAddress; 121 } 122 groupAddress()123 byte[] groupAddress() { 124 return groupAddress; 125 } 126 index()127 int index() { 128 return index; 129 } 130 source()131 byte[] source() { 132 return sourceAddress; 133 } 134 } 135 isValid()136 public boolean isValid() { 137 return valid; 138 } 139 140 // package-private invalidate()141 void invalidate() { 142 valid = false; 143 } 144 drop()145 public void drop() { 146 // delegate to channel 147 ((DatagramChannelImpl)ch).drop(this); 148 } 149 150 @Override channel()151 public MulticastChannel channel() { 152 return ch; 153 } 154 155 @Override group()156 public InetAddress group() { 157 return group; 158 } 159 160 @Override networkInterface()161 public NetworkInterface networkInterface() { 162 return interf; 163 } 164 165 @Override sourceAddress()166 public InetAddress sourceAddress() { 167 return source; 168 } 169 170 @Override block(InetAddress toBlock)171 public MembershipKey block(InetAddress toBlock) 172 throws IOException 173 { 174 if (source != null) 175 throw new IllegalStateException("key is source-specific"); 176 177 synchronized (stateLock) { 178 if ((blockedSet != null) && blockedSet.contains(toBlock)) { 179 // already blocked, nothing to do 180 return this; 181 } 182 183 ((DatagramChannelImpl)ch).block(this, toBlock); 184 185 // created blocked set if required and add source address 186 if (blockedSet == null) 187 blockedSet = new HashSet<InetAddress>(); 188 blockedSet.add(toBlock); 189 } 190 return this; 191 } 192 193 @Override unblock(InetAddress toUnblock)194 public MembershipKey unblock(InetAddress toUnblock) { 195 synchronized (stateLock) { 196 if ((blockedSet == null) || !blockedSet.contains(toUnblock)) 197 throw new IllegalStateException("not blocked"); 198 199 ((DatagramChannelImpl)ch).unblock(this, toUnblock); 200 201 blockedSet.remove(toUnblock); 202 } 203 return this; 204 } 205 206 @Override toString()207 public String toString() { 208 StringBuilder sb = new StringBuilder(64); 209 sb.append('<'); 210 sb.append(group.getHostAddress()); 211 sb.append(','); 212 sb.append(interf.getName()); 213 if (source != null) { 214 sb.append(','); 215 sb.append(source.getHostAddress()); 216 } 217 sb.append('>'); 218 return sb.toString(); 219 } 220 } 221