Add Registration functionality and tidy up
[WeStealzYourDataz.git] / src / uk / ac / ntu / n0521366 / wsyd / libs / net / NetworkServerUDPMulticast.java
1 /*
2  * The MIT License
3  *
4  * Copyright 2015 Eddie Berrisford-Lynch <dev@fun2be.me>.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 package uk.ac.ntu.n0521366.wsyd.libs.net;
25
26 import java.io.IOException;
27 import java.net.MulticastSocket;
28 import java.net.SocketException;
29 import java.net.NetworkInterface;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32 import java.util.ArrayList;
33 import java.util.Enumeration;
34
35 /**
36  *
37  * @author Eddie Berrisford-Lynch <dev@fun2be.me>
38  */
39 public class NetworkServerUDPMulticast extends NetworkServerUDP {
40     
41     /**
42      * the Multicast socket.
43      * 
44      * Deliberately hides the DatagramSocket in NetworkServerUDP so that inherited methods
45      * can access the same name.
46      */
47     private MulticastSocket _multicastSocket = null;
48     /**
49      * Construct the server with a Logger.
50      * 
51      * No socket is opened.
52      * 
53      * @param socketAddress The socket to listen on
54      * @param title source identifier for use in log messages and sent NetworkMessage objects
55      * @param serviceToHostMap the map object used for host <> InetSocketAddress lookups
56      * @param logger An instance of Logger to be used by all objects of this class
57      */
58     public NetworkServerUDPMulticast(WSYD_SocketAddress socketAddress, String title, ServiceAddressMap serviceToHostMap, Logger logger) {
59         super(socketAddress, title, serviceToHostMap, logger);
60     }
61
62     /**
63      * Construct the server without a Logger.
64      * 
65      * No socket is opened.
66      * 
67      * @param socketAddress The socket to listen on
68      * @param title source identifier for use in log messages and sent NetworkMessage objects
69      * @param serviceToHostMap the map object used for host <> InetSocketAddress lookups
70      */
71     public NetworkServerUDPMulticast(WSYD_SocketAddress socketAddress, String title, ServiceAddressMap serviceToHostMap) {
72         super(socketAddress, title, serviceToHostMap);
73     }
74
75     /**
76      * Get the MulticastSocket object for this service.
77      * 
78      * @return the base-class DatagramSocket type
79      */
80     @Override
81     public java.net.DatagramSocket getSocket() {
82         return this._multicastSocket;
83     }
84     /**
85      * Join the multicast group on all interfaces ready for accepting packets.
86      * 
87      * It should also set a reasonable socket timeout with a call to setSoTimeout()
88      * to prevent unnecessary blocking.
89      * 
90      * @throws SocketException 
91      */
92     @Override
93     public  void serverOpen() throws SocketException {
94         try {
95             ArrayList<String> messages = new ArrayList<>();
96
97             this._multicastSocket = new MulticastSocket(_socketAddress.getPort());
98             this._multicastSocket.setTimeToLive(2); // don't traverse more than 2 routers
99             this._multicastSocket.setSoTimeout(100); // 1/10th second blocking timeout on receive()
100             this._multicastSocket.setLoopbackMode(false); // inverted logic; true == disable. Don't want to receive our own sent packets
101             
102             Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces();
103             while (ifs.hasMoreElements()) {
104                 NetworkInterface iface = ifs.nextElement();
105                 messages.clear();
106                 messages.add(iface.getName());
107                 messages.add(Boolean.toString(iface.supportsMulticast()));
108                 log(Level.INFO, _title, "Interface {0}: probe multicast support: {1}", messages);
109                 if (iface.supportsMulticast()) {
110                     try {
111                         messages.clear();
112                         messages.add(iface.getName());
113                         messages.add(_socketAddress.getSocketAddress().getAddress().toString());
114                         this._multicastSocket.joinGroup(_socketAddress.getSocketAddress(), iface);
115                     log(Level.INFO, _title, "Interface {0}: joined multicast group {1}", messages);
116                     } catch (Exception e) {
117                         messages.clear();
118                         messages.add(iface.getName());
119                         log(Level.SEVERE, _title, "Interface {0}: failed to join multicast group", messages);
120                     }
121                 }
122             }
123         } catch (IOException e) {
124             log(Level.SEVERE, _title, "Failed to open multicast socket");
125         }
126     }
127
128     /**
129      * Close the socket.
130      * 
131      * @throws SocketException
132      */
133     @Override
134     public void serverClose() throws SocketException {
135         if (this._multicastSocket != null) {
136             try {
137                 log(Level.INFO, _title, "Leaving multicast group");
138                 this._multicastSocket.leaveGroup(_socketAddress.getAddress());
139                 this._multicastSocket.close();
140             } catch (IOException e) {
141                 log(Level.SEVERE, _title, "failed to leave multicast group");
142             }
143             
144         }
145     }
146 }