apply upstream updates to UDPSocket;

pull/1/head
Bryan Biedenkapp 5 years ago
parent 646217ac8d
commit 6640485dad

@ -32,7 +32,8 @@
#include "network/Network.h"
#if defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/time.h>
#endif

@ -33,6 +33,7 @@
#include "Defines.h"
#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <pthread.h>

@ -33,6 +33,7 @@
#include "Defines.h"
#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/time.h>

@ -33,6 +33,7 @@
#include "Defines.h"
#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <pthread.h>

@ -32,6 +32,7 @@
#include "dmr/Control.h"
#include "p25/Control.h"
#include "modem/SerialController.h"
#include "network/UDPSocket.h"
#include "lookups/RSSIInterpolator.h"
#include "host/Host.h"
#include "HostMain.h"
@ -97,7 +98,7 @@ Host::Host(const std::string& confFile) :
m_tidLookup(NULL),
m_remoteControl(NULL)
{
/* stub */
UDPSocket::startup();
}
/// <summary>
@ -105,7 +106,7 @@ Host::Host(const std::string& confFile) :
/// </summary>
Host::~Host()
{
/* stub */
UDPSocket::shutdown();
}
/// <summary>

@ -46,7 +46,8 @@ using namespace modem;
#include <ctime>
#if defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#endif

@ -37,6 +37,7 @@
#include <string>
#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

@ -62,6 +62,8 @@ BaseNetwork::BaseNetwork(uint32_t localPort, uint32_t id, bool duplex, bool debu
m_allowDiagnosticTransfer(allowDiagnosticTransfer),
m_duplex(duplex),
m_debug(debug),
m_addr(),
m_addrLen(0U),
m_socket(localPort),
m_status(NET_STAT_INVALID),
m_retryTimer(1000U, 10U),
@ -948,19 +950,16 @@ bool BaseNetwork::writeP25PDU(const uint32_t id, const uint32_t streamId, const
/// </summary>
/// <param name="buffer">Buffer to write to the network.</param>
/// <param name="length">Length of buffer to write.</param>
/// <param name="address">IP address to write data to.</param>
/// <param name="port">Port number for remote UDP socket.</param>
/// <returns>True, if buffer is written to the network, otherwise false.</returns>
bool BaseNetwork::write(const uint8_t* data, uint32_t length, const in_addr& address, uint32_t port)
bool BaseNetwork::write(const uint8_t* data, uint32_t length)
{
assert(data != NULL);
assert(length > 0U);
assert(port > 0U);
// if (m_debug)
// Utils::dump(1U, "Network Transmitted", data, length);
bool ret = m_socket.write(data, length, address, port);
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
if (!ret) {
LogError(LOG_NET, "Socket has failed when writing data to the peer, retrying connection");
return false;

@ -247,6 +247,8 @@ namespace network
bool m_duplex;
bool m_debug;
sockaddr_storage m_addr;
unsigned int m_addrLen;
UDPSocket m_socket;
NET_CONN_STATUS m_status;
@ -280,9 +282,7 @@ namespace network
bool writeP25PDU(const uint32_t id, const uint32_t streamId, const uint32_t llId, const uint8_t dataType, const uint8_t* data, const uint32_t len);
/// <summary>Writes data to the network.</summary>
virtual bool write(const uint8_t* data, uint32_t length) = 0;
/// <summary>Writes data to the network.</summary>
virtual bool write(const uint8_t* data, uint32_t length, const in_addr& address, uint32_t port);
virtual bool write(const uint8_t* data, uint32_t length);
};
} // namespace network

@ -61,8 +61,7 @@ using namespace network;
Network::Network(const std::string& address, uint32_t port, uint32_t local, uint32_t id, const std::string& password,
bool duplex, bool debug, bool slot1, bool slot2, bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup) :
BaseNetwork(local, id, duplex, debug, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer),
m_addressStr(address),
m_address(),
m_address(address),
m_port(port),
m_password(password),
m_enabled(false),
@ -85,8 +84,6 @@ Network::Network(const std::string& address, uint32_t port, uint32_t local, uint
assert(!address.empty());
assert(port > 0U);
assert(!password.empty());
m_address = UDPSocket::lookup(address);
}
/// <summary>
@ -171,7 +168,7 @@ void Network::clock(uint32_t ms)
if (m_status == NET_STAT_WAITING_CONNECT) {
m_retryTimer.clock(ms);
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
bool ret = m_socket.open();
bool ret = m_socket.open(m_addr.ss_family);
if (ret) {
ret = writeLogin();
if (!ret)
@ -187,9 +184,9 @@ void Network::clock(uint32_t ms)
return;
}
in_addr address;
uint32_t port;
int length = m_socket.read(m_buffer, DATA_PACKET_LENGTH, address, port);
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(m_buffer, DATA_PACKET_LENGTH, address, addrLen);
if (length < 0) {
LogError(LOG_NET, "Socket has failed, retrying connection to the master");
close();
@ -200,7 +197,12 @@ void Network::clock(uint32_t ms)
if (m_debug && length > 0)
Utils::dump(1U, "Network Received", m_buffer, length);
if (length > 0 && m_address.s_addr == address.s_addr && m_port == port) {
if (length > 0) {
if (!UDPSocket::match(m_addr, address)) {
LogError(LOG_NET, "Packet received from an invalid source");
return;
}
if (::memcmp(m_buffer, TAG_DMR_DATA, 4U) == 0) {
if (m_enabled) {
if (m_debug)
@ -388,8 +390,9 @@ bool Network::open()
if (m_debug)
LogMessage(LOG_NET, "Opening Network");
if (m_address.s_addr == INADDR_NONE) {
m_address = UDPSocket::lookup(m_addressStr);
if (UDPSocket::lookup(m_address, m_port, m_addr, m_addrLen) != 0) {
LogMessage(LOG_NET, "Could not lookup the address of the master");
return false;
}
m_status = NET_STAT_WAITING_CONNECT;
@ -545,17 +548,3 @@ bool Network::writePing()
return write(buffer, 11U);
}
/// <summary>
/// Writes data to the network.
/// </summary>
/// <param name="data">Buffer to write to the network.</param>
/// <param name="length">Length of buffer to write.</param>
/// <returns>True, if buffer is written to the network, otherwise false.</returns>
bool Network::write(const uint8_t* data, uint32_t length)
{
assert(data != NULL);
assert(length > 0U);
return BaseNetwork::write(data, length, m_address, m_port);
}

@ -77,9 +77,8 @@ namespace network
void close();
private:
std::string m_addressStr;
in_addr m_address;
uint32_t m_port;
std::string m_address;
unsigned int m_port;
std::string m_password;
@ -117,9 +116,6 @@ namespace network
bool writeConfig();
/// <summary>Writes a network stay-alive ping.</summary>
bool writePing();
/// <summary>Writes data to the network.</summary>
bool write(const uint8_t* data, uint32_t length);
};
} // namespace network

@ -164,10 +164,10 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25)
args.clear();
uint8_t buffer[RC_BUFFER_LENGTH];
in_addr address;
uint32_t port;
uint32_t ret = m_socket.read((uint8_t*)buffer, RC_BUFFER_LENGTH, address, port);
sockaddr_storage address;
unsigned int addrLen;
uint32_t ret = m_socket.read((uint8_t*)buffer, RC_BUFFER_LENGTH, address, addrLen);
if (ret > 0U) {
buffer[ret] = '\0';

@ -11,7 +11,7 @@
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2006-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL
*
* This program is free software; you can redistribute it and/or modify
@ -32,8 +32,6 @@
#include "network/UDPSocket.h"
#include "Log.h"
using namespace network;
#include <cassert>
#if !defined(_WIN32) && !defined(_WIN64)
@ -41,6 +39,8 @@ using namespace network;
#include <cstring>
#endif
using namespace network;
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@ -49,35 +49,34 @@ using namespace network;
/// </summary>
/// <param name="address">Hostname/IP address to connect to.</param>
/// <param name="port">Port number.</param>
UDPSocket::UDPSocket(const std::string& address, uint32_t port) :
m_address(address),
m_port(port),
m_fd(-1)
UDPSocket::UDPSocket(const std::string& address, unsigned int port) :
m_address_save(address),
m_port_save(port),
m_counter(0U)
{
assert(!address.empty());
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError(LOG_NET, "Error from WSAStartup");
#endif
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
m_address[i] = "";
m_port[i] = 0U;
m_af[i] = 0U;
m_fd[i] = -1;
}
}
/// <summary>
/// Initializes a new instance of the UDPSocket class.
/// </summary>
/// <param name="port">Port number.</param>
UDPSocket::UDPSocket(uint32_t port) :
m_address(),
m_port(port),
m_fd(-1)
UDPSocket::UDPSocket(unsigned int port) :
m_address_save(),
m_port_save(port),
m_counter(0U)
{
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0)
LogError(LOG_NET, "Error from WSAStartup");
#endif
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
m_address[i] = "";
m_port[i] = 0U;
m_af[i] = 0U;
m_fd[i] = -1;
}
}
/// <summary>
@ -85,48 +84,74 @@ UDPSocket::UDPSocket(uint32_t port) :
/// </summary>
UDPSocket::~UDPSocket()
{
#if defined(_WIN32) || defined(_WIN64)
::WSACleanup();
#endif
/* stub */
}
/// <summary>
/// Opens UDP socket connection.
/// </summary>
/// <param name="address"></param>
/// <returns>True, if UDP socket is opened, otherwise false.</returns>
bool UDPSocket::open()
bool UDPSocket::open(const sockaddr_storage& address)
{
m_fd = ::socket(PF_INET, SOCK_DGRAM, 0);
if (m_fd < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Cannot create the UDP socket, err: %lu", ::GetLastError());
#else
LogError(LOG_NET, "Cannot create the UDP socket, err: %d", errno);
#endif
return open(address.ss_family);
}
/// <summary>
/// Opens UDP socket connection.
/// </summary>
/// <param name="af"></param>
/// <returns>True, if UDP socket is opened, otherwise false.</returns>
bool UDPSocket::open(unsigned int af)
{
return open(0, af, m_address_save, m_port_save);
}
/// <summary>
/// Opens UDP socket connection.
/// </summary>
/// <param name="index"></param>
/// <param name="af"></param>
/// <param name="address"></param>
/// <param name="port"></param>
/// <returns>True, if UDP socket is opened, otherwise false.</returns>
bool UDPSocket::open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port)
{
sockaddr_storage addr;
unsigned int addrlen;
struct addrinfo hints;
::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = af;
/* to determine protocol family, call lookup() first. */
int err = lookup(address, port, addr, addrlen, hints);
if (err != 0) {
LogError(LOG_NET, "The local address is invalid - %s", address.c_str());
return false;
}
if (m_port > 0U) {
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
close(index);
if (!m_address.empty()) {
int fd = ::socket(addr.ss_family, SOCK_DGRAM, 0);
if (fd < 0) {
#if defined(_WIN32) || defined(_WIN64)
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
LogError(LOG_NET, "Cannot create the UDP socket, err: %lu", ::GetLastError());
#else
addr.sin_addr.s_addr = ::inet_addr(m_address.c_str());
LogError(LOG_NET, "Cannot create the UDP socket, err: %d", errno);
#endif
if (addr.sin_addr.s_addr == INADDR_NONE) {
LogError(LOG_NET, "The local address is invalid - %s", m_address.c_str());
return false;
}
}
m_address[index] = address;
m_port[index] = port;
m_af[index] = addr.ss_family;
m_fd[index] = fd;
if (port > 0U) {
int reuse = 1;
if (::setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) == -1) {
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)& reuse, sizeof(reuse)) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Cannot set the UDP socket option, err: %lu", ::GetLastError());
#else
@ -135,7 +160,7 @@ bool UDPSocket::open()
return false;
}
if (::bind(m_fd, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
if (::bind(fd, (sockaddr*)& addr, addrlen) == -1) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Cannot bind the UDP address, err: %lu", ::GetLastError());
#else
@ -143,6 +168,8 @@ bool UDPSocket::open()
#endif
return false;
}
LogInfo("Opening UDP port on %u", port);
}
return true;
@ -154,64 +181,81 @@ bool UDPSocket::open()
/// <param name="buffer">Buffer to read data into.</param>
/// <param name="length">Length of data to read.</param>
/// <param name="address">IP address to read data from.</param>
/// <param name="port">Port number for remote UDP socket.</param>
/// <param name="addrLen"></param>
/// <returns>Actual length of data read from remote UDP socket.</returns>
int UDPSocket::read(uint8_t* buffer, uint32_t length, in_addr& address, uint32_t& port)
int UDPSocket::read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int& addrLen)
{
assert(buffer != NULL);
assert(length > 0U);
// Check that the readfrom() won't block
fd_set readFds;
FD_ZERO(&readFds);
int i, n;
struct pollfd pfd[UDP_SOCKET_MAX];
for (i = n = 0; i < UDP_SOCKET_MAX; i++) {
if (m_fd[i] >= 0) {
pfd[n].fd = m_fd[i];
pfd[n].events = POLLIN;
n++;
}
}
// no socket descriptor to receive
if (n == 0)
return 0;
// Return immediately
#if defined(_WIN32) || defined(_WIN64)
FD_SET((uint32_t)m_fd, &readFds);
int ret = WSAPoll(pfd, n, 0);
#else
FD_SET(m_fd, &readFds);
int ret = ::poll(pfd, n, 0);
#endif
// Return immediately
timeval tv;
tv.tv_sec = 0L;
tv.tv_usec = 0L;
int ret = ::select(m_fd + 1, &readFds, NULL, NULL, &tv);
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Error returned from UDP select, err: %lu", ::GetLastError());
LogError(LOG_NET, "Error returned from UDP poll, err: %lu", ::GetLastError());
#else
LogError(LOG_NET, "Error returned from UDP select, err: %d", errno);
LogError(LOG_NET, "Error returned from UDP poll, err: %d", errno);
#endif
return -1;
}
if (ret == 0)
int index;
for (i = 0; i < n; i++) {
// round robin
index = (i + m_counter) % n;
if (pfd[index].revents & POLLIN)
break;
}
if (i == n)
return 0;
sockaddr_in addr;
#if defined(_WIN32) || defined(_WIN64)
int size = sizeof(sockaddr_in);
int size = sizeof(sockaddr_storage);
#else
socklen_t size = sizeof(sockaddr_in);
socklen_t size = sizeof(sockaddr_storage);
#endif
#if defined(_WIN32) || defined(_WIN64)
int len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
int len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr*)& address, &size);
#else
ssize_t len = ::recvfrom(m_fd, (char*)buffer, length, 0, (sockaddr *)&addr, &size);
ssize_t len = ::recvfrom(pfd[index].fd, (char*)buffer, length, 0, (sockaddr*)& address, &size);
#endif
if (len <= 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Error returned from recvfrom, err: %lu", ::GetLastError());
#else
LogError(LOG_NET, "Error returned from recvfrom, err: %d", errno);
if (len == -1 && errno == ENOTSOCK) {
LogMessage(LOG_NET, "Re-opening UDP port on %u", m_port);
close();
open();
}
#endif
return -1;
}
address = addr.sin_addr;
port = ntohs(addr.sin_port);
m_counter++;
addrLen = size;
return len;
}
@ -221,43 +265,44 @@ int UDPSocket::read(uint8_t* buffer, uint32_t length, in_addr& address, uint32_t
/// <param name="buffer">Buffer containing data to write to socket.</param>
/// <param name="length">Length of data to write.</param>
/// <param name="address">IP address to write data to.</param>
/// <param name="port">Port number for remote UDP socket.</param>
/// <param name="addrLen"></param>
/// <returns>Actual length of data written to remote UDP socket.</returns>
bool UDPSocket::write(const uint8_t* buffer, uint32_t length, const in_addr& address, uint32_t port)
bool UDPSocket::write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addrLen)
{
assert(buffer != NULL);
assert(length > 0U);
sockaddr_in addr;
::memset(&addr, 0x00, sizeof(sockaddr_in));
bool result = false;
addr.sin_family = AF_INET;
addr.sin_addr = address;
addr.sin_port = htons(port);
for (int i = 0; i < UDP_SOCKET_MAX; i++) {
if (m_fd[i] < 0 || m_af[i] != address.ss_family)
continue;
#if defined(_WIN32) || defined(_WIN64)
int ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
int ret = ::sendto(m_fd[i], (char*)buffer, length, 0, (sockaddr*)& address, addrLen);
#else
ssize_t ret = ::sendto(m_fd, (char *)buffer, length, 0, (sockaddr *)&addr, sizeof(sockaddr_in));
ssize_t ret = ::sendto(m_fd[i], (char*)buffer, length, 0, (sockaddr*)& address, addrLen);
#endif
if (ret < 0) {
#if defined(_WIN32) || defined(_WIN64)
LogError(LOG_NET, "Error returned from sendto, err: %lu", ::GetLastError());
#else
LogError(LOG_NET, "Error returned from sendto, err: %d", errno);
#endif
return false;
}
else {
#if defined(_WIN32) || defined(_WIN64)
if (ret != int(length))
return false;
if (ret == int(length))
result = true;
#else
if (ret != ssize_t(length))
return false;
if (ret == ssize_t(length))
result = true;
#endif
}
}
return true;
return result;
}
/// <summary>
@ -265,10 +310,47 @@ bool UDPSocket::write(const uint8_t* buffer, uint32_t length, const in_addr& add
/// </summary>
void UDPSocket::close()
{
for (int i = 0; i < UDP_SOCKET_MAX; i++)
close(i);
}
/// <summary>
/// Closes the UDP socket connection.
/// </summary>
/// <param name="index"></param>
void UDPSocket::close(const unsigned int index)
{
if ((index < UDP_SOCKET_MAX) && (m_fd[index] >= 0)) {
#if defined(_WIN32) || defined(_WIN64)
::closesocket(m_fd);
::closesocket(m_fd[index]);
#else
::close(m_fd);
::close(m_fd[index]);
#endif
m_fd[index] = -1;
}
}
/// <summary>
///
/// </summary>
void UDPSocket::startup()
{
#if defined(_WIN32) || defined(_WIN64)
WSAData data;
int wsaRet = ::WSAStartup(MAKEWORD(2, 2), &data);
if (wsaRet != 0) {
LogError(LOG_NET, "Error from WSAStartup");
}
#endif
}
/// <summary>
///
/// </summary>
void UDPSocket::shutdown()
{
#if defined(_WIN32) || defined(_WIN64)
::WSACleanup();
#endif
}
@ -276,43 +358,110 @@ void UDPSocket::close()
/// Helper to lookup a hostname and resolve it to an IP address.
/// </summary>
/// <param name="hostname">String containing hostname to resolve.</param>
/// <returns>IP address structure for containing resolved hostname.</returns>
in_addr UDPSocket::lookup(const std::string& hostname)
/// <param name="port">Numeric port number of service to resolve.</param>
/// <param name="addr">Socket address structure.</param>
/// <param name="addrLen"></param>
/// <returns>Zero if no error during lookup, otherwise error.</returns>
int UDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& addrLen)
{
in_addr addr;
#if defined(_WIN32) || defined(_WIN64)
unsigned long address = ::inet_addr(hostname.c_str());
if (address != INADDR_NONE && address != INADDR_ANY) {
addr.s_addr = address;
return addr;
struct addrinfo hints;
::memset(&hints, 0, sizeof(hints));
return lookup(hostname, port, addr, addrLen, hints);
}
struct hostent* hp = ::gethostbyname(hostname.c_str());
if (hp != NULL) {
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
return addr;
/// <summary>
/// Helper to lookup a hostname and resolve it to an IP address.
/// </summary>
/// <param name="hostname">String containing hostname to resolve.</param>
/// <param name="port">Numeric port number of service to resolve.</param>
/// <param name="addr">Socket address structure.</param>
/// <param name="addrLen"></param>
/// <param name="hints"></param>
/// <returns>Zero if no error during lookup, otherwise error.</returns>
int UDPSocket::lookup(const std::string& hostname, unsigned int port, sockaddr_storage& addr, unsigned int& addrLen, struct addrinfo& hints)
{
std::string portstr = std::to_string(port);
struct addrinfo* res;
/* port is always digits, no needs to lookup service */
hints.ai_flags |= AI_NUMERICSERV;
int err = getaddrinfo(hostname.empty() ? NULL : hostname.c_str(), portstr.c_str(), &hints, &res);
if (err != 0) {
sockaddr_in* paddr = (sockaddr_in*)& addr;
::memset(paddr, 0x00U, addrLen = sizeof(sockaddr_in));
paddr->sin_family = AF_INET;
paddr->sin_port = htons(port);
paddr->sin_addr.s_addr = htonl(INADDR_NONE);
LogError("Cannot find address for host %s", hostname.c_str());
return err;
}
LogError(LOG_NET, "Cannot find address for host %s", hostname.c_str());
::memcpy(&addr, res->ai_addr, addrLen = res->ai_addrlen);
addr.s_addr = INADDR_NONE;
return addr;
#else
in_addr_t address = ::inet_addr(hostname.c_str());
if (address != in_addr_t(-1)) {
addr.s_addr = address;
return addr;
freeaddrinfo(res);
return 0;
}
struct hostent* hp = ::gethostbyname(hostname.c_str());
if (hp != NULL) {
::memcpy(&addr, hp->h_addr_list[0], sizeof(struct in_addr));
return addr;
/// <summary>
///
/// </summary>
/// <param name="addr1"></param>
/// <param name="addr2"></param>
/// <param name="type"></param>
/// <returns></returns>
bool UDPSocket::match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type)
{
if (addr1.ss_family != addr2.ss_family)
return false;
if (type == IMT_ADDRESS_AND_PORT) {
switch (addr1.ss_family) {
case AF_INET:
struct sockaddr_in* in_1, * in_2;
in_1 = (struct sockaddr_in*) & addr1;
in_2 = (struct sockaddr_in*) & addr2;
return (in_1->sin_addr.s_addr == in_2->sin_addr.s_addr) && (in_1->sin_port == in_2->sin_port);
case AF_INET6:
struct sockaddr_in6* in6_1, *in6_2;
in6_1 = (struct sockaddr_in6*) & addr1;
in6_2 = (struct sockaddr_in6*) & addr2;
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr) && (in6_1->sin6_port == in6_2->sin6_port);
default:
return false;
}
}
else if (type == IMT_ADDRESS_ONLY) {
switch (addr1.ss_family) {
case AF_INET:
struct sockaddr_in* in_1, * in_2;
in_1 = (struct sockaddr_in*) & addr1;
in_2 = (struct sockaddr_in*) & addr2;
return in_1->sin_addr.s_addr == in_2->sin_addr.s_addr;
case AF_INET6:
struct sockaddr_in6* in6_1, * in6_2;
in6_1 = (struct sockaddr_in6*) & addr1;
in6_2 = (struct sockaddr_in6*) & addr2;
return IN6_ARE_ADDR_EQUAL(&in6_1->sin6_addr, &in6_2->sin6_addr);
default:
return false;
}
}
else {
return false;
}
}
LogError(LOG_NET, "Cannot find address for host %s", hostname.c_str());
/// <summary>
///
/// </summary>
/// <param name="addr"></param>
/// <returns></returns>
bool UDPSocket::isNone(const sockaddr_storage& addr)
{
struct sockaddr_in* in = (struct sockaddr_in*) & addr;
addr.s_addr = INADDR_NONE;
return addr;
#endif
return ((addr.ss_family == AF_INET) && (in->sin_addr.s_addr == htonl(INADDR_NONE)));
}

@ -11,7 +11,7 @@
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -39,14 +39,25 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#if !defined(UDP_SOCKET_MAX)
#define UDP_SOCKET_MAX 1
#endif
enum IPMATCHTYPE {
IMT_ADDRESS_AND_PORT,
IMT_ADDRESS_ONLY
};
namespace network
{
// ---------------------------------------------------------------------------
@ -58,31 +69,54 @@ namespace network
class HOST_SW_API UDPSocket {
public:
/// <summary>Initializes a new instance of the UDPSocket class.</summary>
UDPSocket(const std::string& address, uint32_t port = 0U);
UDPSocket(const std::string& address, unsigned int port = 0U);
/// <summary>Initializes a new instance of the UDPSocket class.</summary>
UDPSocket(unsigned int port = 0U);
/// <summary>Initializes a new instance of the UDPSocket class.</summary>
UDPSocket(uint32_t port = 0U);
/// <summary>Finalizes a instance of the UDPSocket class.</summary>
~UDPSocket();
/// <summary>Opens UDP socket connection.</summary>
bool open();
bool open(unsigned int af = AF_UNSPEC);
/// <summary>Opens UDP socket connection.</summary>
bool open(const sockaddr_storage& address);
/// <summary>Opens UDP socket connection.</summary>
bool open(const unsigned int index, const unsigned int af, const std::string& address, const unsigned int port);
/// <summary>Read data from the UDP socket.</summary>
int read(uint8_t* buffer, uint32_t length, in_addr& address, uint32_t& port);
int read(unsigned char* buffer, unsigned int length, sockaddr_storage& address, unsigned int& addrLen);
/// <summary>Write data to the UDP socket.</summary>
bool write(const uint8_t* buffer, uint32_t length, const in_addr& address, uint32_t port);
bool write(const unsigned char* buffer, unsigned int length, const sockaddr_storage& address, unsigned int addrLen);
/// <summary>Closes the UDP socket connection.</summary>
void close();
/// <summary>Closes the UDP socket connection.</summary>
void close(const unsigned int index);
/// <summary></summary>
static void startup();
/// <summary></summary>
static void shutdown();
/// <summary>Helper to lookup a hostname and resolve it to an IP address.</summary>
static in_addr lookup(const std::string& hostName);
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& addrLen);
/// <summary>Helper to lookup a hostname and resolve it to an IP address.</summary>
static int lookup(const std::string& hostName, unsigned int port, sockaddr_storage& address, unsigned int& addrLen, struct addrinfo& hints);
/// <summary></summary>
static bool match(const sockaddr_storage& addr1, const sockaddr_storage& addr2, IPMATCHTYPE type = IMT_ADDRESS_AND_PORT);
/// <summary></summary>
static bool isNone(const sockaddr_storage& addr);
private:
std::string m_address;
uint16_t m_port;
int m_fd;
std::string m_address_save;
unsigned short m_port_save;
std::string m_address[UDP_SOCKET_MAX];
unsigned short m_port[UDP_SOCKET_MAX];
unsigned int m_af[UDP_SOCKET_MAX];
int m_fd[UDP_SOCKET_MAX];
unsigned int m_counter;
};
} // namespace Net
} // namespace network
#endif // __UDP_SOCKET_H__

@ -47,19 +47,6 @@ using namespace p25::data;
#include <cstring>
#include <ctime>
#if !defined(_WIN32) && !defined(_WIN64)
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#else
#include <winsock.h>
#endif
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------

Loading…
Cancel
Save

Powered by TurnKey Linux.