MembershipRegistry.java revision 49965c1dc9da104344f4893a05e45795a5740d20
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
26package sun.nio.ch;
27
28import java.nio.channels.*;
29import java.net.InetAddress;
30import java.net.NetworkInterface;
31import 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
39class 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}
132