From 2f9f39764d81102b4b227308a622888152179c24 Mon Sep 17 00:00:00 2001 From: xiangxistu <52819708+xiangxistu@users.noreply.github.com> Date: Tue, 31 May 2022 11:50:17 +0800 Subject: [PATCH] [add] winsock implement on windows simulator. (#6010) * [add] winsock implement on windows simulator. --- bsp/simulator/Kconfig | 1 - bsp/simulator/drivers/SConscript | 43 +-- bsp/simulator/drivers/winsock/drv_win_eth.c | 115 +++++++ bsp/simulator/drivers/winsock/rtt_winsock.h | 117 +++++++ bsp/simulator/drivers/winsock/sal_winsock.c | 320 ++++++++++++++++++++ components/net/sal/Kconfig | 4 - components/net/sal/SConscript | 3 - components/net/sal/impl/af_inet_winsock.c | 12 - 8 files changed, 578 insertions(+), 37 deletions(-) create mode 100644 bsp/simulator/drivers/winsock/drv_win_eth.c create mode 100644 bsp/simulator/drivers/winsock/rtt_winsock.h create mode 100644 bsp/simulator/drivers/winsock/sal_winsock.c delete mode 100644 components/net/sal/impl/af_inet_winsock.c diff --git a/bsp/simulator/Kconfig b/bsp/simulator/Kconfig index f30daf163b..a125b2daac 100644 --- a/bsp/simulator/Kconfig +++ b/bsp/simulator/Kconfig @@ -46,7 +46,6 @@ menu "Peripheral Drivers" bool "Enable BSD Socket" select RT_USING_POSIX_FS select RT_USING_POSIX_SOCKET - select SAL_USING_WINSOCK default y config BSP_USING_LVGL diff --git a/bsp/simulator/drivers/SConscript b/bsp/simulator/drivers/SConscript index 34f7103810..9db472bec0 100644 --- a/bsp/simulator/drivers/SConscript +++ b/bsp/simulator/drivers/SConscript @@ -4,7 +4,7 @@ from building import * Import('rtconfig') cwd = GetCurrentDir() -src = Glob('*.c') +src = ['board.c', 'uart_console.c'] LIBS = [] LIBPATH = [] CPPPATH = [cwd] @@ -30,28 +30,37 @@ if rtconfig.CROSS_TOOL == 'msvc': ] # remove no need file. -if GetDepend('PKG_USING_GUIENGINE') == False: - SrcRemove(src, 'sdl_fb.c') +if GetDepend('PKG_USING_GUIENGINE') == True: + src += ['sdl_fb.c'] else: LIBS.append('SDL2') if sys.platform == 'win32': LIBPATH.append(os.path.abspath(os.path.join(cwd, '../SDL2/lib/x86'))) CPPPATH.append(os.path.abspath(os.path.join(cwd, '../SDL2/include'))) -if GetDepend('BSP_USING_RTC') == False: - SrcRemove(src, 'drv_rtc.c') -if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_DFS_ELMFAT') == False: - SrcRemove(src, 'sd_sim.c') -if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_MTD_NAND') == False: - SrcRemove(src, 'nanddrv_file.c') -if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_MTD_NOR') == False: - SrcRemove(src, 'sst25vfxx_mtd_sim.c') -if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_DFS_WINSHAREDIR') == False: - SrcRemove(src, 'dfs_win32.c') -if GetDepend('RT_USING_DFS') == False or GetDepend('RT_USING_MODULE') == False: - SrcRemove(src, ['module_win32.c']) -if sys.platform[0:5]=="linux": #check whether under linux - SrcRemove(src, ['module_win32.c', 'dfs_win32.c']) + +if GetDepend('RT_USING_DFS') == True: + if GetDepend('RT_USING_DFS_ELMFAT') == True: + src += ['sd_sim.c'] + + if GetDepend('RT_USING_MTD_NAND') == True: + src += ['nanddrv_file.c'] + + if GetDepend('RT_USING_MTD_NOR') == True: + src += ['sst25vfxx_mtd_sim.c'] + + if sys.platform == "win32": + if GetDepend('RT_USING_DFS_WINSHAREDIR') == True: + src += ['dfs_win32.c'] + if GetDepend('RT_USING_MODULE') == True: + src += ['module_win32.c'] + +if GetDepend('BSP_USING_RTC') == True: + src += ['drv_rtc.c'] + +if GetDepend('BSP_USING_SOCKET') == True: + src += [cwd + '/winsock/drv_win_eth.c'] + src += [cwd + '/winsock/sal_winsock.c'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, LIBS=LIBS, LIBPATH=LIBPATH, CPPDEFINES=CPPDEFINES) diff --git a/bsp/simulator/drivers/winsock/drv_win_eth.c b/bsp/simulator/drivers/winsock/drv_win_eth.c new file mode 100644 index 0000000000..d53f46f9d5 --- /dev/null +++ b/bsp/simulator/drivers/winsock/drv_win_eth.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-26 xiangxistu first version + */ + +#include +#include +#include +#include +#include +#include +#include "rtt_winsock.h" + +static win_netdev_ping(struct netdev* netif, const char* host, size_t data_len, + uint32_t timeout, struct netdev_ping_resp* ping_resp) +{ + return 0; +} + +const struct netdev_ops win_netdev_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, + RT_NULL, +#ifdef RT_USING_FINSH + win_netdev_ping, + RT_NULL, +#endif /* RT_USING_FINSH */ + RT_NULL, +}; + + static const struct sal_socket_ops windows_socket_ops = + { + win_socket, + win_closesocket, + win_bind, + win_listen, + win_connect, + win_accept, + win_sendto, + win_recvfrom, + win_getsockopt, + win_setsockopt, + win_shutdown, + win_getpeername, + win_getsockname, + win_ioctlsocket, + #ifdef SAL_USING_POSIX + inet_poll, + #else + RT_NULL, + #endif + }; + + static const struct sal_netdb_ops windows_netdb_ops = + { + win_gethostbyname, + RT_NULL, + win_getaddrinfo, + win_freeaddrinfo, + }; + + static const struct sal_proto_family windows_inet_family = + { + AF_INET, + AF_INET6, + &windows_socket_ops, + &windows_netdb_ops, + }; + + /* Set lwIP network interface device protocol family information */ + int sal_win_netdev_set_pf_info(struct netdev* netdev) + { + RT_ASSERT(netdev); + + netdev->sal_user_data = (void*)&windows_inet_family; + return 0; + } + +static int win_netdev_add(void) +{ +#define ETHERNET_MTU 1500 +#define HWADDR_LEN 6 + + rt_err_t result = RT_EOK; + struct netdev* netdev = RT_NULL; + + char name[RT_NAME_MAX] = {0}; + + netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev)); + if (netdev == RT_NULL) + { + return -RT_EEMPTY; + } + + sal_win_netdev_set_pf_info(netdev); + + rt_strncpy(name, "win_e0", RT_NAME_MAX); + result = netdev_register(netdev, name, RT_NULL); + + netdev->flags = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP; + netdev->mtu = ETHERNET_MTU; + netdev->ops = &win_netdev_ops; + netdev->hwaddr_len = HWADDR_LEN; + + return result; +} +INIT_ENV_EXPORT(win_netdev_add); diff --git a/bsp/simulator/drivers/winsock/rtt_winsock.h b/bsp/simulator/drivers/winsock/rtt_winsock.h new file mode 100644 index 0000000000..63c8fae600 --- /dev/null +++ b/bsp/simulator/drivers/winsock/rtt_winsock.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-30 xiangxistu first version + */ + +#define DNS_MAX_NAME_LENGTH 256 + +/* + * 1. Define the structure to avoid conflict with winsock's structure. + * 2. And the same time, in the "af_inet_winsock.c" shouldn't include header files aboult "sal", + * if include header files aboult "sal", the complier in the vs2012 will give me "structure redefined error". + * + * So, i define the same structure with "sal" but not include header files aboult "sal". + * The same sturcture means the same memory in the system. I can offer wonderful compatibility with "sal" ,"winsock", "lwip" and so on. + * + * + * Aross the way, "WinSock2.h" only be included in the "af_inet_winsock.c", the more software packages aboult network can + * work that useless modification is required for "winsock". + * + */ +typedef uint32_t sal_type_socklen_t; +typedef uint16_t in_port_t; +typedef uint8_t sa_family_t; +typedef uint32_t in_addr_t; + +typedef struct sal_type_ip4_addr +{ + uint32_t addr; +} sal_type_ip4_addr_t; +typedef sal_type_ip4_addr_t sal_type_ip_addr_t; + +struct sal_type_sockaddr +{ + uint8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sal_type_in_addr +{ + in_addr_t sal_type_s_addr; +}; + +struct sal_type_sockaddr_in +{ + uint8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct sal_type_in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; + +struct sal_type_sockaddr_storage +{ + uint8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + uint32_t s2_data2[3]; +#if NETDEV_IPV6 + uint32_t s2_data3[3]; +#endif /* NETDEV_IPV6 */ +}; + +struct sal_type_addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sal_type_sockaddr* ai_addr; /* Socket address of socket. */ + char* ai_canonname; /* Canonical name of service location. */ + struct sal_type_addrinfo* ai_next; /* Pointer to next in list. */ +}; + +struct sal_type_hostent { + char* h_name; /* Official name of the host. */ + char** h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char** h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + + +/* sal_socket_ops */ +int win_socket(int domain, int type, int protocol); +int win_closesocket(int s); +int win_bind(int s, const struct sal_type_sockaddr* name, sal_type_socklen_t namelen); +int win_listen(int s, int backlog); +int win_connect(int s, const struct sal_type_sockaddr* name, sal_type_socklen_t namelen); +int win_accept(int s, struct sal_type_sockaddr* addr, sal_type_socklen_t* addrlen); +int win_sendto(int s, const void* data, size_t size, int flags, const struct sal_type_sockaddr* to, sal_type_socklen_t tolen); +int win_recvfrom(int s, void* mem, size_t len, int flags, struct sal_type_sockaddr* from, sal_type_socklen_t* fromlen); +int win_getsockopt(int s, int level, int optname, void* optval, sal_type_socklen_t* optlen); +int win_setsockopt(int s, int level, int optname, const void* optval, sal_type_socklen_t optlen); +int win_shutdown(int s, int how); +int win_getpeername(int s, struct sal_type_sockaddr* name, sal_type_socklen_t* namelen); +int win_getsockname(int s, struct sal_type_sockaddr* name, sal_type_socklen_t* namelen); +int win_ioctlsocket(int s, long cmd, void* arg); + +#ifdef SAL_USING_POSIX +int inet_poll(struct dfs_fd* file, struct rt_pollreq* req); +#endif /* SAL_USING_POSIX */ + + +/* sal_netdb_ops */ +struct sal_type_hostent* win_gethostbyname(const char* name); +int win_getaddrinfo(const char* nodename, const char* servname, const struct sal_type_addrinfo* hints, struct sal_type_addrinfo** res); +void win_freeaddrinfo(struct sal_type_addrinfo* ai); diff --git a/bsp/simulator/drivers/winsock/sal_winsock.c b/bsp/simulator/drivers/winsock/sal_winsock.c new file mode 100644 index 0000000000..6a43670f5d --- /dev/null +++ b/bsp/simulator/drivers/winsock/sal_winsock.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-05-26 xiangxistu first version + */ + +/* Do NOT include sys/time.h in this file */ +#include +#include +#include +#include + +#define DBG_TAG "sal.winsock" +#define DBG_LVL DBG_INFO +#include + +#include "rtt_winsock.h" + +static struct sal_type_hostent sal_hostent; +static sal_type_ip_addr_t hostent_addr = { 0 }; +static sal_type_ip_addr_t* hostent_addr_p = RT_NULL; + +/* Important, must reserve */ +#pragma comment( lib, "ws2_32.lib" ) + +/* + * reserve for select / poll + * + * #define WINDOWS_STACK_SIZE 2048 + * #define WINDOWS_PRIORITY 2048 + * #define WINDOWS_TICK 10 + * + * struct poll_thread_list + * { + * int socket; + * rt_slist_t slist; + * }; + * static rt_slist_t poll_pending_list = RT_SLIST_OBJECT_INIT(poll_pending_list); + * + **/ + +#define WINDOWS_PERVIOS_COMAMND \ + do \ + { \ + int iResult; \ + WSADATA wsa_data; \ + \ + iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data); \ + if (iResult != 0) \ + { \ + LOG_E("WSAStartup failed: %d\n", iResult); \ + return -RT_ERROR; \ + } \ + }while(0) + +static void data_sync_sockaddr(struct sal_type_sockaddr* sal, struct sockaddr** window) +{ + /* + * ws2def.h + * typedef struct sockaddr { + * + * #if (_WIN32_WINNT < 0x0600) + * u_short sa_family; + * #else + * ADDRESS_FAMILY sa_family; // Address family. + * #endif //(_WIN32_WINNT < 0x0600) + * + * CHAR sa_data[14]; // Up to 14 bytes of direct address. + * } SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR; + * + *********************************** + * sal_socket.h + * struct sockaddr + * { + * uint8_t sa_len; + * sa_family_t sa_family; + * char sa_data[14]; + * }; + */ + ADDRESS_FAMILY family = 0; + family = sal->sa_family; + + *window = sal; + (* window)->sa_family = family; +} + +int win_socket(int domain, int type, int protocol) +{ + WINDOWS_PERVIOS_COMAMND; + + return (int)socket(domain, type, protocol); +} + +int win_closesocket(int s) +{ + return (int)closesocket(s); +} + +int win_bind(int s, const struct sal_type_sockaddr *name, sal_type_socklen_t namelen) +{ + return (int)bind(s, name, namelen); +} + +int win_listen(int s, int backlog) +{ + return (int)listen(s, backlog); +} + +int win_connect(int s, const struct sal_type_sockaddr *name, sal_type_socklen_t namelen) +{ + struct sockaddr *windows_addr = RT_NULL; + data_sync_sockaddr(name, &windows_addr); + + return (int)connect(s, windows_addr, namelen); +} + +int win_accept(int s, struct sal_type_sockaddr *addr, sal_type_socklen_t *addrlen) +{ + WINDOWS_PERVIOS_COMAMND; + + return (int)accept(s, addr, addrlen); +} + +int win_sendto(int s, const void *data, size_t size, int flags, const struct sal_type_sockaddr *to, sal_type_socklen_t tolen) +{ + return (int)sendto(s, data, size, flags, to, tolen); +} + +int win_recvfrom(int s, void *mem, size_t len, int flags, struct sal_type_sockaddr *from, sal_type_socklen_t *fromlen) +{ + return (int)recvfrom(s, mem, len, flags, from, fromlen); +} + +int win_getsockopt(int s, int level, int optname, void *optval, sal_type_socklen_t *optlen) +{ + return (int)getsockopt(s, level, optname, optval, optlen); +} + +int win_setsockopt(int s, int level, int optname, const void *optval, sal_type_socklen_t optlen) +{ + return (int)setsockopt(s, level, optname, optval, optlen); +} + +int win_shutdown(int s, int how) +{ + return (int)shutdown(s, how); +} + +int win_getpeername(int s, struct sal_type_sockaddr *name, sal_type_socklen_t *namelen) +{ + return (int)getpeername(s, name, namelen); +} + +int win_getsockname(int s, struct sal_type_sockaddr *name, sal_type_socklen_t *namelen) +{ + return (int)getsockname(s, name, namelen); +} + +int win_ioctlsocket(int s, long cmd, void *arg) +{ + return (int)ioctlsocket(s, cmd, arg); +} + +#ifdef SAL_USING_POSIX +/* use windows poll, but not wait */ +int inet_poll(struct dfs_fd* file, struct rt_pollreq* req) +{ + /*WSAPOLLFD winpoll; + struct sal_socket* sal_sock; + int mask = 0; + int poll_event = 0; + + sal_sock = sal_get_socket((int)file->data); + if (!sal_sock) + { + return -1; + } + + winpoll.fd = sal_sock->socket; + poll_event &= POLLERR | POLLHUP; + winpoll.events = req->_key & (~poll_event); + poll_event = 0; + + mask = WSAPoll(&winpoll, 1, 0); + if (mask == 0) + return 0; + + return winpoll.revents;*/ +} +#endif /* SAL_USING_POSIX */ + +struct sal_type_hostent* win_gethostbyname(const char* name) +{ + struct hostent *windows_hostent; + char** h_addr_list; + + WINDOWS_PERVIOS_COMAMND; + + windows_hostent = gethostbyname(name); + + sal_hostent.h_name = windows_hostent->h_name; + sal_hostent.h_aliases = windows_hostent->h_aliases; + sal_hostent.h_addrtype = windows_hostent->h_addrtype; + sal_hostent.h_length = windows_hostent->h_length; + sal_hostent.h_addr_list = windows_hostent->h_addr_list; + hostent_addr.addr = ((struct in_addr*)windows_hostent->h_addr)->s_addr; + hostent_addr_p = &hostent_addr; + sal_hostent.h_addr_list = &hostent_addr_p; + + return &sal_hostent; +} + +int win_getaddrinfo(const char* nodename, const char* servname, const struct sal_type_addrinfo* hints, struct sal_type_addrinfo** res) +{ + int port_nr = 0; + sal_type_ip_addr_t addr = { 0 }; + struct sal_type_addrinfo* ai; + struct sal_type_sockaddr_storage* sa; + size_t total_size = 0; + size_t namelen = 0; + char* change_point; + + if (res == RT_NULL) + return EAI_FAIL; + *res = RT_NULL; + + if ((nodename == RT_NULL) && (servname == RT_NULL)) + return EAI_NONAME; + + if ((hints != RT_NULL) + && (hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)) + return EAI_FAMILY; + + if (servname != RT_NULL) + { + /* service name specified: convert to port number */ + port_nr = atoi(servname); + if ((port_nr <= 0) || (port_nr > 0xffff)) + { + return EAI_SERVICE; + } + } + + if (nodename != RT_NULL) + { + WINDOWS_PERVIOS_COMAMND; + struct hostent* hostent = gethostbyname(nodename); + if (hostent == RT_NULL) + return EAI_FAIL; + addr.addr = ((struct in_addr*)hostent->h_addr)->s_addr; + } + + total_size = sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage); + if (nodename != RT_NULL) + { + namelen = strlen(nodename); + if (namelen > DNS_MAX_NAME_LENGTH) + { + /* invalid name length */ + return EAI_FAIL; + } + RT_ASSERT(total_size + namelen + 1 > total_size); + total_size += namelen + 1; + } + + RT_ASSERT(total_size <= sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1); + ai = (struct sal_type_addrinfo*)rt_malloc(total_size); + if (ai == RT_NULL) + { + return EAI_MEMORY; + } + rt_memset(ai, 0, total_size); + + /* cast through void* to get rid of alignment warnings */ + sa = (struct sal_type_sockaddr_storage*)(void*)((uint8_t*)ai + sizeof(struct sal_type_addrinfo)); + struct sal_type_sockaddr_in* sa4 = (struct sal_type_sockaddr_in*)sa; + + sa4->sin_family = AF_INET; + sa4->sin_addr.sal_type_s_addr = addr.addr; + sa4->sin_port = htons((uint16_t)port_nr); + + /* set up addrinfo */ + if (hints != RT_NULL) + { + /* copy socktype & protocol from hints if specified */ + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + } + if (nodename != RT_NULL) + { + /* copy nodename to canonname if specified */ + ai->ai_canonname = ((char*)ai + sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage)); + rt_memcpy(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } + + ai->ai_addrlen = sizeof(struct sal_type_sockaddr_storage); + ai->ai_addr = (struct sal_type_sockaddr*)sa; + ai->ai_family = sa4->sin_family; + + *res = ai; + + return 0; +} + +void win_freeaddrinfo(struct sal_type_addrinfo* ai) +{ + struct sal_type_addrinfo* next; + + while (ai != NULL) + { + next = ai->ai_next; + rt_free(ai); + ai = next; + } +} diff --git a/components/net/sal/Kconfig b/components/net/sal/Kconfig index 6e7e44f98f..e5395a6631 100644 --- a/components/net/sal/Kconfig +++ b/components/net/sal/Kconfig @@ -21,10 +21,6 @@ if RT_USING_SAL bool "Docking with AT commands stack" default n - config SAL_USING_WINSOCK - bool "Docking with Windows socket (winsock)" - default n - config SAL_USING_TLS bool "Docking with MbedTLS protocol" default n diff --git a/components/net/sal/SConscript b/components/net/sal/SConscript index 9611af1d2b..437b6ce2e0 100644 --- a/components/net/sal/SConscript +++ b/components/net/sal/SConscript @@ -19,9 +19,6 @@ if GetDepend('SAL_USING_LWIP'): if GetDepend('SAL_USING_AT'): src += ['impl/af_inet_at.c'] -if GetDepend('SAL_USING_WINSOCK'): - src += ['impl/af_inet_winsock.c'] - if GetDepend('SAL_USING_TLS'): src += ['impl/proto_mbedtls.c'] diff --git a/components/net/sal/impl/af_inet_winsock.c b/components/net/sal/impl/af_inet_winsock.c deleted file mode 100644 index f3f103d0ca..0000000000 --- a/components/net/sal/impl/af_inet_winsock.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#include - -/* Do NOT include sys/time.h in this file */