/*
Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications
Research Center Canada)
Copyright (C) 2016
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
*/
/*
This file is part of ODR-DabMux.
ODR-DabMux 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 of the
License, or (at your option) any later version.
ODR-DabMux 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 ODR-DabMux. If not, see .
*/
#include "input/Udp.h"
#include
#include
#include
#include
#include
#include
#include "utils.h"
using namespace std;
namespace Inputs {
int Udp::open(const std::string& name)
{
// Skip the udp:// part if it is present
const string endpoint = (name.substr(0, 6) == "udp://") ?
name.substr(6) : name;
// The endpoint should be address:port
const auto colon_pos = endpoint.find_first_of(":");
if (colon_pos == string::npos) {
stringstream ss;
ss << "'" << name <<
" is an invalid format for udp address: "
"expected [udp://]address:port";
throw invalid_argument(ss.str());
}
const auto address = endpoint.substr(0, colon_pos);
const auto port_str = endpoint.substr(colon_pos + 1);
const long port = strtol(port_str.c_str(), nullptr, 10);
if ((port == LONG_MIN or port == LONG_MAX) and errno == ERANGE) {
throw out_of_range("udp input: port out of range");
}
else if (port == 0 and errno != 0) {
stringstream ss;
ss << "udp input port parse error: " << strerror(errno);
throw invalid_argument(ss.str());
}
if (port == 0) {
throw out_of_range("can't use port number 0 in udp address");
}
if (m_sock.reinit(port, address) == -1) {
stringstream ss;
ss << "Could not init UDP socket: " << inetErrMsg;
throw runtime_error(ss.str());
}
if (m_sock.setBlocking(false) == -1) {
stringstream ss;
ss << "Could not set non-blocking UDP socket: " << inetErrMsg;
throw runtime_error(ss.str());
}
return 0;
}
int Udp::readFrame(uint8_t* buffer, size_t size)
{
uint8_t* data = reinterpret_cast(buffer);
// Regardless of buffer contents, try receiving data.
UdpPacket packet;
int ret = m_sock.receive(packet);
if (ret == -1) {
stringstream ss;
ss << "Could not read from UDP socket: " << inetErrMsg;
throw runtime_error(ss.str());
}
std::copy(packet.getData(), packet.getData() + packet.getSize(),
back_inserter(m_buffer));
// Take data from the buffer if it contains enough data,
// in any case write the buffer
if (m_buffer.size() >= (size_t)size) {
std::copy(m_buffer.begin(), m_buffer.begin() + size, data);
}
else {
memset(data, 0x0, size);
}
return size;
}
int Udp::setBitrate(int bitrate)
{
if (bitrate <= 0) {
etiLog.log(error, "Invalid bitrate (%i)\n", bitrate);
return -1;
}
return bitrate;
}
int Udp::close()
{
return m_sock.close();
}
};