extmod/modlwip: Implement raw sockets for lwIP.
Configurable via MICROPY_PY_LWIP_SOCK_RAW.
This commit is contained in:
parent
00e7fe8ab1
commit
80f5cef8d4
120
extmod/modlwip.c
120
extmod/modlwip.c
@ -40,7 +40,7 @@
|
|||||||
#include "lwip/init.h"
|
#include "lwip/init.h"
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
//#include "lwip/raw.h"
|
#include "lwip/raw.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
#if LWIP_VERSION_MAJOR < 2
|
#if LWIP_VERSION_MAJOR < 2
|
||||||
@ -280,6 +280,7 @@ typedef struct _lwip_socket_obj_t {
|
|||||||
volatile union {
|
volatile union {
|
||||||
struct tcp_pcb *tcp;
|
struct tcp_pcb *tcp;
|
||||||
struct udp_pcb *udp;
|
struct udp_pcb *udp;
|
||||||
|
struct raw_pcb *raw;
|
||||||
} pcb;
|
} pcb;
|
||||||
volatile union {
|
volatile union {
|
||||||
struct pbuf *pbuf;
|
struct pbuf *pbuf;
|
||||||
@ -361,6 +362,26 @@ static inline void exec_user_callback(lwip_socket_obj_t *socket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
// Callback for incoming raw packets.
|
||||||
|
#if LWIP_VERSION_MAJOR < 2
|
||||||
|
STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
|
||||||
|
#else
|
||||||
|
STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
|
||||||
|
|
||||||
|
if (socket->incoming.pbuf != NULL) {
|
||||||
|
pbuf_free(p);
|
||||||
|
} else {
|
||||||
|
socket->incoming.pbuf = p;
|
||||||
|
memcpy(&socket->peer, addr, sizeof(socket->peer));
|
||||||
|
}
|
||||||
|
return 1; // we ate the packet
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Callback for incoming UDP packets. We simply stash the packet and the source address,
|
// Callback for incoming UDP packets. We simply stash the packet and the source address,
|
||||||
// in case we need it for recvfrom.
|
// in case we need it for recvfrom.
|
||||||
#if LWIP_VERSION_MAJOR < 2
|
#if LWIP_VERSION_MAJOR < 2
|
||||||
@ -515,8 +536,8 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
|
|||||||
// Functions for socket send/receive operations. Socket send/recv and friends call
|
// Functions for socket send/receive operations. Socket send/recv and friends call
|
||||||
// these to do the work.
|
// these to do the work.
|
||||||
|
|
||||||
// Helper function for send/sendto to handle UDP packets.
|
// Helper function for send/sendto to handle raw/UDP packets.
|
||||||
STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
|
STATIC mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
|
||||||
if (len > 0xffff) {
|
if (len > 0xffff) {
|
||||||
// Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try
|
// Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try
|
||||||
len = 0xffff;
|
len = 0xffff;
|
||||||
@ -536,12 +557,26 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
|
|||||||
|
|
||||||
err_t err;
|
err_t err;
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
if (socket->type == MOD_NETWORK_SOCK_RAW) {
|
||||||
|
err = raw_send(socket->pcb.raw, p);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
err = udp_send(socket->pcb.udp, p);
|
err = udp_send(socket->pcb.udp, p);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ip_addr_t dest;
|
ip_addr_t dest;
|
||||||
IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]);
|
IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]);
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
if (socket->type == MOD_NETWORK_SOCK_RAW) {
|
||||||
|
err = raw_sendto(socket->pcb.raw, p, &dest);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
err = udp_sendto(socket->pcb.udp, p, &dest, port);
|
err = udp_sendto(socket->pcb.udp, p, &dest, port);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
|
|
||||||
@ -558,8 +593,8 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for recv/recvfrom to handle UDP packets
|
// Helper function for recv/recvfrom to handle raw/UDP packets
|
||||||
STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
STATIC mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
||||||
|
|
||||||
if (socket->incoming.pbuf == NULL) {
|
if (socket->incoming.pbuf == NULL) {
|
||||||
if (socket->timeout != -1) {
|
if (socket->timeout != -1) {
|
||||||
@ -795,7 +830,13 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
|
|||||||
socket->pcb.udp = udp_new();
|
socket->pcb.udp = udp_new();
|
||||||
socket->incoming.pbuf = NULL;
|
socket->incoming.pbuf = NULL;
|
||||||
break;
|
break;
|
||||||
//case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break;
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW: {
|
||||||
|
mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]);
|
||||||
|
socket->pcb.raw = raw_new(proto);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default: mp_raise_OSError(MP_EINVAL);
|
default: mp_raise_OSError(MP_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,6 +858,14 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
|
|||||||
udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket);
|
udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW: {
|
||||||
|
// Register our receive callback now. Since raw sockets don't require binding or connection
|
||||||
|
// before use, there's no other good time to do it.
|
||||||
|
raw_recv(socket->pcb.raw, _lwip_raw_incoming, (void*)socket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
socket->timeout = -1;
|
socket->timeout = -1;
|
||||||
@ -1045,6 +1094,12 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
|||||||
err = udp_connect(socket->pcb.udp, &dest, port);
|
err = udp_connect(socket->pcb.udp, &dest, port);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW: {
|
||||||
|
err = raw_connect(socket->pcb.raw, &dest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
@ -1079,11 +1134,13 @@ STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
|
|||||||
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
|
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOD_NETWORK_SOCK_DGRAM: {
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
mp_raise_OSError(_errno);
|
mp_raise_OSError(_errno);
|
||||||
}
|
}
|
||||||
@ -1108,11 +1165,13 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
|||||||
ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
|
ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOD_NETWORK_SOCK_DGRAM: {
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
mp_raise_OSError(_errno);
|
mp_raise_OSError(_errno);
|
||||||
}
|
}
|
||||||
@ -1143,11 +1202,13 @@ STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t
|
|||||||
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
|
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOD_NETWORK_SOCK_DGRAM: {
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
mp_raise_OSError(_errno);
|
mp_raise_OSError(_errno);
|
||||||
}
|
}
|
||||||
@ -1176,11 +1237,13 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
|
|||||||
ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
|
ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOD_NETWORK_SOCK_DGRAM: {
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
mp_raise_OSError(_errno);
|
mp_raise_OSError(_errno);
|
||||||
}
|
}
|
||||||
@ -1331,7 +1394,10 @@ STATIC mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
|
|||||||
case MOD_NETWORK_SOCK_STREAM:
|
case MOD_NETWORK_SOCK_STREAM:
|
||||||
return lwip_tcp_receive(socket, buf, size, errcode);
|
return lwip_tcp_receive(socket, buf, size, errcode);
|
||||||
case MOD_NETWORK_SOCK_DGRAM:
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
return lwip_udp_receive(socket, buf, size, NULL, NULL, errcode);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode);
|
||||||
}
|
}
|
||||||
// Unreachable
|
// Unreachable
|
||||||
return MP_STREAM_ERROR;
|
return MP_STREAM_ERROR;
|
||||||
@ -1344,7 +1410,10 @@ STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t
|
|||||||
case MOD_NETWORK_SOCK_STREAM:
|
case MOD_NETWORK_SOCK_STREAM:
|
||||||
return lwip_tcp_send(socket, buf, size, errcode);
|
return lwip_tcp_send(socket, buf, size, errcode);
|
||||||
case MOD_NETWORK_SOCK_DGRAM:
|
case MOD_NETWORK_SOCK_DGRAM:
|
||||||
return lwip_udp_send(socket, buf, size, NULL, 0, errcode);
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW:
|
||||||
|
#endif
|
||||||
|
return lwip_raw_udp_send(socket, buf, size, NULL, 0, errcode);
|
||||||
}
|
}
|
||||||
// Unreachable
|
// Unreachable
|
||||||
return MP_STREAM_ERROR;
|
return MP_STREAM_ERROR;
|
||||||
@ -1385,6 +1454,11 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
|
|||||||
if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) {
|
if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) {
|
||||||
// UDP socket is writable
|
// UDP socket is writable
|
||||||
ret |= MP_STREAM_POLL_WR;
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
} else if (socket->type == MOD_NETWORK_SOCK_RAW && socket->pcb.raw != NULL) {
|
||||||
|
// raw socket is writable
|
||||||
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
#endif
|
||||||
} else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
|
} else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
|
||||||
// TCP socket is writable
|
// TCP socket is writable
|
||||||
// Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
|
// Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
|
||||||
@ -1438,7 +1512,9 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break;
|
case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break;
|
||||||
//case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break;
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
|
case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
socket->pcb.tcp = NULL;
|
socket->pcb.tcp = NULL;
|
||||||
@ -1660,7 +1736,9 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
|
|||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
|
{ MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
|
{ MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
|
||||||
|
#if MICROPY_PY_LWIP_SOCK_RAW
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
|
{ MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
|
||||||
|
#endif
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) },
|
{ MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) },
|
{ MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user