From 9083ae5a5985eb7dea8aba6a7012a855af6336db Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 6 May 2024 17:35:55 +0200 Subject: [PATCH] Port remaining functions --- src/arch/posix/eventloop_mbed.cpp | 123 ++++++++++++++++++++++++++++++ src/arch/posix/mbed_tcp.cpp | 58 ++++++++++++-- src/arch/posix/mbed_tcp.h | 73 +++++++++++++++--- src/arch/posix/ua_architecture.h | 11 ++- 4 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 src/arch/posix/eventloop_mbed.cpp diff --git a/src/arch/posix/eventloop_mbed.cpp b/src/arch/posix/eventloop_mbed.cpp new file mode 100644 index 0000000..ded55c4 --- /dev/null +++ b/src/arch/posix/eventloop_mbed.cpp @@ -0,0 +1,123 @@ +#include "../eventloop_posix.h" +#include "mbed.h" + +UA_StatusCode +UA_EventLoopPOSIX_setNonBlocking(UA_FD sockfd) { + ((Socket*)sockfd)->set_blocking(false); + return UA_STATUSCODE_GOOD; +} + +UA_StatusCode +UA_EventLoopPOSIX_setNoSigPipe(UA_FD sockfd) { + return UA_STATUSCODE_GOOD; +} + +UA_StatusCode +UA_EventLoopPOSIX_setReusable(UA_FD sockfd) { + return UA_STATUSCODE_GOOD; +} + +UA_StatusCode +UA_EventLoopPOSIX_registerFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { + UA_LOCK_ASSERT(&el->elMutex, 1); + UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, + "Registering fd: %u", (unsigned)rfd->fd); + + /* Realloc */ + UA_RegisteredFD **fds_tmp = (UA_RegisteredFD**) + UA_realloc(el->fds, sizeof(UA_RegisteredFD*) * (el->fdsSize + 1)); + if(!fds_tmp) { + return UA_STATUSCODE_BADOUTOFMEMORY; + } + el->fds = fds_tmp; + + /* Add to the last entry */ + el->fds[el->fdsSize] = rfd; + el->fdsSize++; + return UA_STATUSCODE_GOOD; +} + +UA_StatusCode +UA_EventLoopPOSIX_modifyFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { + /* Do nothing, it is enough if the data was changed in the rfd */ + UA_LOCK_ASSERT(&el->elMutex, 1); + return UA_STATUSCODE_GOOD; +} + +void +UA_EventLoopPOSIX_deregisterFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { + UA_LOCK_ASSERT(&el->elMutex, 1); + UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, + "Unregistering fd: %u", (unsigned)rfd->fd); + + /* Find the entry */ + size_t i = 0; + for(; i < el->fdsSize; i++) { + if(el->fds[i] == rfd) + break; + } + + /* Not found? */ + if(i == el->fdsSize) + return; + + if(el->fdsSize > 1) { + /* Move the last entry in the ith slot and realloc. */ + el->fdsSize--; + el->fds[i] = el->fds[el->fdsSize]; + UA_RegisteredFD **fds_tmp = (UA_RegisteredFD**) + UA_realloc(el->fds, sizeof(UA_RegisteredFD*) * el->fdsSize); + /* if realloc fails the fds are still in a correct state with + * possibly lost memory, so failing silently here is ok */ + if(fds_tmp) + el->fds = fds_tmp; + } else { + /* Remove the last entry */ + UA_free(el->fds); + el->fds = NULL; + el->fdsSize = 0; + } +} + +rtos::EventFlags _events; + +UA_StatusCode +UA_EventLoopPOSIX_pollFDs(UA_EventLoopPOSIX *el, UA_DateTime listenTimeout) { + UA_assert(listenTimeout >= 0); + UA_LOCK_ASSERT(&el->elMutex, 1); + + + auto flag = _events.wait_any(0x7fffffff, 10); + if (flag & 0x80000000) { + yield(); + return UA_STATUSCODE_GOOD; + } + UA_FD ev_sock = flag; + + /* Loop over all registered FD to see if an event arrived. Yes, this is why + * select is slow for many open sockets. */ + for(size_t i = 0; i < el->fdsSize; i++) { + UA_RegisteredFD *rfd = el->fds[i]; + + if (el->fds[i]->fd != (UA_FD)ev_sock) { + // TODO: find out why we don't receive the first accepted socket event + //continue; + } + + /* The rfd is already registered for removal. Don't process incoming + * events any longer. */ + if(rfd->dc.callback) + continue; + + /* Event signaled for the fd? */ + short event = rfd->listenEvents; + + UA_LOG_INFO(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, + "Processing event %u on fd %u", (unsigned)event, + (unsigned)rfd->fd); + + /* Call the EventSource callback */ + rfd->eventSourceCB(rfd->es, rfd, event); + } + return UA_STATUSCODE_GOOD; +} diff --git a/src/arch/posix/mbed_tcp.cpp b/src/arch/posix/mbed_tcp.cpp index 458efb1..8dd22bd 100644 --- a/src/arch/posix/mbed_tcp.cpp +++ b/src/arch/posix/mbed_tcp.cpp @@ -32,10 +32,10 @@ int mbed_close(UA_FD fd) return rc; } -int mbed_connect(UA_FD fd, SocketAddress* addr) +int mbed_connect(UA_FD fd, struct sockaddr* addr) { TCPSocket * sock = (TCPSocket *)fd; - nsapi_error_t const rc = sock->connect(*addr); + nsapi_error_t const rc = sock->connect(*((SocketAddress*)addr)); return rc; } @@ -60,12 +60,56 @@ void event(Socket * s) //printf("Processing event: %x\n", (uint32_t)s); } -TCPSocket * socket(int /* family */, int /* type */, int /* proto */) +UA_SOCKET mbed_accept(UA_FD fd, struct sockaddr* s, size_t* s_sz) { + // TODO: do something to retrieve s (getpeername?) + nsapi_error_t error; + TCPSocket* sock = ((TCPSocket*)fd)->accept(&error); + if (sock && error == NSAPI_ERROR_OK) { + sock->sigio(mbed::callback(event, sock)); + sock->getpeername((SocketAddress*)s); + sock->set_timeout(1500); + sock->set_blocking(false); + } else { + errno = UA_INTERRUPTED; + } + return (UA_SOCKET)sock; +} + +int mbed_bind(UA_FD fd, struct sockaddr* addr, size_t s_sz) { + return ((TCPSocket*)fd)->bind(((SocketAddress*)addr)->get_port()); +} + +int mbed_getnameinfo(struct sockaddr* fd, size_t sa_sz, char* name, size_t host_sz, struct sockaddr*, uint8_t, uint8_t) { + memcpy(name, ((SocketAddress*)fd)->get_ip_address(), strlen(((SocketAddress*)fd)->get_ip_address())); + return 0; +} + +int mbed_addrinfo(const char* hostname, const char* portstr, struct addrinfo* hints, struct addrinfo** info) { + auto ret = NetworkInterface::get_default_instance()->getaddrinfo(hostname, (SocketAddress*)&hints, (SocketAddress**)&info); + hints->ai_addr = (struct sockaddr*)hints; + (*info)->ai_addr = (struct sockaddr*)info; + return ret; +} + +int mbed_listen(UA_FD fd, int ignored) { + ((TCPSocket*)fd)->set_blocking(false); + return ((TCPSocket*)fd)->listen(1); +} + +UA_SOCKET socket(int /* family */, int /* type */, int proto) { - TCPSocket * tcp_socket = new TCPSocket(); - tcp_socket->sigio(mbed::callback(event, tcp_socket)); - tcp_socket->open(NetworkInterface::get_default_instance()); - return tcp_socket; + if (proto == IPPROTO_TCP) { + TCPSocket * _socket = new TCPSocket(); + _socket->sigio(mbed::callback(event, _socket)); + _socket->open(NetworkInterface::get_default_instance()); + return (UA_SOCKET)_socket; + } + if (proto == IPPROTO_UDP) { + UDPSocket * _socket = new UDPSocket(); + _socket->sigio(mbed::callback(event, _socket)); + _socket->open(NetworkInterface::get_default_instance()); + return (UA_SOCKET)_socket; + } } void freeaddrinfo(void * /* c */) diff --git a/src/arch/posix/mbed_tcp.h b/src/arch/posix/mbed_tcp.h index 9c7d818..a9c5f41 100644 --- a/src/arch/posix/mbed_tcp.h +++ b/src/arch/posix/mbed_tcp.h @@ -4,12 +4,67 @@ #include "mbed.h" -int mbed_send(UA_FD fd, const void * data, size_t size, int ignored); -int mbed_recv(UA_FD fd, void * data, nsapi_size_t size, int ignored); -int mbed_close(UA_FD fd); -int mbed_connect(UA_FD fd, SocketAddress* addr); -int mbed_setsockopt(UA_FD fd, int level, int optname, const void *optval, unsigned optlen); -int mbed_getsockopt(UA_FD fd, int level, int optname, void *optval, unsigned *optlen); - -TCPSocket * socket(int family, int type, int proto); -void freeaddrinfo(void * c); +#define socklen_t size_t + +struct sockaddr { + SocketAddress ai; +}; + +struct sockaddr_storage { + SocketAddress ai; +}; + +struct addrinfo { + SocketAddress ai; + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; /* canonical name */ + struct addrinfo *ai_next; /* this struct can form a linked list */ +}; + +extern "C" +{ + int mbed_send(UA_FD fd, const void * data, size_t size, int ignored); + int mbed_recv(UA_FD fd, void * data, nsapi_size_t size, int ignored); + int mbed_close(UA_FD fd); + int mbed_connect(UA_FD fd, struct sockaddr* addr); + int mbed_setsockopt(UA_FD fd, int level, int optname, const void *optval, unsigned optlen); + int mbed_getsockopt(UA_FD fd, int level, int optname, void *optval, unsigned *optlen); + UA_SOCKET mbed_accept(UA_FD fd, struct sockaddr* s, size_t* s_sz); + int mbed_bind(UA_FD fd, struct sockaddr* addr, size_t s_sz); + int mbed_getnameinfo(struct sockaddr* sa, size_t sa_sz, char* hoststr, size_t host_sz, struct sockaddr*, uint8_t, uint8_t); + int mbed_listen(UA_FD fd, int ignored); + int mbed_addrinfo(const char* hostname, const char* portstr, struct addrinfo* hints, struct addrinfo** info); + + UA_SOCKET socket(int family, int type, int proto); + void freeaddrinfo(void * c); + int gethostname(char *str, size_t len); + + inline char* gai_strerror(int err) { + char str[8]; + return itoa(err, str, 10); + } + inline void shutdown(UA_SOCKET s, uint8_t flag) { + delete (Socket*)s; + } +} + +#define IPPROTO_TCP 0 +#define IPPROTO_UDP 1 +#define TCP_NODELAY 0 +#define SOL_SOCKET NSAPI_SOCKET +#define SO_REUSEPORT 0 +#define SO_REUSEADDR NSAPI_REUSEADDR +#define SO_ERROR 0 +#define NI_NUMERICHOST 0 +#define NI_NUMERICHOST 0 +#define AF_INET6 6 +#define IPPROTO_IPV6 6 +#define IPV6_V6ONLY 6 +#define AF_UNSPEC 5 +#define SOCK_STREAM 8 +#define AI_PASSIVE 2 diff --git a/src/arch/posix/ua_architecture.h b/src/arch/posix/ua_architecture.h index bf0835e..7e7dc51 100644 --- a/src/arch/posix/ua_architecture.h +++ b/src/arch/posix/ua_architecture.h @@ -15,7 +15,7 @@ _UA_BEGIN_DECLS #define UA_IPV6 1 -#define UA_SOCKET uintptr_t +#define UA_SOCKET uintptr_t //(Socket*) #define UA_INVALID_SOCKET -1 #define UA_ERRNO errno #define UA_INTERRUPTED EINTR @@ -24,10 +24,8 @@ _UA_BEGIN_DECLS #define UA_WOULDBLOCK EWOULDBLOCK #define UA_POLLIN POLLIN #define UA_POLLOUT POLLOUT -#define UA_SHUT_RDWR SHUT_RDWR +#define UA_SHUT_RDWR 0 -#define UA_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \ - getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) #define UA_poll poll #define UA_send mbed_send #define UA_recv mbed_recv @@ -35,6 +33,11 @@ _UA_BEGIN_DECLS #define UA_connect mbed_connect #define UA_getsockopt mbed_getsockopt #define UA_setsockopt mbed_setsockopt +#define UA_accept mbed_accept +#define UA_listen mbed_listen +#define UA_getnameinfo mbed_getnameinfo +#define UA_getaddrinfo mbed_addrinfo +#define UA_bind mbed_bind #define UA_inet_pton inet_pton #if UA_IPV6 # define UA_if_nametoindex if_nametoindex