-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathudp-socket.cpp
68 lines (55 loc) · 1.74 KB
/
udp-socket.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "udp-socket.h"
#include "posix-error-check.h"
#include <unistd.h>
udp_socket_t::udp_socket_t()
: fd_(check_error(::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP), "socket"))
{}
udp_socket_t::~udp_socket_t()
{
::close(fd_);
}
int udp_socket_t::native() const
{
return fd_;
}
void udp_socket_t::bind(const endpoint_t &endpoint)
{
sockaddr_in addr = get_sockaddr(endpoint);
int rc = ::bind(fd_, (const sockaddr*)&addr, sizeof(addr));
check_error(rc, "bind");
}
size_t udp_socket_t::recv(void *buffer, size_t len)
{
ssize_t bytes = ::recv(fd_, buffer, len, 0);
check_error(bytes, "recv");
return static_cast<size_t>(bytes);
}
size_t udp_socket_t::sendto(const endpoint_t &endpoint, const void *buffer, size_t len)
{
sockaddr_in addr = get_sockaddr(endpoint);
ssize_t written = ::sendto(fd_, buffer, len, 0, (const sockaddr*)&addr, sizeof(addr));
check_error(written, "sendto");
return static_cast<size_t>(written);
}
void udp_socket_t::set_option(const socket_option_t &opt)
{
const auto &value = opt.value();
int rc = ::setsockopt(fd_, opt.level(), opt.name(), value.data(), value.size());
check_error(rc, "setsockopt");
}
sockaddr_in udp_socket_t::get_sockaddr(const endpoint_t &endpoint)
{
const auto &ipv4_endpoint = endpoint_cast(endpoint);
sockaddr_in addr{};
addr.sin_family = ipv4_endpoint.family();
addr.sin_addr.s_addr = htonl(ipv4_endpoint.address());
addr.sin_port = htons(ipv4_endpoint.port());
return addr;
}
const ipv4_endpoint_t& udp_socket_t::endpoint_cast(const endpoint_t &endpoint)
{
if (endpoint.family() != AF_INET) {
throw std::system_error(EAFNOSUPPORT, std::generic_category());
}
return static_cast<const ipv4_endpoint_t&>(endpoint);
}