524N/A/*
2362N/A * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
524N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
524N/A *
524N/A * This code is free software; you can redistribute it and/or modify it
524N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
524N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
524N/A *
524N/A * This code is distributed in the hope that it will be useful, but WITHOUT
524N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
524N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
524N/A * version 2 for more details (a copy is included in the LICENSE file that
524N/A * accompanied this code).
524N/A *
524N/A * You should have received a copy of the GNU General Public License version
524N/A * 2 along with this work; if not, write to the Free Software Foundation,
524N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
524N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
524N/A */
524N/A
524N/Apackage sun.nio.ch;
524N/A
524N/Aimport java.nio.channels.*;
524N/Aimport java.net.InetAddress;
524N/Aimport java.net.NetworkInterface;
524N/Aimport java.io.IOException;
524N/Aimport java.util.HashSet;
524N/A
524N/A/**
524N/A * MembershipKey implementation.
524N/A */
524N/A
524N/Aclass MembershipKeyImpl
524N/A extends MembershipKey
524N/A{
524N/A private final MulticastChannel ch;
524N/A private final InetAddress group;
524N/A private final NetworkInterface interf;
524N/A private final InetAddress source;
524N/A
524N/A // true when key is valid
524N/A private volatile boolean valid = true;
524N/A
524N/A // lock used when creating or accessing blockedSet
524N/A private Object stateLock = new Object();
524N/A
524N/A // set of source addresses that are blocked
524N/A private HashSet<InetAddress> blockedSet;
524N/A
524N/A private MembershipKeyImpl(MulticastChannel ch,
524N/A InetAddress group,
524N/A NetworkInterface interf,
524N/A InetAddress source)
524N/A {
524N/A this.ch = ch;
524N/A this.group = group;
524N/A this.interf = interf;
524N/A this.source = source;
524N/A }
524N/A
524N/A /**
524N/A * MembershipKey will additional context for IPv4 membership
524N/A */
524N/A static class Type4 extends MembershipKeyImpl {
524N/A private final int groupAddress;
524N/A private final int interfAddress;
524N/A private final int sourceAddress;
524N/A
524N/A Type4(MulticastChannel ch,
524N/A InetAddress group,
524N/A NetworkInterface interf,
524N/A InetAddress source,
524N/A int groupAddress,
524N/A int interfAddress,
524N/A int sourceAddress)
524N/A {
524N/A super(ch, group, interf, source);
524N/A this.groupAddress = groupAddress;
524N/A this.interfAddress = interfAddress;
524N/A this.sourceAddress = sourceAddress;
524N/A }
524N/A
893N/A int groupAddress() {
524N/A return groupAddress;
524N/A }
524N/A
524N/A int interfaceAddress() {
524N/A return interfAddress;
524N/A }
524N/A
524N/A int source() {
524N/A return sourceAddress;
524N/A }
524N/A }
524N/A
524N/A /**
524N/A * MembershipKey will additional context for IPv6 membership
524N/A */
524N/A static class Type6 extends MembershipKeyImpl {
524N/A private final byte[] groupAddress;
524N/A private final int index;
524N/A private final byte[] sourceAddress;
524N/A
524N/A Type6(MulticastChannel ch,
524N/A InetAddress group,
524N/A NetworkInterface interf,
524N/A InetAddress source,
524N/A byte[] groupAddress,
524N/A int index,
524N/A byte[] sourceAddress)
524N/A {
524N/A super(ch, group, interf, source);
524N/A this.groupAddress = groupAddress;
524N/A this.index = index;
524N/A this.sourceAddress = sourceAddress;
524N/A }
524N/A
893N/A byte[] groupAddress() {
524N/A return groupAddress;
524N/A }
524N/A
524N/A int index() {
524N/A return index;
524N/A }
524N/A
524N/A byte[] source() {
524N/A return sourceAddress;
524N/A }
524N/A }
524N/A
524N/A public boolean isValid() {
524N/A return valid;
524N/A }
524N/A
524N/A // package-private
524N/A void invalidate() {
524N/A valid = false;
524N/A }
524N/A
893N/A public void drop() {
524N/A // delegate to channel
524N/A ((DatagramChannelImpl)ch).drop(this);
524N/A }
524N/A
524N/A @Override
893N/A public MulticastChannel channel() {
524N/A return ch;
524N/A }
524N/A
524N/A @Override
893N/A public InetAddress group() {
524N/A return group;
524N/A }
524N/A
524N/A @Override
893N/A public NetworkInterface networkInterface() {
524N/A return interf;
524N/A }
524N/A
524N/A @Override
893N/A public InetAddress sourceAddress() {
524N/A return source;
524N/A }
524N/A
524N/A @Override
524N/A public MembershipKey block(InetAddress toBlock)
524N/A throws IOException
524N/A {
524N/A if (source != null)
524N/A throw new IllegalStateException("key is source-specific");
524N/A
524N/A synchronized (stateLock) {
524N/A if ((blockedSet != null) && blockedSet.contains(toBlock)) {
524N/A // already blocked, nothing to do
524N/A return this;
524N/A }
524N/A
524N/A ((DatagramChannelImpl)ch).block(this, toBlock);
524N/A
524N/A // created blocked set if required and add source address
524N/A if (blockedSet == null)
524N/A blockedSet = new HashSet<InetAddress>();
524N/A blockedSet.add(toBlock);
524N/A }
524N/A return this;
524N/A }
524N/A
524N/A @Override
893N/A public MembershipKey unblock(InetAddress toUnblock) {
524N/A synchronized (stateLock) {
524N/A if ((blockedSet == null) || !blockedSet.contains(toUnblock))
524N/A throw new IllegalStateException("not blocked");
524N/A
524N/A ((DatagramChannelImpl)ch).unblock(this, toUnblock);
524N/A
524N/A blockedSet.remove(toUnblock);
524N/A }
524N/A return this;
524N/A }
524N/A
524N/A @Override
524N/A public String toString() {
524N/A StringBuilder sb = new StringBuilder(64);
524N/A sb.append('<');
524N/A sb.append(group.getHostAddress());
524N/A sb.append(',');
524N/A sb.append(interf.getName());
524N/A if (source != null) {
524N/A sb.append(',');
524N/A sb.append(source.getHostAddress());
524N/A }
524N/A sb.append('>');
524N/A return sb.toString();
524N/A }
524N/A}