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