package network.platform.ip;
import model.interfaces.network.INetworkServer;
import model.interfaces.network.INetworkTraffic;
import network.platform.PlatformMessagesReceptor;
import network.platform.NetworkPlatformMessage;
import util.NetworkAddress;
import java.net.MulticastSocket;
import java.net.InetAddress;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import util.Parameters;
import platform.servicesregister.ServicesRegisterManager;
import platform.servicesregister.ServiceClosedException;
import platform.context.ContextManager;
import platform.context.ContextInformation;
import platform.plugins.installables.network.DNS.KalimuchoDNS;
import network.AddressesChecker;
/**
* Receive multicasted NetworkMessages on UDP for the platform
* @author Dalmau
*/
public class IPPlatformBroadcastReceptionServer extends Thread implements INetworkServer, INetworkTraffic {
private MulticastSocket socket;
private InetAddress group;
private boolean arret;
private PlatformMessagesReceptor messagesRecus; // buffer de depot des messages de la PF
private NetworkAddress monAdresse;
private int numPort;
private ContextManager gestionnaireContexte;
private int receivedData;
private KalimuchoDNS dns;
private String myID;
/**
* Server that receives messages on an UDP multicast socket an gives them to the PF message receptor
* @param adr the addres if this host on the network on which this server works
* @param b the PF message to receptor to send the received messages to
* @param p the UDP port number on which the server listen
*/
public IPPlatformBroadcastReceptionServer(NetworkAddress adr, PlatformMessagesReceptor b, int p) {
monAdresse = adr;
messagesRecus = b;
numPort = p;
AddressesChecker addressesChecker = (AddressesChecker)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_ADDRESSES);
myID = addressesChecker.getHostIdentifier();
receivedData = 0;
try {
socket = new MulticastSocket(numPort);
group = InetAddress.getByName(Parameters.UDP_BROADCAST_GROUP_PF);
socket.joinGroup(group);
}
catch (IOException ioe) {
socket = null;
group = null;
System.err.println("Error creating broadcast IP server for class finder");
}
arret = false;
gestionnaireContexte = (ContextManager)ServicesRegisterManager.platformWaitForService(Parameters.CONTEXT_MANAGER);
setPriority(Thread.NORM_PRIORITY+2);
start();
}
/**
* Stops the broadacst server for the platform
*/
public void stopThread() {
arret = true;
try {
socket.leaveGroup(group);
socket.close();
}
catch (IOException ioe) {
System.err.println("Error stopping broadcast IP server for class finder");
}
}
/**
* Wait for multicast messages an give them to the PF message receptor.
* Because multicast messages are received by the sender, messages received from this host are deleted.
*/
@Override
public void run() {
DatagramPacket packet;
while (!arret) {
try {
byte[] buf = new byte[Parameters.MAX_BROADCAST_MESSAGE_SIZE];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// message recu = (classe, demandeur, relais)
NetworkPlatformMessage message = new NetworkPlatformMessage(packet.getData());
receivedData = packet.getLength();
// la condition suivante sert a simuler une non connectivite avec un hote
if ((!packet.getAddress().getHostAddress().contains(Parameters.NETWORK_EXCLUSION)) || (message.getSenderID().equals("Deployment"))) {
if (!message.getSenderID().equals(myID)) {
// je ne suis pas emetteur de ce broadcast => traiter
message.setAddress(message.getExpeditorAddress());
try {
dns = (KalimuchoDNS)ServicesRegisterManager.lookForService(Parameters.KALIMUCHO_DNS_MANAGER);
dns.addReference(message.getSenderID(), packet.getAddress().getHostAddress(), true);
if (!(new NetworkAddress(message.getExpeditorAddress()).equals(new NetworkAddress(packet.getAddress().getHostAddress()))))
dns.addReference(message.getExpeditorID(), message.getExpeditorAddress(), false);
}
catch (ServiceClosedException sce) { }
messagesRecus.deposerMessage(message); // le deposer dans le buffer pour la PF
}
}
}
catch (SecurityException ioe) {
if (!arret) {
gestionnaireContexte.signalEvent(new ContextInformation("Error when receiving PF broadcast message: security"));
}
}
catch (SocketTimeoutException ioe) {
if (!arret) {
gestionnaireContexte.signalEvent(new ContextInformation("Error when receiving PF broadcast message: time out"));
}
}
catch (SocketException ioe) {
if (!arret) {
gestionnaireContexte.signalEvent(new ContextInformation("Error when receiving PF broadcast message: socket"));
}
}
catch (IOException ioe) {
if (!arret) {
gestionnaireContexte.signalEvent(new ContextInformation("Error when receiving PF broadcast message: IO"));
}
}
}
}
/**
* Returns the number of bytes received on network by the PF in broadcast since the last call of this method.
* @return the number of bytes received on network by the PF in broadcast since the last call of this method.
*/
public int getDataSize() {
int ret = receivedData;
receivedData = 0;
return ret;
}
}