// // Copyright © 2020 Thomas A. Early, N7TAE // // ---------------------------------------------------------------------------- // // xlxd 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. // // xlxd 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 Foobar. If not, see . // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "UDPSocket.h" //////////////////////////////////////////////////////////////////////////////////////// // constructor CUDPSocket::CUDPSocket() : m_fd(-1) {} //////////////////////////////////////////////////////////////////////////////////////// // destructor CUDPSocket::~CUDPSocket() { Close(); } //////////////////////////////////////////////////////////////////////////////////////// // open & close bool CUDPSocket::Open(const CSockAddress &addr) { // create socket m_fd = socket(addr.GetFamily(), SOCK_DGRAM, 0); if (0 > m_fd) { std::cerr << "Cannot create socket on " << addr << ", " << strerror(errno) << std::endl; return true; } if (0 > fcntl(m_fd, F_SETFL, O_NONBLOCK)) { std::cerr << "cannot set socket " << addr << " to non-blocking: " << strerror(errno) << std::endl; close(m_fd); m_fd = -1; return true; } const int reuse = 1; if (0 > setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))) { std::cerr << "Cannot set the UDP socket option on " << m_addr << ", err: " << strerror(errno) << std::endl; close(m_fd); m_fd = -1; return true; } // initialize sockaddr struct m_addr = addr; if (0 != bind(m_fd, m_addr.GetCPointer(), m_addr.GetSize())) { std::cerr << "bind failed on " << m_addr << ", " << strerror(errno) << std::endl; close(m_fd); m_fd = -1; return true; } return false; } void CUDPSocket::Close(void) { if ( m_fd >= 0 ) { close(m_fd); m_fd = -1; } } //////////////////////////////////////////////////////////////////////////////////////// // read size_t CUDPSocket::Read(unsigned char *buf, const size_t size, CSockAddress &Ip) { if ( 0 > m_fd ) return 0; unsigned int len = sizeof(struct sockaddr_storage); auto rval = recvfrom(m_fd, buf, size, 0, Ip.GetPointer(), &len); if (0 > rval) std::cerr << "Read error on port " << m_addr << ": " << strerror(errno) << std::endl; return rval; } void CUDPSocket::Write(const void *Buffer, const size_t size, const CSockAddress &Ip) const { auto rval = sendto(m_fd, Buffer, size, 0, Ip.GetCPointer(), Ip.GetSize()); if (0 > rval) std::cerr << "Write error to " << Ip << ", " << strerror(errno) << std::endl; else if ((size_t)rval != size) std::cerr << "Short write, " << rval << "<" << size << " to " << Ip << std::endl; }