001: /* ----- BEGIN LICENSE BLOCK -----
002: * Version: MPL 1.1
003: *
004: * The contents of this file are subject to the Mozilla Public License Version
005: * 1.1 (the "License"); you may not use this file except in compliance with
006: * the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS" basis,
010: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: * for the specific language governing rights and limitations under the
012: * License.
013: *
014: * The Original Code is the DataShare server.
015: *
016: * The Initial Developer of the Original Code is
017: * Ball Aerospace & Technologies Corp, Fairborn, Ohio
018: * Portions created by the Initial Developer are Copyright (C) 2001
019: * the Initial Developer. All Rights Reserved.
020: *
021: * Contributor(s): Charles Wood <cwood@ball.com>
022: *
023: * ----- END LICENSE BLOCK ----- */
024: /* RCS $Id: MulticastSocketServer.java,v 1.3 2002/02/04 13:51:40 lizellaman Exp $
025: * $Log: MulticastSocketServer.java,v $
026: * Revision 1.3 2002/02/04 13:51:40 lizellaman
027: * Remove all references to past product names (or)
028: * Add PublicAPI for creating Rendezvous Sessions
029: *
030: * Revision 1.2 2002/01/29 20:50:17 lizellaman
031: * Added LoggingInterface, modified the PropertiesInterface implementation
032: *
033: * Revision 1.1.1.1 2001/10/23 13:37:19 lizellaman
034: * initial sourceforge release
035: *
036: */
037:
038: package org.datashare;
039:
040: import java.net.DatagramPacket;
041: import java.net.MulticastSocket;
042: import java.net.SocketException;
043: import java.util.Hashtable;
044: import java.util.Enumeration;
045: import java.net.InetAddress;
046: import java.io.IOException;
047:
048: /**
049: * We need one of these for each Multicast connection that clients might use
050: * @date March 01, 2001
051: * @author Charles Wood
052: * @version 1.0
053: */
054: public class MulticastSocketServer extends Thread implements
055: SocketServerInterface {
056: DataReceiverInterface dri = null;
057: MulticastSocket socket = null;
058: DatagramPacket sndPacket = null;
059: DatagramPacket rcvPacket = null;
060: boolean running = true;
061: Hashtable connections = new Hashtable();
062: InetAddress myIpAddress; // the multicast IP address
063: String keyValue;
064: boolean active = false;
065: int priority;
066: int port; // normally the server port, it is the Multicast port for this channel here
067:
068: public MulticastSocketServer(InetAddress myIpAddress,
069: DataReceiverInterface dri, int port, int priority) {
070: SessionUtilities.getLoggingInterface().debugMsg(
071: SessionUtilities.getLoggingInterface().DEBUG,
072: SessionUtilities.getLoggingInterface().NETWORK,
073: "MulticastSocketServer for IP:port " + myIpAddress
074: + ":" + port);
075: this .dri = dri;
076: this .port = port;
077: this .priority = priority;
078: this .myIpAddress = myIpAddress;
079: keyValue = "MULTICAST:" + port;
080: this .setName("DataShare.SocketServer." + keyValue);
081: createSocket(true);
082: if (SessionUtilities.getVerbose()) {
083: try {
084: SessionUtilities.getLoggingInterface().debugMsg(
085: SessionUtilities.getLoggingInterface().DEBUG,
086: SessionUtilities.getLoggingInterface().NETWORK,
087: "Multicast socket max receive size is "
088: + socket.getReceiveBufferSize() + "\n"
089: + "Multicast socket max send size is "
090: + socket.getSendBufferSize());
091: } catch (Exception e) {
092: }
093: }
094: }
095:
096: /**
097: * actually creates the socket
098: */
099: private void createSocket(boolean firsttime) {
100: SessionUtilities.getLoggingInterface().debugMsg(
101: SessionUtilities.getLoggingInterface().DEBUG,
102: SessionUtilities.getLoggingInterface().NETWORK,
103: (firsttime ? "Creating" : "Re-creating")
104: + this .getName());
105: try {
106: socket = new MulticastSocket(port); // set local port to same as server port
107: socket.joinGroup(myIpAddress);
108: socket.setReceiveBufferSize(99999);
109: socket.setSendBufferSize(99999);
110: } catch (Exception e) {
111: e.printStackTrace();
112: }
113: }
114:
115: /**
116: * returns true if ready to receive connections
117: */
118: public boolean getReady() {
119: return active;
120: }
121:
122: /**
123: * return our local port
124: */
125: public int getLocalPort() {
126: return port;
127: }
128:
129: /**
130: * returns our keyValue
131: */
132: public String getKeyValue() {
133: return this .keyValue;
134: }
135:
136: /**
137: * this method is where we receive data and establish new 'connections'
138: */
139: public void run() {
140: String udpKey = "";
141: SessionUtilities.getLoggingInterface()
142: .debugMsg(
143: SessionUtilities.getLoggingInterface().DEBUG,
144: SessionUtilities.getLoggingInterface().NETWORK,
145: "Setting " + this .keyValue + " to priority "
146: + priority);
147: setPriority(priority);
148: while (running) {
149: try {
150: DatagramPacket packet = new DatagramPacket(
151: new byte[10001], 10001);
152: active = true;
153: udpKey = "";
154: socket.receive(packet); // blocks until client connects
155: // create unique (to this class) key for 'connection'
156: // note that packet getAddress() for a received Multicast packet is the real IP address?! (not Multicast IP address)
157: udpKey = packet.getAddress().getHostAddress() + ":"
158: + packet.getPort();
159: SessionUtilities.getLoggingInterface().debugMsg(
160: SessionUtilities.getLoggingInterface().DEBUG,
161: SessionUtilities.getLoggingInterface().NETWORK,
162: "Recvd Multicast length " + packet.getLength()
163: + " from " + udpKey);
164: // do not need to forward packets for Multicast
165: if (connections.containsKey(udpKey)) {
166: MultiCastSocket handler = (MultiCastSocket) connections
167: .get(udpKey);
168: handler.newData(packet);
169: } else {
170: // new client!
171: MultiCastSocket newHandler = new MultiCastSocket(
172: this , socket, packet, dri, myIpAddress);
173: connections.put(udpKey, newHandler);
174: dri.newConnection(newHandler); // now our new socket is known to the DataReceiverAdapter
175: newHandler.newData(packet); // now send this data to handler
176: }
177: Thread.currentThread().yield();
178: } // end of try
179: catch (IOException ioe) {
180: if (running) // ignore any errors if we have decided to shutdown
181: {
182: boolean found = false;
183: SessionUtilities
184: .getLoggingInterface()
185: .debugMsg(
186: SessionUtilities
187: .getLoggingInterface().WARNING,
188: SessionUtilities
189: .getLoggingInterface().NETWORK,
190: "Problems ("
191: + ioe
192: + ") receiving data over Multicast socket "
193: + udpKey);
194: if (!udpKey.equals("")) // try to shutdown just the connection that had problems...
195: {
196: if (connections.containsKey(udpKey)) {
197: found = true;
198: MulticastSocket handler = (MulticastSocket) connections
199: .get(udpKey);
200: handler.close();
201: }
202: }
203: if (!found) {
204: SessionUtilities
205: .getLoggingInterface()
206: .debugMsg(
207: SessionUtilities
208: .getLoggingInterface().WARNING,
209: SessionUtilities
210: .getLoggingInterface().NETWORK,
211: "MulticastSocketServer Problem that was not traced to a known socket:");
212: ioe.printStackTrace();
213: //close();
214: }
215: }
216: } catch (Exception e) {
217: e.printStackTrace();
218: close();
219: }
220: } // end of the while loop
221: SessionUtilities.getLoggingInterface().debugMsg(
222: SessionUtilities.getLoggingInterface().DEBUG,
223: SessionUtilities.getLoggingInterface().NETWORK,
224: "Thread " + getName() + " has stopped (scheduled)");
225: }
226:
227: /**
228: * close the socket server, stops any thread, and notifies the listener
229: */
230: public void close()
231: {
232: SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
233: SessionUtilities.getLoggingInterface().NETWORK,
234: "removing socket server " + keyValue);
235: try{
236: running = false;
237: socket.leaveGroup(myIpAddress);
238: socket.close();
239: dri.lostServerSocket(keyValue);
240: // close all the spawned sockets
241: for(Enumeration enum = connections.elements(); enum.hasMoreElements();)
242: {
243: MultiCastSocket mcs = (MultiCastSocket)enum.nextElement();
244: mcs.close();
245: }
246: }
247: catch(Exception e)
248: {
249: e.printStackTrace();
250: }
251: }
252:
253: /**
254: * called by socket when it closes itself
255: */
256: public void closeSocket(MultiCastSocket socket) {
257: String udpKey = socket.getRemoteIP().getHostAddress() + ":"
258: + socket.getLocalPort();
259: SessionUtilities.getLoggingInterface().debugMsg(
260: SessionUtilities.getLoggingInterface().DEBUG,
261: SessionUtilities.getLoggingInterface().NETWORK,
262: "removing/closing socket " + socket.getKeyValue());
263: connections.remove(udpKey);
264: }
265:
266: }
|