// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

const char* sa_to_str(const struct sockaddr* sa, char* str, size_t strlen) {
  if (sa->sa_family == AF_INET) {
    struct sockaddr_in* sin = (struct sockaddr_in*)sa;
    return inet_ntop(AF_INET, &sin->sin_addr, str, strlen);
  } else if (sa->sa_family == AF_INET6) {
    struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa;
    return inet_ntop(AF_INET6, &sin6->sin6_addr, str, strlen);
  } else {
    return NULL;
  }
}

int client(const char* if_address, const char* mc_address,
           const char* service) {
  unsigned short port = atoi(service);

  int s = socket(PF_INET, SOCK_DGRAM, 0);
  if (s < 0) {
    printf("socket failed (errno = %d)\n", errno);
    return -1;
  }

  unsigned char mc_ttl = 1;
  if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &mc_ttl, sizeof(mc_ttl)) <
      0) {
    printf("setsockopt: IP_MULTICAST_TTL failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  struct in_addr if_addr;
  if_addr.s_addr = inet_addr(if_address);
  if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &if_addr, sizeof(if_addr)) <
      0) {
    printf("setsockopt: IP_MULTICAST_IF failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  struct sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(mc_address);
  addr.sin_port = htons(port);

  char str[INET6_ADDRSTRLEN];
  printf("sending to %s\n",
         sa_to_str((struct sockaddr*)&addr, str, sizeof(str)));

  char message[1024];
  memset(message, 0, sizeof(message));
  while (fgets(message, sizeof(message), stdin)) {
    if (message[0] == '\n')
      break;

    int nsendto;
    nsendto = sendto(s, message, strlen(message), 0, (struct sockaddr*)&addr,
                     sizeof(addr));
    if (nsendto < 0) {
      printf("sendto failed (%d) (errno = %d)\n", nsendto, errno);
      close(s);
      return -1;
    }
  }
  close(s);

  return 0;
}

int server(const char* if_address, const char* mc_address,
           const char* service) {
  unsigned short port = atoi(service);

  int s = socket(PF_INET, SOCK_DGRAM, 0);
  if (s < 0) {
    printf("socket failed (errno = %d)\n", errno);
    return -1;
  }

  int on = 1;
  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
    printf("setsockopt: SO_REUSEADDR failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  struct sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(port);

  if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
    printf("bind failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  struct ip_mreqn mc_reqn;

  // optlen is set to either sizeof(struct ip_mreq) or sizeof(struct ip_mreqn)
  // depending on how we can parse if_address.
  size_t optlen = sizeof(struct ip_mreqn);

  if (!inet_aton(mc_address, &(mc_reqn.imr_multiaddr))) {
    printf("Invalid multicast_address: %s\n", mc_address);
    return -1;
  }

  // First try parsing |if_address| as an integer NIC ID. If it fails then parse
  // it as an IP address.
  char* end;
  mc_reqn.imr_ifindex = strtol(if_address, &end, 10);
  if (*end != '\0') {
    mc_reqn.imr_ifindex = 0;
    optlen = sizeof(struct ip_mreq);
    if (!inet_aton(if_address, &(mc_reqn.imr_address))) {
      // If if_address isn't an IP address then try parsing it as an integer and
      // pass it as NIC address in struct mc_reqn.
      printf("Invalid if_address: %s\n", if_address);
      return -1;
    }
  }

  if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc_reqn, optlen) != 0) {
    printf("setsockopt: IP_ADD_MEMBERSHIP failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc_reqn, optlen) == 0) {
    printf(
        "setsockopt: duplicate IP_ADD_MEMBERSHIP succeeded when it should have "
        "failed\n");
  }

  const int kIterations = 4;
  for (int i = 0; i < kIterations; i++) {
    printf("waiting %s:%d...\n", mc_address, port);

    char buf[128];
    int nrecv;
    socklen_t addrlen = sizeof(addr);
    nrecv = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &addrlen);
    if (nrecv < 0) {
      printf("recvfrom failed (%d) (errno = %d)\n", nrecv, errno);
      close(s);
      return -1;
    }
    char str[INET6_ADDRSTRLEN];
    printf("received %d bytes from %s\n", nrecv,
           sa_to_str((struct sockaddr*)&addr, str, sizeof(str)));
  }

  if (setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mc_reqn, optlen) != 0) {
    printf("setsockopt: IP_DROP_MEMBERSHIP failed (errno = %d)\n", errno);
    close(s);
    return -1;
  }

  if (setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mc_reqn, optlen) == 0) {
    printf(
        "setsockopt: duplicate IP_DROP_MEMBERSHIP succeeded when it should "
        "have failed\n");
  }
  close(s);

  return 0;
}

void usage(void) {
  printf(
      "usage: mctest server (if_address|nic_index) [multicast_address port]\n"
      "       mctest client if_address [multicast_address port]\n");
}

int main(int argc, char** argv) {
  if (argc == 3 || argc == 5) {
    char* mc_address = "232.43.211.234";
    char* service = "4321";
    if (argc == 5) {
      mc_address = argv[3];
      service = argv[4];
    }
    switch (argv[1][0]) {
      case 'c':  // client
        return client(argv[2], mc_address, service);
      case 's':  // server
        return server(argv[2], mc_address, service);
    }
  }
  usage();
  return -1;
}
