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: 1b0ce40afde2
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 69f8c030fdd0
Choose a head ref
  • 7 commits
  • 6 files changed
  • 1 contributor

Commits on Jan 4, 2016

  1. Copy the full SHA
    33e09e6 View commit details
  2. Copy the full SHA
    bf0a102 View commit details
  3. Copy the full SHA
    570704c View commit details
  4. Expand lazy init to support UNIX server and datagram sockets.

    UNIX datagram sockets still require implementation in jnr-enxio.
    headius committed Jan 4, 2016
    Copy the full SHA
    b859493 View commit details
  5. Copy the full SHA
    276caa9 View commit details
  6. Copy the full SHA
    85b3b6d View commit details
  7. Copy the full SHA
    69f8c03 View commit details
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -4012,6 +4012,8 @@ public RaiseException newIOErrorFromException(final IOException ex) {
return newErrnoENFILEError();
case "Network is unreachable" :
return newErrnoENETUNREACHError();
case "Address already in use" :
return newErrnoEADDRINUSEError();
default :
if ( Platform.IS_WINDOWS ) {
if ( errorMessage.contains("connection was aborted") ) {
77 changes: 53 additions & 24 deletions core/src/main/java/org/jruby/ext/socket/RubyIPSocket.java
Original file line number Diff line number Diff line change
@@ -30,12 +30,14 @@

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubySymbol;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.TypeConverter;
import org.jruby.util.io.BadDescriptorException;
import org.jruby.util.io.Sockaddr;

@@ -57,33 +59,25 @@ static void createIPSocket(Ruby runtime) {
public RubyIPSocket(Ruby runtime, RubyClass type) {
super(runtime, type);
}

public IRubyObject addr(ThreadContext context) {
return addrCommon(context, true);
}

@JRubyMethod(name = "addr")
public IRubyObject addr19(ThreadContext context) {
return addrCommon(context, true);
public IRubyObject addr(ThreadContext context) {
return addrCommon(context, !context.getRuntime().isDoNotReverseLookupEnabled());
}

@JRubyMethod(name = "addr")
public IRubyObject addr19(ThreadContext context, IRubyObject reverse) {
return addrCommon(context, reverse.isTrue());
}

public IRubyObject peeraddr(ThreadContext context) {
return peeraddrCommon(context, true);
public IRubyObject addr(ThreadContext context, IRubyObject reverse) {
return addrCommon(context, reverse);
}

@JRubyMethod(name = "peeraddr")
public IRubyObject peeraddr19(ThreadContext context) {
return peeraddrCommon(context, true);
public IRubyObject peeraddr(ThreadContext context) {
return peeraddrCommon(context, !context.getRuntime().isDoNotReverseLookupEnabled());
}

@JRubyMethod(name = "peeraddr")
public IRubyObject peeraddr19(ThreadContext context, IRubyObject reverse) {
return peeraddrCommon(context, reverse.isTrue());
public IRubyObject peeraddr(ThreadContext context, IRubyObject reverse) {
return peeraddrCommon(context, reverse);
}

@JRubyMethod(meta = true)
@@ -147,26 +141,61 @@ public IRubyObject getpeername(ThreadContext context) {
return Sockaddr.packSockaddrFromAddress(context, sock);
}

private IRubyObject addrCommon(ThreadContext context, IRubyObject reverse) {
Boolean doReverse = doReverseLookup(context, reverse);
if (doReverse == null) doReverse = false;

return addrCommon(context, doReverse);
}

private IRubyObject addrCommon(ThreadContext context, boolean reverse) {
InetSocketAddress address = getInetSocketAddress();
InetSocketAddress address = getInetSocketAddress();

if (address == null) {
throw context.runtime.newErrnoENOTSOCKError("Not socket or not connected");
}
checkAddress(context, address);

return addrFor(context, address, reverse);
return addrFor(context, address, reverse);
}

private IRubyObject peeraddrCommon(ThreadContext context, boolean reverse) {
InetSocketAddress address = getInetRemoteSocket();

private void checkAddress(ThreadContext context, InetSocketAddress address) {
if (address == null) {
throw context.runtime.newErrnoENOTSOCKError("Not socket or not connected");
}
}

private IRubyObject peeraddrCommon(ThreadContext context, IRubyObject reverse) {
Boolean doReverse = doReverseLookup(context, reverse);
if (doReverse == null) doReverse = !context.runtime.isDoNotReverseLookupEnabled();

return peeraddrCommon(context, doReverse);
}

private IRubyObject peeraddrCommon(ThreadContext context, boolean reverse) {
InetSocketAddress address = getInetRemoteSocket();

checkAddress(context, address);

return addrFor(context, address, reverse);
}

private Boolean doReverseLookup(ThreadContext context, IRubyObject noreverse) {
Ruby runtime = context.runtime;

if (noreverse == runtime.getTrue()) {
return false;
} else if (noreverse == runtime.getFalse()) {
return true;
} else if (noreverse == context.nil) {
return null;
} else {
TypeConverter.checkType(context, noreverse, runtime.getSymbol());
switch (noreverse.toString()) {
case "numeric": return true;
case "hostname": return false;
default: throw runtime.newArgumentError("invalid reverse_lookup flag: " + noreverse);
}
}
}

@Deprecated
public IRubyObject addr() {
return addr(getRuntime().getCurrentContext());
87 changes: 53 additions & 34 deletions core/src/main/java/org/jruby/ext/socket/RubySocket.java
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@
import jnr.constants.platform.SocketOption;
import jnr.constants.platform.TCP;
import jnr.netdb.Protocol;
import jnr.unixsocket.UnixServerSocket;
import jnr.unixsocket.UnixServerSocketChannel;
import jnr.unixsocket.UnixSocketAddress;
import jnr.unixsocket.UnixSocketChannel;
@@ -219,21 +220,17 @@ public IRubyObject connect(ThreadContext context, IRubyObject arg) {

@JRubyMethod()
public IRubyObject bind(ThreadContext context, IRubyObject arg) {
final InetSocketAddress iaddr;
final SocketAddress sockaddr;

if (arg instanceof Addrinfo) {
Addrinfo addr = (Addrinfo) arg;
if (!addr.ip_p(context).isTrue()) {
throw context.runtime.newTypeError("not an INET or INET6 address: " + addr);
}
iaddr = new InetSocketAddress(addr.getInetAddress().getHostAddress(), addr.getPort());
}
else {
iaddr = Sockaddr.addressFromSockaddr_in(context, arg);
sockaddr = addr.getSocketAddress();
} else {
sockaddr = Sockaddr.addressFromSockaddr(context, arg);
}

// We will lazily bind later once we know what kind of channel to create
doBind(context, iaddr);
doBind(context, sockaddr);

return RubyFixnum.zero(context.runtime);
}
@@ -484,34 +481,35 @@ protected ChannelFD initChannelFD(ThreadContext context, boolean server) {

try {
Channel channel;
switch (soType) {
case SOCK_STREAM:
if ( soProtocolFamily == ProtocolFamily.PF_UNIX ||
soProtocolFamily == ProtocolFamily.PF_LOCAL ) {
if (server) {
channel = UnixServerSocketChannel.open();
} else {
channel = UnixSocketChannel.open();
}
}
else if ( soProtocolFamily == ProtocolFamily.PF_INET ||
soProtocolFamily == ProtocolFamily.PF_INET6 ||
soProtocolFamily == ProtocolFamily.PF_UNSPEC ) {
if (server) {
channel = ServerSocketChannel.open();
} else {
channel = SocketChannel.open();
}
}
else {
throw runtime.newArgumentError("unsupported protocol family `" + soProtocolFamily + "'");
switch (soProtocolFamily) {
case PF_UNIX:
case PF_LOCAL:
if (server) {
channel = UnixServerSocketChannel.open();
} else {
channel = UnixSocketChannel.open();
}
break;
case SOCK_DGRAM:
channel = DatagramChannel.open();
case PF_INET:
case PF_INET6:
case PF_UNSPEC:
switch (soType) {
case SOCK_STREAM:
if (server) {
channel = ServerSocketChannel.open();
} else {
channel = SocketChannel.open();
}
break;
case SOCK_DGRAM:
channel = DatagramChannel.open();
break;
default:
throw runtime.newArgumentError("unsupported socket type `" + soType + "'");
}
break;
default:
throw runtime.newArgumentError("unsupported socket type `" + soType + "'");
throw runtime.newArgumentError("unsupported protocol family `" + soProtocolFamily + "'");
}

return newChannelFD(runtime, channel);
@@ -653,12 +651,25 @@ else if (channel instanceof DatagramChannel) {
protected void doBind(ThreadContext context, SocketAddress iaddr) {
bindAddress = iaddr;

if ((soProtocolFamily == ProtocolFamily.PF_INET || soProtocolFamily == ProtocolFamily.PF_INET6) && soType == Sock.SOCK_DGRAM) {
if (canBindImmediately()) {
// datagram sockets can be initialized immediately after bind
lazyInit(context, false);
}
}

private boolean canBindImmediately() {
switch (soProtocolFamily) {
case PF_INET:
case PF_INET6:
if (soType == Sock.SOCK_DGRAM) return true;
break;
case PF_UNIX:
if (soType == Sock.SOCK_DGRAM) return true;
break;
}
return false;
}

protected void lazyBind(ThreadContext context) {
if (bindAddress == null) return;

@@ -679,6 +690,14 @@ else if (channel instanceof ServerSocketChannel) {
socket.bind(bindAddress, backlog);
}
}
else if (channel instanceof UnixServerSocketChannel) {
UnixServerSocket unixServer = ((UnixServerSocketChannel) channel).socket();
if (backlog == -1) {
unixServer.bind(bindAddress);
} else {
unixServer.bind(bindAddress, backlog);
}
}
else if (channel instanceof UnixSocketChannel) {
// do nothing
}
Original file line number Diff line number Diff line change
@@ -124,7 +124,7 @@ public IRubyObject peeraddr(ThreadContext context) {

return runtime.newArray(
runtime.newString("AF_UNIX"),
runtime.newString(openFile.getPath()));
runtime.newString(getUnixRemoteSocket().path()));
}

@JRubyMethod(name = "recvfrom", required = 1, optional = 1)
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/socket/SocketType.java
Original file line number Diff line number Diff line change
@@ -246,7 +246,7 @@ public SocketAddress getRemoteSocketAddress(Channel channel) {
}

public SocketAddress getLocalSocketAddress(Channel channel) {
return new UnixSocketAddress(new File("empty-path"));
return new UnixSocketAddress(new File(""));
}
},

56 changes: 44 additions & 12 deletions core/src/main/java/org/jruby/util/io/Sockaddr.java
Original file line number Diff line number Diff line change
@@ -49,17 +49,6 @@ public static String stringFromAddress(Ruby runtime, InetAddress as) {
}
}

public static InetSocketAddress addressFromSockaddr_in(ThreadContext context, IRubyObject arg) {
RubyArray sockaddr = (RubyArray) unpack_sockaddr_in(context, arg);

IRubyObject addr = sockaddr.pop(context);
IRubyObject _port = sockaddr.pop(context);
int port = SocketUtils.portToInt(_port);

return new InetSocketAddress(
addr.convertToString().toString(), port);
}

public static InetSocketAddress addressFromArg(ThreadContext context, IRubyObject arg) {
InetSocketAddress iaddr;
if (arg instanceof Addrinfo) {
@@ -75,8 +64,47 @@ public static InetSocketAddress addressFromArg(ThreadContext context, IRubyObjec
return iaddr;
}

public static InetSocketAddress addressFromSockaddr_in(ThreadContext context, IRubyObject arg) {
ByteList val = arg.convertToString().getByteList();
return addressFromSockaddr_in(context, val);
}

public static InetSocketAddress addressFromSockaddr_in(ThreadContext context, ByteList val) {
RubyArray sockaddr = (RubyArray) unpack_sockaddr_in(context, val);

IRubyObject addr = sockaddr.pop(context);
IRubyObject _port = sockaddr.pop(context);
int port = SocketUtils.portToInt(_port);

return new InetSocketAddress(
addr.convertToString().toString(), port);
}

public static SocketAddress addressFromSockaddr(ThreadContext context, IRubyObject arg) {
Ruby runtime = context.runtime;

ByteList val = arg.convertToString().getByteList();

AddressFamily af = getAddressFamilyFromSockaddr(runtime, val);

switch (af) {
case AF_UNIX:
return addressFromSockaddr_un(context, val);
case AF_INET:
case AF_INET6:
return addressFromSockaddr_in(context, val);
default:
throw runtime.newArgumentError("can't resolve socket address of wrong type");

}
}

public static UnixSocketAddress addressFromSockaddr_un(ThreadContext context, IRubyObject arg) {
ByteList bl = arg.convertToString().getByteList();
return addressFromSockaddr_un(context, bl);
}

public static UnixSocketAddress addressFromSockaddr_un(ThreadContext context, ByteList bl) {
byte[] raw = bl.bytes();

int end = 2;
@@ -91,8 +119,12 @@ public static UnixSocketAddress addressFromSockaddr_un(ThreadContext context, IR
}

public static IRubyObject unpack_sockaddr_in(ThreadContext context, IRubyObject addr) {
Ruby runtime = context.runtime;
ByteList val = addr.convertToString().getByteList();
return unpack_sockaddr_in(context, val);
}

public static IRubyObject unpack_sockaddr_in(ThreadContext context, ByteList val) {
Ruby runtime = context.runtime;

validateSockaddr(runtime, val);