kopia lustrzana https://github.com/micropython/micropython
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
rodzic
07f229e030
commit
ad908fa9bd
|
@ -53,6 +53,16 @@
|
||||||
#include "extmod/vfs.h"
|
#include "extmod/vfs.h"
|
||||||
#include <poll.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
|
The idea of this module is to implement reasonable minimum of
|
||||||
socket-related functions to write typical clients and servers.
|
socket-related functions to write typical clients and servers.
|
||||||
|
@ -71,18 +81,18 @@
|
||||||
// fields should have the same layout.
|
// fields should have the same layout.
|
||||||
typedef struct _mp_obj_socket_t {
|
typedef struct _mp_obj_socket_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
int fd;
|
socket_t fd;
|
||||||
bool blocking;
|
bool blocking;
|
||||||
} mp_obj_socket_t;
|
} mp_obj_socket_t;
|
||||||
|
|
||||||
const mp_obj_type_t mp_type_socket;
|
const mp_obj_type_t mp_type_socket;
|
||||||
|
|
||||||
// Helper functions
|
// 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);
|
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);
|
mp_obj_socket_t *o = mp_obj_malloc(mp_obj_socket_t, &mp_type_socket);
|
||||||
o->fd = fd;
|
o->fd = fd;
|
||||||
o->blocking = true;
|
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) {
|
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);
|
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||||
ssize_t r;
|
socket_size_t r;
|
||||||
MP_HAL_RETRY_SYSCALL(r, read(o->fd, buf, size), {
|
MP_HAL_RETRY_SYSCALL(r, read_socket(o->fd, buf, size), {
|
||||||
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
||||||
// timed out, and need to convert that to ETIMEDOUT.
|
// timed out, and need to convert that to ETIMEDOUT.
|
||||||
if (err == EAGAIN && o->blocking) {
|
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) {
|
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);
|
mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||||
ssize_t r;
|
socket_size_t r;
|
||||||
MP_HAL_RETRY_SYSCALL(r, write(o->fd, buf, size), {
|
MP_HAL_RETRY_SYSCALL(r, write_socket(o->fd, buf, size), {
|
||||||
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
// On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO
|
||||||
// timed out, and need to convert that to ETIMEDOUT.
|
// timed out, and need to convert that to ETIMEDOUT.
|
||||||
if (err == EAGAIN && o->blocking) {
|
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
|
// file descriptor. If you're interested to catch I/O errors before
|
||||||
// closing fd, fsync() it.
|
// closing fd, fsync() it.
|
||||||
MP_THREAD_GIL_EXIT();
|
MP_THREAD_GIL_EXIT();
|
||||||
close(self->fd);
|
close_socket(self->fd);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
return 0;
|
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);
|
int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
int err = errno;
|
int err = socket_errno;
|
||||||
if (self->blocking) {
|
if (self->blocking) {
|
||||||
if (err == EINTR) {
|
if (err == socket_eintr) {
|
||||||
mp_handle_pending(true);
|
mp_handle_pending(true);
|
||||||
continue;
|
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();
|
MP_THREAD_GIL_EXIT();
|
||||||
int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
|
int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(r, errno);
|
RAISE_ERRNO(r, socket_errno);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
static MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
|
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();
|
MP_THREAD_GIL_EXIT();
|
||||||
int r = listen(self->fd, backlog);
|
int r = listen(self->fd, backlog);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(r, errno);
|
RAISE_ERRNO(r, socket_errno);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen);
|
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)
|
// sockaddr_storage isn't stack-friendly (129 bytes or so)
|
||||||
// struct sockaddr_storage addr;
|
// struct sockaddr_storage addr;
|
||||||
byte addr[32];
|
byte addr[32];
|
||||||
socklen_t addr_len = sizeof(addr);
|
sock_len_t addr_len = sizeof(addr);
|
||||||
int fd;
|
socket_t fd;
|
||||||
MP_HAL_RETRY_SYSCALL(fd, accept(self->fd, (struct sockaddr *)&addr, &addr_len), {
|
MP_HAL_RETRY_SYSCALL(fd, accept(self->fd, (struct sockaddr *)&addr, &addr_len), {
|
||||||
// EAGAIN on a blocking socket means the operation timed out
|
// EAGAIN on a blocking socket means the operation timed out
|
||||||
if (self->blocking && err == EAGAIN) {
|
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);
|
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_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);
|
mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
|
||||||
m_del(char, buf, 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;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
sock_len_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
byte *buf = m_new(byte, sz);
|
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_HAL_RETRY_SYSCALL(out_sz, recvfrom(self->fd, buf, sz, flags, (struct sockaddr *)&addr, &addr_len),
|
||||||
mp_raise_OSError(err));
|
mp_raise_OSError(err));
|
||||||
mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
|
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_buffer_info_t bufinfo;
|
||||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
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_HAL_RETRY_SYSCALL(out_sz, send(self->fd, bufinfo.buf, bufinfo.len, flags),
|
||||||
mp_raise_OSError(err));
|
mp_raise_OSError(err));
|
||||||
return MP_OBJ_NEW_SMALL_INT(out_sz);
|
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_buffer_info_t bufinfo, addr_bi;
|
||||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||||
mp_get_buffer_raise(dst_addr, &addr_bi, 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,
|
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));
|
(struct sockaddr *)addr_bi.buf, addr_bi.len), mp_raise_OSError(err));
|
||||||
return MP_OBJ_NEW_SMALL_INT(out_sz);
|
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]);
|
int option = mp_obj_get_int(args[2]);
|
||||||
|
|
||||||
const void *optval;
|
const void *optval;
|
||||||
socklen_t optlen;
|
sock_len_t optlen;
|
||||||
int val;
|
int val;
|
||||||
if (mp_obj_is_int(args[3])) {
|
if (mp_obj_is_int(args[3])) {
|
||||||
val = mp_obj_int_get_truncated(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();
|
MP_THREAD_GIL_EXIT();
|
||||||
int r = setsockopt(self->fd, level, option, optval, optlen);
|
int r = setsockopt(self->fd, level, option, optval, optlen);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(r, errno);
|
RAISE_ERRNO(r, socket_errno);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
|
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);
|
int flags = fcntl(self->fd, F_GETFL, 0);
|
||||||
if (flags == -1) {
|
if (flags == -1) {
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(flags, errno);
|
RAISE_ERRNO(flags, socket_errno);
|
||||||
}
|
}
|
||||||
if (val) {
|
if (val) {
|
||||||
flags &= ~O_NONBLOCK;
|
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);
|
flags = fcntl(self->fd, F_SETFL, flags);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(flags, errno);
|
RAISE_ERRNO(flags, socket_errno);
|
||||||
self->blocking = val;
|
self->blocking = val;
|
||||||
return mp_const_none;
|
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));
|
r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
MP_THREAD_GIL_ENTER();
|
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));
|
r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(r, errno);
|
RAISE_ERRNO(r, socket_errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->blocking != new_blocking) {
|
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();
|
MP_THREAD_GIL_EXIT();
|
||||||
int fd = socket(family, type, proto);
|
socket_t fd = socket(family, type, proto);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
RAISE_ERRNO(fd, errno);
|
RAISE_ERRNO(fd, socket_errno);
|
||||||
return MP_OBJ_FROM_PTR(socket_new(fd));
|
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);
|
int family = mp_obj_get_int(family_in);
|
||||||
byte binaddr[BINADDR_MAX_LEN];
|
byte binaddr[BINADDR_MAX_LEN];
|
||||||
int r = inet_pton(family, mp_obj_str_get_str(addr_in), binaddr);
|
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) {
|
if (r == 0) {
|
||||||
mp_raise_OSError(MP_EINVAL);
|
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_t vstr;
|
||||||
vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
|
vstr_init_len(&vstr, family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN);
|
||||||
if (inet_ntop(family, bufinfo.buf, vstr.buf, vstr.len) == NULL) {
|
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);
|
vstr.len = strlen(vstr.buf);
|
||||||
return mp_obj_new_str_from_utf8_vstr(&vstr);
|
return mp_obj_new_str_from_utf8_vstr(&vstr);
|
||||||
|
|
Ładowanie…
Reference in New Issue