Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2007 Damian Steer <pldms@mac.com> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby.ext.socket;
 
 
 import org.jruby.Ruby;

Author(s):
Damian Steer
 
 @JRubyClass(name="UDPSocket", parent="IPSocket")
 public class RubyUDPSocket extends RubyIPSocket {
 
     static void createUDPSocket(Ruby runtime) {
         RubyClass rb_cUDPSocket = runtime.defineClass("UDPSocket"runtime.getClass("IPSocket"), );
         
         rb_cUDPSocket.includeModule(runtime.getClass("Socket").getConstant("Constants"));
 
         rb_cUDPSocket.defineAnnotatedMethods(RubyUDPSocket.class);
 
         runtime.getObject().setConstant("UDPsocket"rb_cUDPSocket);
     }
 
     private static ObjectAllocator UDPSOCKET_ALLOCATOR = new ObjectAllocator() {
 
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new RubyUDPSocket(runtimeklass);
         }
     };
 
     public RubyUDPSocket(Ruby runtimeRubyClass type) {
         super(runtimetype);
     }
 
     @JRubyMethod(visibility = .)
     public IRubyObject initialize(ThreadContext context) {
         Ruby runtime = context.runtime;
 
         try {
             DatagramChannel channel = DatagramChannel.open();
             initSocket(runtimenew ChannelDescriptor(channelnewModeFlags(runtime.)));
 
         } catch (ConnectException e) {
            throw runtime.newErrnoECONNREFUSEDError();
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"initialize: name or service not known");
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"initialize: name or service not known");
        }
        return this;
    }
    @JRubyMethod(visibility = .)
    public IRubyObject initialize(ThreadContext contextIRubyObject protocol) {
        // we basically ignore protocol. let someone report it...
        return initialize(context);
    }
    public IRubyObject bind(ThreadContext contextIRubyObject hostIRubyObject _port) {
        Ruby runtime = context.runtime;
        InetSocketAddress addr = null;
        try {
            Channel channel = getChannel();
            int port = SocketUtils.portToInt(_port);
            if (host.isNil()
                || ((host instanceof RubyString)
                && ((RubyStringhost).isEmpty())) {
                // host is nil or the empty string, bind to INADDR_ANY
                addr = new InetSocketAddress(port);
            } else if (host instanceof RubyFixnum) {
                // passing in something like INADDR_ANY
                int intAddr = RubyNumeric.fix2int(host);
                RubyModule socketMod = runtime.getModule("Socket");
                if (intAddr == RubyNumeric.fix2int(socketMod.getConstant("INADDR_ANY"))) {
                    addr = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), port);
                }
            } else {
                // passing in something like INADDR_ANY
                addr = new InetSocketAddress(InetAddress.getByName(host.convertToString().toString()), port);
            }
            if ( == null) {
                ((DatagramChannelchannel).socket().bind(addr);
            } else {
                .rebindToPort(port);
            }
            return RubyFixnum.zero(runtime);
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"bind: name or service not known");
        } catch (SocketException e) {
            throw SocketUtils.sockerr(runtime"bind: name or service not known");
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"bind: name or service not known");
        } catch (Error e) {
            // Workaround for a bug in Sun's JDK 1.5.x, see
            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6303753
            if (e.getCause() instanceof SocketException) {
                throw SocketUtils.sockerr(runtime"bind: name or service not known");
            } else {
                throw e;
            }
        }
    }
    public IRubyObject connect(ThreadContext contextIRubyObject hostIRubyObject port) {
        Ruby runtime = context.runtime;
        try {
            InetSocketAddress addr = new InetSocketAddress(InetAddress.getByName(host.convertToString().toString()), SocketUtils.portToInt(port));
            ((DatagramChannelthis.getChannel()).connect(addr);
            return RubyFixnum.zero(runtime);
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"connect: name or service not known");
            
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"connect: name or service not known");
        }
    }
    public IRubyObject recvfrom_nonblock(ThreadContext contextIRubyObject _length) {
        Ruby runtime = context.runtime;
        try {
            int length = RubyNumeric.fix2int(_length);
            ReceiveTuple tuple = doReceiveNonblockTuple(runtimelength);
            IRubyObject addressArray = addrFor(contexttuple.senderfalse);
            return runtime.newArray(tuple.resultaddressArray);
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"recvfrom: name or service not known");
        } catch (PortUnreachableException e) {
            throw runtime.newErrnoECONNREFUSEDError();
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"recvfrom: name or service not known");
        }
    }
    public IRubyObject recvfrom_nonblock(ThreadContext contextIRubyObject _lengthIRubyObject _flags) {
        // TODO: handle flags
        return recvfrom_nonblock(context_length);
    }
    public IRubyObject send(ThreadContext contextIRubyObject _mesgIRubyObject _flags) {
        // TODO: implement flags
        Ruby runtime = context.runtime;
        try {
            int written;
            RubyString data = _mesg.convertToString();
            ByteBuffer buf = ByteBuffer.wrap(data.getBytes());
            written = ((DatagramChannelthis.getChannel()).write(buf);
            return runtime.newFixnum(written);
        } catch (NotYetConnectedException nyce) {
            throw runtime.newErrnoEDESTADDRREQError("send(2)");
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"send: name or service not known");
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"send: name or service not known");
        }
    }
    public IRubyObject send(ThreadContext contextIRubyObject _mesgIRubyObject _flagsIRubyObject _to) {
        return send(context_mesg_flags);
    }
    @JRubyMethod(required = 2, optional = 2)
    public IRubyObject send(ThreadContext contextIRubyObject[] args) {
        // TODO: implement flags
        Ruby runtime = context.runtime;
        IRubyObject _mesg = args[0];
        IRubyObject _flags = args[1];
        try {
            int written;
            if (args.length == 2 || args.length == 3) {
                return send(context_mesg_flags);
            }
            
            IRubyObject _host = args[2];
            IRubyObject _port = args[3];
            RubyString nameStr = _host.convertToString();
            RubyString data = _mesg.convertToString();
            ByteBuffer buf = ByteBuffer.wrap(data.getBytes());
            byte[] buf2 = data.getBytes();
            DatagramPacket sendDP = null;
            int port;
            if (_port instanceof RubyString) {
                Service service = Service.getServiceByName(_port.asJavaString(), "udp");
                if (service != null) {
                    port = service.getPort();
                } else {
                    port = (int)_port.convertToInteger("to_i").getLongValue();
                }
            } else {
                port = (int)_port.convertToInteger().getLongValue();
            }
            InetAddress address = SocketUtils.getRubyInetAddress(nameStr.getByteList());
            InetSocketAddress addr = new InetSocketAddress(addressport);
            if (this. == null) {
                written = ((DatagramChannelthis.getChannel()).send(bufaddr);
            } else {
                sendDP = new DatagramPacket(buf2buf2.lengthaddressport);
                .rebindToPort(port);
                MulticastSocket ms = this..getMulticastSocket();
                ms.send(sendDP);
                written = sendDP.getLength();
            }
            return runtime.newFixnum(written);
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"send: name or service not known");
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"send: name or service not known");
        }
    }
    @JRubyMethod(rest = true, meta = true)
    public static IRubyObject open(ThreadContext contextIRubyObject recvIRubyObject[] argsBlock block) {
        RubyUDPSocket sock = (RubyUDPSocketrecv.callMethod(context"new"args);
        if (!block.isGiven()) {
            return sock;
        }
        try {
            return block.yield(contextsock);
        } finally {
            if (sock.openFile.isOpen()) {
                sock.close();
            }
        }
    }

    
Overrides IPSocket#recvfrom
    @Override
    public IRubyObject recvfrom(ThreadContext contextIRubyObject _length) {
        Ruby runtime = context.runtime;
        try {
            int length = RubyNumeric.fix2int(_length);
            ReceiveTuple tuple = doReceiveTuple(runtimelength);
            IRubyObject addressArray = addrFor(contexttuple.senderfalse);
            return runtime.newArray(tuple.resultaddressArray);
        } catch (UnknownHostException e) {
            throw SocketUtils.sockerr(runtime"recvfrom: name or service not known");
        } catch (PortUnreachableException e) {
            throw runtime.newErrnoECONNREFUSEDError();
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"recvfrom: name or service not known");
        }
    }

    
Overrides IPSocket#recvfrom
    @Override
    public IRubyObject recvfrom(ThreadContext contextIRubyObject _lengthIRubyObject _flags) {
        // TODO: handle flags
        return recvfrom(context_length);
    }

    
Overrides BasicSocket#recv
    @Override
    public IRubyObject recv(ThreadContext contextIRubyObject _length) {
        Ruby runtime = context.runtime;
        try {
            return doReceive(runtime, RubyNumeric.fix2int(_length));
        } catch (IOException e) {
            throw SocketUtils.sockerr(runtime"recv: name or service not known");
        }
    }

    
Overrides BasicSocket#recv
    @Override
    public IRubyObject recv(ThreadContext contextIRubyObject _lengthIRubyObject _flags) {
        // TODO: implement flags
        return recv(context_length);
    }
    private ReceiveTuple doReceiveTuple(Ruby runtimeint lengththrows IOException {
        ReceiveTuple tuple = new ReceiveTuple();
        if (this. == null) {
            doReceive(runtimelengthtuple);
        } else {
            doReceiveMulticast(runtimelengthtuple);
        }
        return tuple;
    }
    private ReceiveTuple doReceiveNonblockTuple(Ruby runtimeint lengththrows IOException {
        DatagramChannel channel = (DatagramChannel)getChannel();
        synchronized (channel.blockingLock()) {
            boolean oldBlocking = channel.isBlocking();
            channel.configureBlocking(false);
            try {
                return doReceiveTuple(runtimelength);
            } finally {
                channel.configureBlocking(oldBlocking);
            }
        }
    }
    private static class ReceiveTuple {
        ReceiveTuple() {}
        ReceiveTuple(RubyString resultInetSocketAddress sender) {
            this. = result;
            this. = sender;
        }
        RubyString result;
        InetSocketAddress sender;
    }
    private IRubyObject doReceive(Ruby runtimeint lengththrows IOException {
        return doReceive(runtimelengthnull);
    }
    private IRubyObject doReceive(Ruby runtimeint lengthReceiveTuple tuplethrows IOException {
        DatagramChannel channel = (DatagramChannel)getChannel();
        ByteBuffer buf = ByteBuffer.allocate(length);
        InetSocketAddress sender = (InetSocketAddress)channel.receive(buf);
        if (sender == null) {
            // noblocking receive
            if (runtime.is1_9()) {
                throw runtime.newErrnoEAGAINReadableError("recvfrom(2) would block");
            } else {
                throw runtime.newErrnoEAGAINError("recvfrom(2) would block");
            }
        }
        // see JRUBY-4678
        if (sender == null) {
            throw runtime.newErrnoECONNRESETError();
        }
        RubyString result = runtime.newString(new ByteList(buf.array(), 0, buf.position()));
        if (tuple != null) {
            tuple.result = result;
            tuple.sender = sender;
        }
        return result;
    }
    private IRubyObject doReceiveMulticast(Ruby runtimeint lengthReceiveTuple tuplethrows IOException {
        byte[] buf2 = new byte[length];
        DatagramPacket recv = new DatagramPacket(buf2buf2.length);
        try {
            ms.receive(recv);
        } catch (IllegalBlockingModeException ibme) {
            // MulticastSocket does not support nonblocking
            // TODO: Use Java 7 NIO.2 DatagramChannel to do multicast
            if (runtime.is1_9()) {
                throw runtime.newErrnoEAGAINReadableError("multicast UDP does not support nonblocking");
            } else {
                throw runtime.newErrnoEAGAINError("multicast UDP does not support nonblocking");
            }
        }
        InetSocketAddress sender = (InetSocketAddressrecv.getSocketAddress();
        // see JRUBY-4678
        if (sender == null) {
            throw runtime.newErrnoECONNRESETError();
        }
        RubyString result = runtime.newString(new ByteList(recv.getData(), 0, recv.getLength()));
        if (tuple != null) {
            tuple.result = result;
            tuple.sender = sender;
        }
        return result;
    }
    @Deprecated
    public IRubyObject bind(IRubyObject hostIRubyObject port) {
        return bind(getRuntime().getCurrentContext(), hostport);
    }
    @Deprecated
    public IRubyObject connect(IRubyObject hostIRubyObject port) {
        return connect(getRuntime().getCurrentContext(), hostport);
    }
    @Deprecated
    public IRubyObject recvfrom(IRubyObject[] args) {
        return recvfrom(getRuntime().getCurrentContext(), args);
    }
    @Deprecated
    public IRubyObject send(IRubyObject[] args) {
        return send(getRuntime().getCurrentContext(), args);
    }
    @Deprecated
    public static IRubyObject open(IRubyObject recvIRubyObject[] argsBlock block) {
        return open(recv.getRuntime().getCurrentContext(), recvargsblock);
    }
}// RubyUDPSocket