/*
* 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.pieShareServer.services.loopHoleService;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import org.pieShare.pieTools.piePlate.service.serializer.api.ISerializerService;
import org.pieShare.pieTools.piePlate.service.serializer.exception.SerializerServiceException;
import org.pieShare.pieTools.pieUtilities.service.beanService.IBeanService;
import org.pieShare.pieTools.pieUtilities.service.pieExecutorService.PieExecutorService;
import org.pieShare.pieTools.pieUtilities.service.pieLogger.PieLogger;
import org.pieShare.pieShareServer.services.loopHoleService.api.ILoopHoleService;
import org.pieShare.pieShareServer.services.loopHoleService.api.IUserPersistanceService;
import org.pieShare.pieShareServer.tasks.LoopHoleListenerTask;
import org.pieShare.pieShareServer.tasks.LoopHoleServerAckTask;
import org.pieShare.pieShareServer.tasks.RegisterTask;
import org.pieShare.pieShareServer.tasks.WaitForAckFromClientTask;
import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.LoopHoleAckMessage;
import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.RegisterMessage;
import org.pieShare.pieTools.piePlate.model.message.loopHoleMessages.api.IUdpMessage;
import org.pieShare.pieTools.pieUtilities.service.pieExecutorService.PieExecutorTaskFactory;
/**
*
* @author Richard
*/
public class LoopHoleService implements ILoopHoleService {
private int serverPort;
private IBeanService beanService;
private DatagramSocket socket;
private PieExecutorService executorService;
private IUserPersistanceService userPersistanceService;
private ISerializerService serializerService;
private PieExecutorTaskFactory executorFactory;
private HashMap<String, WaitForAckFromClientTask> waitForAckQueue;
public void setExecutorFactory(PieExecutorTaskFactory executorFactory) {
this.executorFactory = executorFactory;
}
public void setSerializerService(ISerializerService serializerService) {
this.serializerService = serializerService;
}
public void setUserPersistanceService(IUserPersistanceService userPersistanceService) {
this.userPersistanceService = userPersistanceService;
}
public void setBeanService(IBeanService beanService) {
this.beanService = beanService;
}
public void setExecutorService(PieExecutorService executorService) {
this.executorService = executorService;
}
@Override
public synchronized void ackArrived(String ID) {
if (waitForAckQueue.containsKey(ID)) {
waitForAckQueue.get(ID).ackArrived();
}
waitForAckQueue.remove(ID);
}
@PostConstruct
public void init() {
executorFactory.registerTask(RegisterMessage.class, RegisterTask.class);
executorFactory.registerTask(LoopHoleAckMessage.class, LoopHoleServerAckTask.class);
waitForAckQueue = new HashMap<>();
PieLogger.info(this.getClass(), "Set up Loop Hole Service!");
serverPort = 6312;
try {
socket = new DatagramSocket(serverPort);
} catch (SocketException ex) {
PieLogger.error(this.getClass(), "Error starting loop hole punch service!", ex);
}
LoopHoleListenerTask listenerTask = beanService.getBean(LoopHoleListenerTask.class);
listenerTask.setSocket(socket);
executorService.execute(listenerTask);
}
@Override
public synchronized void send(IUdpMessage msg, InetSocketAddress address) {
try {
byte[] bytes = serializerService.serialize(msg);
PieLogger.info(this.getClass(), "Add new AckWaitTask.");
WaitForAckFromClientTask waitTask = beanService.getBean(WaitForAckFromClientTask.class);
waitTask.setMmsgToSend(msg);
waitTask.setUdpAddress(address);
waitForAckQueue.put(msg.getLocalLoopID(), waitTask);
executorService.execute(waitTask);
PieLogger.info(this.getClass(), String.format("Sending to Host: %s, Port: %s. Data: %s", address.getAddress().getHostAddress(), address.getPort(), new String(bytes)));
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(address.getAddress().getHostAddress()), address.getPort());
socket.send(packet);
Thread.sleep(1000);
} 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);
}
}
}