kopia lustrzana https://github.com/micropython/micropython
Merge dc44e7c434
into 7b050b366b
commit
951994e384
|
@ -61,7 +61,7 @@ jobs:
|
|||
- name: Build mpy-cross.exe
|
||||
run: msbuild mpy-cross\mpy-cross.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }}
|
||||
- name: Update submodules
|
||||
run: git submodule update --init lib/micropython-lib
|
||||
run: msbuild ports\windows\micropython.vcxproj -target:UpdateSubmodules -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }}
|
||||
- name: Build micropython.exe
|
||||
run: msbuild ports\windows\micropython.vcxproj -maxcpucount -property:Configuration=${{ matrix.configuration }} -property:Platform=${{ matrix.platform }} -property:PyVariant=${{ matrix.variant }}
|
||||
- name: Get micropython.exe path
|
||||
|
|
|
@ -36,10 +36,26 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
// To get inet_pton and inet_ntop.
|
||||
#ifdef __MINGW32__
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#ifndef __MINGW32__
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -51,7 +67,109 @@
|
|||
#include "py/mphal.h"
|
||||
#include "py/mpthread.h"
|
||||
#include "extmod/vfs.h"
|
||||
#include <poll.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// Some extra info regarding the windows-specific code:
|
||||
// - like CPython, most of the error codes raised as OSError will be the WSA error codes, not errno.
|
||||
// - places where EAGAIN is turned into MP_ETIMEOUT are generally not needed On windows since the
|
||||
// socket calls already return WSAETIMEDOUT.
|
||||
// - makefile() and poll functionality are not implemented.
|
||||
|
||||
typedef int sock_len_t;
|
||||
typedef int socket_size_t;
|
||||
typedef SOCKET socket_t;
|
||||
|
||||
// Just to make sure since we rely on this.
|
||||
#if SOCKET_ERROR != -1
|
||||
#error socket functions must return -1 for errors
|
||||
#endif
|
||||
#if NO_ERROR != 0
|
||||
#error socket functions must return 0 for no errors
|
||||
#endif
|
||||
|
||||
#define socket_errno WSAGetLastError()
|
||||
#define socket_eintr WSAEINTR
|
||||
#define read_socket(fd, buf, size) recv(fd, buf, size, 0)
|
||||
#define write_socket(fd, buf, size) send(fd, buf, size, 0)
|
||||
#define close_socket(fd) closesocket(fd)
|
||||
|
||||
void wsa_startup() {
|
||||
WSADATA wsaData;
|
||||
(void)WSAStartup(MAKEWORD(1, 1), &wsaData);
|
||||
}
|
||||
|
||||
void wsa_cleanup() {
|
||||
(void)WSACleanup();
|
||||
}
|
||||
|
||||
// Socket calls are syscalls but with WSA error codes, not errno.
|
||||
#ifdef MP_HAL_RETRY_SYSCALL
|
||||
#undef MP_HAL_RETRY_SYSCALL
|
||||
#endif
|
||||
|
||||
#define MP_HAL_RETRY_SYSCALL(ret, syscall, raise) { \
|
||||
for (;;) { \
|
||||
MP_THREAD_GIL_EXIT(); \
|
||||
ret = syscall; \
|
||||
MP_THREAD_GIL_ENTER(); \
|
||||
if (ret == -1) { \
|
||||
int err = WSAGetLastError(); \
|
||||
if (err == WSAEINTR) { \
|
||||
mp_handle_pending(true); \
|
||||
continue; \
|
||||
} \
|
||||
raise; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Get SO_RCVTIMEO or SO_SNDTIMEO values.
|
||||
DWORD get_socket_timeout(socket_t sock, bool read_or_write) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
DWORD timeout = 0;
|
||||
int opt_len = sizeof(timeout);
|
||||
const int opt_name = read_or_write ? SO_RCVTIMEO : SO_SNDTIMEO;
|
||||
const int r = getsockopt(sock, SOL_SOCKET, opt_name, (char *)&timeout, &opt_len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
RAISE_ERRNO(r, WSAGetLastError());
|
||||
return timeout;
|
||||
}
|
||||
|
||||
// Perform select() call, raising timeout error if timed out.
|
||||
void select_on_socket(socket_t sock, bool read_or_write, DWORD timeout) {
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout * 1000) % 1000;
|
||||
int r;
|
||||
fd_set *read_fd = read_or_write ? &fdset : NULL;
|
||||
fd_set *write_fd = read_or_write ? NULL : &fdset;
|
||||
// First argument is ignored: "The nfds parameter is included only for
|
||||
// compatibility with Berkeley sockets".
|
||||
MP_HAL_RETRY_SYSCALL(r, select(1, read_fd, write_fd, NULL, &tv), {
|
||||
// r < 0 is error, r == 0 is timeout, r > 0 = no timeout.
|
||||
RAISE_ERRNO(r, WSAGetLastError());
|
||||
});
|
||||
if (r == 0) {
|
||||
mp_raise_OSError(MP_ETIMEDOUT);
|
||||
}
|
||||
}
|
||||
#else
|
||||
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
|
||||
|
||||
#define initialize_socket_system() {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
The idea of this module is to implement reasonable minimum of
|
||||
|
@ -67,22 +185,20 @@
|
|||
should be add to separate modules (C or Python level).
|
||||
*/
|
||||
|
||||
// This type must "inherit" from mp_obj_fdfile_t, i.e. matching subset of
|
||||
// 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 +214,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 +230,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,10 +257,11 @@ 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;
|
||||
|
||||
#ifndef _WIN32
|
||||
case MP_STREAM_GET_FILENO:
|
||||
return self->fd;
|
||||
|
||||
|
@ -179,6 +296,7 @@ static mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
|
|||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
default:
|
||||
*errcode = MP_EINVAL;
|
||||
|
@ -186,11 +304,13 @@ static mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static mp_obj_t socket_fileno(mp_obj_t self_in) {
|
||||
mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(self->fd);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
|
||||
#endif
|
||||
|
||||
static mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
@ -200,13 +320,22 @@ static mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
|||
// special case of PEP 475 to retry only if blocking so we can't use
|
||||
// MP_HAL_RETRY_SYSCALL() here
|
||||
for (;;) {
|
||||
#ifdef _WIN32
|
||||
// The connect() call has no timeout so implement it by first calling select().
|
||||
// In theory there's a race condition here between select() returning and connect()
|
||||
// being called, in practice doesn't seem worth fixing.
|
||||
const DWORD timeout = get_socket_timeout(self->fd, true);
|
||||
if (timeout > 0 && self->blocking) {
|
||||
select_on_socket(self->fd, true, timeout);
|
||||
}
|
||||
#endif
|
||||
MP_THREAD_GIL_EXIT();
|
||||
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 +358,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 +376,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 +386,28 @@ 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;
|
||||
#ifdef _WIN32
|
||||
// The accept() call has no timeout so manually implement it by first calling select().
|
||||
const DWORD timeout = get_socket_timeout(self->fd, true);
|
||||
if (timeout > 0 && self->blocking) {
|
||||
select_on_socket(self->fd, true, timeout);
|
||||
}
|
||||
// The accept() call returns a socket, not an int, so cannot use MP_HAL_RETRY_SYSCALL.
|
||||
for (;;) {
|
||||
fd = accept(self->fd, (struct sockaddr *)&addr, &addr_len);
|
||||
if (fd == INVALID_SOCKET) {
|
||||
const int err = WSAGetLastError();
|
||||
if (err == WSAEINTR) {
|
||||
mp_handle_pending(1);
|
||||
continue;
|
||||
}
|
||||
mp_raise_OSError(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#else
|
||||
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) {
|
||||
|
@ -266,6 +415,7 @@ static mp_obj_t socket_accept(mp_obj_t self_in) {
|
|||
}
|
||||
mp_raise_OSError(err);
|
||||
});
|
||||
#endif
|
||||
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
|
||||
t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd));
|
||||
|
@ -288,8 +438,8 @@ 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;
|
||||
MP_HAL_RETRY_SYSCALL(out_sz, recv(self->fd, buf, sz, flags), mp_raise_OSError(err));
|
||||
socket_size_t out_sz;
|
||||
MP_HAL_RETRY_SYSCALL(out_sz, recv(self->fd, (char *)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);
|
||||
return ret;
|
||||
|
@ -306,11 +456,11 @@ 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;
|
||||
MP_HAL_RETRY_SYSCALL(out_sz, recvfrom(self->fd, buf, sz, flags, (struct sockaddr *)&addr, &addr_len),
|
||||
socket_size_t out_sz;
|
||||
MP_HAL_RETRY_SYSCALL(out_sz, recvfrom(self->fd, (char *)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);
|
||||
m_del(char, buf, sz);
|
||||
|
@ -336,7 +486,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 +506,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 +520,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 +535,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);
|
||||
|
@ -394,10 +544,15 @@ static mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
|
|||
mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
int val = mp_obj_is_true(flag_in);
|
||||
MP_THREAD_GIL_EXIT();
|
||||
#ifdef _WIN32
|
||||
u_long mode = val ? 0 : 1;
|
||||
// Called 'flags' but here it's just the return value.
|
||||
const int flags = ioctlsocket(self->fd, FIONBIO, &mode);
|
||||
#else
|
||||
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;
|
||||
|
@ -405,8 +560,9 @@ static mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
|
|||
flags |= O_NONBLOCK;
|
||||
}
|
||||
flags = fcntl(self->fd, F_SETFL, flags);
|
||||
#endif
|
||||
MP_THREAD_GIL_ENTER();
|
||||
RAISE_ERRNO(flags, errno);
|
||||
RAISE_ERRNO(flags, socket_errno);
|
||||
self->blocking = val;
|
||||
return mp_const_none;
|
||||
}
|
||||
|
@ -415,6 +571,14 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
|
|||
static mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
||||
mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
struct timeval tv = {0, };
|
||||
#ifdef _WIN32
|
||||
DWORD time_val = 0;
|
||||
const char *ptv = (const char *)&time_val;
|
||||
const int opt_len = sizeof(DWORD);
|
||||
#else
|
||||
struct timeval *ptv = &tv;
|
||||
const int opt_len = sizeof(struct timeval);
|
||||
#endif
|
||||
bool new_blocking = true;
|
||||
|
||||
// Timeout of None means no timeout, which in POSIX is signified with 0 timeout,
|
||||
|
@ -428,6 +592,9 @@ static mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
|||
#else
|
||||
tv.tv_sec = mp_obj_get_int(timeout_in);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
time_val = tv.tv_usec / 1000 + tv.tv_sec * 1000;
|
||||
#endif
|
||||
|
||||
// For SO_RCVTIMEO/SO_SNDTIMEO, zero timeout means infinity, but
|
||||
// for Python API it means non-blocking.
|
||||
|
@ -439,14 +606,14 @@ static mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
|||
if (new_blocking) {
|
||||
int r;
|
||||
MP_THREAD_GIL_EXIT();
|
||||
r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
|
||||
r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, ptv, opt_len);
|
||||
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));
|
||||
r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, ptv, opt_len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
RAISE_ERRNO(r, errno);
|
||||
RAISE_ERRNO(r, socket_errno);
|
||||
}
|
||||
|
||||
if (self->blocking != new_blocking) {
|
||||
|
@ -457,6 +624,7 @@ static mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
|
|||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
|
||||
|
||||
#ifndef _WIN32
|
||||
static mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
|
||||
// TODO: CPython explicitly says that closing returned object doesn't close
|
||||
// the original socket (Python2 at all says that fd is dup()ed). But we
|
||||
|
@ -468,6 +636,7 @@ static mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
|
|||
return mp_vfs_open(n_args, new_args, (mp_map_t *)&mp_const_empty_map);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile);
|
||||
#endif
|
||||
|
||||
static mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
(void)type_in;
|
||||
|
@ -491,15 +660,22 @@ 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);
|
||||
#ifdef _WIN32
|
||||
const int err = fd == INVALID_SOCKET ? -1 : 0;
|
||||
#else
|
||||
const int err = fd;
|
||||
#endif
|
||||
MP_THREAD_GIL_ENTER();
|
||||
RAISE_ERRNO(fd, errno);
|
||||
RAISE_ERRNO(err, socket_errno);
|
||||
return MP_OBJ_FROM_PTR(socket_new(fd));
|
||||
}
|
||||
|
||||
static const mp_rom_map_elem_t socket_locals_dict_table[] = {
|
||||
#ifndef _WIN32
|
||||
{ MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
|
@ -541,7 +717,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 +741,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);
|
||||
|
@ -700,7 +876,9 @@ static const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
|
|||
C(SOCK_RAW),
|
||||
|
||||
C(MSG_DONTROUTE),
|
||||
#ifndef _WIN32
|
||||
C(MSG_DONTWAIT),
|
||||
#endif
|
||||
|
||||
C(SOL_SOCKET),
|
||||
C(SO_BROADCAST),
|
||||
|
|
|
@ -56,6 +56,7 @@ SRC_C = \
|
|||
shared/runtime/gchelper_generic.c \
|
||||
ports/unix/main.c \
|
||||
ports/unix/input.c \
|
||||
ports/unix/modsocket.c \
|
||||
ports/unix/gccollect.c \
|
||||
windows_mphal.c \
|
||||
realpath.c \
|
||||
|
|
|
@ -69,6 +69,7 @@ In the IDE, open `micropython-cross.vcxproj` and `micropython.vcxproj` and build
|
|||
To build from the command line:
|
||||
|
||||
msbuild ../../mpy-cross/mpy-cross.vcxproj
|
||||
msbuild micropython.vcxproj /t:UpdateSubmodules
|
||||
msbuild micropython.vcxproj
|
||||
|
||||
__Variants__
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
@ -34,6 +35,11 @@
|
|||
|
||||
extern BOOL WINAPI console_sighandler(DWORD evt);
|
||||
|
||||
#if MICROPY_PY_SOCKET
|
||||
extern void wsa_startup();
|
||||
extern void wsa_cleanup();
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void invalid_param_handler(const wchar_t *expr, const wchar_t *fun, const wchar_t *file, unsigned int line, uintptr_t p) {
|
||||
}
|
||||
|
@ -61,8 +67,14 @@ void init() {
|
|||
_set_output_format(_TWO_DIGIT_EXPONENT);
|
||||
#endif
|
||||
set_fmode_binary();
|
||||
#if MICROPY_PY_SOCKET
|
||||
wsa_startup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
SetConsoleCtrlHandler(console_sighandler, FALSE);
|
||||
#if MICROPY_PY_SOCKET
|
||||
wsa_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="@(PyCoreSource)" />
|
||||
<ClCompile Include="@(PyExtModSource)" />
|
||||
<ClCompile Include="@(PyThirdPartySource)" />
|
||||
<ClCompile Include="$(PyBaseDir)shared\readline\*.c" />
|
||||
<ClCompile Include="$(PyBaseDir)shared\runtime\gchelper_generic.c" />
|
||||
<ClCompile Include="$(PyBaseDir)ports\windows\*.c" />
|
||||
|
@ -94,6 +95,7 @@
|
|||
<ClCompile Include="$(PyBaseDir)ports\unix\gccollect.c"/>
|
||||
<ClCompile Include="$(PyBaseDir)ports\unix\input.c"/>
|
||||
<ClCompile Include="$(PyBaseDir)ports\unix\main.c"/>
|
||||
<ClCompile Include="$(PyBaseDir)ports\unix\modsocket.c" />
|
||||
<ClCompile Include="$(PyVariantDir)*.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -107,7 +109,7 @@
|
|||
</ItemGroup>
|
||||
<Import Project="msvc/genhdr.targets" />
|
||||
<Import Project="$(CustomPropsFile)" Condition="exists('$(CustomPropsFile)')" />
|
||||
<Target Name="GenerateMicroPythonSources" BeforeTargets="BuildGenerateSources" DependsOnTargets="GenerateHeaders;FreezeModules">
|
||||
<Target Name="GenerateMicroPythonSources" BeforeTargets="BuildGenerateSources" DependsOnTargets="UpdateSubmodulesIfInIDE;GenerateHeaders;FreezeModules">
|
||||
</Target>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
|
||||
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
|
||||
#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0)
|
||||
#define MICROPY_PY_SOCKET (1)
|
||||
#define MICROPY_PY_SYS_EXIT (1)
|
||||
#define MICROPY_PY_SYS_ATEXIT (1)
|
||||
#define MICROPY_PY_SYS_PLATFORM "win32"
|
||||
|
|
|
@ -62,4 +62,16 @@
|
|||
<Copy SourceFiles="%(PyOutputFiles.Identity)" DestinationFiles="%(PyOutputFiles.Destination)"/>
|
||||
<WriteLinesToFile File="$(TLogLocation)$(ProjectName).write.u.tlog" Lines="$(PyFileCopyCookie);@(PyOutputFiles->'%(Destination)')" Overwrite="True"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="UpdateSubmodules" Condition="@(PySubmodules) != ''">
|
||||
<Message Text="Updating submodules: @(PySubmodules)"/>
|
||||
<Exec Command="git submodule sync $(PyBaseDir)%(PySubmodules.Identity)"/>
|
||||
<Exec Command="git submodule update --init $(PyBaseDir)%(PySubmodules.Identity)"/>
|
||||
</Target>
|
||||
|
||||
<!-- Within an IDE it's usually not simple to manually select Targets to build so allow doing
|
||||
this automatically to be able to build from scratch. Still make this optional though because it isn't exactly fast. -->
|
||||
<Target Name="UpdateSubmodulesIfInIDE" DependsOnTargets="UpdateSubmodules"
|
||||
Condition="'$(BuildingInsideVisualStudio)' == 'True' And '$(PySkipModuleUpdate)' != 'True'">
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -66,7 +66,7 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
|
|||
<ItemGroup>
|
||||
<PyIncDirs Include="$(PyIncDirs)"/>
|
||||
<PreProcDefs Include="%(ClCompile.PreProcessorDefinitions);NO_QSTR"/>
|
||||
<PyQstrSourceFiles Include="@(ClCompile)" Exclude="$(PyBuildDir)\frozen_content.c">
|
||||
<PyQstrSourceFiles Include="@(ClCompile)" Exclude="$(PyBuildDir)\frozen_content.c;@(PyThirdPartySource)">
|
||||
<Changed>False</Changed>
|
||||
<OutFile>$([System.String]::new('%(FullPath)').Replace('$(PyBaseDir)', '$(DestDir)qstr\'))</OutFile>
|
||||
</PyQstrSourceFiles>
|
||||
|
@ -82,7 +82,9 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
|
|||
</QstrDependencies>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<PyPreProcCommand>$(PyClTool) /nologo /I@(PyIncDirs, ' /I') /D@(PreProcDefs, ' /D')</PyPreProcCommand>
|
||||
<!--Command is going to run via shell so need to escape quotes. -->
|
||||
<UnescapedPreProcDefs>/D@(PreProcDefs, ' /D')</UnescapedPreProcDefs>
|
||||
<PyPreProcCommand>$(PyClTool) /nologo /I@(PyIncDirs, ' /I') $([System.String]::Copy('$(UnescapedPreProcDefs)').Replace('"','\"'))</PyPreProcCommand>
|
||||
<ForceQstrRebuild>@(QstrDependencies->AnyHaveMetadataValue('Changed', 'True'))</ForceQstrRebuild>
|
||||
<RunPreProcConcat>@(PyQstrSourceFiles->AnyHaveMetadataValue('Changed', 'True'))</RunPreProcConcat>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -8,4 +8,7 @@
|
|||
<PreprocessorDefinitions>%(PreprocessorDefinitions);MICROPY_ROM_TEXT_COMPRESSION=1</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<PySubmodules Include="lib/micropython-lib" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -26,3 +26,7 @@
|
|||
|
||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
|
||||
#ifndef __MINGW32__
|
||||
#define MICROPY_PY_SSL (1)
|
||||
#define MICROPY_SSL_MBEDTLS (1)
|
||||
#endif
|
||||
|
|
|
@ -2,5 +2,90 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
|
||||
<PropertyGroup>
|
||||
<FrozenManifest>$(PyWinDir)\variants\manifest.py</FrozenManifest>
|
||||
<PyIncDirs>$(PyIncDirs);$(PyBaseDir)lib\mbedtls\include</PyIncDirs>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>MBEDTLS_CONFIG_FILE="$(PyBaseDir)ports\unix\mbedtls\mbedtls_config_port.h";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<PySubmodules Include="lib/mbedtls" />
|
||||
<PySubmodules Include="lib/micropython-lib" />
|
||||
<!--See extmod.mk.-->
|
||||
<PyExtModSource Include="$(PyBaseDir)extmod\modtls_mbedtls.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls_errors\mp_mbedtls_errors.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\aes.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\aesni.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\asn1parse.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\asn1write.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\base64.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\bignum_core.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\bignum_mod.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\bignum_mod_raw.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\bignum.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\camellia.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ccm.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\chacha20.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\chachapoly.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\cipher.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\cipher_wrap.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\nist_kw.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\aria.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\cmac.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\constant_time.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\mps_reader.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\mps_trace.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ctr_drbg.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\debug.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\des.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\dhm.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ecdh.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ecdsa.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ecjpake.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ecp.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ecp_curves.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\entropy.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\entropy_poll.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\gcm.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\hmac_drbg.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\md5.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\md.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\oid.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\padlock.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pem.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pk.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pkcs12.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pkcs5.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pkparse.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pk_wrap.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\pkwrite.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\platform.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\platform_util.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\poly1305.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ripemd160.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\rsa.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\rsa_alt_helpers.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\sha1.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\sha256.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\sha512.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_cache.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_ciphersuites.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_client.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_cookie.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_debug_helpers_generated.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_msg.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_ticket.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_tls.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_tls12_client.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\ssl_tls12_server.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\timing.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509_create.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509_crl.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509_crt.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509_csr.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509write_crt.c" />
|
||||
<PyThirdPartySource Include="$(PyBaseDir)lib\mbedtls\library\x509write_csr.c" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -11,4 +11,4 @@ s = socket.socket()
|
|||
try:
|
||||
s.recv(1)
|
||||
except OSError as er:
|
||||
print("ENOTCONN:", er.errno == errno.ENOTCONN)
|
||||
print("ENOTCONN:", er.errno in (errno.ENOTCONN, 10057))
|
||||
|
|
|
@ -18,4 +18,4 @@ s.settimeout(0)
|
|||
try:
|
||||
s.recv(1)
|
||||
except OSError as er:
|
||||
print("EAGAIN:", er.errno == errno.EAGAIN)
|
||||
print("EAGAIN:", er.errno in (errno.EAGAIN, 10035))
|
||||
|
|
|
@ -21,7 +21,7 @@ async def handle_connection(reader, writer):
|
|||
writer.close()
|
||||
await writer.wait_closed()
|
||||
except OSError as er:
|
||||
print("OSError", er.errno)
|
||||
print("OSError", er.errno in (22, 104))
|
||||
ev.set()
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--- instance0 ---
|
||||
b'GET / HTTP'
|
||||
OSError 104
|
||||
OSError True
|
||||
--- instance1 ---
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ def instance0():
|
|||
try:
|
||||
print("recv", s.recv(10)) # should raise Errno 107 ENOTCONN
|
||||
except OSError as er:
|
||||
print(er.errno in (107, 128))
|
||||
print(er.errno in (107, 128, 10057))
|
||||
s.close()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import errno
|
||||
import socket
|
||||
|
||||
PORT = 8000
|
||||
|
||||
|
||||
# Server
|
||||
def instance0():
|
||||
multitest.globals(IP=multitest.get_network_ip())
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
|
||||
s.listen()
|
||||
multitest.next()
|
||||
s2, _ = s.accept()
|
||||
s2.settimeout(0.2)
|
||||
try:
|
||||
s2.recv(1)
|
||||
except OSError as er:
|
||||
print(er.errno in (errno.ETIMEDOUT, errno.EAGAIN) or str(er) == "timed out")
|
||||
multitest.next()
|
||||
s2.close()
|
||||
s.close()
|
||||
|
||||
|
||||
# Client
|
||||
def instance1():
|
||||
multitest.next()
|
||||
s = socket.socket()
|
||||
s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
|
||||
s.settimeout(0.2)
|
||||
try:
|
||||
s.recv(1)
|
||||
except OSError as er:
|
||||
print(er.errno in (errno.ETIMEDOUT, errno.EAGAIN) or str(er) == "timed out")
|
||||
multitest.next()
|
||||
s.close()
|
|
@ -0,0 +1,6 @@
|
|||
--- instance0 ---
|
||||
True
|
||||
NEXT
|
||||
--- instance1 ---
|
||||
True
|
||||
NEXT
|
|
@ -9,5 +9,5 @@ s.listen(1)
|
|||
try:
|
||||
s.accept()
|
||||
except OSError as er:
|
||||
print(er.errno == 11) # 11 is EAGAIN
|
||||
print(er.errno in (11, 10035)) # 11 is EAGAIN
|
||||
s.close()
|
||||
|
|
|
@ -15,5 +15,7 @@ s.listen(1)
|
|||
try:
|
||||
s.accept()
|
||||
except OSError as er:
|
||||
print(er.errno in (errno.ETIMEDOUT, "timed out")) # CPython uses a string instead of errno
|
||||
print(
|
||||
er.errno == errno.ETIMEDOUT or str(er) == "timed out"
|
||||
) # CPython uses a string instead of errno
|
||||
s.close()
|
||||
|
|
|
@ -9,7 +9,7 @@ def test(peer_addr):
|
|||
try:
|
||||
s.connect(peer_addr)
|
||||
except OSError as er:
|
||||
print(er.errno == errno.EINPROGRESS)
|
||||
print(er.errno in (errno.EINPROGRESS, 10035))
|
||||
s.close()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import errno
|
||||
import socket
|
||||
|
||||
|
||||
def test(peer_addr):
|
||||
s = socket.socket()
|
||||
s.settimeout(1)
|
||||
try:
|
||||
s.connect(peer_addr)
|
||||
except OSError as er:
|
||||
print(er.errno == errno.ETIMEDOUT or str(er) == "timed out")
|
||||
s.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test(socket.getaddrinfo("192.0.0.0", 8888)[0][-1])
|
|
@ -0,0 +1 @@
|
|||
True
|
|
@ -12,7 +12,7 @@ def test(addr, hostname, block=True):
|
|||
s.connect(addr)
|
||||
print("connected")
|
||||
except OSError as e:
|
||||
if e.errno != errno.EINPROGRESS:
|
||||
if e.errno not in (errno.EINPROGRESS, 10035):
|
||||
raise
|
||||
print("EINPROGRESS")
|
||||
|
||||
|
|
|
@ -711,6 +711,11 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
|||
# Some tests use unsupported features on Windows
|
||||
if os.name == "nt":
|
||||
skip_tests.add("import/import_file.py") # works but CPython prints forward slashes
|
||||
# Socket + select is not implemented.
|
||||
skip_tests.add("extmod/select_ipoll.py")
|
||||
skip_tests.add("extmod/select_poll_basic.py")
|
||||
skip_tests.add("extmod/select_poll_custom.py")
|
||||
skip_tests.add("extmod/select_poll_udp.py")
|
||||
|
||||
# Some tests are known to fail with native emitter
|
||||
# Remove them from the below when they work
|
||||
|
|
Ładowanie…
Reference in New Issue