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); } }
public static IRubyObject doAcceptNonblock(RubySocket sock, ThreadContext context, boolean ex) { try { Channel channel = sock.getChannel(); if (channel instanceof SelectableChannel) { SelectableChannel selectable = (SelectableChannel) channel; synchronized (selectable.blockingLock()) { boolean oldBlocking = selectable.isBlocking(); try { selectable.configureBlocking(false); IRubyObject socket = doAccept(sock, context, ex); if (!(socket instanceof RubySocket)) return socket; SocketChannel socketChannel = (SocketChannel) ((RubySocket) socket).getChannel(); InetSocketAddress addr = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); return context.runtime.newArray( socket, Sockaddr.packSockaddrFromAddress(context, addr)); } finally { selectable.configureBlocking(oldBlocking); } } } else { throw context.runtime.newErrnoENOPROTOOPTError(); } } catch (IOException e) { throw sockerr(context.runtime, e.getLocalizedMessage(), e); } }
@JRubyMethod(name = {"getsockname", "__getsockname"}) public IRubyObject getsockname(ThreadContext context) { SocketAddress sock = getLocalSocket(); if (null == sock) { return RubySocket.pack_sockaddr_in(context, null, 0, "0.0.0.0"); } return context.getRuntime().newString(sock.toString()); }
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; }
@JRubyMethod( name = "initialize", required = 1, optional = 1, visibility = Visibility.PRIVATE, backtrace = true) public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { IRubyObject hostname = args[0]; IRubyObject port = args.length > 1 ? args[1] : context.getRuntime().getNil(); if (hostname.isNil() || ((hostname instanceof RubyString) && ((RubyString) hostname).isEmpty())) { hostname = context.getRuntime().newString("0.0.0.0"); } else if (hostname instanceof RubyFixnum) { // numeric host, use it for port port = hostname; hostname = context.getRuntime().newString("0.0.0.0"); } String shost = hostname.convertToString().toString(); try { InetAddress addr = InetAddress.getByName(shost); ssc = ServerSocketChannel.open(); int portInt; if (port instanceof RubyInteger) { portInt = RubyNumeric.fix2int(port); } else { IRubyObject portString = port.convertToString(); IRubyObject portInteger = portString.convertToInteger("to_i"); portInt = RubyNumeric.fix2int(portInteger); if (portInt <= 0) { portInt = RubyNumeric.fix2int( RubySocket.getservbyname( context, context.getRuntime().getObject(), new IRubyObject[] {portString})); } } socket_address = new InetSocketAddress(addr, portInt); ssc.socket().bind(socket_address); initSocket(context.getRuntime(), new ChannelDescriptor(ssc, new ModeFlags(ModeFlags.RDWR))); } catch (InvalidValueException ex) { throw context.getRuntime().newErrnoEINVALError(); } catch (UnknownHostException e) { throw sockerr(context.getRuntime(), "initialize: name or service not known"); } catch (BindException e) { // e.printStackTrace(); String msg = e.getMessage(); if (msg == null) { msg = "bind"; } else { msg = "bind - " + msg; } // This is ugly, but what can we do, Java provides the same BindingException // for both EADDRNOTAVAIL and EADDRINUSE, so we differentiate the errors // based on BindException's message. if (ADDR_NOT_AVAIL_PATTERN.matcher(msg).find()) { throw context.getRuntime().newErrnoEADDRNOTAVAILError(msg); } else { throw context.getRuntime().newErrnoEADDRINUSEError(msg); } } catch (SocketException e) { String msg = e.getMessage(); if (msg.indexOf("Permission denied") != -1) { throw context.getRuntime().newErrnoEACCESError("bind(2)"); } else { throw sockerr(context.getRuntime(), "initialize: name or service not known"); } } catch (IOException e) { throw sockerr(context.getRuntime(), "initialize: name or service not known"); } catch (IllegalArgumentException iae) { throw sockerr(context.getRuntime(), iae.getMessage()); } return this; }