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