@JRubyMethod
  public IRubyObject setsockopt(
      ThreadContext context, IRubyObject _level, IRubyObject _opt, IRubyObject val) {
    Ruby runtime = context.runtime;

    SocketLevel level = levelFromArg(_level);
    SocketOption opt = optionFromArg(_opt);

    try {
      Channel channel = getOpenChannel();
      SocketType socketType = SocketType.forChannel(channel);

      switch (level) {
        case SOL_IP:
        case SOL_SOCKET:
        case SOL_TCP:
        case SOL_UDP:
          if (opt == SocketOption.SO_LINGER) {
            if (val instanceof RubyBoolean && !val.isTrue()) {
              socketType.setSoLinger(channel, false, 0);
            } else {
              int num = asNumber(val);
              if (num == -1) {
                socketType.setSoLinger(channel, false, 0);
              } else {
                socketType.setSoLinger(channel, true, num);
              }
            }

          } else {
            socketType.setSocketOption(channel, opt, asNumber(val));
          }

          break;

        default:
          int intLevel = (int) _level.convertToInteger().getLongValue();
          int intOpt = (int) _opt.convertToInteger().getLongValue();
          if (IPPROTO_TCP.intValue() == intLevel && TCP_NODELAY.intValue() == intOpt) {
            socketType.setTcpNoDelay(channel, asBoolean(val));

          } else if (IPPROTO_IP.intValue() == intLevel) {
            if (MulticastStateManager.IP_ADD_MEMBERSHIP == intOpt) {
              joinMulticastGroup(val);
            }

          } else {
            throw runtime.newErrnoENOPROTOOPTError();
          }
      }

    } catch (BadDescriptorException e) {
      throw runtime.newErrnoEBADFError();

    } catch (IOException e) {
      throw runtime.newErrnoENOPROTOOPTError();
    }
    return runtime.newFixnum(0);
  }
  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
  public IRubyObject getsockopt(ThreadContext context, IRubyObject _level, IRubyObject _opt) {
    Ruby runtime = context.runtime;

    SocketLevel level = levelFromArg(_level);
    SocketOption opt = optionFromArg(_opt);

    int value = 0;

    try {
      Channel channel = getOpenChannel();

      switch (level) {
        case SOL_SOCKET:
        case SOL_IP:
        case SOL_TCP:
        case SOL_UDP:
          if (opt == SocketOption.__UNKNOWN_CONSTANT__) {
            throw runtime.newErrnoENOPROTOOPTError();
          }

          value = SocketType.forChannel(channel).getSocketOption(channel, opt);

          if (runtime.is1_9()) {
            return new Option(runtime, ProtocolFamily.PF_INET, level, opt, value);
          } else {
            return number(runtime, SocketType.forChannel(channel).getSocketOption(channel, opt));
          }

        default:
          throw runtime.newErrnoENOPROTOOPTError();
      }

    } catch (BadDescriptorException e) {
      throw runtime.newErrnoEBADFError();

    } catch (IOException e) {
      throw runtime.newErrnoENOPROTOOPTError();
    }
  }
  private void doBind(
      ThreadContext context, Channel channel, InetSocketAddress iaddr, int backlog) {
    Ruby runtime = context.runtime;

    try {
      if (channel instanceof ServerSocketChannel) {
        ServerSocket socket = ((ServerSocketChannel) channel).socket();
        socket.bind(iaddr, backlog);
      } else {
        throw runtime.newErrnoENOPROTOOPTError();
      }
    } catch (UnknownHostException e) {
      throw SocketUtils.sockerr(runtime, "bind(2): unknown host");
    } catch (SocketException e) {
      handleSocketException(runtime, e, "bind(2)", iaddr);
    } catch (IOException e) {
      throw sockerr(runtime, "bind(2): name or service not known", e);
    } catch (IllegalArgumentException e) {
      throw sockerr(runtime, e.getMessage(), e);
    }
  }