/*
* Copyright Ericsson AB 2011-2014. All Rights Reserved.
*
* The contents of this file are subject to the Lesser GNU Public License,
* (the "License"), either version 2.1 of the License, or
* (at your option) any later version.; you may not use this file except in
* compliance with the License. You should have received a copy of the
* License along with this software. If not, it can be
* retrieved online at https://www.gnu.org/licenses/lgpl.html. Moreover
* it could also be requested from Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
* WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
* EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
* OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
* LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE,
* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
*
* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
* WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
* REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
* DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
* DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
* (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
* INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE
* OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
* HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
*/
package com.ericsson.deviceaccess.coap.basedriver.communication;
import com.ericsson.deviceaccess.coap.basedriver.osgi.IncomingMessageListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class represents the UDP thread for listening to incoming UDP
*/
public class UDPReceiver implements Runnable, TransportLayerReceiver {
private static final Logger LOGGER = LoggerFactory.getLogger(UDPReceiver.class);
private final DatagramSocket socket;
private final List<IncomingMessageListener> coapListeners = Collections.synchronizedList(new ArrayList<>());
Thread thread;
private volatile AtomicBoolean running = new AtomicBoolean(false);
/**
* Constructor using DatagramSocket
*
* @param socket
*/
public UDPReceiver(DatagramSocket socket) {
LOGGER.debug("UDP receiver with datagram socket");
this.socket = socket;
}
public void cleanup() {
coapListeners.clear();
socket.close();
}
@Override
public void run() {
while (running.get()) {
// TODO allocate buffer properly
byte[] buffer = new byte[UDPConstants.MAX_DATAGRAM_SIZE + 1];
DatagramPacket datagram = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(datagram);
} catch (IOException ex) {
ex.printStackTrace();
}
// socket.close() will interrupt socket.receive()
if (socket.isClosed()) {
running.set(false);
} else {
this.datagramReceived(datagram);
}
}
}
@Override
public void start() {
running.set(true);
thread = new Thread(this);
thread.start();
}
/**
* This method is used for notifying the CoAP listeners when a UDP datagram
* is received
*
* @param datagram received datagram
*/
private void datagramReceived(DatagramPacket datagram) {
coapListeners.forEach(listener -> listener.messageReceived(datagram));
}
/**
* Add an incoming message listener
*
* @param listener listener to add
*/
@Override
public void addListener(IncomingMessageListener listener) {
coapListeners.add(listener);
}
/**
* Removes an incomingmessagelistener
*
* @param listener
* @return Returns true if the list contained the specified element
*/
@Override
public boolean removeListener(IncomingMessageListener listener) {
return coapListeners.remove(listener);
}
@Override
public void stopService() {
cleanup();
}
}