2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2001 by Sun Microsystems, Inc.
2N/A * All rights reserved.
2N/A *
2N/A */
2N/A
2N/A// Listener.java: Organize basic listening for slpd and specifically
2N/A// support datagram listening.
2N/A// Author: James Kempf
2N/A// Created On: Mon May 18 12:43:50 1998
2N/A// Last Modified By: James Kempf
2N/A// Last Modified On: Thu Jan 7 08:39:19 1999
2N/A// Update Count: 54
2N/A//
2N/A
2N/Apackage com.sun.slp;
2N/A
2N/Aimport java.util.*;
2N/Aimport java.net.*;
2N/Aimport java.io.*;
2N/A
2N/A/**
2N/A * This class supplies the basic listening function for the DA
2N/A * and SA. On creation, a StreamListener is created to listen for
2N/A * clients that need to initiate unicast connections. The main object
2N/A * listens on the SLP multicast address for SLP multicasts, and
2N/A * passes the results off to the RequestHandler for direction to
2N/A * the proper table. The RequestHandler object is executed in a different
2N/A * thread to maximize throughput. Note that unicast datagram requests
2N/A * may also enter through this class, since many systems don't distinguish
2N/A * between the multicast and datagram queues for a port.
2N/A *
2N/A * @author James Kempf, Erik Guttman
2N/A */
2N/A
2N/Aclass Listener extends Thread {
2N/A
2N/A private DatagramSocket dss = null; // SLP multicast/broadcast socket.
2N/A private InetAddress interfac = null; // Interface on which we listen.
2N/A private int pktsize = 0; // MTU of network packet.
2N/A private Vector groups = new Vector(); // Multicast groups monitored.
2N/A
2N/A static private SLPConfig config = null; // Config object for properties
2N/A static private Hashtable listeners =
2N/A new Hashtable(); // Listeners keyed by interface.
2N/A
2N/A // Initialize the complex of listener/sender objects on the interface.
2N/A // This includes a datagram listener, a DAAdvertiser (which shares
2N/A // the same socket as the datagram listener) if a DA, and a
2N/A // stream listener.
2N/A
2N/A static void initializeInterfaceManagers(InetAddress interfac)
2N/A throws ServiceLocationException {
2N/A
2N/A // If we've done the intializtion, forget it.
2N/A
2N/A if (listeners.get(interfac) != null) {
2N/A return;
2N/A
2N/A }
2N/A
2N/A // Get config object.
2N/A
2N/A if (config == null) {
2N/A config = SLPConfig.getSLPConfig();
2N/A
2N/A }
2N/A
2N/A // Create a listener object for this interface.
2N/A
2N/A Listener listener = new Listener(interfac);
2N/A
2N/A // Start thread to listen for incoming datagram request.
2N/A
2N/A listener.start();
2N/A
2N/A // Create a stream listener object for this interface.
2N/A
2N/A StreamListener.initializeStreamListenerOnInterface(interfac);
2N/A
2N/A // We wait until this point to advertise ourselves as DAs. At
2N/A // this point, we have the listeners up to handle any messages
2N/A // that might come in as a result.
2N/A
2N/A }
2N/A
2N/A // Return the socket for the listener on the designated interface.
2N/A // DAAdvertisers and the SLPv1 codes uses this to share the
2N/A // same socket as the main datagram listener.
2N/A
2N/A static DatagramSocket returnListenerSocketOnInterface(
2N/A InetAddress interfac) {
2N/A
2N/A Listener listener = (Listener)listeners.get(interfac);
2N/A
2N/A if (listener != null) {
2N/A return listener.dss;
2N/A }
2N/A
2N/A return null;
2N/A }
2N/A
2N/A // Add the listener on the interface to the multicast group.
2N/A
2N/A static void
2N/A addListenerToMulticastGroup(InetAddress interfac, InetAddress maddr)
2N/A throws ServiceLocationException {
2N/A
2N/A Listener listener = (Listener)listeners.get(interfac);
2N/A
2N/A // Ignore if we haven't got it.
2N/A
2N/A if (listener == null) {
2N/A return;
2N/A
2N/A }
2N/A
2N/A DatagramSocket dss = listener.dss;
2N/A
2N/A // Only add if we're multicast.
2N/A
2N/A if (dss instanceof MulticastSocket) {
2N/A MulticastSocket mss = (MulticastSocket)dss;
2N/A
2N/A try {
2N/A mss.joinGroup(maddr);
2N/A
2N/A // Record the groups monitored.
2N/A
2N/A listener.groups.addElement(maddr);
2N/A
2N/A } catch (IOException ex) {
2N/A new ServiceLocationException(
2N/A ServiceLocationException.NETWORK_INIT_FAILED,
2N/A "socket_initializtion_failure",
2N/A new Object[] {maddr, ex.getMessage()});
2N/A
2N/A }
2N/A }
2N/A }
2N/A
2N/A // Refresh the listener socket on the interface. If there is no
2N/A // listener, then simply return a new send socket.
2N/A
2N/A static DatagramSocket
2N/A refreshSocketOnInterface(InetAddress interfac) {
2N/A
2N/A Listener listener = (Listener)listeners.get(interfac);
2N/A
2N/A if (listener == null) {
2N/A return config.refreshMulticastSocketOnInterface(interfac, null);
2N/A
2N/A }
2N/A
2N/A listener.dss.close();
2N/A
2N/A listener.dss =
2N/A config.refreshMulticastSocketOnInterface(interfac,
2N/A listener.groups);
2N/A
2N/A return listener.dss;
2N/A
2N/A }
2N/A
2N/A // Create a Listener for the interface.
2N/A
2N/A private Listener(InetAddress interfac) throws ServiceLocationException {
2N/A
2N/A // Get packet size.
2N/A
2N/A this.pktsize = config.getMTU();
2N/A
2N/A this.interfac = interfac;
2N/A
2N/A // Get a socket for this interface.
2N/A
2N/A this.dss = config.getMulticastSocketOnInterface(interfac, false);
2N/A
2N/A // Record here so we can use standard utility to add to multicast
2N/A // group.
2N/A
2N/A listeners.put(interfac, this);
2N/A
2N/A // If we're multicasting, add to the default SLP group.
2N/A
2N/A addListenerToMulticastGroup(interfac, config.getMulticastAddress());
2N/A
2N/A }
2N/A
2N/A // Listen on multicast for incoming requests, spawn a RequestHandler
2N/A // to process the datagram.
2N/A
2N/A public void run() {
2N/A
2N/A boolean retry = true;
2N/A String castName = "Multicast";
2N/A
2N/A if (config.isBroadcastOnly()) {
2N/A castName = "Broadcast";
2N/A
2N/A }
2N/A
2N/A setName("SLP "+castName+" Datagram Listener:"+
2N/A dss.getLocalAddress()+"/"+
2N/A dss.getLocalPort());
2N/A
2N/A // Loop forever, receiving datagrams and spawning a request handler
2N/A // to handle it.
2N/A
2N/A while (true) {
2N/A byte[] inbuf = new byte[pktsize];
2N/A DatagramPacket incoming = new DatagramPacket(inbuf, pktsize);
2N/A
2N/A // Block on datagram receive.
2N/A
2N/A try {
2N/A dss.receive(incoming);
2N/A
2N/A if (config.traceMsg()) {
2N/A config.writeLog("request_in",
2N/A new Object[] {incoming.getAddress(),
2N/A interfac});
2N/A }
2N/A
2N/A RequestHandler rh =
2N/A new RequestHandler(incoming, interfac, config);
2N/A rh.start();
2N/A
2N/A } catch (IOException ex) {
2N/A
2N/A // Die if we can't retry.
2N/A
2N/A Assert.slpassert(retry,
2N/A "datagram_io_error",
2N/A new Object[] {dss.getLocalAddress(),
2N/A ex.getMessage()});
2N/A
2N/A retry = false;
2N/A
2N/A config.writeLog("datagram_io_error",
2N/A new Object[] {dss.getLocalAddress(),
2N/A ex.getMessage()});
2N/A
2N/A // Close cast socket, get a new one and try again.
2N/A
2N/A dss.close();
2N/A dss = config.refreshMulticastSocketOnInterface(interfac,
2N/A groups);
2N/A
2N/A }
2N/A }
2N/A }
2N/A}