@JRubyMethod(name = {"socketpair", "pair"}, meta = true) public static IRubyObject socketpair(ThreadContext context, IRubyObject recv, IRubyObject domain, IRubyObject type) { AddressFamily af = SocketUtils.addressFamilyFromArg(domain); if (af == null) af = AddressFamily.AF_UNIX; Sock s = SocketUtils.sockFromArg(type); if (s == null) s = Sock.SOCK_STREAM; if (af != AddressFamily.AF_UNIX || s != Sock.SOCK_STREAM) { throw context.runtime.newErrnoEOPNOTSUPPError("Socket.socketpair only supports streaming UNIX sockets"); } final Ruby runtime = context.runtime; // TODO: type and protocol UnixSocketChannel[] sp; try { sp = UnixSocketChannel.pair(); final RubyClass socketClass = runtime.getClass("Socket"); RubySocket sock0 = new RubySocket(runtime, socketClass); ChannelFD fd0 = newChannelFD(runtime, sp[0]); sock0.initFieldsFromDescriptor(runtime, fd0); sock0.initSocket(fd0); RubySocket sock1 = new RubySocket(runtime, socketClass); ChannelFD fd1 = newChannelFD(runtime, sp[1]); sock1.initFieldsFromDescriptor(runtime, fd1); sock1.initSocket(fd1); return runtime.newArray(sock0, sock1); } catch (IOException ioe) { throw runtime.newIOErrorFromException(ioe); } }
@JRubyMethod() public IRubyObject connect_nonblock(ThreadContext context, IRubyObject arg) { SocketAddress addr = addressForChannel(context, arg); doConnectNonblock(context, getChannel(), addr); return RubyFixnum.zero(context.runtime); }
@JRubyMethod() public IRubyObject bind(ThreadContext context, IRubyObject arg) { InetSocketAddress iaddr = Sockaddr.addressFromSockaddr_in(context, arg); doBind(context, getChannel(), iaddr); return RubyFixnum.zero(context.runtime); }
@JRubyMethod() public IRubyObject connect_nonblock(ThreadContext context, IRubyObject arg, IRubyObject opts) { SocketAddress addr = addressForChannel(context, arg); return doConnectNonblock(context, addr, extractExceptionArg(context, opts)); }
@JRubyMethod() public IRubyObject connect(ThreadContext context, IRubyObject arg) { SocketAddress addr = addressForChannel(context, arg); return doConnect(context, addr, true); }
protected void doBind(ThreadContext context, SocketAddress iaddr) { Ruby runtime = context.runtime; Channel channel = getChannel(); handleSocketException(runtime, e, "bind(2)", iaddr); // throws throw sockerr(runtime, "bind(2): name or service not known", e); throw sockerr(runtime, e.getMessage(), e);
@JRubyMethod() public IRubyObject connect(ThreadContext context, IRubyObject arg) { SocketAddress addr = addressForChannel(context, arg); doConnect(context, getChannel(), addr); return RubyFixnum.zero(context.runtime); }
public static IRubyObject doAccept(RubySocket sock, ThreadContext context, boolean ex) { Ruby runtime = context.runtime; Channel channel = sock.getChannel(); try { if (channel instanceof ServerSocketChannel) { ServerSocketChannel serverChannel = (ServerSocketChannel)sock.getChannel(); SocketChannel socket = serverChannel.accept(); if (socket == null) { // This appears to be undocumented in JDK; null as a sentinel value // for a nonblocking accept with nothing available. We raise for Ruby. // indicates that no connection is available in non-blocking mode if (!ex) return runtime.newSymbol("wait_readable"); throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } RubySocket rubySocket = new RubySocket(runtime, runtime.getClass("Socket")); rubySocket.initFromServer(runtime, sock, socket); return runtime.newArray(rubySocket, new Addrinfo(runtime, runtime.getClass("Addrinfo"), socket.getRemoteAddress())); } throw runtime.newErrnoENOPROTOOPTError(); } catch (IllegalBlockingModeException e) { // indicates that no connection is available in non-blocking mode if (!ex) return runtime.newSymbol("wait_readable"); throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } catch (IOException e) { throw sockerr(runtime, e.getLocalizedMessage(), e); } }
@JRubyMethod(meta = true) public static IRubyObject for_fd(ThreadContext context, IRubyObject socketClass, IRubyObject fd) { Ruby runtime = context.runtime; if (fd instanceof RubyFixnum) { int intFD = (int)((RubyFixnum)fd).getLongValue(); ChannelDescriptor descriptor = ChannelDescriptor.getDescriptorByFileno(intFD); if (descriptor == null) { throw runtime.newErrnoEBADFError(); } RubySocket socket = (RubySocket)((RubyClass)socketClass).allocate(); socket.initFieldsFromDescriptor(runtime, descriptor); socket.initSocket(runtime, descriptor); return socket; } else { throw runtime.newTypeError(fd, context.runtime.getFixnum()); } }
private IRubyObject doConnectNonblock(ThreadContext context, SocketAddress addr, boolean ex) { Channel channel = getChannel(); if ( ! (channel instanceof SelectableChannel) ) { throw context.runtime.newErrnoENOPROTOOPTError(); } SelectableChannel selectable = (SelectableChannel) channel; synchronized (selectable.blockingLock()) { boolean oldBlocking = selectable.isBlocking(); try { selectable.configureBlocking(false); try { return doConnect(context, addr, ex); } finally { selectable.configureBlocking(oldBlocking); } } catch (ClosedChannelException e) { throw context.runtime.newErrnoECONNREFUSEDError(); } catch (IOException e) { throw sockerr(context.runtime, "connect(2): name or service not known", e); } } }
private RubySocket doAccept(ThreadContext context, Channel channel) { Ruby runtime = context.runtime; try { if (channel instanceof ServerSocketChannel) { ServerSocketChannel serverChannel = (ServerSocketChannel)getChannel(); SocketChannel socket = serverChannel.accept(); if (socket == null) { // This appears to be undocumented in JDK; null as a sentinel value // for a nonblocking accept with nothing available. We raise for Ruby. // indicates that no connection is available in non-blocking mode throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } RubySocket rubySocket = new RubySocket(runtime, runtime.getClass("Socket")); rubySocket.initFromServer(runtime, this, socket); return rubySocket; } else { throw runtime.newErrnoENOPROTOOPTError(); } } catch (IllegalBlockingModeException ibme) { // indicates that no connection is available in non-blocking mode throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } catch(IOException e) { throw SocketUtils.sockerr(runtime, e.getLocalizedMessage()); } }
protected SocketAddress getSocketAddress() { Channel channel = getChannel(); return SocketType.forChannel(channel).getLocalSocketAddress(channel); }
private void doConnectNonblock(ThreadContext context, Channel channel, SocketAddress addr) { if (!(channel instanceof SelectableChannel)) { throw getRuntime().newErrnoENOPROTOOPTError(); } SelectableChannel selectable = (SelectableChannel)channel; synchronized (selectable.blockingLock()) { boolean oldBlocking = selectable.isBlocking(); try { selectable.configureBlocking(false); try { doConnect(context, channel, addr); } finally { selectable.configureBlocking(oldBlocking); } } catch(ClosedChannelException e) { throw context.runtime.newErrnoECONNREFUSEDError(); } catch(IOException e) { throw SocketUtils.sockerr(context.runtime, "connect(2): name or service not known"); } } }
@Override public IRubyObject allocate(Ruby runtime, RubyClass klass) { return new RubySocket(runtime, klass); } };
public static int getPortFrom(ThreadContext context, IRubyObject _port) { int port; if (_port instanceof RubyInteger) { port = RubyNumeric.fix2int(_port); } else { IRubyObject portString = _port.convertToString(); IRubyObject portInteger = portString.convertToInteger( "to_i"); port = RubyNumeric.fix2int(portInteger); if (port <= 0) { port = RubyNumeric.fix2int(RubySocket.getservbyname( context, context.runtime.getObject(), new IRubyObject[]{portString})); } } return port; }
public void load(final Ruby runtime, boolean wrap) throws IOException { runtime.defineClass("SocketError", runtime.getStandardError(), runtime.getStandardError().getAllocator()); RubyBasicSocket.createBasicSocket(runtime); RubySocket.createSocket(runtime); RubyServerSocket.createServerSocket(runtime); if (runtime.getInstanceConfig().isNativeEnabled() && !Platform.IS_WINDOWS) { RubyUNIXSocket.createUNIXSocket(runtime); RubyUNIXServer.createUNIXServer(runtime); } RubyIPSocket.createIPSocket(runtime); RubyTCPSocket.createTCPSocket(runtime); RubyTCPServer.createTCPServer(runtime); RubyUDPSocket.createUDPSocket(runtime); Addrinfo.createAddrinfo(runtime); Option.createOption(runtime); Ifaddr.createIfaddr(runtime); } }
protected void doBind(ThreadContext context, Channel channel, InetSocketAddress iaddr) { Ruby runtime = context.runtime; try { if (channel instanceof SocketChannel) { Socket socket = ((SocketChannel)channel).socket(); socket.bind(iaddr); } else if (channel instanceof UnixSocketChannel) { // do nothing } else if (channel instanceof DatagramChannel) { DatagramSocket socket = ((DatagramChannel)channel).socket(); socket.bind(iaddr); } else { throw runtime.newErrnoENOPROTOOPTError(); } } catch(UnknownHostException e) { throw SocketUtils.sockerr(runtime, "bind(2): unknown host"); } catch(SocketException e) { handleSocketException(runtime, "bind", e); } catch(IOException e) { throw SocketUtils.sockerr(runtime, "bind(2): name or service not known"); } catch (IllegalArgumentException iae) { throw SocketUtils.sockerr(runtime, iae.getMessage()); } }
@JRubyMethod() public IRubyObject bind(ThreadContext context, IRubyObject arg) { final SocketAddress sockaddr; if (arg instanceof Addrinfo) { Addrinfo addr = (Addrinfo) arg; sockaddr = addr.getSocketAddress(); } else { sockaddr = Sockaddr.addressFromSockaddr(context, arg); } doBind(context, sockaddr); return RubyFixnum.zero(context.runtime); }
protected void doBind(ThreadContext context, SocketAddress iaddr) { Ruby runtime = context.runtime; Channel channel = getChannel(); handleSocketException(runtime, e, "bind(2)", iaddr); // throws throw sockerr(runtime, "bind(2): name or service not known", e); throw sockerr(runtime, e.getMessage(), e);
@JRubyMethod() public IRubyObject connect(ThreadContext context, IRubyObject arg) { SocketAddress addr = addressForChannel(context, arg); doConnect(context, getChannel(), addr); return RubyFixnum.zero(context.runtime); }