Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@
"nullopt",
"chrono",
"ciphersuite",
"rmap"
"rmap",
"WSAPOLLFD"
],
"flagWords": [
"hte"
Expand Down
7 changes: 7 additions & 0 deletions include/dpp/discordvoiceclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,13 @@ class DPP_EXPORT discord_voice_client : public websocket_client
*/
dave_version_t dave_version;

/**
* @brief Destination address for where packets go
* on the UDP socket
*/
address_t destination{};


/**
* @brief Send data to UDP socket immediately.
*
Expand Down
37 changes: 29 additions & 8 deletions include/dpp/dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <sys/types.h>
#include <string>
#include <unordered_map>
#include <cstring>
#include <dpp/socket.h>

namespace dpp {

Expand All @@ -40,23 +42,42 @@ namespace dpp {
*/
struct dns_cache_entry {
/**
* @brief Resolved address information
* @brief Resolved address metadata
*/
addrinfo addr;

/**
* @brief Socket address.
* Discord only supports ipv4, but sockaddr_in6 is larger
* than sockaddr_in, sockaddr_storage will hold either. This
* means that if discord ever do support ipv6 we just flip
* one value in dns.cpp and that should be all that is needed.
* @brief Resolved address as string.
* The metadata is needed to know what type of address it is.
* Do not do silly stuff like just looking to see if '.' is in it!
*/
sockaddr_storage ai_addr;
std::string resolved_addr;

/**
* @brief Time at which this cache entry is invalidated
*/
time_t expire_timestamp;

/**
* @brief Get address length
* @return address length
*/
[[nodiscard]] int size() const;

/**
* @brief Get the address_t that corresponds to this cache entry
* for use when connecting with ::connect()
* @param port Port number to connect to
* @return address_t prefilled with the IP and port number
*/
[[nodiscard]] const address_t get_connecting_address(uint16_t port) const;

/**
* @brief Allocate a socket file descriptor for the given dns address
* @return File descriptor ready for calling connect(), or INVALID_SOCKET
* on failure.
*/
[[nodiscard]] socket make_connecting_socket() const;
};

/**
Expand All @@ -73,4 +94,4 @@ namespace dpp {
* @throw dpp::connection_exception On failure to resolve hostname
*/
const dns_cache_entry* resolve_hostname(const std::string& hostname, const std::string& port);
} // namespace dpp
}
135 changes: 130 additions & 5 deletions include/dpp/socket.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once

#include <dpp/export.h>
#ifdef _WIN32
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <io.h>
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
#define pollfd WSAPOLLFD
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#endif
#include <string_view>
#include <cstdint>


namespace dpp
{
/**
* @brief Represents a socket file descriptor.
* This is used to ensure parity between windows and unix-like systems.
*/
/**
* @brief Represents a socket file descriptor.
* This is used to ensure parity between windows and unix-like systems.
*/
#ifndef _WIN32
using socket = int;
#else
using socket = SOCKET;
#endif
} // namespace dpp

#ifndef SOCKET_ERROR
/**
Expand All @@ -26,3 +62,92 @@ namespace dpp
*/
#define INVALID_SOCKET ~0
#endif

/**
* @brief Represents an IPv4 address for use with socket functions such as
* bind().
*
* Avoids type punning with C style casts from sockaddr_in to sockaddr pointers.
*/
class DPP_EXPORT address_t {
/**
* @brief Internal sockaddr struct
*/
sockaddr socket_addr{};

public:

/**
* @brief Create a new address_t
* @param ip IPv4 address
* @param port Port number
* @note Leave both as defaults to create a default bind-to-any setting
*/
address_t(const std::string_view ip = "0.0.0.0", uint16_t port = 0);

/**
* @brief Get sockaddr
* @return sockaddr pointer
*/
[[nodiscard]] sockaddr *get_socket_address();

/**
* @brief Returns size of sockaddr_in
* @return sockaddr_in size
* @note It is important the size this returns is sizeof(sockaddr_in) not
* sizeof(sockaddr), this is NOT a bug but requirement of C socket functions.
*/
[[nodiscard]] size_t size();

/**
* @brief Get the port bound to a file descriptor
* @param fd File descriptor
* @return Port number, or 0 if no port bound
*/
[[nodiscard]] uint16_t get_port(socket fd);
};

/**
* @brief Allocates a dpp::socket, closing it on destruction
*/
struct DPP_EXPORT raii_socket {
/**
* @brief File descriptor
*/
socket fd;

/**
* @brief Construct a socket.
* Calls socket() and returns a new file descriptor
*/
raii_socket();

/**
* @brief Non-copyable
*/
raii_socket(raii_socket&) = delete;

/**
* @brief Non-movable
*/
raii_socket(raii_socket&&) = delete;

/**
* @brief Non-copyable
*/
raii_socket operator=(raii_socket&) = delete;

/**
* @brief Non-movable
*/
raii_socket operator=(raii_socket&&) = delete;

/**
* @brief Destructor
* Frees the socket by closing it
*/
~raii_socket();
};


}
Loading
Loading