/*
JTestServer is a client/server framework for testing any JVM implementation.
Copyright (C) 2009 Fabien DUMINY (fduminy@jnode.org)
JTestServer 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.
JTestServer 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 org.jtestserver.common.protocol.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jtestserver.common.protocol.Protocol;
import org.jtestserver.common.protocol.ProtocolException;
import org.jtestserver.common.protocol.ReceivedMessage;
import org.jtestserver.common.protocol.TimeoutException;
public class UDPProtocol extends Protocol<DatagramSocket> {
private static final Logger LOGGER = Logger.getLogger(UDPProtocol.class.getName());
private static final int MAX_SIZE = Integer.MAX_VALUE; // 1024 * 1024;
//private static final int CHAR_SIZE = 2; // size of a char in bytes
private static final int INT_SIZE = 4; // size of an int in bytes
@Override
public final UDPClient createClient(InetAddress serverIp, int serverPort) throws ProtocolException {
try {
return new UDPClient(this, serverIp, serverPort);
} catch (SocketException e) {
throw new ProtocolException(e);
}
}
@Override
public final UDPServer createServer(int localPort) throws ProtocolException {
try {
return new UDPServer(this, localPort);
} catch (SocketException e) {
throw new ProtocolException(e);
}
}
@Override
protected void sendMessage(DatagramSocket socket, String message, SocketAddress remoteAddress)
throws ProtocolException, TimeoutException {
try {
final byte[] bytes = message.getBytes();
// send size of data
ByteBuffer byteBuffer = ByteBuffer.allocate(INT_SIZE).putInt(bytes.length);
byte[] data = byteBuffer.array();
remoteAddress = (remoteAddress == null) ? socket.getRemoteSocketAddress() : remoteAddress;
DatagramPacket packet = new DatagramPacket(data, data.length, remoteAddress);
socket.send(packet);
LOGGER.log(Level.INFO, "nb bytes sent : " + bytes.length);
// send data
packet = new DatagramPacket(bytes, bytes.length, remoteAddress);
socket.send(packet);
// ByteBuffer bb = ByteBuffer.allocate(command.length() * CHAR_SIZE + INT_SIZE);
// bb.putInt(command.length()).asCharBuffer().append(command);
// socket.getChannel().send(bb, socket.getRemoteSocketAddress());
} catch (SocketTimeoutException e) {
throw new TimeoutException("timeout in receive", e);
} catch (IOException e) {
throw new ProtocolException("error in receive", e);
}
}
@Override
protected ReceivedMessage receiveMessage(DatagramSocket socket) throws ProtocolException, TimeoutException {
try {
// receive size of data
byte[] data = new byte[INT_SIZE];
DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
int size = ByteBuffer.wrap(data).getInt();
LOGGER.log(Level.INFO, "nb bytes received : " + size);
if (size > MAX_SIZE) {
throw new ProtocolException(
"stream probably corrupted : received more than "
+ MAX_SIZE + " bytes (" + size + ")");
}
// receive actual data
data = new byte[size];
packet = new DatagramPacket(data, data.length);
socket.receive(packet);
return new ReceivedMessage(new String(packet.getData()), packet.getSocketAddress());
// ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
// socket.getChannel().read(bb);
// int size = bb.getInt();
// bb = ByteBuffer.allocate(size);
// socket.getChannel().read(bb);
//
// return bb.asCharBuffer().rewind().toString();
} catch (SocketTimeoutException e) {
throw new TimeoutException("timeout in receive", e);
} catch (IOException e) {
throw new ProtocolException("error in receive", e);
}
}
}