21 last_error_ =
"Failed to create UDP socket: " + std::string(strerror(errno));
27 if (setsockopt(
socket_fd_, SOL_SOCKET, SO_REUSEADDR, &reuse,
sizeof(reuse)) < 0) {
29 std::cerr <<
"[UDPSocket] Warning: Failed to set SO_REUSEADDR: " << strerror(errno)
33 struct sockaddr_in addr = {};
34 addr.sin_family = AF_INET;
35 addr.sin_port = htons(bind_port);
37 if (bind_address ==
"0.0.0.0" || bind_address.empty()) {
38 addr.sin_addr.s_addr = INADDR_ANY;
40 if (inet_aton(bind_address.c_str(), &addr.sin_addr) == 0) {
41 last_error_ =
"Invalid bind address: " + bind_address;
48 if (bind(
socket_fd_,
reinterpret_cast<struct sockaddr*
>(&addr),
sizeof(addr)) < 0) {
49 last_error_ =
"Failed to bind UDP socket: " + std::string(strerror(errno));
57 fcntl(
socket_fd_, F_SETFL, flags | O_NONBLOCK);
61 const std::string& bind_address)
65 last_error_ =
"Failed to create UDP socket: " + std::string(strerror(errno));
72 if (!bind_address.empty() && bind_address !=
"0.0.0.0") {
73 struct sockaddr_in local;
74 memset(&local, 0,
sizeof(local));
75 local.sin_family = AF_INET;
77 if (inet_aton(bind_address.c_str(), &local.sin_addr) == 0) {
78 std::cerr <<
"[UDPSocket] Warning: bad bind address '" << bind_address <<
"'"
80 }
else if (bind(
socket_fd_,
reinterpret_cast<struct sockaddr*
>(&local),
sizeof(local)) <
82 std::cerr <<
"[UDPSocket] Warning: failed to bind sender to " << bind_address <<
": "
83 << strerror(errno) << std::endl;
89 fcntl(
socket_fd_, F_SETFL, flags | O_NONBLOCK);
104 ssize_t received = recvfrom(
socket_fd_, buffer, max_size, 0,
nullptr,
nullptr);
106 if (errno == EAGAIN || errno == EWOULDBLOCK) {
109 last_error_ =
"Receive error: " + std::string(strerror(errno));
117 uint16_t& source_port) {
123 struct sockaddr_in addr = {};
124 socklen_t addr_len =
sizeof(addr);
126 ssize_t received = recvfrom(
socket_fd_, buffer, max_size, 0,
127 reinterpret_cast<struct sockaddr*
>(&addr), &addr_len);
129 if (errno == EAGAIN || errno == EWOULDBLOCK) {
132 last_error_ =
"Receive error: " + std::string(strerror(errno));
136 source_address = inet_ntoa(addr.sin_addr);
137 source_port = ntohs(addr.sin_port);
145 if (setsockopt(
socket_fd_, SOL_SOCKET, SO_BROADCAST, &opt,
sizeof(opt)) < 0) {
146 last_error_ =
"Failed to set SO_BROADCAST: " + std::string(strerror(errno));
158 struct sockaddr_in addr = {};
159 addr.sin_family = AF_INET;
160 addr.sin_port = htons(dest_port);
161 if (inet_aton(dest_address.c_str(), &addr.sin_addr) == 0) {
162 last_error_ =
"Invalid destination: " + dest_address;
165 ssize_t sent = ::sendto(
socket_fd_, data, size, 0,
reinterpret_cast<struct sockaddr*
>(&addr),
168 if (errno == EAGAIN || errno == EWOULDBLOCK)
170 last_error_ =
"sendto error: " + std::string(strerror(errno));
184 struct sockaddr_in addr = {};
185 addr.sin_family = AF_INET;
192 ssize_t sent = sendto(
socket_fd_, data, size, 0,
reinterpret_cast<struct sockaddr*
>(&addr),
195 if (errno == EAGAIN || errno == EWOULDBLOCK) {
198 last_error_ =
"Send error: " + std::string(strerror(errno));
204 last_error_ =
"Cannot send on bound UDP socket without destination";
231 last_error_ =
"Failed to create TCP socket: " + std::string(strerror(errno));
235 struct sockaddr_in addr = {};
236 addr.sin_family = AF_INET;
237 addr.sin_port = htons(remote_port);
239 if (inet_aton(remote_address.c_str(), &addr.sin_addr) == 0) {
240 last_error_ =
"Invalid remote address: " + remote_address;
246 if (connect(
socket_fd_,
reinterpret_cast<struct sockaddr*
>(&addr),
sizeof(addr)) < 0) {
247 last_error_ =
"Failed to connect TCP socket: " + std::string(strerror(errno));
255 setsockopt(
socket_fd_, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
sizeof(keepalive));
264 ssize_t received = recv(
socket_fd_, buffer, max_size, 0);
266 if (errno == EAGAIN || errno == EWOULDBLOCK) {
269 last_error_ =
"Receive error: " + std::string(strerror(errno));
271 }
else if (received == 0) {
286 if (errno == EAGAIN || errno == EWOULDBLOCK) {
289 last_error_ =
"Send error: " + std::string(strerror(errno));
static void enable(board_bringup_t *b, uint16_t device_id)
void setup_socket(const std::string &remote_address, uint16_t remote_port)
TCPSocket(const std::string &remote_address, uint16_t remote_port)
Create TCP socket connected to remote address.
ssize_t send(const uint8_t *data, size_t size) override
Send data through the socket.
std::string last_error() const override
Get the last error message.
ssize_t receive(uint8_t *buffer, size_t max_size) override
Receive data from the socket.
bool is_valid() const override
Check if socket is valid and ready.
std::string last_error() const override
Get the last error message.
ssize_t send_to(const std::string &dest_address, uint16_t dest_port, const uint8_t *data, size_t size)
Send UDP packet to specific destination (works on bound sockets).
UDPSocket(const std::string &bind_address, uint16_t bind_port)
Create UDP socket bound to local address.
bool is_valid() const override
Check if socket is valid and ready.
std::string remote_address_
bool set_broadcast(bool enable)
Enable broadcast (required before send_to to 255.255.255.255).
ssize_t receive(uint8_t *buffer, size_t max_size) override
Receive data from the socket.
ssize_t receive_from(uint8_t *buffer, size_t max_size, std::string &source_address, uint16_t &source_port)
Receive with source address information.
ssize_t send(const uint8_t *data, size_t size) override
Send data through the socket.