/*
 * 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.
 */

#include <assert.h>
#include <string.h>
#include <stdint.h>

#include "os/mynewt.h"

#if (MYNEWT_VAL(OC_TRANSPORT_IP) == 1) && (MYNEWT_VAL(OC_TRANSPORT_IPV4) == 1)
#include <log/log.h>
#include <mn_socket/mn_socket.h>
#include <stats/stats.h>

#include "oic/oc_log.h"
#include "oic/port/oc_connectivity.h"
#include "oic/port/mynewt/adaptor.h"
#include "oic/port/mynewt/transport.h"
#include "oic/port/mynewt/ip.h"

static void oc_send_buffer_ip4(struct os_mbuf *m);
static void oc_send_buffer_ip4_mcast(struct os_mbuf *m);
static uint8_t oc_ep_ip4_size(const struct oc_endpoint *oe);
static char *oc_log_ep_ip4(char *ptr, int maxlen, const struct oc_endpoint *);
static int oc_connectivity_init_ip4(void);
void oc_connectivity_shutdown_ip4(void);
static void oc_event_ip4(struct os_event *ev);

static const struct oc_transport oc_ip4_transport = {
    .ot_flags = 0,
    .ot_ep_size = oc_ep_ip4_size,
    .ot_tx_ucast = oc_send_buffer_ip4,
    .ot_tx_mcast = oc_send_buffer_ip4_mcast,
    .ot_get_trans_security = NULL,
    .ot_ep_str = oc_log_ep_ip4,
    .ot_init = oc_connectivity_init_ip4,
    .ot_shutdown = oc_connectivity_shutdown_ip4
};

static struct os_event oc_sock4_read_event = {
    .ev_cb = oc_event_ip4,
};

#define COAP_PORT_UNSECURED (5683)

/* 224.0.1.187 */
static const struct mn_in_addr coap_all_nodes_v4 = {
    .s_addr = htonl(0xe00001bb)
};

STATS_SECT_START(oc_ip4_stats)
    STATS_SECT_ENTRY(iframe)
    STATS_SECT_ENTRY(ibytes)
    STATS_SECT_ENTRY(ierr)
    STATS_SECT_ENTRY(oucast)
    STATS_SECT_ENTRY(omcast)
    STATS_SECT_ENTRY(obytes)
    STATS_SECT_ENTRY(oerr)
STATS_SECT_END
STATS_SECT_DECL(oc_ip4_stats) oc_ip4_stats;
STATS_NAME_START(oc_ip4_stats)
    STATS_NAME(oc_ip4_stats, iframe)
    STATS_NAME(oc_ip4_stats, ibytes)
    STATS_NAME(oc_ip4_stats, ierr)
    STATS_NAME(oc_ip4_stats, oucast)
    STATS_NAME(oc_ip4_stats, omcast)
    STATS_NAME(oc_ip4_stats, obytes)
    STATS_NAME(oc_ip4_stats, oerr)
STATS_NAME_END(oc_ip4_stats)

/* sockets to use for coap unicast and multicast */
static struct mn_socket *oc_ucast4;

#if (MYNEWT_VAL(OC_SERVER) == 1)
static struct mn_socket *oc_mcast4;
#endif

#ifdef OC_SECURITY
#error This implementation does not yet support security
#endif

static char *
oc_log_ep_ip4(char *ptr, int maxlen, const struct oc_endpoint *oe)
{
    const struct oc_endpoint_ip *oe_ip = (const struct oc_endpoint_ip *)oe;
    int len;

    mn_inet_ntop(MN_PF_INET, oe_ip->v4.address, ptr, maxlen);
    len = strlen(ptr);
    snprintf(ptr + len, maxlen - len, "-%u", oe_ip->port);
    return ptr;
}

static uint8_t
oc_ep_ip4_size(const struct oc_endpoint *oe)
{
    return sizeof(struct oc_endpoint_ip);
}

static void
oc_send_buffer_ip4_int(struct os_mbuf *m, int is_mcast)
{
    struct mn_sockaddr_in to;
    struct oc_endpoint_ip *oe_ip;
    struct mn_itf itf;
    uint32_t if2_idx;
    struct os_mbuf *n;
    int rc;

    assert(OS_MBUF_USRHDR_LEN(m) >= sizeof(struct oc_endpoint_ip));
    oe_ip = (struct oc_endpoint_ip *)OC_MBUF_ENDPOINT(m);
    to.msin_len = sizeof(to);
    to.msin_family = MN_AF_INET;
    to.msin_port = htons(oe_ip->port);
    memcpy(&to.msin_addr, oe_ip->v4.address, sizeof(to.msin_addr));

    STATS_INCN(oc_ip4_stats, obytes, OS_MBUF_PKTLEN(m));
    if (is_mcast) {
        memset(&itf, 0, sizeof(itf));
        if2_idx = 0;

        while (1) {
            rc = mn_itf_getnext(&itf);
            if (rc) {
                break;
            }

            if ((itf.mif_flags & (MN_ITF_F_UP | MN_ITF_F_MULTICAST)) !=
              (MN_ITF_F_UP | MN_ITF_F_MULTICAST)) {
                continue;
            }

            if (!if2_idx) {
                if2_idx = itf.mif_idx;
                continue;
            }

            rc = mn_setsockopt(oc_ucast4, MN_SO_LEVEL, MN_MCAST_IF, &if2_idx);
            if (rc) {
                STATS_INC(oc_ip4_stats, oerr);
                continue;
            }
            n = os_mbuf_dup(m);
            if (!n) {
                STATS_INC(oc_ip4_stats, oerr);
                break;
            }
            rc = mn_sendto(oc_ucast4, n, (struct mn_sockaddr *)&to);
            if (rc != 0) {
                OC_LOG(ERROR, "Failed to send buffer %u on %x\n",
                             OS_MBUF_PKTHDR(m)->omp_len, if2_idx);
                STATS_INC(oc_ip4_stats, oerr);
                os_mbuf_free_chain(n);
            }
            if2_idx = itf.mif_idx;
        }
        if (if2_idx) {
            rc = mn_setsockopt(oc_ucast4, MN_SO_LEVEL, MN_MCAST_IF, &if2_idx);
            if (rc) {
                STATS_INC(oc_ip4_stats, oerr);
                os_mbuf_free_chain(m);
            } else {
                rc = mn_sendto(oc_ucast4, m, (struct mn_sockaddr *) &to);
                if (rc != 0) {
                    OC_LOG(ERROR, "Failed sending buffer %u on itf %x\n",
                                 OS_MBUF_PKTHDR(m)->omp_len, if2_idx);
                    STATS_INC(oc_ip4_stats, oerr);
                    os_mbuf_free_chain(m);
                }
            }
        } else {
            os_mbuf_free_chain(m);
        }
    } else {
        rc = mn_sendto(oc_ucast4, m, (struct mn_sockaddr *) &to);
        if (rc != 0) {
            OC_LOG(ERROR, "Failed to send buffer %u ucast\n",
                         OS_MBUF_PKTHDR(m)->omp_len);
            STATS_INC(oc_ip4_stats, oerr);
            os_mbuf_free_chain(m);
        }
    }
}

void
oc_send_buffer_ip4(struct os_mbuf *m)
{
    STATS_INC(oc_ip4_stats, oucast);
    oc_send_buffer_ip4_int(m, 0);
}
void
oc_send_buffer_ip4_mcast(struct os_mbuf *m)
{
    STATS_INC(oc_ip4_stats, omcast);
    oc_send_buffer_ip4_int(m, 1);
}

static struct os_mbuf *
oc_attempt_rx_ip4_sock(struct mn_socket *rxsock)
{
    int rc;
    struct os_mbuf *m;
    struct os_mbuf *n;
    struct oc_endpoint_ip *oe_ip;
    struct mn_sockaddr_in from;

    rc = mn_recvfrom(rxsock, &n, (struct mn_sockaddr *) &from);
    if (rc != 0) {
        return NULL;
    }
    assert(OS_MBUF_IS_PKTHDR(n));

    STATS_INC(oc_ip4_stats, iframe);
    STATS_INCN(oc_ip4_stats, ibytes, OS_MBUF_PKTLEN(n));
    m = os_msys_get_pkthdr(0, sizeof(struct oc_endpoint_ip));
    if (!m) {
        OC_LOG(ERROR, "Could not allocate RX buffer\n");
        goto rx_attempt_err;
    }
    OS_MBUF_PKTHDR(m)->omp_len = OS_MBUF_PKTHDR(n)->omp_len;
    SLIST_NEXT(m, om_next) = n;

    oe_ip = (struct oc_endpoint_ip *)OC_MBUF_ENDPOINT(m);

    oe_ip->ep.oe_type = oc_ip4_transport_id;
    oe_ip->ep.oe_flags = 0;
    memcpy(&oe_ip->v4.address, &from.msin_addr, sizeof(oe_ip->v4.address));
    oe_ip->port = ntohs(from.msin_port);

    return m;

    /* add the addr info to the message */
rx_attempt_err:
    STATS_INC(oc_ip4_stats, ierr);
    os_mbuf_free_chain(n);
    return NULL;
}

static struct os_mbuf *
oc_attempt_rx_ip4(void)
{
    struct os_mbuf *m;

    m = oc_attempt_rx_ip4_sock(oc_ucast4);
#if (MYNEWT_VAL(OC_SERVER) == 1)
    if (m == NULL) {
        m = oc_attempt_rx_ip4_sock(oc_mcast4);
    }
#endif
    return m;
}

static void oc_socks4_readable(void *cb_arg, int err);

union mn_socket_cb oc_sock4_cbs = {
    .socket.readable = oc_socks4_readable,
    .socket.writable = NULL
};

void
oc_socks4_readable(void *cb_arg, int err)
{
    os_eventq_put(oc_evq_get(), &oc_sock4_read_event);
}

void
oc_connectivity_shutdown_ip4(void)
{
    if (oc_ucast4) {
        mn_close(oc_ucast4);
    }

#if (MYNEWT_VAL(OC_SERVER) == 1)
    if (oc_mcast4) {
        mn_close(oc_mcast4);
    }
#endif
}

static void
oc_event_ip4(struct os_event *ev)
{
    struct os_mbuf *m;

    while ((m = oc_attempt_rx_ip4()) != NULL) {
        oc_recv_message(m);
    }
}

int
oc_connectivity_init_ip4(void)
{
    int rc;
    struct mn_sockaddr_in sin;
    struct mn_itf itf;

    memset(&itf, 0, sizeof(itf));

    rc = mn_socket(&oc_ucast4, MN_PF_INET, MN_SOCK_DGRAM, 0);
    if (rc != 0 || !oc_ucast4) {
        OC_LOG(ERROR, "Could not create oc unicast v4 socket\n");
        return rc;
    }
    mn_socket_set_cbs(oc_ucast4, oc_ucast4, &oc_sock4_cbs);

#if (MYNEWT_VAL(OC_SERVER) == 1)
    rc = mn_socket(&oc_mcast4, MN_PF_INET, MN_SOCK_DGRAM, 0);
    if (rc != 0 || !oc_mcast4) {
        mn_close(oc_ucast4);
        OC_LOG(ERROR, "Could not create oc multicast v4 socket\n");
        return rc;
    }
    mn_socket_set_cbs(oc_mcast4, oc_mcast4, &oc_sock4_cbs);
#endif

    sin.msin_len = sizeof(sin);
    sin.msin_family = MN_AF_INET;
    sin.msin_port = 0;
    memset(&sin.msin_addr, 0, sizeof(sin.msin_addr));

    rc = mn_bind(oc_ucast4, (struct mn_sockaddr *)&sin);
    if (rc != 0) {
        OC_LOG(ERROR, "Could not bind oc unicast v4 socket\n");
        goto oc_connectivity_init_err;
    }

#if (MYNEWT_VAL(OC_SERVER) == 1)
    /* Set socket option to join multicast group on all valid interfaces */
    while (1) {
        struct mn_mreq join;

        rc = mn_itf_getnext(&itf);
        if (rc) {
            break;
        }

        if ((itf.mif_flags & (MN_ITF_F_UP | MN_ITF_F_MULTICAST)) !=
          (MN_ITF_F_UP | MN_ITF_F_MULTICAST)) {
            continue;
        }

        memcpy(&join.mm_addr.v4, &coap_all_nodes_v4, sizeof(coap_all_nodes_v4));
        join.mm_idx = itf.mif_idx;
        join.mm_family = MN_AF_INET;

        rc = mn_setsockopt(oc_mcast4, MN_SO_LEVEL, MN_MCAST_JOIN_GROUP, &join);
        if (rc != 0) {
            continue;
        }

        OC_LOG(DEBUG, "Joined Coap v4 mcast group on %s\n", itf.mif_name);
    }

    sin.msin_port = htons(COAP_PORT_UNSECURED);
    rc = mn_bind(oc_mcast4, (struct mn_sockaddr *)&sin);
    if (rc != 0) {
        OC_LOG(ERROR, "Could not bind oc v4 multicast socket\n");
        goto oc_connectivity_init_err;
    }
#endif

    return 0;

oc_connectivity_init_err:
    oc_connectivity_shutdown_ip4();
    return rc;
}

#endif

uint8_t oc_ip4_transport_id = -1;

void
oc_register_ip4(void)
{
#if (MYNEWT_VAL(OC_TRANSPORT_IP) == 1) && (MYNEWT_VAL(OC_TRANSPORT_IPV4) == 1)
    oc_ip4_transport_id = oc_transport_register(&oc_ip4_transport);
#endif
}
