/* -*- c++ -*- */
/*
 * Copyright 2013 Free Software Foundation, Inc.
 *
 * This file is part of GNU Radio
 *
 * GNU Radio is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * GNU Radio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU Radio; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/thread/thread.h>
#include <gnuradio/io_signature.h>
#include <gnuradio/blocks/pdu.h>
#include <pmt/pmt.h>

#include <boost/lexical_cast.hpp>
#include "udp_socket.h"

using boost::asio::ip::udp;

namespace gr {
  namespace grgsm {

    udp_socket::udp_socket(
      const std::string &remote_addr,
      const std::string &src_port,
      const std::string &dst_port)
    {
      // Resolve remote host address
      udp::resolver resolver(d_io_service);

      udp::resolver::query rx_query(
        udp::v4(), remote_addr, src_port,
        boost::asio::ip::resolver_query_base::passive);
      udp::resolver::query tx_query(
        udp::v4(), remote_addr, dst_port,
        boost::asio::ip::resolver_query_base::passive);

      d_udp_endpoint_rx = *resolver.resolve(rx_query);
      d_udp_endpoint_tx = *resolver.resolve(tx_query);

      // Create a socket
      d_udp_socket.reset(new udp::socket(d_io_service, d_udp_endpoint_rx));

      // Setup read handler
      d_udp_socket->async_receive_from(
        boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx,
        boost::bind(&udp_socket::handle_udp_read, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));

      // Start server
      d_thread = gr::thread::thread(
        boost::bind(&udp_socket::run_io_service, this));
    }

    udp_socket::~udp_socket()
    {
      // Stop server
      d_io_service.stop();
      d_thread.interrupt();
      d_thread.join();
    }

    void
    udp_socket::run_io_service(void)
    {
      d_io_service.run();
    }

    void
    udp_socket::udp_send(uint8_t *data, size_t len)
    {
      d_udp_socket->send_to(
        boost::asio::buffer(data, len),
        d_udp_endpoint_tx);
    }

    void
    udp_socket::handle_udp_read(
      const boost::system::error_code& error,
      size_t bytes_transferred)
    {
      if (error)
        return;

      pmt::pmt_t vector = pmt::init_u8vector(bytes_transferred,
        (const uint8_t *) &d_rxbuf[0]);
      pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector);

      // TODO: call handler here

      d_udp_socket->async_receive_from(
        boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx,
        boost::bind(&udp_socket::handle_udp_read, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }

  } /* namespace blocks */
}/* namespace gr */
