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