pull/12810/merge
stinos 2024-04-25 22:52:09 +02:00 zatwierdzone przez GitHub
commit 951994e384
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
26 zmienionych plików z 417 dodań i 49 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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),

Wyświetl plik

@ -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 \

Wyświetl plik

@ -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__

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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">

Wyświetl plik

@ -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"

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -8,4 +8,7 @@
<PreprocessorDefinitions>%(PreprocessorDefinitions);MICROPY_ROM_TEXT_COMPRESSION=1</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<PySubmodules Include="lib/micropython-lib" />
</ItemGroup>
</Project>

Wyświetl plik

@ -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

Wyświetl plik

@ -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>

Wyświetl plik

@ -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))

Wyświetl plik

@ -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))

Wyświetl plik

@ -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()

Wyświetl plik

@ -1,5 +1,5 @@
--- instance0 ---
b'GET / HTTP'
OSError 104
OSError True
--- instance1 ---

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()

Wyświetl plik

@ -0,0 +1,6 @@
--- instance0 ---
True
NEXT
--- instance1 ---
True
NEXT

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()

Wyświetl plik

@ -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()

Wyświetl plik

@ -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])

Wyświetl plik

@ -0,0 +1 @@
True

Wyświetl plik

@ -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")

Wyświetl plik

@ -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