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.util.*;
  32 
  33 /**
  34  * Simple registry of membership keys for a MulticastChannel.
  35  *
  36  * Instances of this object are not safe by multiple concurrent threads.
  37  */
  38 
  39 class MembershipRegistry {
  40 
  41     // map multicast group to keys
  42     private Map<InetAddress,List<MembershipKeyImpl>> groups = null;
  43 
  44     MembershipRegistry() {
  45     }
  46 
  47     /**
  48      * Checks registry for membership of the group on the given
  49      * network interface.
  50      */
  51     MembershipKey checkMembership(InetAddress group, NetworkInterface interf,
  52                                   InetAddress source)
  53     {
  54         if (groups != null) {
  55             List<MembershipKeyImpl> keys = groups.get(group);
  56             if (keys != null) {
  57                 for (MembershipKeyImpl key: keys) {
  58                     if (key.networkInterface().equals(interf)) {
  59                         // already a member to receive all packets so return
  60                         // existing key or detect conflict
  61                         if (source == null) {
  62                             if (key.sourceAddress() == null)
  63                                 return key;
  64                             throw new IllegalStateException("Already a member to receive all packets");
  65                         }
  66 
  67                         // already have source-specific membership so return key
  68                         // or detect conflict
  69                         if (key.sourceAddress() == null)
  70                             throw new IllegalStateException("Already have source-specific membership");
  71                         if (source.equals(key.sourceAddress()))
  72                             return key;
  73                     }
  74                 }
  75             }
  76         }
  77         return null;
  78     }
  79 
  80     /**
  81      * Add membership to the registry, returning a new membership key.
  82      */
  83     void add(MembershipKeyImpl key) {
  84         InetAddress group = key.group();
  85         List<MembershipKeyImpl> keys;
  86         if (groups == null) {
  87             groups = new HashMap<InetAddress,List<MembershipKeyImpl>>();
  88             keys = null;
  89         } else {
  90             keys = groups.get(group);
  91         }
  92         if (keys == null) {
  93             keys = new LinkedList<MembershipKeyImpl>();
  94             groups.put(group, keys);
  95         }
  96         keys.add(key);
  97     }
  98 
  99     /**
 100      * Remove a key from the registry
 101      */
 102     void remove(MembershipKeyImpl key) {
 103         InetAddress group = key.group();
 104         List<MembershipKeyImpl> keys = groups.get(group);
 105         if (keys != null) {
 106             Iterator<MembershipKeyImpl> i = keys.iterator();
 107             while (i.hasNext()) {
 108                 if (i.next() == key) {
 109                     i.remove();
 110                     break;
 111                 }
 112             }
 113             if (keys.isEmpty()) {
 114                 groups.remove(group);
 115             }
 116         }
 117     }
 118 
 119     /**
 120      * Invalidate all keys in the registry
 121      */
 122     void invalidateAll() {
 123         if (groups != null) {
 124             for (InetAddress group: groups.keySet()) {
 125                 for (MembershipKeyImpl key: groups.get(group)) {
 126                     key.invalidate();
 127                 }
 128             }
 129         }
 130     }
 131 }