unix/modsocket: Introduce typedefs and macros.

Upcoming commits are going to port this file to work with sockets
on windows so prepare for that with the platform-specific bits.

Signed-off-by: stijn <stijn@ignitron.net>
pull/12810/head
stijn 2023-10-25 16:53:28 +02:00
rodzic 07f229e030
commit ad908fa9bd
1 zmienionych plików z 39 dodań i 29 usunięć

Wyświetl plik

@ -53,6 +53,16 @@
#include "extmod/vfs.h"
#include <poll.h>
typedef socklen_t sock_len_t;
typedef int socket_t;
typedef ssize_t socket_size_t;
#define socket_errno errno
#define socket_eintr EINTR
#define read_socket read
#define write_socket write
#define close_socket close
/*
The idea of this module is to implement reasonable minimum of
socket-related functions to write typical clients and servers.
@ -71,18 +81,18 @@
// fields should have the same layout.
typedef struct _mp_obj_socket_t {
mp_obj_base_t base;
int fd;
socket_t fd;
bool blocking;
} mp_obj_socket_t;
const mp_obj_type_t mp_type_socket;
// Helper functions
static inline mp_obj_t mp_obj_from_sockaddr(const struct sockaddr *addr, socklen_t len) {
static inline mp_obj_t mp_obj_from_sockaddr(const struct sockaddr *addr, sock_len_t len) {
return mp_obj_new_bytes((const byte *)addr, len);
}
static mp_obj_socket_t *socket_new(int fd) {
static mp_obj_socket_t *socket_new(socket_t fd) {
mp_obj_socket_t *o = mp_obj_malloc(mp_obj_socket_t, &mp_type_socket);
o->fd = fd;
o->blocking = true;
@ -98,8 +108,8 @@ static void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
static mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
ssize_t r;
MP_HAL_RETRY_SYSCALL(r, read(o->fd, buf, size), {
socket_size_t r;
MP_HAL_RETRY_SYSCALL(r, read_socket(o->fd, buf, size), {
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
// timed out, and need to convert that to ETIMEDOUT.
if (err == EAGAIN && o->blocking) {
@ -114,8 +124,8 @@ static mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
static mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
ssize_t r;
MP_HAL_RETRY_SYSCALL(r, write(o->fd, buf, size), {
socket_size_t r;
MP_HAL_RETRY_SYSCALL(r, write_socket(o->fd, buf, size), {
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
// timed out, and need to convert that to ETIMEDOUT.
if (err == EAGAIN && o->blocking) {
@ -141,7 +151,7 @@ static mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
// file descriptor. If you're interested to catch I/O errors before
// closing fd, fsync() it.
MP_THREAD_GIL_EXIT();
close(self->fd);
close_socket(self->fd);
MP_THREAD_GIL_ENTER();
return 0;
@ -204,9 +214,9 @@ static mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
MP_THREAD_GIL_ENTER();
if (r == -1) {
int err = errno;
int err = socket_errno;
if (self->blocking) {
if (err == EINTR) {
if (err == socket_eintr) {
mp_handle_pending(true);
continue;
}
@ -229,7 +239,7 @@ static mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
MP_THREAD_GIL_EXIT();
int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
@ -247,7 +257,7 @@ static mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) {
MP_THREAD_GIL_EXIT();
int r = listen(self->fd, backlog);
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen);
@ -257,8 +267,8 @@ static mp_obj_t socket_accept(mp_obj_t self_in) {
// sockaddr_storage isn't stack-friendly (129 bytes or so)
// struct sockaddr_storage addr;
byte addr[32];
socklen_t addr_len = sizeof(addr);
int fd;
sock_len_t addr_len = sizeof(addr);
socket_t fd;
MP_HAL_RETRY_SYSCALL(fd, accept(self->fd, (struct sockaddr *)&addr, &addr_len), {
// EAGAIN on a blocking socket means the operation timed out
if (self->blocking && err == EAGAIN) {
@ -288,7 +298,7 @@ static mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) {
}
byte *buf = m_new(byte, sz);
ssize_t out_sz;
socket_size_t out_sz;
MP_HAL_RETRY_SYSCALL(out_sz, recv(self->fd, buf, sz, flags), mp_raise_OSError(err));
mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
m_del(char, buf, sz);
@ -306,10 +316,10 @@ static mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) {
}
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
sock_len_t addr_len = sizeof(addr);
byte *buf = m_new(byte, sz);
ssize_t out_sz;
socket_size_t out_sz;
MP_HAL_RETRY_SYSCALL(out_sz, recvfrom(self->fd, buf, sz, flags, (struct sockaddr *)&addr, &addr_len),
mp_raise_OSError(err));
mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
@ -336,7 +346,7 @@ static mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
ssize_t out_sz;
socket_size_t out_sz;
MP_HAL_RETRY_SYSCALL(out_sz, send(self->fd, bufinfo.buf, bufinfo.len, flags),
mp_raise_OSError(err));
return MP_OBJ_NEW_SMALL_INT(out_sz);
@ -356,7 +366,7 @@ static mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo, addr_bi;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ);
ssize_t out_sz;
socket_size_t out_sz;
MP_HAL_RETRY_SYSCALL(out_sz, sendto(self->fd, bufinfo.buf, bufinfo.len, flags,
(struct sockaddr *)addr_bi.buf, addr_bi.len), mp_raise_OSError(err));
return MP_OBJ_NEW_SMALL_INT(out_sz);
@ -370,7 +380,7 @@ static mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
int option = mp_obj_get_int(args[2]);
const void *optval;
socklen_t optlen;
sock_len_t optlen;
int val;
if (mp_obj_is_int(args[3])) {
val = mp_obj_int_get_truncated(args[3]);
@ -385,7 +395,7 @@ static mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
MP_THREAD_GIL_EXIT();
int r = setsockopt(self->fd, level, option, optval, optlen);
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
@ -397,7 +407,7 @@ static mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
int flags = fcntl(self->fd, F_GETFL, 0);
if (flags == -1) {
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(flags, errno);
RAISE_ERRNO(flags, socket_errno);
}
if (val) {
flags &= ~O_NONBLOCK;
@ -406,7 +416,7 @@ static mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
}
flags = fcntl(self->fd, F_SETFL, flags);
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(flags, errno);
RAISE_ERRNO(flags, socket_errno);
self->blocking = val;
return mp_const_none;
}
@ -442,11 +452,11 @@ static mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
if (r == -1) {
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
}
r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
}
if (self->blocking != new_blocking) {
@ -491,9 +501,9 @@ static mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
}
MP_THREAD_GIL_EXIT();
int fd = socket(family, type, proto);
socket_t fd = socket(family, type, proto);
MP_THREAD_GIL_ENTER();
RAISE_ERRNO(fd, errno);
RAISE_ERRNO(fd, socket_errno);
return MP_OBJ_FROM_PTR(socket_new(fd));
}
@ -541,7 +551,7 @@ static mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) {
int family = mp_obj_get_int(family_in);
byte binaddr[BINADDR_MAX_LEN];
int r = inet_pton(family, mp_obj_str_get_str(addr_in), binaddr);
RAISE_ERRNO(r, errno);
RAISE_ERRNO(r, socket_errno);
if (r == 0) {
mp_raise_OSError(MP_EINVAL);
}
@ -565,7 +575,7 @@ static mp_obj_t mod_socket_inet_ntop(mp_obj_t family_in, mp_obj_t binaddr_in) {
vstr_t vstr;
vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
if (inet_ntop(family, bufinfo.buf, vstr.buf, vstr.len) == NULL) {
mp_raise_OSError(errno);
mp_raise_OSError(socket_errno);
}
vstr.len = strlen(vstr.buf);
return mp_obj_new_str_from_utf8_vstr(&vstr);