/*
* Minha.pt: middleware testing platform.
* Copyright (c) 2011-2014, Universidade do Minho.
*
* 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
* of the License, 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package pt.minha.models.global.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import pt.minha.models.global.io.BlockingHelper;
/**
* Simulated UDP socket.
*
* @author jop
*/
public class UDPSocket extends AbstractSocket {
private List<DatagramPacket> incoming = new ArrayList<DatagramPacket>();
public BlockingHelper readers, writers;
private InetSocketAddress remote;
public UDPSocket(NetworkStack stack) {
super(stack);
readers = new BlockingHelper() {
public boolean isReady() {
return !incoming.isEmpty();
}
};
writers = new BlockingHelper() {
public boolean isReady() {
/* This is needed to support select() in datagram channels. */
return true;
}
};
}
@Override
public void bind(InetSocketAddress addr) throws SocketException {
// FIXME: Bind address is ignored
if (addr != null && addr.getPort()!=0)
super.bind(stack.getUDPBindAddress(addr.getPort()));
else
super.bind(stack.getUDPBindAddress(0));
stack.addUDPSocket(getLocalAddress(), this);
}
public void joinGroup(InetAddress addr) throws IOException {
stack.getNetwork().addToGroup(addr, stack);
stack.addUDPSocket(new InetSocketAddress(addr, getLocalAddress().getPort()), this);
}
public void leaveGroup(InetAddress addr) throws IOException {
stack.getNetwork().removeFromGroup(addr, stack);
stack.removeUDPSocket(new InetSocketAddress(addr, getLocalAddress().getPort()));
}
public void connect(InetSocketAddress addr) {
remote = addr;
}
public void send(DatagramPacket packet) throws SocketException {
byte[] data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, data.length);
DatagramPacket dp = new DatagramPacket(data, data.length, getLocalAddress());
InetSocketAddress destination = new InetSocketAddress(packet.getAddress(), packet.getPort());
stack.relayUDP(destination, dp);
}
public DatagramPacket receive() {
return incoming.remove(0);
}
public void shutdown() {
readers.wakeup();
stack.removeUDPSocket(getLocalAddress());
}
public void queue(DatagramPacket packet) {
incoming.add(packet);
readers.wakeup();
}
public InetSocketAddress getRemoteAddress() {
return remote;
}
}