From 51491533a312884862849082b3507e49c1829d22 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 4 Nov 2016 14:27:50 +0100 Subject: Add new UDP input --- src/input/Udp.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/input/Udp.h | 52 +++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 src/input/Udp.cpp create mode 100644 src/input/Udp.h (limited to 'src/input') diff --git a/src/input/Udp.cpp b/src/input/Udp.cpp new file mode 100644 index 0000000..e534a06 --- /dev/null +++ b/src/input/Udp.cpp @@ -0,0 +1,134 @@ +/* + 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(void* buffer, int 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(); +} + +}; diff --git a/src/input/Udp.h b/src/input/Udp.h new file mode 100644 index 0000000..b6705e9 --- /dev/null +++ b/src/input/Udp.h @@ -0,0 +1,52 @@ +/* + 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 . + */ + +#pragma once + +#include +#include +#include "input/inputs.h" +#include "UdpSocket.h" + +namespace Inputs { + +class Udp : public InputBase { + public: + virtual int open(const std::string& name); + virtual int readFrame(void* buffer, int size); + virtual int setBitrate(int bitrate); + virtual int close(); + + private: + UdpSocket m_sock; + + // The content of the UDP packets gets written into the + // buffer, and the UDP packet boundaries disappear there. + std::vector m_buffer; +}; + +}; + -- cgit v1.2.3