1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2001 by Sun Microsystems, Inc. 23 * All rights reserved. 24 * 25 */ 26 27 // Listener.java: Organize basic listening for slpd and specifically 28 // support datagram listening. 29 // Author: James Kempf 30 // Created On: Mon May 18 12:43:50 1998 31 // Last Modified By: James Kempf 32 // Last Modified On: Thu Jan 7 08:39:19 1999 33 // Update Count: 54 34 // 35 36 package com.sun.slp; 37 38 import java.util.*; 39 import java.net.*; 40 import java.io.*; 41 42 /** 43 * This class supplies the basic listening function for the DA 44 * and SA. On creation, a StreamListener is created to listen for 45 * clients that need to initiate unicast connections. The main object 46 * listens on the SLP multicast address for SLP multicasts, and 47 * passes the results off to the RequestHandler for direction to 48 * the proper table. The RequestHandler object is executed in a different 49 * thread to maximize throughput. Note that unicast datagram requests 50 * may also enter through this class, since many systems don't distinguish 51 * between the multicast and datagram queues for a port. 52 * 53 * @author James Kempf, Erik Guttman 54 */ 55 56 class Listener extends Thread { 57 58 private DatagramSocket dss = null; // SLP multicast/broadcast socket. 59 private InetAddress interfac = null; // Interface on which we listen. 60 private int pktsize = 0; // MTU of network packet. 61 private Vector groups = new Vector(); // Multicast groups monitored. 62 63 static private SLPConfig config = null; // Config object for properties 64 static private Hashtable listeners = 65 new Hashtable(); // Listeners keyed by interface. 66 67 // Initialize the complex of listener/sender objects on the interface. 68 // This includes a datagram listener, a DAAdvertiser (which shares 69 // the same socket as the datagram listener) if a DA, and a 70 // stream listener. 71 72 static void initializeInterfaceManagers(InetAddress interfac) 73 throws ServiceLocationException { 74 75 // If we've done the intializtion, forget it. 76 77 if (listeners.get(interfac) != null) { 78 return; 79 80 } 81 82 // Get config object. 83 84 if (config == null) { 85 config = SLPConfig.getSLPConfig(); 86 87 } 88 89 // Create a listener object for this interface. 90 91 Listener listener = new Listener(interfac); 92 93 // Start thread to listen for incoming datagram request. 94 95 listener.start(); 96 97 // Create a stream listener object for this interface. 98 99 StreamListener.initializeStreamListenerOnInterface(interfac); 100 101 // We wait until this point to advertise ourselves as DAs. At 102 // this point, we have the listeners up to handle any messages 103 // that might come in as a result. 104 105 } 106 107 // Return the socket for the listener on the designated interface. 108 // DAAdvertisers and the SLPv1 codes uses this to share the 109 // same socket as the main datagram listener. 110 111 static DatagramSocket returnListenerSocketOnInterface( 112 InetAddress interfac) { 113 114 Listener listener = (Listener)listeners.get(interfac); 115 116 if (listener != null) { 117 return listener.dss; 118 } 119 120 return null; 121 } 122 123 // Add the listener on the interface to the multicast group. 124 125 static void 126 addListenerToMulticastGroup(InetAddress interfac, InetAddress maddr) 127 throws ServiceLocationException { 128 129 Listener listener = (Listener)listeners.get(interfac); 130 131 // Ignore if we haven't got it. 132 133 if (listener == null) { 134 return; 135 136 } 137 138 DatagramSocket dss = listener.dss; 139 140 // Only add if we're multicast. 141 142 if (dss instanceof MulticastSocket) { 143 MulticastSocket mss = (MulticastSocket)dss; 144 145 try { 146 mss.joinGroup(maddr); 147 148 // Record the groups monitored. 149 150 listener.groups.addElement(maddr); 151 152 } catch (IOException ex) { 153 new ServiceLocationException( 154 ServiceLocationException.NETWORK_INIT_FAILED, 155 "socket_initializtion_failure", 156 new Object[] {maddr, ex.getMessage()}); 157 158 } 159 } 160 } 161 162 // Refresh the listener socket on the interface. If there is no 163 // listener, then simply return a new send socket. 164 165 static DatagramSocket 166 refreshSocketOnInterface(InetAddress interfac) { 167 168 Listener listener = (Listener)listeners.get(interfac); 169 170 if (listener == null) { 171 return config.refreshMulticastSocketOnInterface(interfac, null); 172 173 } 174 175 listener.dss.close(); 176 177 listener.dss = 178 config.refreshMulticastSocketOnInterface(interfac, 179 listener.groups); 180 181 return listener.dss; 182 183 } 184 185 // Create a Listener for the interface. 186 187 private Listener(InetAddress interfac) throws ServiceLocationException { 188 189 // Get packet size. 190 191 this.pktsize = config.getMTU(); 192 193 this.interfac = interfac; 194 195 // Get a socket for this interface. 196 197 this.dss = config.getMulticastSocketOnInterface(interfac, false); 198 199 // Record here so we can use standard utility to add to multicast 200 // group. 201 202 listeners.put(interfac, this); 203 204 // If we're multicasting, add to the default SLP group. 205 206 addListenerToMulticastGroup(interfac, config.getMulticastAddress()); 207 208 } 209 210 // Listen on multicast for incoming requests, spawn a RequestHandler 211 // to process the datagram. 212 213 public void run() { 214 215 boolean retry = true; 216 String castName = "Multicast"; 217 218 if (config.isBroadcastOnly()) { 219 castName = "Broadcast"; 220 221 } 222 223 setName("SLP "+castName+" Datagram Listener:"+ 224 dss.getLocalAddress()+"/"+ 225 dss.getLocalPort()); 226 227 // Loop forever, receiving datagrams and spawning a request handler 228 // to handle it. 229 230 while (true) { 231 byte[] inbuf = new byte[pktsize]; 232 DatagramPacket incoming = new DatagramPacket(inbuf, pktsize); 233 234 // Block on datagram receive. 235 236 try { 237 dss.receive(incoming); 238 239 if (config.traceMsg()) { 240 config.writeLog("request_in", 241 new Object[] {incoming.getAddress(), 242 interfac}); 243 } 244 245 RequestHandler rh = 246 new RequestHandler(incoming, interfac, config); 247 rh.start(); 248 249 } catch (IOException ex) { 250 251 // Die if we can't retry. 252 253 Assert.slpassert(retry, 254 "datagram_io_error", 255 new Object[] {dss.getLocalAddress(), 256 ex.getMessage()}); 257 258 retry = false; 259 260 config.writeLog("datagram_io_error", 261 new Object[] {dss.getLocalAddress(), 262 ex.getMessage()}); 263 264 // Close cast socket, get a new one and try again. 265 266 dss.close(); 267 dss = config.refreshMulticastSocketOnInterface(interfac, 268 groups); 269 270 } 271 } 272 } 273 } 274