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 
MembershipRegistry()44     MembershipRegistry() {
45     }
46 
47     /**
48      * Checks registry for membership of the group on the given
49      * network interface.
50      */
checkMembership(InetAddress group, NetworkInterface interf, InetAddress source)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      */
add(MembershipKeyImpl key)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      */
remove(MembershipKeyImpl key)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      */
invalidateAll()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 }
132