/**
*
* Copyright (c) 2009-2016 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
package com.freedomotic.helpers;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class implements an UDP server listening for incoming packets and
* provides a method to send UDP packets to a specified server
*
* @author Mauro Cicolella
*/
public class UdpHelper {
private static final Logger LOG = LoggerFactory.getLogger(UdpHelper.class.getName());
private static UDPThreadServer server;
private static DatagramSocket serverDatagramSocket;
/**
* Starts an UDP server listening on the given address and port. It allows
* to bind a consumer which will be notified of any message received by the
* UDP server.
*
* @param serverAddress Server UDP address
* @param serverPort Server UDP port number
* @param consumer UdpListener for incoming packets
*/
public void startServer(String serverAddress, int serverPort, final UdpListener consumer) {
server = new UDPThreadServer(serverAddress, serverPort, consumer);
server.start();
}
/**
* Stops the UDP server closing the socket.
*/
public void stopServer() {
if (serverDatagramSocket.isBound()) {
serverDatagramSocket.close();
LOG.info("UDP server listening on {}:{} stopped.", new Object[]{serverDatagramSocket.getInetAddress(), serverDatagramSocket.getPort()});
}
}
/**
* Sends an UDP packet to the server
*
* @param serverAddress UDP server address
* @param serverPort UDP server port number
* @param payload data to send
* @throws java.io.IOException
*/
public void send(String serverAddress, int serverPort, String payload) throws IOException {
DatagramSocket datagramSocket = null;
try {
InetAddress inetAddress = InetAddress.getByName(serverAddress);
int port = serverPort;
datagramSocket = new DatagramSocket();
DatagramPacket out_datagramPacket = new DatagramPacket(
payload.getBytes(),
payload.length(),
inetAddress,
port);
datagramSocket.send(out_datagramPacket);
if (LOG.isDebugEnabled()) {
LOG.debug("Sending UDP packet to {}:{}", new Object[]{serverAddress, serverPort});
}
} catch (UnknownHostException ex) {
throw new IOException("Unknown UDP server. Packet not sent", ex);
} catch (SocketException ex) {
throw new IOException("Socket exception. Packet not sent", ex);
} finally {
if (datagramSocket != null) {
datagramSocket.close();
}
}
}
/**
* UDP server thread
*/
private static class UDPThreadServer extends Thread {
private String serverAddress;
private int serverPort;
private UdpListener consumer;
UDPThreadServer(String serverAddress, int serverPort, final UdpListener consumer) {
this.serverAddress = serverAddress;
this.serverPort = serverPort;
this.consumer = consumer;
if (LOG.isDebugEnabled()) {
LOG.debug("UDP server starting on {}:{}", new Object[]{serverAddress, serverPort});
}
}
@Override
public void run() {
try {
serverDatagramSocket = new DatagramSocket(null);
serverDatagramSocket.setReuseAddress(true);
InetSocketAddress address = new InetSocketAddress(serverAddress, serverPort);
serverDatagramSocket.bind(address);
//buffer to receive incoming data
byte[] buffer = new byte[65536];
DatagramPacket inPacket = new DatagramPacket(buffer, buffer.length);
LOG.info("UDP server started. Waiting for incoming data on {}:{}", new Object[]{serverAddress, serverPort});
//communication loop
while (true) {
serverDatagramSocket.receive(inPacket);
byte[] payload = inPacket.getData();
String sourceAddress = inPacket.getAddress().getHostAddress();
Integer sourcePort = inPacket.getPort();
String data = new String(payload, 0, inPacket.getLength());
if (LOG.isDebugEnabled()) {
LOG.debug("UDP server receives packet from {}:{}", new Object[]{sourceAddress, sourcePort});
}
consumer.onDataAvailable(sourceAddress, sourcePort, data);
}
} catch (IOException e) {
LOG.error("UDP server not started for ", e);
}
}
}
}