/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.pieShare.pieTools.piePlate.service.loophole; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.annotation.PostConstruct; import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.LoopHoleAckMessage; import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.LoopHoleCompleteMessage; import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.LoopHoleConnectionMessage; import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.LoopHolePunchMessage; import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.api.IUdpMessage; import org.pieShare.pieTools.piePlate.service.loophole.api.ILoopHoleFactory; import org.pieShare.pieTools.piePlate.service.loophole.api.ILoopHoleService; import org.pieShare.pieTools.piePlate.service.loophole.event.NewLoopHoleConnectionEvent; import org.pieShare.pieTools.piePlate.service.loophole.event.api.INewLoopHoleConnectionEventListener; import org.pieShare.pieTools.piePlate.service.serializer.api.ISerializerService; import org.pieShare.pieTools.piePlate.service.serializer.exception.SerializerServiceException; import org.pieShare.pieTools.piePlate.task.LoopHoleAckTask; import org.pieShare.pieTools.piePlate.task.LoopHoleCompleteTask; import org.pieShare.pieTools.piePlate.task.LoopHoleConnectionTask; import org.pieShare.pieTools.piePlate.task.LoopHolePuncherTask; import org.pieShare.pieTools.pieUtilities.service.beanService.IBeanService; import org.pieShare.pieTools.pieUtilities.service.eventBase.IEventBase; import org.pieShare.pieTools.pieUtilities.service.idService.api.IIDService; import org.pieShare.pieTools.pieUtilities.service.networkService.api.IUdpPortService; import org.pieShare.pieTools.pieUtilities.service.pieExecutorService.PieExecutorService; import org.pieShare.pieTools.pieUtilities.service.pieExecutorService.PieExecutorTaskFactory; import org.pieShare.pieTools.pieUtilities.service.pieLogger.PieLogger; /** * * @author RicLeo00 */ public class LoopHoleFactory implements ILoopHoleFactory { private final HashMap<String, ILoopHoleService> loopQueue; private IUdpPortService udpPortService; private int nextUdpPort; private IBeanService beanService; private String clientID; private IIDService idService; private ISerializerService serializerService; private final InetSocketAddress serverAddress; private String name; private PieExecutorTaskFactory executorFactory; private PieExecutorService executorService; private IEventBase<INewLoopHoleConnectionEventListener, NewLoopHoleConnectionEvent> newLoopHoleConnectionEvent; private List<InetSocketAddress> members; private List<Integer> localUsedPorts; public LoopHoleFactory() { loopQueue = new HashMap<>(); nextUdpPort = 1234; serverAddress = new InetSocketAddress("server.piesystems.org", 6312); localUsedPorts = new ArrayList<>(); members = new ArrayList<>(); } @PostConstruct public void init() { this.executorFactory.registerTask(LoopHoleConnectionMessage.class, LoopHoleConnectionTask.class); this.executorFactory.registerTask(LoopHolePunchMessage.class, LoopHolePuncherTask.class); this.executorFactory.registerTask(LoopHoleAckMessage.class, LoopHoleAckTask.class); this.executorFactory.registerTask(LoopHoleCompleteMessage.class, LoopHoleCompleteTask.class); clientID = idService.getNewID(); } public void setMembers(List<InetSocketAddress> members) { this.members = members; } @Override public void addLocalUsedPort(int port) { localUsedPorts.add(port); } @Override public IEventBase<INewLoopHoleConnectionEventListener, NewLoopHoleConnectionEvent> getNewLoopHoleConnectionEvent() { return newLoopHoleConnectionEvent; } public void setNewLoopHoleConnectionEvent(IEventBase<INewLoopHoleConnectionEventListener, NewLoopHoleConnectionEvent> newLoopHoleConnectionEvent) { this.newLoopHoleConnectionEvent = newLoopHoleConnectionEvent; } @Override public synchronized void newClientAvailable(InetSocketAddress address, DatagramSocket socket) { members.add(address); PieLogger.info(this.getClass(), String.format("New UPD connection available. Host: %s, Port: %s", address.getHostString(), address.getPort())); newLoopHoleConnectionEvent.fireEvent(new NewLoopHoleConnectionEvent(this, address, socket)); initializeNewLoopHole(); } @Override public String getClientID() { return clientID; } public void setExecutorFactory(PieExecutorTaskFactory executorFactory) { this.executorFactory = executorFactory; } public void setExecutorService(PieExecutorService executorService) { this.executorService = executorService; } public String getName() { return name; } @Override public void setName(String name) { this.name = name; } public void setSerializerService(ISerializerService serializerService) { this.serializerService = serializerService; } public void setIdService(IIDService idService) { this.idService = idService; } public void setBeanService(IBeanService beanService) { this.beanService = beanService; } public void setUdpPortService(IUdpPortService udpPortService) { this.udpPortService = udpPortService; } @Override public void initializeNewLoopHole() { ILoopHoleService loopHoleService = beanService.getBean(LoopHoleService.class); nextUdpPort = udpPortService.getNewPortFrom(nextUdpPort); int newPort = 0; while (newPort != nextUdpPort) { newPort = nextUdpPort; if (localUsedPorts.contains(newPort)) { nextUdpPort++; } } loopHoleService.setLocalPort(nextUdpPort); loopHoleService.setName(name); loopHoleService.init(); } @Override public void sendToServer(DatagramSocket socket, IUdpMessage msg) { send(socket, msg, serverAddress); } private synchronized void send(DatagramSocket socket, IUdpMessage msg, InetSocketAddress address) { try { msg.setSenderID(this.clientID); byte[] bytes = serializerService.serialize(msg); DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address.getAddress(), address.getPort()); socket.send(packet); Thread.sleep(500); } catch (SerializerServiceException ex) { PieLogger.error(this.getClass(), "Error serializing message", ex); } catch (UnknownHostException ex) { PieLogger.error(this.getClass(), "UnknownHostException", ex); } catch (IOException ex) { PieLogger.error(this.getClass(), "IOException", ex); } catch (InterruptedException ex) { PieLogger.error(this.getClass(), "InterruptedException", ex); } } @Override public ILoopHoleService getLoopHoleService(String clientID) { return loopQueue.get(clientID); } @Override public void insertLoopHoleService(String ID, ILoopHoleService service) { loopQueue.put(ID, service); } }