/**************************************************************************
* Parts copyright (c) 2001 by Punch Telematix. All rights reserved. *
* Parts copyright (c) 2007, 2013 by Chris Gray, /k/ Embedded Java *
* Solutions. All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. 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. *
* 3. Neither the name of Punch Telematix or of /k/ Embedded Java Solutions*
* nor the names of other contributors may be used to endorse or promote*
* products derived from this software without specific prior written *
* permission. *
* *
* THIS SOFTWARE IS PROVIDED ``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 PUNCH TELEMATIX, /K/ EMBEDDED JAVA SOLUTIONS OR OTHER *
* 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 java.net;
import java.io.*;
class PlainDatagramSocketImpl extends DatagramSocketImpl {
private int timeout; //0 = blocks forever
private boolean open;
public PlainDatagramSocketImpl(){}
/**
* Create a datagram socket
*/
protected synchronized void create() throws SocketException {
fd = new FileDescriptor();
nativeCreate();
}
private native void nativeCreate();
/**
* Binds a datagram socket to a local port and address.
*/
protected synchronized native void bind(int lport, InetAddress laddr) throws SocketException;
/**
* Sends a datagram packet. The packet contains the data and the destination address to send the packet to.
*/
protected native void send(DatagramPacket p) throws IOException;
/**
* Peek at the packet to see who it is from.
*/
protected native int peek(InetAddress i) throws IOException;
/**
* Receive the datagram packet.
*/
protected void receive(DatagramPacket p) throws IOException {
synchronized(p){
try {
SocketUsers.put(this, Thread.currentThread());
int ip = _receive(p);
p.setAddress(InetAddress.createInetAddress(ip));
}
finally {
SocketUsers.remove(this);
}
}
}
private native int _receive(DatagramPacket p) throws IOException;
/**
* @deprecated. use setTimeToLive instead.
* Set the TTL (time-to-live) option.
*/
protected synchronized void setTTL(byte ttl) throws IOException {
setTimeToLive(0x0ff & ttl);
}
/**
* @deprecated. use getTimeToLive instead.
* Retrieve the TTL (time-to-live) option.
*/
protected synchronized byte getTTL()throws IOException {
return (byte)getTimeToLive();
}
/**
* Join the multicast group.
*/
protected void join(InetAddress inetaddr) throws IOException {
join(inetaddr, null);
}
/**
* Join the multicast group.
*/
protected void joinGroup(InetAddress inetaddr, NetworkInterface nw) throws IOException {
join(inetaddr, (InetAddress) nw.getInetAddresses().nextElement());
}
/**
* Leave the multicast group.
*/
protected synchronized native void leave(InetAddress inetaddr) throws IOException;
/**
* Close the socket.
*/
protected void close() {
Thread t = SocketUsers.get(this);
_close();
if (t != null) {
signal(t);
}
}
protected synchronized native void _close();
/**
* Set the TTL (time-to-live) option.
*/
protected synchronized native void setTimeToLive(int ttl) throws IOException;
/**
* Retrieve the TTL (time-to-live) option.
*/
protected synchronized native int getTimeToLive() throws IOException;
public synchronized Object getOption(int opt) throws SocketException {
int sock = getSocket();
if(opt == SO_TIMEOUT){
return new Integer(timeout);
}
return options(opt, null, sock);
}
public synchronized void setOption(int opt, Object value) throws SocketException {
if(value == null){
throw new SocketException("a non 'null' option value is required");
}
int sock = getSocket();
if(opt == SO_TIMEOUT){
if(value instanceof Integer){
timeout = ((Integer)value).intValue();
setSoTimeout(sock, timeout);
}
}
else {
options(opt, value, sock);
}
}
private native int getSocket() throws SocketException;
/*
SO_BINDADDR = 0x000F; --> InetAddress
SO_LINGER = 0x0080; --> Boolean or Integer
TCP_NODELAY = 0x0001; --> Boolean
IP_MULTICAST_IF = 0x10; --> InetAddress
SO_REUSEADDR = 0x04; --> Integer
SO_TIMEOUT = 0x1006; --> Integer
SO_SNDBUF =0x1001; --> Integer
SO_RCVBUF = 0x1002; --> Integer
*/
static Object options(int opt, Object value, int sock) throws SocketException {
try {
int i=0;
switch (opt) {
case SO_BINDADDR:
if(value == null){//get
return InetAddress.createInetAddress(getBindAddress(sock));
}
break;
case SO_BROADCAST:
if(value == null){//get
return new Boolean(optIntOptions(sock, -1, 7) != 0);
}
optIntOptions(sock, ((Boolean)value).booleanValue() ? 1 : 0, 7); //set
break;
case SO_LINGER:
if(value == null){//get
int res = optLinger(sock, -1);
if (res == 0){
return new Boolean(false);
}
else {
return new Integer(res);
}
}
else {//set
if((value instanceof Boolean) && !((Boolean)value).booleanValue()){
optLinger(sock, 0);
}
else {
optLinger(sock, ((Integer)value).intValue());
}
}
break;
case TCP_NODELAY:
if(value == null){//get
return new Boolean(optNoDelay(sock, true, true));
}
optNoDelay(sock, ((Boolean)value).booleanValue(), false); //set
break;
case SO_SNDBUF:
i++;
case SO_RCVBUF:
i++;
case SO_REUSEADDR:
if(value == null){//get
return new Integer(optIntOptions(sock, -1, i));
}
/*
* According to http://java.sun.com/javame/reference/apis/jsr219/java/net/SocketOptions.html
* this code should handle being passed a Boolean or a Integer
* also should review other SocketOptions and refactor as required.
*/
try {
optIntOptions(sock, ((Boolean)value).booleanValue() ? 1 : 0, i); //set
} catch (ClassCastException cce) {
optIntOptions(sock, 1, i); //set
}
break;
case IP_MULTICAST_IF:
if(value == null){//get
return InetAddress.createInetAddress(optMulticastIF(sock, null, true));
}
optMulticastIF(sock, (InetAddress)value, false); //set
break;
default:
throw new SocketException("no valid option specified");
}
} catch(ClassCastException cce){
throw new SocketException("no valid value specified");
}
return null;
}
protected native void finalize();
private native void signal(Thread t);
// sock is the filedesc of the socket
private static native int getBindAddress(int sock) throws SocketException ;
private static native int optLinger(int sock, int value) throws SocketException ; // value == -1 if get is wanted ...
private static native boolean optNoDelay(int sock, boolean value, boolean set) throws SocketException ;
private static native int optMulticastIF(int sock, InetAddress value, boolean set) throws SocketException ;
private static native int optIntOptions(int sock, int value, int opt) throws SocketException ;// value == -1 if get is wanted
private static native void setSoTimeout(int sock, int t) throws SocketException;
private synchronized native void join(InetAddress group, InetAddress local) throws IOException;
}