Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 869c5e5667aa
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1a6f27a91684
Choose a head ref
  • 13 commits
  • 9 files changed
  • 2 contributors

Commits on Oct 10, 2016

  1. Copy the full SHA
    d73a809 View commit details
  2. Copy the full SHA
    3f36e15 View commit details
  3. Copy the full SHA
    76120f9 View commit details
  4. Clean up unused imports.

    headius authored and etehtsea committed Oct 10, 2016
    Copy the full SHA
    093d234 View commit details
  5. Copy the full SHA
    9bcfdd8 View commit details
  6. Add UDPSocket.new specs

    etehtsea committed Oct 10, 2016

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6227536 View commit details
  7. Fixes for UDPSocket.send based on rubysl-socket specs.

    * Handle Addrinfo or packed sockaddr as destination.
    * Try all addresses for a given hostname.
    headius authored and etehtsea committed Oct 10, 2016
    Copy the full SHA
    b56a192 View commit details
  8. Untag related mri tests

    etehtsea committed Oct 10, 2016
    Copy the full SHA
    d659903 View commit details
  9. Last fixes for UDPSocket based on rubysl-socket specs.

    * Handle family argument to initialize better.
    * Try all addresses for connect when no explicit family specified.
    * Raise proper error for wrong family.
    headius authored and etehtsea committed Oct 10, 2016
    Copy the full SHA
    9337fdd View commit details
  10. Copy the full SHA
    2c34eff View commit details
  11. Copy the full SHA
    4207acd View commit details

Commits on Oct 11, 2016

  1. Fix Addrinfo initialization

    Fixed initialization with nil nodename
    `Addrinfo.new(['AF_INET6', 59656, nil, '::1'], 30, 1, 6)`
    etehtsea committed Oct 11, 2016
    Copy the full SHA
    a5bf7de View commit details
  2. Merge pull request #4216 from etehtsea/socket-udp-improvements

    UDP socket improvements
    headius authored Oct 11, 2016
    Copy the full SHA
    1a6f27a View commit details
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -3778,6 +3778,10 @@ public RaiseException newErrnoEINTRError() {
return newRaiseException(getErrno().getClass("EINTR"), "Interrupted");
}

public RaiseException newErrnoEAFNOSUPPORTError(String message) {
return newRaiseException(getErrno().getClass("EAFNOSUPPORT"), message);
}

public RaiseException newErrnoFromLastPOSIXErrno() {
RubyClass errnoClass = getErrno(getPosix().errno());
if (errnoClass == null) errnoClass = systemCallError;
71 changes: 33 additions & 38 deletions core/src/main/java/org/jruby/ext/socket/Addrinfo.java
Original file line number Diff line number Diff line change
@@ -16,13 +16,10 @@
import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.Visibility;
import org.jruby.util.ByteList;

import java.io.ByteArrayOutputStream;
@@ -36,9 +33,9 @@
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.net.SocketException;

import java.util.regex.Pattern;
import org.jruby.exceptions.RaiseException;

import org.jruby.util.TypeConverter;
import org.jruby.util.io.Sockaddr;

@@ -174,6 +171,7 @@ private void initializeCommon(ThreadContext context, IRubyObject sockaddr, IRuby

try {
IRubyObject _sockaddrAry = TypeConverter.checkArrayType(sockaddr);

if (!_sockaddrAry.isNil()) {
RubyArray sockaddAry = (RubyArray)_sockaddrAry;

@@ -199,17 +197,13 @@ private void initializeCommon(ThreadContext context, IRubyObject sockaddr, IRuby
IRubyObject nodename = sockaddAry.eltOk(2);
IRubyObject numericnode = sockaddAry.eltOk(3);

if (!nodename.isNil()) {
nodename = nodename.convertToString();
}
numericnode = numericnode.convertToString();

InetAddress inetAddress = null;
int _port = service.convertToInteger().getIntValue();
try {
socketAddress = new InetSocketAddress(SocketUtils.getRubyInetAddress(nodename.convertToString().getByteList()), _port);
} catch (UnknownHostException uhe) {
socketAddress = new InetSocketAddress(SocketUtils.getRubyInetAddress(numericnode.convertToString().getByteList()), _port);
}

if (!nodename.isNil()) inetAddress = getRubyInetAddress(nodename);
if (inetAddress == null) inetAddress = getRubyInetAddress(numericnode);

this.socketAddress = new InetSocketAddress(inetAddress, _port);

// fall through below to finish setting up
} else {
@@ -222,28 +216,27 @@ private void initializeCommon(ThreadContext context, IRubyObject sockaddr, IRuby

InetAddress inetAddress = null;

try {
inetAddress = SocketUtils.getRubyInetAddress(sockaddrString.getByteList());

int _port;
if (port != null) {
_port = SocketUtils.portToInt(port);
} else {
_port = 0;
}

this.socketAddress = new InetSocketAddress(inetAddress, _port);

if (getInetAddress() instanceof Inet4Address) {
this.pfamily = PF_INET;
} else {
this.pfamily = PF_INET6;
}
} catch (UnknownHostException uhe) {
inetAddress = getRubyInetAddress(sockaddr);
if (inetAddress == null) {
// try unpacking
// FIXME: inefficient to allow exception before trying unpack
this.socketAddress = Sockaddr.sockaddrFromBytes(runtime, sockaddr.convertToString().getBytes());
}

int _port;
if (port != null) {
_port = SocketUtils.portToInt(port);
} else {
_port = 0;
}

this.socketAddress = new InetSocketAddress(inetAddress, _port);

if (getInetAddress() instanceof Inet4Address) {
this.pfamily = PF_INET;
} else {
this.pfamily = PF_INET6;
}
}

this.socketType = SocketType.SOCKET;
@@ -294,7 +287,6 @@ public IRubyObject inspect_sockaddr(ThreadContext context) {

int port = getInetSocketAddress().getPort();

// getHostAddress() returns ip in the full form, but MRI uses short;
if (getInetAddress() instanceof Inet6Address) {
String host = ipv6_ip();
String hostPort = port == 0 ? host : "[" + host + "]:" + port;
@@ -669,11 +661,15 @@ private String ipv6_ip() {
InetAddress in = getInetAddress();

if (in.isLoopbackAddress()) return "::1";
return ipv6Compact(in.getHostAddress());
return SocketUtilsIPV6.getIPV6Address(in.getHostAddress());
}

private static String ipv6Compact(String fullHost) {
return IPV6_COMPACT.matcher(fullHost).replaceAll("::$2");
private InetAddress getRubyInetAddress(IRubyObject node) {
try {
return SocketUtils.getRubyInetAddresses(node.convertToString().getByteList())[0];
} catch (UnknownHostException uhe) {
return null;
}
}

@JRubyMethod(optional = 1)
@@ -788,5 +784,4 @@ AddressFamily getAddressFamily() {
private NetworkInterface networkInterface;
private boolean isBroadcast;
private Protocol protocol = Protocol.getProtocolByNumber(0);
private static final Pattern IPV6_COMPACT = Pattern.compile("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)");
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/socket/Ifaddr.java
Original file line number Diff line number Diff line change
@@ -154,7 +154,7 @@ private void setNetmask(InterfaceAddress it) throws Exception {
SubnetUtils utils = new SubnetUtils(subnet);
netmask = utils.getInfo().getNetmask();
} else if ( (it.getNetworkPrefixLength() != 0 ) && ( address instanceof Inet6Address) ) {
netmask = new SocketUtilsIPV6().getIPV6NetMask(ipAddress() + "/" + it.getNetworkPrefixLength());
netmask = SocketUtilsIPV6.getIPV6NetMask(ipAddress() + "/" + it.getNetworkPrefixLength());
}
}

143 changes: 97 additions & 46 deletions core/src/main/java/org/jruby/ext/socket/RubyUDPSocket.java
Original file line number Diff line number Diff line change
@@ -30,8 +30,11 @@
import java.io.IOException;
import java.net.BindException;
import java.net.ConnectException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.PortUnreachableException;
import java.net.ProtocolFamily;
import java.net.SocketAddress;
@@ -65,6 +68,8 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.io.Sockaddr;


/**
* @author <a href="mailto:pldms@mac.com">Damian Steer</a>
@@ -101,13 +106,17 @@ public IRubyObject initialize(ThreadContext context) {

@JRubyMethod(visibility = Visibility.PRIVATE)
public IRubyObject initialize(ThreadContext context, IRubyObject _family) {
int family = _family.convertToInteger().getIntValue();
if (family == AddressFamily.AF_INET.intValue()) {
AddressFamily family = SocketUtils.addressFamilyFromArg(_family);

if (family == AddressFamily.AF_INET) {
explicitFamily = Inet4Address.class;
return initialize(context, StandardProtocolFamily.INET);
} else if (family == AddressFamily.AF_INET6.intValue()) {
} else if (family == AddressFamily.AF_INET6) {
explicitFamily = Inet6Address.class;
return initialize(context, StandardProtocolFamily.INET6);
}
throw SocketUtils.sockerr(context.runtime, "invalid family for UDPSocket: " + _family);

throw context.runtime.newErrnoEAFNOSUPPORTError("invalid family for UDPSocket: " + _family);
}

public IRubyObject initialize(ThreadContext context, ProtocolFamily family) {
@@ -196,15 +205,30 @@ else if (host instanceof RubyFixnum) {
}

@JRubyMethod
public IRubyObject connect(ThreadContext context, IRubyObject host, IRubyObject port) {
public IRubyObject connect(ThreadContext context, IRubyObject _host, IRubyObject port) {
Ruby runtime = context.runtime;

try {
InetSocketAddress addr = new InetSocketAddress(InetAddress.getByName(host.convertToString().toString()), SocketUtils.portToInt(port));
String host = _host.isNil() ? "localhost" : _host.convertToString().toString();
InetAddress[] addrs = InetAddress.getAllByName(host);

((DatagramChannel) this.getChannel()).connect(addr);
for (int i = 0; i < addrs.length; i++) {
InetAddress a = addrs[i];

return RubyFixnum.zero(runtime);
// If an explicit family is specified, don't try all addresses
if (explicitFamily != null && !explicitFamily.isInstance(a)) continue;

try {
InetSocketAddress addr = new InetSocketAddress(addrs[i], SocketUtils.portToInt(port));

((DatagramChannel) this.getChannel()).connect(addr);

return RubyFixnum.zero(runtime);
} catch (NoRouteToHostException nrthe) {
if (i+1 < addrs.length) continue;
throw nrthe;
}
}
}
catch (UnknownHostException e) {
throw SocketUtils.sockerr(runtime, "connect: name or service not known");
@@ -215,6 +239,9 @@ public IRubyObject connect(ThreadContext context, IRubyObject host, IRubyObject
catch (IllegalArgumentException e) {
throw SocketUtils.sockerr(runtime, e.getLocalizedMessage());
}

// should not get here
return context.nil;
}

private DatagramChannel getDatagramChannel() {
@@ -317,11 +344,6 @@ public IRubyObject send(ThreadContext context, IRubyObject _mesg, IRubyObject _f
}
}

@JRubyMethod
public IRubyObject send(ThreadContext context, IRubyObject _mesg, IRubyObject _flags, IRubyObject _to) {
return send(context, _mesg, _flags);
}

@JRubyMethod(required = 2, optional = 2)
public IRubyObject send(ThreadContext context, IRubyObject[] args) {
// TODO: implement flags
@@ -332,64 +354,91 @@ public IRubyObject send(ThreadContext context, IRubyObject[] args) {
try {
int written;

if (args.length == 2 || args.length == 3) {
if (args.length == 2) {
return send(context, _mesg, _flags);
}

IRubyObject _host = args[2];
IRubyObject _port = args[3];
InetAddress[] addrs;
int port;
if (args.length == 3) {
InetSocketAddress sockAddress;
IRubyObject sockaddr = args[2];
if (sockaddr instanceof Addrinfo) {
sockAddress = ((Addrinfo) sockaddr).getInetSocketAddress();
if (sockAddress == null) {
throw SocketUtils.sockerr(runtime, "need AF_INET or AF_INET6 address");
}
} else {
sockAddress = Sockaddr.addressFromSockaddr_in(context, sockaddr);
}
addrs = new InetAddress[] {sockAddress.getAddress()};
port = sockAddress.getPort();
} else { // args.length >= 4
IRubyObject _host = args[2];
IRubyObject _port = args[3];

RubyString nameStr = _host.convertToString();
RubyString data = _mesg.convertToString();
ByteList dataBL = data.getByteList();
ByteBuffer buf = ByteBuffer.wrap(dataBL.unsafeBytes(), dataBL.begin(), dataBL.realSize());
RubyString nameStr = _host.convertToString();

byte[] buf2 = data.getBytes();
DatagramPacket sendDP;
if (_port instanceof RubyString) {

int port;
if (_port instanceof RubyString) {
Service service = Service.getServiceByName(_port.asJavaString(), "udp");

Service service = Service.getServiceByName(_port.asJavaString(), "udp");
if (service != null) {
port = service.getPort();
} else {
port = (int) _port.convertToInteger("to_i").getLongValue();
}

if (service != null) {
port = service.getPort();
} else {
port = (int)_port.convertToInteger("to_i").getLongValue();
port = (int) _port.convertToInteger().getLongValue();
}

} else {
port = (int)_port.convertToInteger().getLongValue();
addrs = SocketUtils.getRubyInetAddresses(nameStr.getByteList());
}

InetAddress address = SocketUtils.getRubyInetAddress(nameStr.getByteList());
InetSocketAddress addr = new InetSocketAddress(address, port);
RubyString data = _mesg.convertToString();
ByteBuffer buf = ByteBuffer.wrap(data.getBytes());

if (this.multicastStateManager == null) {
written = ((DatagramChannel) this.getChannel()).send(buf, addr);
byte[] buf2 = data.getBytes();
DatagramPacket sendDP;

} else {
sendDP = new DatagramPacket(buf2, buf2.length, address, port);
multicastStateManager.rebindToPort(port);
MulticastSocket ms = this.multicastStateManager.getMulticastSocket();
for (int i = 0; i < addrs.length; i++) {
InetAddress inetAddress = addrs[i];
InetSocketAddress addr = new InetSocketAddress(inetAddress, port);

ms.send(sendDP);
written = sendDP.getLength();
}
try {
if (this.multicastStateManager == null) {
written = ((DatagramChannel) this.getChannel()).send(buf, addr);

return runtime.newFixnum(written);
} else {
sendDP = new DatagramPacket(buf2, buf2.length, addr);
multicastStateManager.rebindToPort(addr.getPort());
MulticastSocket ms = this.multicastStateManager.getMulticastSocket();

}
catch (UnknownHostException e) {
ms.send(sendDP);
written = sendDP.getLength();
}

return runtime.newFixnum(written);
} catch (NoRouteToHostException nrthe) {
if (i+1 < addrs.length) {
continue;
}
throw nrthe;
}
}
} catch (UnknownHostException e) {
throw SocketUtils.sockerr(runtime, "send: name or service not known");
}
catch (IOException e) { // SocketException
} catch (IOException e) { // SocketException
throw runtime.newIOErrorFromException(e);
}
catch (RaiseException e) { throw e; }
catch (Exception e) {
throw sockerr(runtime, e.getLocalizedMessage(), e);
}

// should not get here
return context.nil;
}

@JRubyMethod(rest = true, meta = true)
@@ -564,6 +613,8 @@ private static IRubyObject doReceiveMulticast(RubyBasicSocket socket, final Ruby
return result;
}

private volatile Class<? extends InetAddress> explicitFamily;

@Deprecated
public IRubyObject bind(IRubyObject host, IRubyObject port) {
return bind(getRuntime().getCurrentContext(), host, port);
Loading