initial commit

This commit is contained in:
2026-02-12 00:45:31 -08:00
commit 5f168f370b
3024 changed files with 804889 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# FastLED Platform: win
Windowsspecific networking helpers.
## Files (quick pass)
- `socket_win.h`: Normalizes POSIXstyle socket API on Windows (Winsock2). Provides typedefs, constants, and wrappers (`socket/bind/connect/...`) plus init/teardown helpers.
- `socket_win.cpp`: Implementation.
## Behavior and constraints
- Requires Winsock initialization (e.g., `WSAStartup` via helper) and cleanup; wraps errors to POSIXlike errno values (e.g., `EWOULDBLOCK`).
- Mirrors POSIX calls for crossplatform code while respecting Windows differences (e.g., `closesocket` vs `close`).
## Winsock initialization sequence
Before using any socket functions on Windows:
1. Call `fl::win::socket_init()` (wrapper around `WSAStartup`).
2. Use the POSIXstyle wrappers (`socket/bind/connect/send/recv`, etc.).
3. On shutdown, call `fl::win::socket_cleanup()` (wrapper around `WSACleanup`).
Limitations vs POSIX:
- File descriptors are not interchangeable with CRT file handles; always use `closesocket()` (wrapped) rather than `close()`.
- Nonblocking and error codes map to POSIXlike values, but not all errno values are identical. Check for `EWOULDBLOCK`/`EINPROGRESS` via wrapper helpers.

View File

@@ -0,0 +1,318 @@
#if defined(FASTLED_HAS_NETWORKING) && 0
#ifdef _WIN32
#include "socket_win.h"
// Additional includes for platform functions
#include "fl/shared_ptr.h"
// Additional Windows header isolation for implementation
#ifndef NOMSG
#define NOMSG
#endif
#ifndef NOWINSTYLES
#define NOWINSTYLES
#endif
#ifndef NOSYSMETRICS
#define NOSYSMETRICS
#endif
#ifndef NOCLIPBOARD
#define NOCLIPBOARD
#endif
#ifndef NOCOLOR
#define NOCOLOR
#endif
#ifndef NOKERNEL
#define NOKERNEL
#endif
#ifndef NONLS
#define NONLS
#endif
#ifndef NOMEMMGR
#define NOMEMMGR
#endif
#ifndef NOMETAFILE
#define NOMETAFILE
#endif
#ifndef NOOPENFILE
#define NOOPENFILE
#endif
#ifndef NOSCROLL
#define NOSCROLL
#endif
#ifndef NOTEXTMETRIC
#define NOTEXTMETRIC
#endif
#ifndef NOWH
#define NOWH
#endif
#ifndef NOWINOFFSETS
#define NOWINOFFSETS
#endif
#ifndef NOKANJI
#define NOKANJI
#endif
#ifndef NOICONS
#define NOICONS
#endif
#ifndef NORASTEROPS
#define NORASTEROPS
#endif
#ifndef NOSHOWWINDOW
#define NOSHOWWINDOW
#endif
#ifndef OEMRESOURCE
#define OEMRESOURCE
#endif
#ifndef NOATOM
#define NOATOM
#endif
#ifndef NOCTLMGR
#define NOCTLMGR
#endif
#ifndef NODRAWTEXT
#define NODRAWTEXT
#endif
// Additional includes for implementation
#include <sys/types.h>
#include <cstdarg> // For va_list in fcntl emulation
namespace fl {
//=============================================================================
// Helper Functions for Windows Socket Normalization
//=============================================================================
bool initialize_winsock() {
static bool initialized = false;
if (!initialized) {
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
initialized = (result == 0);
}
return initialized;
}
void cleanup_winsock() {
WSACleanup();
}
int translate_windows_error(int wsa_error) {
switch (wsa_error) {
case WSAEWOULDBLOCK: return EWOULDBLOCK;
case WSAECONNREFUSED: return ECONNREFUSED;
case WSAETIMEDOUT: return ETIMEDOUT;
case WSAENETUNREACH: return ENETUNREACH;
case WSAEACCES: return EACCES;
case WSAEADDRINUSE: return EADDRINUSE;
case WSAEINVAL: return EINVAL;
case WSAENOTCONN: return ENOTCONN;
case WSAECONNRESET: return ECONNRESET;
case WSAECONNABORTED: return ECONNABORTED;
default: return wsa_error;
}
}
//=============================================================================
// Normalized POSIX-Style Socket API Functions
//=============================================================================
// Core Socket Operations
int socket(int domain, int type, int protocol) {
if (!initialize_winsock()) {
return -1;
}
SOCKET sock = ::socket(domain, type, protocol);
return (sock == INVALID_SOCKET) ? -1 : static_cast<int>(sock);
}
int socketpair(int domain, int type, int protocol, int sv[2]) {
// Windows doesn't support socketpair - return error
(void)domain; (void)type; (void)protocol; (void)sv;
WSASetLastError(WSAEAFNOSUPPORT);
return -1;
}
// Addressing
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::bind(sock, reinterpret_cast<const ::sockaddr*>(addr), addrlen);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::connect(sock, reinterpret_cast<const ::sockaddr*>(addr), addrlen);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int listen(int sockfd, int backlog) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::listen(sock, backlog);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
SOCKET server_sock = static_cast<SOCKET>(sockfd);
int addr_len = addrlen ? static_cast<int>(*addrlen) : 0;
SOCKET client_sock = ::accept(server_sock, reinterpret_cast<::sockaddr*>(addr), &addr_len);
if (addrlen) *addrlen = static_cast<socklen_t>(addr_len);
return (client_sock == INVALID_SOCKET) ? -1 : static_cast<int>(client_sock);
}
// Data Transfer
ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::send(sock, static_cast<const char*>(buf), static_cast<int>(len), flags);
return (result == SOCKET_ERROR) ? -1 : static_cast<ssize_t>(result);
}
ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::recv(sock, static_cast<char*>(buf), static_cast<int>(len), flags);
return (result == SOCKET_ERROR) ? -1 : static_cast<ssize_t>(result);
}
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::sendto(sock, static_cast<const char*>(buf), static_cast<int>(len), flags,
reinterpret_cast<const ::sockaddr*>(dest_addr), addrlen);
return (result == SOCKET_ERROR) ? -1 : static_cast<ssize_t>(result);
}
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int addr_len = addrlen ? static_cast<int>(*addrlen) : 0;
int result = ::recvfrom(sock, static_cast<char*>(buf), static_cast<int>(len), flags,
reinterpret_cast<::sockaddr*>(src_addr), &addr_len);
if (addrlen) *addrlen = static_cast<socklen_t>(addr_len);
return (result == SOCKET_ERROR) ? -1 : static_cast<ssize_t>(result);
}
// Connection Teardown
int shutdown(int sockfd, int how) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int result = ::shutdown(sock, how);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int close(int fd) {
SOCKET sock = static_cast<SOCKET>(fd);
int result = ::closesocket(sock);
return (result == SOCKET_ERROR) ? -1 : 0;
}
// Socket Options
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
// Handle SO_REUSEPORT specially - not supported on Windows
if (level == SOL_SOCKET && optname == SO_REUSEPORT) {
WSASetLastError(WSAENOPROTOOPT);
return -1;
}
int result = ::setsockopt(sock, level, optname, static_cast<const char*>(optval), optlen);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int len = optlen ? static_cast<int>(*optlen) : 0;
int result = ::getsockopt(sock, level, optname, static_cast<char*>(optval), &len);
if (optlen) *optlen = static_cast<socklen_t>(len);
return (result == SOCKET_ERROR) ? -1 : 0;
}
// Address Information
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int len = addrlen ? static_cast<int>(*addrlen) : 0;
int result = ::getpeername(sock, reinterpret_cast<::sockaddr*>(addr), &len);
if (addrlen) *addrlen = static_cast<socklen_t>(len);
return (result == SOCKET_ERROR) ? -1 : 0;
}
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
SOCKET sock = static_cast<SOCKET>(sockfd);
int len = addrlen ? static_cast<int>(*addrlen) : 0;
int result = ::getsockname(sock, reinterpret_cast<::sockaddr*>(addr), &len);
if (addrlen) *addrlen = static_cast<socklen_t>(len);
return (result == SOCKET_ERROR) ? -1 : 0;
}
// Address Resolution (simplified - Windows has these functions)
int inet_pton(int af, const char *src, void *dst) {
return ::inet_pton(af, src, dst);
}
const char* inet_ntop(int af, const void *src, char *dst, socklen_t size) {
return ::inet_ntop(af, src, dst, static_cast<size_t>(size));
}
// fcntl emulation for non-blocking sockets
int fcntl(int fd, int cmd, ...) {
SOCKET sock = static_cast<SOCKET>(fd);
if (cmd == F_GETFL) {
// Windows doesn't provide a way to query non-blocking status
// Return 0 (blocking) as default
return 0;
} else if (cmd == F_SETFL) {
va_list args;
va_start(args, cmd);
int flags = va_arg(args, int);
va_end(args);
u_long mode = (flags & O_NONBLOCK) ? 1 : 0;
int result = ioctlsocket(sock, FIONBIO, &mode);
return (result == SOCKET_ERROR) ? -1 : 0;
}
WSASetLastError(WSAEINVAL);
return -1;
}
// Error handling
int get_errno() {
return translate_windows_error(WSAGetLastError());
}
//=============================================================================
// Platform-specific functions (required by socket_factory.cpp)
//=============================================================================
fl::shared_ptr<Socket> create_platform_socket(const SocketOptions& options) {
// Windows doesn't have a specific Socket implementation class yet
// Return nullptr for now - this will need a Windows Socket class implementation
(void)options;
return nullptr;
}
bool platform_supports_ipv6() {
// Windows supports IPv6
return true;
}
bool platform_supports_tls() {
// TLS would need to be implemented at a higher level for Windows
return false;
}
bool platform_supports_non_blocking_connect() {
// Windows supports non-blocking operations
return true;
}
bool platform_supports_socket_reuse() {
// Windows supports SO_REUSEADDR
return true;
}
} // namespace fl
#endif // _WIN32
#endif // FASTLED_HAS_NETWORKING

View File

@@ -0,0 +1,209 @@
#pragma once
#ifdef FASTLED_HAS_NETWORKING && 0
#ifdef _WIN32
#include "fl/string.h"
#include "fl/stdint.h"
// Essential Windows header isolation
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef NOGDI
#define NOGDI
#endif
#ifndef NOUSER
#define NOUSER
#endif
// Minimal Windows includes for type definitions
#include <winsock2.h>
#include <ws2tcpip.h>
namespace fl {
//=============================================================================
// Normalized POSIX-Style Socket Types
//=============================================================================
// POSIX-style type definitions that normalize Windows socket types
// Use existing Windows types when available to avoid conflicts
using socklen_t = int;
using ssize_t = int;
// Windows already defines sockaddr, sockaddr_in, sockaddr_in6, in_addr, in6_addr
// We use the existing Windows types directly via using declarations
using ::sockaddr;
using ::sockaddr_in;
using ::sockaddr_in6;
using ::in_addr;
using ::in6_addr;
// Type aliases for consistency with POSIX
using sa_family_t = unsigned short; // Same as ADDRESS_FAMILY
using in_port_t = unsigned short; // Same as USHORT
//=============================================================================
// POSIX Socket Constants (Windows Normalization)
//=============================================================================
// Address families
#ifndef AF_INET
#define AF_INET 2
#endif
#ifndef AF_INET6
#define AF_INET6 23
#endif
// Socket types
#ifndef SOCK_STREAM
#define SOCK_STREAM 1
#endif
#ifndef SOCK_DGRAM
#define SOCK_DGRAM 2
#endif
// Protocols
#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6
#endif
#ifndef IPPROTO_UDP
#define IPPROTO_UDP 17
#endif
// Socket options
#ifndef SOL_SOCKET
#define SOL_SOCKET 0xffff
#endif
#ifndef SO_REUSEADDR
#define SO_REUSEADDR 0x0004
#endif
#ifndef SO_REUSEPORT
#define SO_REUSEPORT 0x0200 // Not supported on Windows - will return error
#endif
#ifndef TCP_NODELAY
#define TCP_NODELAY 1
#endif
// fcntl flags for non-blocking
#ifndef F_GETFL
#define F_GETFL 3
#endif
#ifndef F_SETFL
#define F_SETFL 4
#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK 0x4000
#endif
// Shutdown options
#ifndef SHUT_RD
#define SHUT_RD 0
#endif
#ifndef SHUT_WR
#define SHUT_WR 1
#endif
#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif
//=============================================================================
// Helper Functions for Windows Socket Normalization
//=============================================================================
bool initialize_winsock();
void cleanup_winsock();
int translate_windows_error(int wsa_error);
//=============================================================================
// Normalized POSIX-Style Socket API Functions
//=============================================================================
// Core Socket Operations
int socket(int domain, int type, int protocol);
int socketpair(int domain, int type, int protocol, int sv[2]);
// Addressing
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// Data Transfer
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
// Connection Teardown
int shutdown(int sockfd, int how);
int close(int fd);
// Socket Options
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
// Address Information
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// Address Resolution
int inet_pton(int af, const char *src, void *dst);
const char* inet_ntop(int af, const void *src, char *dst, socklen_t size);
// fcntl emulation for non-blocking sockets
int fcntl(int fd, int cmd, ...);
// Error handling
int get_errno();
// WASM CONSTRAINTS: The following functions are blocking calls and are
// DISALLOWED and NOT AVAILABLE on WASM due to proxying limitations:
// - select()
// - poll()
// These functions are not declared in this API and MUST NOT be used.
// Use per-call non-blocking flags like MSG_DONTWAIT instead.
// (Note: This constraint applies to WASM builds only - Windows builds are not affected)
// POSIX errno constants for Windows
#ifndef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED WSAECONNREFUSED
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT WSAETIMEDOUT
#endif
#ifndef ENETUNREACH
#define ENETUNREACH WSAENETUNREACH
#endif
#ifndef EACCES
#define EACCES WSAEACCES
#endif
#ifndef EADDRINUSE
#define EADDRINUSE WSAEADDRINUSE
#endif
#ifndef EINVAL
#define EINVAL WSAEINVAL
#endif
#ifndef ENOTCONN
#define ENOTCONN WSAENOTCONN
#endif
#ifndef ECONNRESET
#define ECONNRESET WSAECONNRESET
#endif
#ifndef ECONNABORTED
#define ECONNABORTED WSAECONNABORTED
#endif
} // namespace fl
#endif // _WIN32
#endif // FASTLED_HAS_NETWORKING