Implement recvfrom_into and sendto for UDP

This commit is contained in:
Lucian Copeland 2020-11-13 13:12:07 -05:00
parent 21ca1b8c2b
commit 0bbdf05936
4 changed files with 52 additions and 47 deletions

View File

@ -188,6 +188,7 @@ SRC_C += \
lib/utils/pyexec.c \
lib/utils/stdout_helpers.c \
lib/utils/sys_stdio_mphal.c \
lib/netutils/netutils.c \
peripherals/pcnt.c \
peripherals/pins.c \
peripherals/rmt.c \

View File

@ -32,6 +32,11 @@
#include "py/runtime.h"
#include "supervisor/shared/tick.h"
#include "components/lwip/lwip/src/include/lwip/err.h"
#include "components/lwip/lwip/src/include/lwip/sockets.h"
#include "components/lwip/lwip/src/include/lwip/sys.h"
#include "components/lwip/lwip/src/include/lwip/netdb.h"
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms) {
self->timeout_ms = timeout_ms;
}
@ -122,58 +127,55 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
const char* host, size_t hostlen, uint8_t port, const uint8_t* buf, mp_uint_t len) {
// Get the IP address string
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *result;
int error = lwip_getaddrinfo(host, NULL, &hints, &result);
if (error != 0 || result == NULL) {
return 0;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
struct in_addr *addr = &((struct sockaddr_in *)result->ai_addr)->sin_addr;
#pragma GCC diagnostic pop
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(*addr, ip_str, IP4ADDR_STRLEN_MAX);
freeaddrinfo(result);
// Set parameters
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);
dest_addr.sin_addr.s_addr = inet_addr((const char *)ip_str);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
int err = getaddrinfo(host, NULL, &hints, &res);
if (err != 0 || res == NULL) {
return mp_const_none;
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (bytes_sent < 0) {
mp_raise_BrokenPipeError();
return 0;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
#pragma GCC diagnostic pop
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(*addr, ip_str, IP4ADDR_STRLEN_MAX);
mp_obj_t ip_obj = mp_obj_new_str(ip_str, strlen(ip_str));
freeaddrinfo(res);
int err = lwip_sendto(self->num, buf, len, 0 /* flags */,
(struct sockaddr *)&dest_addr, sizeof(dest_addr));
return bytes_sent;
}
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* self,
const uint8_t* buf, mp_uint_t len, uint8_t* ip, uint8_t port) {
uint8_t* buf, mp_uint_t len, uint8_t* ip, uint *port) {
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *res;
int err = getaddrinfo(host, NULL, &hints, &res);
if (err != 0 || res == NULL) {
return mp_const_none;
struct sockaddr_in source_addr;
socklen_t socklen = sizeof(source_addr);
int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen);
memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof source_addr.sin_addr.s_addr);
*port = source_addr.sin_port;
if (bytes_received < 0) {
mp_raise_BrokenPipeError();
return 0;
} else {
buf[bytes_received] = 0; // Null-terminate whatever we received
return bytes_received;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
#pragma GCC diagnostic pop
char ip_str[IP4ADDR_STRLEN_MAX];
inet_ntoa_r(*addr, ip_str, IP4ADDR_STRLEN_MAX);
mp_obj_t ip_obj = mp_obj_new_str(ip_str, strlen(ip_str));
freeaddrinfo(res);
}
void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) {

View File

@ -36,6 +36,8 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "lib/netutils/netutils.h"
//| class Socket:
//| """TCP, UDP and RAW socket. Cannot be created directly. Instead, call
//| `SocketPool.socket()`.
@ -298,7 +300,7 @@ STATIC mp_obj_t socketpool_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_
mp_int_t port = mp_obj_get_int(addr_items[1]);
mp_int_t ret = common_hal_socketpool_socket_sendto(self, host, hostlen, port, bufinfo.buf, bufinfo.len);
if (!ok) {
if (!ret) {
mp_raise_OSError(0);
}
@ -324,11 +326,11 @@ STATIC mp_obj_t socketpool_socket_recvfrom_into(mp_obj_t self_in, mp_obj_t data_
byte ip[4];
mp_uint_t port;
mp_int_t ret = common_hal_socketpool_socket_recvfrom_into(self,
(byte*)bufinfo.buf, len, ip, &port);
(byte*)bufinfo.buf, bufinfo.len, ip, &port);
mp_obj_t tuple_contents[2];
tuple_contents[0] = mp_obj_new_int_from_uint(ret);
tuple_contents[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return mp_obj_new_tuple(2, tuple);
return mp_obj_new_tuple(2, tuple_contents);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_recvfrom_into_obj, socketpool_socket_recvfrom_into);

View File

@ -36,9 +36,9 @@ bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const c
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len);
mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len);
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self,
const uint8_t* host, size_t hostlen, uint8_t port, const uint8_t* buf, mp_uint_t len);
const char* host, size_t hostlen, uint8_t port, const uint8_t* buf, mp_uint_t len);
mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* self,
const uint8_t* buf, mp_uint_t len, uint8_t* ip, uint8_t port);
uint8_t* buf, mp_uint_t len, uint8_t* ip, uint *port);
void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self);
bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t* self);
bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self);