/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.apache.geode.internal.shared;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sun.jna.Callback;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import org.apache.logging.log4j.Logger;

import org.apache.geode.SystemFailure;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.internal.cache.DiskStoreImpl;
import org.apache.geode.internal.process.signal.Signal;
import org.apache.geode.logging.internal.log4j.api.LogService;


/**
 * Implementation of {@link NativeCalls} interface that encapsulates native C calls via JNA. To
 * obtain an instance of JNA based implementation for the current platform, use
 * {@link NativeCallsJNAImpl#getInstance()}.
 *
 * BridJ is supposed to be cleaner, faster but it does not support Solaris/SPARC yet and its not a
 * mature library yet, so not using it. Can revisit once this changes.
 *
 * @since GemFire 8.0
 */
public class NativeCallsJNAImpl {

  private static final Logger logger = LogService.getLogger();

  // no instance allowed
  private NativeCallsJNAImpl() {}

  /**
   * The static instance of the JNA based implementation for this platform.
   */
  @Immutable
  private static final NativeCalls instance = getImplInstance();

  private static NativeCalls getImplInstance() {
    if (Platform.isLinux()) {
      return new LinuxNativeCalls();
    }
    if (Platform.isWindows()) {
      return new WinNativeCalls();
    }
    if (Platform.isSolaris()) {
      return new SolarisNativeCalls();
    }
    if (Platform.isMac()) {
      return new MacOSXNativeCalls();
    }
    if (Platform.isFreeBSD()) {
      return new FreeBSDNativeCalls();
    }
    return new POSIXNativeCalls();
  }

  /**
   * Get an instance of JNA based implementation of {@link NativeCalls} for the current platform.
   */
  public static NativeCalls getInstance() {
    return instance;
  }

  /**
   * Implementation of {@link NativeCalls} for POSIX compatible platforms.
   */
  private static class POSIXNativeCalls extends NativeCalls {

    static {
      Native.register("c");
    }

    public static native int setenv(String name, String value, int overwrite)
        throws LastErrorException;

    public static native int unsetenv(String name) throws LastErrorException;

    public static native String getenv(String name);

    public static native int getpid();

    public static native int kill(int processId, int signal) throws LastErrorException;

    public static native int setsid() throws LastErrorException;

    public static native int umask(int mask);

    public static native int signal(int signum, SignalHandler handler);

    public static native int setsockopt(int sockfd, int level, int optName, IntByReference optVal,
        int optSize) throws LastErrorException;

    public static native int close(int fd) throws LastErrorException;

    public static native int isatty(int fd) throws LastErrorException;

    static final int EPERM = 1;
    static final int ENOSPC = 28;

    /** Signal callback handler for <code>signal</code> native call. */
    interface SignalHandler extends Callback {
      void callback(int signum);
    }

    /**
     * holds a reference of {@link SignalHandler} installed in {@link #daemonize} for SIGHUP to
     * avoid it being GCed. Assumes that the NativeCalls instance itself is a singleton and never
     * GCed.
     */
    SignalHandler hupHandler;

    /**
     * the {@link RehashServerOnSIGHUP} instance sent to {@link #daemonize}
     */
    RehashServerOnSIGHUP rehashCallback;

    /**
     * @see NativeCalls#getOSType()
     */
    @Override
    public OSType getOSType() {
      return OSType.GENERIC_POSIX;
    }

    /**
     * @see NativeCalls#getEnvironment(String)
     */
    @Override
    public synchronized String getEnvironment(final String name) {
      if (name == null) {
        throw new UnsupportedOperationException("getEnvironment() for name=NULL");
      }
      return getenv(name);
    }

    /**
     * @see NativeCalls#getProcessId()
     */
    @Override
    public int getProcessId() {
      return getpid();
    }

    /**
     * @see NativeCalls#isProcessActive(int)
     */
    @Override
    public boolean isProcessActive(final int processId) {
      try {
        return kill(processId, 0) == 0;
      } catch (LastErrorException le) {
        if (le.getErrorCode() == EPERM) {
          // Process exists; it probably belongs to another user (bug 27698).
          return true;
        }
      }
      return false;
    }

    /**
     * @see NativeCalls#killProcess(int)
     */
    @Override
    public boolean killProcess(final int processId) {
      try {
        return kill(processId, 9) == 0;
      } catch (LastErrorException le) {
        return false;
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void daemonize(RehashServerOnSIGHUP callback) throws UnsupportedOperationException {
      UnsupportedOperationException err = null;
      try {
        setsid();
      } catch (LastErrorException le) {
        // errno=EPERM indicates already group leader
        if (le.getErrorCode() != EPERM) {
          err = new UnsupportedOperationException("Failed in setsid() in daemonize() due to "
              + le.getMessage() + " (errno=" + le.getErrorCode() + ')');
        }
      }
      // set umask to something consistent for servers
      final int newMask = 022;
      int oldMask = umask(newMask);
      // check if old umask was more restrictive, and if so then set it back
      if ((oldMask & 077) > newMask) {
        umask(oldMask);
      }
      // catch the SIGHUP signal and invoke any callback provided
      this.rehashCallback = callback;
      this.hupHandler = new SignalHandler() {
        @Override
        public void callback(int signum) {
          // invoke the rehash function if provided
          final RehashServerOnSIGHUP rehashCb = rehashCallback;
          if (signum == Signal.SIGHUP.getNumber() && rehashCb != null) {
            rehashCb.rehash();
          }
        }
      };
      signal(Signal.SIGHUP.getNumber(), this.hupHandler);
      // ignore SIGCHLD and SIGINT
      signal(Signal.SIGCHLD.getNumber(), this.hupHandler);
      signal(Signal.SIGINT.getNumber(), this.hupHandler);
      if (err != null) {
        throw err;
      }
    }

    @Override
    public void preBlow(String path, long maxSize, boolean preAllocate) throws IOException {
      if (logger.isDebugEnabled()) {
        logger.debug("DEBUG preBlow called for path = " + path);
      }
      if (!preAllocate || !hasFallocate(path)) {
        super.preBlow(path, maxSize, preAllocate);
        if (logger.isDebugEnabled()) {
          logger.debug("DEBUG preBlow super.preBlow 1 called for path = " + path);
        }
        return;
      }
      int fd = -1;
      boolean unknownError = false;
      try {
        fd = createFD(path, 00644);
        if (!isOnLocalFileSystem(path)) {
          super.preBlow(path, maxSize, preAllocate);
          if (logger.isDebugEnabled()) {
            logger.debug("DEBUG preBlow super.preBlow 2 called as path = " + path
                + " not on local file system");
          }
          if (DiskStoreImpl.TEST_NO_FALLOC_DIRS != null) {
            DiskStoreImpl.TEST_NO_FALLOC_DIRS.add(path);
          }
          return;
        }
        fallocateFD(fd, 0L, maxSize);
        if (DiskStoreImpl.TEST_CHK_FALLOC_DIRS != null) {
          DiskStoreImpl.TEST_CHK_FALLOC_DIRS.add(path);
        }
        if (logger.isDebugEnabled()) {
          logger.debug("DEBUG preBlow posix_fallocate called for path = " + path
              + " and ret = 0 maxsize = " + maxSize);
        }
      } catch (LastErrorException le) {
        if (logger.isDebugEnabled()) {
          logger.debug("DEBUG preBlow posix_fallocate called for path = " + path + " and ret = "
              + le.getErrorCode() + " maxsize = " + maxSize);
        }
        // check for no space left on device
        if (le.getErrorCode() == ENOSPC) {
          unknownError = false;
          throw new IOException("Not enough space left on device");
        } else {
          unknownError = true;
        }
      } finally {
        if (fd >= 0) {
          try {
            close(fd);
          } catch (Exception e) {
            // ignore
          }
        }
        if (unknownError) {
          super.preBlow(path, maxSize, preAllocate);
          if (logger.isDebugEnabled()) {
            logger.debug("DEBUG preBlow super.preBlow 3 called for path = " + path);
          }
        }
      }
    }

    protected boolean hasFallocate(String path) {
      return false;
    }

    protected int createFD(String path, int flags) throws LastErrorException {
      throw new UnsupportedOperationException("not expected to be invoked");
    }

    protected void fallocateFD(int fd, long offset, long len) throws LastErrorException {
      throw new UnsupportedOperationException("not expected to be invoked");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<TCPSocketOptions, Throwable> setSocketOptions(Socket sock, InputStream sockStream,
        Map<TCPSocketOptions, Object> optValueMap) throws UnsupportedOperationException {
      return super.setGenericSocketOptions(sock, sockStream, optValueMap);
    }

    @Override
    protected int setPlatformSocketOption(int sockfd, int level, int optName, TCPSocketOptions opt,
        Integer optVal, int optSize) throws NativeErrorException {
      try {
        return setsockopt(sockfd, level, optName, new IntByReference(optVal.intValue()), optSize);
      } catch (LastErrorException le) {
        throw new NativeErrorException(le.getMessage(), le.getErrorCode(), le.getCause());
      }
    }

    @Override
    public boolean isTTY() {
      try {
        return isatty(0) == 1;
      } catch (Exception e) {
        throw new RuntimeException("Couldn't find tty impl. ", e);
      }
    }

  }

  /**
   * Implementation of {@link NativeCalls} for Linux platform.
   */
  private static class LinuxNativeCalls extends POSIXNativeCalls {

    static {
      Native.register("c");
    }

    // #define values for keepalive options in /usr/include/netinet/tcp.h
    static final int OPT_TCP_KEEPIDLE = 4;
    static final int OPT_TCP_KEEPINTVL = 5;
    static final int OPT_TCP_KEEPCNT = 6;

    static final int ENOPROTOOPT = 92;
    static final int ENOPROTOOPT_ALPHA = 42;
    static final int ENOPROTOOPT_MIPS = 99;
    static final int ENOPROTOOPT_PARISC = 220;

    /** posix_fallocate returns error number rather than setting errno */
    public static native int posix_fallocate64(int fd, long offset, long len);

    public static native int creat64(String path, int flags) throws LastErrorException;

    /**
     * {@inheritDoc}
     */
    @Override
    public OSType getOSType() {
      return OSType.LINUX;
    }

    @Override
    protected int getPlatformOption(TCPSocketOptions opt) throws UnsupportedOperationException {
      switch (opt) {
        case OPT_KEEPIDLE:
          return OPT_TCP_KEEPIDLE;
        case OPT_KEEPINTVL:
          return OPT_TCP_KEEPINTVL;
        case OPT_KEEPCNT:
          return OPT_TCP_KEEPCNT;
        default:
          throw new UnsupportedOperationException("unknown option " + opt);
      }
    }

    @Override
    protected boolean isNoProtocolOptionCode(int errno) {
      switch (errno) {
        case ENOPROTOOPT:
          return true;
        case ENOPROTOOPT_ALPHA:
          return true;
        case ENOPROTOOPT_MIPS:
          return true;
        case ENOPROTOOPT_PARISC:
          return true;
        default:
          return false;
      }
    }

    static {
      if (Platform.is64Bit()) {
        StatFS64.dummy();
      } else {
        StatFS.dummy();
      }
    }

    private ThreadLocal<Structure> tSpecs = new ThreadLocal<Structure>();

    @MakeNotStatic
    private static boolean isStatFSEnabled;

    public static class FSIDIntArr2 extends Structure {

      public int[] fsid = new int[2];

      @Override
      protected List getFieldOrder() {
        return Arrays.asList(new String[] {"fsid"});
      }
    }

    public static class FSPAREIntArr5 extends Structure {

      public int[] fspare = new int[5];

      @Override
      protected List getFieldOrder() {
        return Arrays.asList(new String[] {"fspare"});
      }
    }

    public static class StatFS extends Structure {
      public int f_type;

      public int f_bsize;

      public int f_blocks;

      public int f_bfree;

      public int f_bavail;

      public int f_files;

      public int f_ffree;

      public FSIDIntArr2 f_fsid;

      public int f_namelen;

      public int f_frsize;

      public FSPAREIntArr5 f_spare;

      static {
        try {
          Native.register("rt");
          StatFS struct = new StatFS();
          int ret = statfs(".", struct);
          if (ret == 0) {
            isStatFSEnabled = true;
          } else {
            isStatFSEnabled = false;
          }
        } catch (VirtualMachineError e) {
          SystemFailure.initiateFailure(e);
          throw e;
        } catch (Throwable t) {
          SystemFailure.checkFailure();
          isStatFSEnabled = false;
        }
      }

      public static native int statfs(String path, StatFS statfs) throws LastErrorException;

      @Override
      protected List getFieldOrder() {
        return Arrays.asList(new String[] {"f_type", "f_bsize", "f_blocks", "f_bfree", "f_bavail",
            "f_files", "f_ffree", "f_fsid", "f_namelen", "f_frsize", "f_spare"});
      }

      // KN: TODO need to add more types which are type of remote.
      // Not sure about these file types which needs to be cheked and added in the list below
      // COH, DEVFS, ISOFS, OPENPROM_SUPER_MAGIC, PROC_SUPER_MAGIC, UDF_SUPER_MAGIC
      // Do man 2 statfs on linux and will give all the file types.
      // Following identified as remote file system types
      // CIFS_MAGIC_NUMBER, CODA_SUPER_MAGIC, NCP_SUPER_MAGIC, NFS_SUPER_MAGIC, SMB_SUPER_MAGIC,
      // TMPFS_MAGIC
      // 0xFF534D42 , 0x73757245 , 0x564c , 0x6969 , 0x517B , 0x01021994
      // 4283649346 , 1937076805 , 22092 , 26985 , 20859 , 16914836
      @Immutable
      private static final int[] REMOTE_TYPES =
          new int[] { /* 4283649346, */ 1937076805, 22092, 26985, 20859, 16914836};

      public boolean isTypeLocal() {
        for (int i = 0; i < REMOTE_TYPES.length; i++) {
          if (REMOTE_TYPES[i] == f_type) {
            return false;
          }
        }
        return true;
      }

      public static void dummy() {

      }
    }

    public static class FSPARELongArr5 extends Structure {

      public long[] fspare = new long[5];

      @Override
      protected List getFieldOrder() {
        return Arrays.asList(new String[] {"fspare"});
      }
    }

    public static class StatFS64 extends Structure {
      public long f_type;

      public long f_bsize;

      public long f_blocks;

      public long f_bfree;

      public long f_bavail;

      public long f_files;

      public long f_ffree;

      public FSIDIntArr2 f_fsid;

      public long f_namelen;

      public long f_frsize;

      public FSPARELongArr5 f_spare;

      // KN: TODO need to add more types which are type of remote.
      // Not sure about these file types which needs to be checked and added in the list below
      // COH, DEVFS, ISOFS, OPENPROM_SUPER_MAGIC, PROC_SUPER_MAGIC, UDF_SUPER_MAGIC
      // Do man 2 statfs on linux and will give all the file types.
      // Following identified as remote file system types
      // CIFS_MAGIC_NUMBER, CODA_SUPER_MAGIC, NCP_SUPER_MAGIC, NFS_SUPER_MAGIC, SMB_SUPER_MAGIC,
      // TMPFS_MAGIC
      // 0xFF534D42 , 0x73757245 , 0x564c , 0x6969 , 0x517B , 0x01021994
      // 4283649346 , 1937076805 , 22092 , 26985 , 20859 , 16914836
      @Immutable
      private static final long[] REMOTE_TYPES =
          new long[] {4283649346l, 1937076805l, 22092l, 26985l, 20859l, 16914836l};

      static {
        try {
          Native.register("rt");
          StatFS64 struct = new StatFS64();
          int ret = statfs(".", struct);
          if (ret == 0) {
            isStatFSEnabled = true;
          } else {
            isStatFSEnabled = false;
          }
        } catch (Throwable t) {
          System.out.println("got error t: " + t.getMessage());
          t.printStackTrace();
          isStatFSEnabled = false;
        }
      }

      public static native int statfs(String path, StatFS64 statfs) throws LastErrorException;

      @Override
      protected List getFieldOrder() {
        return Arrays.asList(new String[] {"f_type", "f_bsize", "f_blocks", "f_bfree", "f_bavail",
            "f_files", "f_ffree", "f_fsid", "f_namelen", "f_frsize", "f_spare"});
      }


      public boolean isTypeLocal() {
        for (int i = 0; i < REMOTE_TYPES.length; i++) {
          if (REMOTE_TYPES[i] == f_type) {
            return false;
          }
        }
        return true;
      }

      public static void dummy() {

      }
    }

    /**
     * Get the file store type of a path. for example, /dev/sdd1(store name) /w2-gst-dev40d(mount
     * point) ext4(type)
     *
     * @return file store type
     */
    public String getFileStoreType(final String path) {
      File diskFile = new File(path);
      if (!diskFile.exists()) {
        diskFile = diskFile.getParentFile();
      }
      Path currentPath = diskFile.toPath();
      if (currentPath.isAbsolute() && Files.exists(currentPath)) {
        try {
          FileStore store = Files.getFileStore(currentPath);
          return store.type();
        } catch (IOException e) {
          return null;
        }
      }
      return null;
    }

    /**
     * This will return whether the path passed in as arg is part of a local file system or a remote
     * file system. This method is mainly used by the DiskCapacityMonitor thread and we don't want
     * to monitor remote fs available space as due to network problems/firewall issues the call to
     * getUsableSpace can hang. See bug #49155. On platforms other than Linux this will return false
     * even if it on local file system for now.
     */
    @Override
    public boolean isOnLocalFileSystem(final String path) {
      if (!isStatFSEnabled) {
        // if (logger != null && logger.fineEnabled()) {
        // logger.info("DEBUG isOnLocalFileSystem returning false 1 for path = " + path);
        // }
        return false;
      }
      final int numTries = 10;
      for (int i = 1; i <= numTries; i++) {
        try {
          if (Platform.is64Bit()) {
            StatFS64 stat = new StatFS64();
            StatFS64.statfs(path, stat);
            // if (logger != null && logger.fineEnabled()) {
            // logger.info("DEBUG 64 isOnLocalFileSystem returning " + stat.isTypeLocal() + " for
            // path = " + path);
            // }
            return stat.isTypeLocal();
          } else {
            StatFS stat = new StatFS();
            StatFS.statfs(path, stat);
            // if (logger != null && logger.fineEnabled()) {
            // logger.fine("DEBUG 32 isOnLocalFileSystem returning " + stat.isTypeLocal() + " for
            // path = " + path);
            // }
            return stat.isTypeLocal();
          }
        } catch (LastErrorException le) {
          // ignoring it as NFS mounted can give this exception
          // and we just want to retry to remove transient problem.
          if (logger.isDebugEnabled()) {
            logger.debug("DEBUG isOnLocalFileSystem got ex = " + le + " msg = " + le.getMessage());
          }
        }
      }
      return false;
    }

    @Immutable
    private static final String[] FallocateFileSystems = {"ext4", "xfs", "btrfs", "ocfs2"};

    @Override
    protected boolean hasFallocate(String path) {
      String fstype = getFileStoreType(path);
      for (String type : FallocateFileSystems) {
        if (type.equalsIgnoreCase(fstype)) {
          return true;
        }
      }
      return false;
    }

    @Override
    protected int createFD(String path, int flags) throws LastErrorException {
      return creat64(path, flags);
    }

    @Override
    protected void fallocateFD(int fd, long offset, long len) throws LastErrorException {
      int errno = posix_fallocate64(fd, offset, len);
      if (errno != 0) {
        throw new LastErrorException(errno);
      }
    }
  }

  /**
   * Implementation of {@link NativeCalls} for Solaris platform.
   */
  private static class SolarisNativeCalls extends POSIXNativeCalls {

    static {
      Native.register("nsl");
      Native.register("socket");
    }

    // #define values for keepalive options in /usr/include/netinet/tcp.h
    // Below are only available on Solaris 11 and above but older platforms will
    // throw an exception which higher layers will handle appropriately
    static final int OPT_TCP_KEEPALIVE_THRESHOLD = 0x16;
    static final int OPT_TCP_KEEPALIVE_ABORT_THRESHOLD = 0x17;

    static final int ENOPROTOOPT = 99;

    /**
     * {@inheritDoc}
     */
    @Override
    public OSType getOSType() {
      return OSType.SOLARIS;
    }

    @Override
    protected int getPlatformOption(TCPSocketOptions opt) throws UnsupportedOperationException {
      switch (opt) {
        case OPT_KEEPIDLE:
          return OPT_TCP_KEEPALIVE_THRESHOLD;
        case OPT_KEEPINTVL:
        case OPT_KEEPCNT:
          return UNSUPPORTED_OPTION;
        default:
          throw new UnsupportedOperationException("unknown option " + opt);
      }
    }

    @Override
    protected int setPlatformSocketOption(int sockfd, int level, int optName, TCPSocketOptions opt,
        Integer optVal, int optSize) throws NativeErrorException {
      try {
        switch (optName) {
          case OPT_TCP_KEEPALIVE_THRESHOLD:
            // value required is in millis
            final IntByReference timeout = new IntByReference(optVal.intValue() * 1000);
            int result = setsockopt(sockfd, level, optName, timeout, optSize);
            if (result == 0) {
              // setting ABORT_THRESHOLD to be same as KEEPALIVE_THRESHOLD
              return setsockopt(sockfd, level, OPT_TCP_KEEPALIVE_ABORT_THRESHOLD, timeout, optSize);
            } else {
              return result;
            }
          default:
            throw new UnsupportedOperationException("unsupported option " + opt);
        }
      } catch (LastErrorException le) {
        throw new NativeErrorException(le.getMessage(), le.getErrorCode(), le.getCause());
      }
    }

    @Override
    protected boolean isNoProtocolOptionCode(int errno) {
      return (errno == ENOPROTOOPT);
    }
  }

  /**
   * Implementation of {@link NativeCalls} for MacOSX platform.
   */
  private static class MacOSXNativeCalls extends POSIXNativeCalls {

    // #define values for keepalive options in /usr/include/netinet/tcp.h
    static final int OPT_TCP_KEEPALIVE = 0x10;

    static final int ENOPROTOOPT = 42;

    /**
     * {@inheritDoc}
     */
    @Override
    public OSType getOSType() {
      return OSType.MACOSX;
    }

    @Override
    protected int getPlatformOption(TCPSocketOptions opt) throws UnsupportedOperationException {
      switch (opt) {
        case OPT_KEEPIDLE:
          return OPT_TCP_KEEPALIVE;
        case OPT_KEEPINTVL:
        case OPT_KEEPCNT:
          return UNSUPPORTED_OPTION;
        default:
          throw new UnsupportedOperationException("unknown option " + opt);
      }
    }

    @Override
    protected boolean isNoProtocolOptionCode(int errno) {
      return (errno == ENOPROTOOPT);
    }
  }

  /**
   * Implementation of {@link NativeCalls} for FreeBSD platform.
   */
  private static class FreeBSDNativeCalls extends POSIXNativeCalls {

    // #define values for keepalive options in /usr/include/netinet/tcp.h
    static final int OPT_TCP_KEEPALIVE = 0x100;
    static final int OPT_TCP_KEEPINTVL = 0x200;
    static final int OPT_TCP_KEEPCNT = 0x400;

    static final int ENOPROTOOPT = 42;

    /**
     * {@inheritDoc}
     */
    @Override
    public OSType getOSType() {
      return OSType.FREEBSD;
    }

    @Override
    protected int getPlatformOption(TCPSocketOptions opt) throws UnsupportedOperationException {
      switch (opt) {
        case OPT_KEEPIDLE:
          return OPT_TCP_KEEPALIVE;
        case OPT_KEEPINTVL:
          return OPT_TCP_KEEPINTVL;
        case OPT_KEEPCNT:
          return OPT_TCP_KEEPCNT;
        default:
          throw new UnsupportedOperationException("unknown option " + opt);
      }
    }

    @Override
    protected boolean isNoProtocolOptionCode(int errno) {
      return (errno == ENOPROTOOPT);
    }
  }

  /**
   * Implementation of {@link NativeCalls} for Windows platforms.
   */
  private static class WinNativeCalls extends NativeCalls {

    static {
      // for socket operations
      Native.register("Ws2_32");
    }

    @SuppressWarnings("unused")
    public static class TcpKeepAlive extends Structure {
      public int onoff;
      public int keepalivetime;
      public int keepaliveinterval;

      @Override
      protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] {"onoff", "keepalivetime", "keepaliveinterval"});
      }
    }

    public static native int WSAIoctl(NativeLong sock, int controlCode, TcpKeepAlive value,
        int valueSize, Pointer outValue, int outValueSize, IntByReference bytesReturned,
        Pointer overlapped, Pointer completionRoutine) throws LastErrorException;

    static final int WSAENOPROTOOPT = 10042;
    static final int SIO_KEEPALIVE_VALS = -1744830460;

    private static class Kernel32 {

      static {
        // kernel32 requires stdcall calling convention
        Map<String, Object> kernel32Options = new HashMap<String, Object>();
        kernel32Options.put(Library.OPTION_CALLING_CONVENTION, StdCallLibrary.STDCALL_CONVENTION);
        kernel32Options.put(Library.OPTION_FUNCTION_MAPPER, StdCallLibrary.FUNCTION_MAPPER);
        final NativeLibrary kernel32Lib = NativeLibrary.getInstance("kernel32", kernel32Options);
        Native.register(kernel32Lib);
      }

      // Values below from windows.h header are hard-coded since there
      // does not seem any simple way to get those at build or run time.
      // Hopefully these will never change else all hell will break
      // loose in Windows world ...
      static final int PROCESS_QUERY_INFORMATION = 0x0400;
      static final int PROCESS_TERMINATE = 0x0001;
      static final int STILL_ACTIVE = 259;
      static final int INVALID_HANDLE = -1;

      public static native boolean SetEnvironmentVariableA(String name, String value)
          throws LastErrorException;

      public static native int GetEnvironmentVariableA(String name, byte[] pvalue, int psize);

      public static native int GetCurrentProcessId();

      public static native Pointer OpenProcess(int desiredAccess, boolean inheritHandle,
          int processId) throws LastErrorException;

      public static native boolean TerminateProcess(Pointer processHandle, int exitCode)
          throws LastErrorException;

      public static native boolean GetExitCodeProcess(Pointer processHandle,
          IntByReference exitCode) throws LastErrorException;

      public static native boolean CloseHandle(Pointer handle) throws LastErrorException;
    }

    /**
     * @see NativeCalls#getOSType()
     */
    @Override
    public OSType getOSType() {
      return OSType.WIN;
    }

    /**
     * @see NativeCalls#getEnvironment(String)
     */
    @Override
    public synchronized String getEnvironment(final String name) {
      if (name == null) {
        throw new UnsupportedOperationException("getEnvironment() for name=NULL");
      }
      int psize = Kernel32.GetEnvironmentVariableA(name, null, 0);
      if (psize > 0) {
        for (;;) {
          byte[] result = new byte[psize];
          psize = Kernel32.GetEnvironmentVariableA(name, result, psize);
          if (psize == (result.length - 1)) {
            return new String(result, 0, psize);
          } else if (psize <= 0) {
            return null;
          }
        }
      } else {
        return null;
      }
    }

    /**
     * @see NativeCalls#getProcessId()
     */
    @Override
    public int getProcessId() {
      return Kernel32.GetCurrentProcessId();
    }

    /**
     * @see NativeCalls#isProcessActive(int)
     */
    @Override
    public boolean isProcessActive(final int processId) {
      try {
        final Pointer procHandle =
            Kernel32.OpenProcess(Kernel32.PROCESS_QUERY_INFORMATION, false, processId);
        final long hval;
        if (procHandle == null
            || (hval = Pointer.nativeValue(procHandle)) == Kernel32.INVALID_HANDLE || hval == 0) {
          return false;
        } else {
          final IntByReference status = new IntByReference();
          final boolean result =
              Kernel32.GetExitCodeProcess(procHandle, status)
                  && status.getValue() == Kernel32.STILL_ACTIVE;
          Kernel32.CloseHandle(procHandle);
          return result;
        }
      } catch (LastErrorException le) {
        // some problem in getting process status
        return false;
      }
    }

    /**
     * @see NativeCalls#killProcess(int)
     */
    @Override
    public boolean killProcess(final int processId) {
      try {
        final Pointer procHandle =
            Kernel32.OpenProcess(Kernel32.PROCESS_TERMINATE, false, processId);
        final long hval;
        if (procHandle == null
            || (hval = Pointer.nativeValue(procHandle)) == Kernel32.INVALID_HANDLE || hval == 0) {
          return false;
        } else {
          final boolean result = Kernel32.TerminateProcess(procHandle, -1);
          Kernel32.CloseHandle(procHandle);
          return result;
        }
      } catch (LastErrorException le) {
        // some problem in killing the process
        return false;
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void daemonize(RehashServerOnSIGHUP callback)
        throws UnsupportedOperationException, IllegalStateException {
      throw new IllegalStateException("daemonize() not applicable for Windows platform");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<TCPSocketOptions, Throwable> setSocketOptions(Socket sock, InputStream sockStream,
        Map<TCPSocketOptions, Object> optValueMap) throws UnsupportedOperationException {
      final TcpKeepAlive optValue = new TcpKeepAlive();
      final int optSize = (Integer.SIZE / Byte.SIZE) * 3;
      TCPSocketOptions errorOpt = null;
      Throwable error = null;
      for (Map.Entry<TCPSocketOptions, Object> e : optValueMap.entrySet()) {
        TCPSocketOptions opt = e.getKey();
        Object value = e.getValue();
        // all options currently require an integer argument
        if (value == null || !(value instanceof Integer)) {
          throw new IllegalArgumentException("bad argument type "
              + (value != null ? value.getClass().getName() : "NULL") + " for " + opt);
        }
        switch (opt) {
          case OPT_KEEPIDLE:
            optValue.onoff = 1;
            // in millis
            optValue.keepalivetime = ((Integer) value).intValue() * 1000;
            break;
          case OPT_KEEPINTVL:
            optValue.onoff = 1;
            // in millis
            optValue.keepaliveinterval = ((Integer) value).intValue() * 1000;
            break;
          case OPT_KEEPCNT:
            errorOpt = opt;
            error = new UnsupportedOperationException(getUnsupportedSocketOptionMessage(opt));
            break;
          default:
            throw new UnsupportedOperationException("unknown option " + opt);
        }
      }
      final int sockfd = getSocketKernelDescriptor(sock, sockStream);
      final IntByReference nBytes = new IntByReference(0);
      try {
        if (WSAIoctl(new NativeLong(sockfd), SIO_KEEPALIVE_VALS, optValue, optSize, null, 0, nBytes,
            null, null) != 0) {
          errorOpt = TCPSocketOptions.OPT_KEEPIDLE; // using some option here
          error = new SocketException(getOSType() + ": error setting options: " + optValueMap);
        }
      } catch (LastErrorException le) {
        // check if the error indicates that option is not supported
        errorOpt = TCPSocketOptions.OPT_KEEPIDLE; // using some option here
        if (le.getErrorCode() == WSAENOPROTOOPT) {
          error = new UnsupportedOperationException(getUnsupportedSocketOptionMessage(errorOpt),
              new NativeErrorException(le.getMessage(), le.getErrorCode(), le.getCause()));
        } else {
          final SocketException se =
              new SocketException(getOSType() + ": failed to set options: " + optValueMap);
          se.initCause(le);
          error = se;
        }
      }
      return errorOpt != null ? Collections.singletonMap(errorOpt, error) : null;
    }
  }
}
