blob: 0193e1c2e513f4bc4aaca6c9801b5e4c056119e6 [file] [log] [blame]
/*
* Copyright (c) 2011 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.network.kernel.udp;
import com.jme3.network.kernel.Connector;
import com.jme3.network.kernel.ConnectorException;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A straight forward datagram socket-based UDP connector
* implementation.
*
* @version $Revision: 8843 $
* @author Paul Speed
*/
public class UdpConnector implements Connector
{
private DatagramSocket sock = new DatagramSocket();
private SocketAddress remoteAddress;
private byte[] buffer = new byte[65535];
private AtomicBoolean connected = new AtomicBoolean(false);
/**
* In order to provide proper available() checking, we
* potentially queue one datagram.
*/
private DatagramPacket pending;
/**
* Creates a new UDP connection that send datagrams to the
* specified address and port.
*/
public UdpConnector( InetAddress remote, int remotePort ) throws IOException
{
InetSocketAddress localSocketAddress = new InetSocketAddress(0);
this.sock = new DatagramSocket( localSocketAddress );
remoteAddress = new InetSocketAddress( remote, remotePort );
// Setup to receive only from the remote address
sock.connect( remoteAddress );
connected.set(true);
}
protected void checkClosed()
{
if( sock == null )
throw new ConnectorException( "Connection is closed:" + remoteAddress );
}
public boolean isConnected()
{
if( sock == null )
return false;
return sock.isConnected();
}
public void close()
{
checkClosed();
DatagramSocket temp = sock;
sock = null;
connected.set(false);
temp.close();
}
/**
* This always returns false since the simple DatagramSocket usage
* cannot be run in a non-blocking way.
*/
public boolean available()
{
// It would take a separate thread or an NIO Selector based implementation to get this
// to work. If a polling strategy is never employed by callers then it doesn't
// seem worth it to implement all of that just for this method.
checkClosed();
return false;
}
public ByteBuffer read()
{
checkClosed();
try {
DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
sock.receive(packet);
// Wrap it in a ByteBuffer for the caller
return ByteBuffer.wrap( buffer, 0, packet.getLength() );
} catch( IOException e ) {
if( !connected.get() ) {
// Nothing to see here... just move along
return null;
}
throw new ConnectorException( "Error reading from connection to:" + remoteAddress, e );
}
}
public void write( ByteBuffer data )
{
checkClosed();
try {
DatagramPacket p = new DatagramPacket( data.array(), data.position(), data.remaining(),
remoteAddress );
sock.send(p);
} catch( IOException e ) {
throw new ConnectorException( "Error writing to connection:" + remoteAddress, e );
}
}
}