/*
 * 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.logging.LogService;
import org.apache.geode.internal.process.signal.Signal;


/**
 * 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;
    }
  }
}
