/*
 * Copyright 2015 Twitter, Inc.
 *
 * Licensed 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.
 */

#include "basics/sockutils.h"
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include "glog/logging.h"
#include "config/heron-config.h"
#include "basics/sprcodes.h"
#include "basics/spconsts.h"

sp_int32 SockUtils::setNonBlocking(sp_int32 fd) {
  sp_int32 flags;
  if ((flags = ::fcntl(fd, F_GETFL, 0)) < 0) return SP_NOTOK;

  if (::fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) return SP_NOTOK;

  return SP_OK;
}

sp_int32 SockUtils::getSendBufferSize(sp_int32 fd, sp_int32 &size) {
  socklen_t optlen = sizeof(sp_int32);
  return ::getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, &optlen);
}

sp_int32 SockUtils::setSendBufferSize(sp_int32 fd, sp_int32 size) {
  return ::setsockopt(fd, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char *>(&size), sizeof(size));
}

sp_int32 SockUtils::getRecvBufferSize(sp_int32 fd, sp_int32 &size) {
  socklen_t optlen = sizeof(sp_int32);
  return ::getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, &optlen);
}

sp_int32 SockUtils::setRecvBufferSize(sp_int32 fd, sp_int32 size) {
  return ::setsockopt(fd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char *>(&size), sizeof(size));
}

sp_int32 SockUtils::setKeepAlive(sp_int32 fd) {
  sp_int32 alive = 1;
  return ::setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<char *>(&alive),
                      sizeof(alive));
}

sp_int32 SockUtils::setReuseAddress(sp_int32 fd) {
  sp_int32 sopt = 1;
  return ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&sopt), sizeof(sopt));
}

sp_int32 SockUtils::setKeepIdleTime(sp_int32 fd, sp_int32 time) {
#if defined(IS_MACOSX)
  sp_int32 on = 1;
  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) return SP_NOTOK;
  return ::setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, reinterpret_cast<char *>(&time),
                      sizeof(time));
#else
  return ::setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, reinterpret_cast<char *>(&time), sizeof(time));
#endif
}

sp_int32 SockUtils::setKeepIdleCount(sp_int32 fd, sp_int32 count) {
#if defined(IS_MACOSX)
  return ::setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, reinterpret_cast<char *>(&count),
                      sizeof(count));
#else
  return ::setsockopt(fd, SOL_TCP, TCP_KEEPCNT, reinterpret_cast<char *>(&count), sizeof(count));
#endif
}

sp_int32 SockUtils::setKeepIdleInterval(sp_int32 fd, sp_int32 interval) {
#if defined(IS_MACOSX)
  return ::setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, reinterpret_cast<char *>(&interval),
                      sizeof(interval));
#else
  return ::setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, reinterpret_cast<char *>(&interval),
                      sizeof(interval));
#endif
}

sp_int32 SockUtils::setKeepIdleParams(sp_int32 fd, sp_int32 time, sp_int32 count,
                                      sp_int32 interval) {
  if (SockUtils::setKeepIdleTime(fd, time) < 0) {
    PLOG(ERROR) << "unable to set keep idle time ";
    return SP_NOTOK;
  }

  if (SockUtils::setKeepIdleCount(fd, count) < 0) {
    PLOG(ERROR) << "unable to set keep idle count ";
    return SP_NOTOK;
  }

  if (SockUtils::setKeepIdleInterval(fd, interval) < 0) {
    PLOG(ERROR) << "unable to set keep idle interval ";
    return SP_NOTOK;
  }

  return SP_OK;
}

sp_int32 SockUtils::setTcpNoDelay(sp_int32 fd) {
  sp_int32 on = 1;
  return ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&on), sizeof(on));
}

sp_int32 SockUtils::setSocketDefaults(sp_int32 fd) {
  // set the max send buffer size so that it makes the pipe fatter
  sp_int32 send_buff;

  // get the send buffer size
  auto res = SockUtils::getSendBufferSize(fd, send_buff);
  if (res == SP_NOTOK) {
    PLOG(ERROR) << "Could not get the max SO_SNDBUF size";
  } else {
    // Set to a dummy high value. Linux will fall back to max. OSX will throw an error.
    send_buff *= 100;
    res = SockUtils::setSendBufferSize(fd, send_buff);
    if (res == SP_NOTOK) {
      PLOG(ERROR) << "Could not set SO_SNDBUF to max " << send_buff;
    }
  }

  // set the max recv buffer size so that it makes the pipe fatter

  // get the recv buffer size
  sp_int32 recv_buff;
  res = SockUtils::getRecvBufferSize(fd, recv_buff);
  if (res == SP_NOTOK) {
    PLOG(ERROR) << "Could not get the max SO_RCVBUF size";
  } else {
    // Set to a dummy high value. Linux will fall back to max. OSX will throw an error.
    recv_buff *= 100;
    res = SockUtils::setRecvBufferSize(fd, recv_buff);
    if (res == SP_NOTOK) {
      PLOG(ERROR) << "Could not set SO_RCVBUF to max " << recv_buff;
    }
  }

  // make it non blocking
  if (SockUtils::setNonBlocking(fd) < 0) {
    PLOG(ERROR) << "unable to make socket non blocking";
    return SP_NOTOK;
  }

  // enable keepalive for this socket
  if (SockUtils::setKeepAlive(fd) < 0) {
    PLOG(ERROR) << "setsockopt for keepalive failed in server";
    return SP_NOTOK;
  }

  // set a reasonable keepalive
  sp_int32 ka_idle = constTcpKeepAliveSecs;
  sp_int32 ka_interval = constTcpKeepAliveProbeInterval;
  sp_int32 ka_nprobes = constTcpKeepAliveProbes;

  if (SockUtils::setKeepIdleParams(fd, ka_idle, ka_nprobes, ka_interval) < 0) {
    PLOG(ERROR) << "setsockopt for keepalive failed ";
    return SP_NOTOK;
  }

  if (SockUtils::setTcpNoDelay(fd)) {
    PLOG(ERROR) << "setting tcp_nodelay failed ";
    return SP_NOTOK;
  }

  return SP_OK;
}
