From b64a234f8a4cd1d8a3b4ab81c26050529b513f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 12 Oct 2022 19:35:23 +0800 Subject: [PATCH] Networking: support Windows --- CMakeLists.txt | 1 + src/common/networking.c | 66 ++++++++++++++++++++++++++++++----------- src/common/networking.h | 14 +++++++-- src/modules/publicip.c | 4 +-- src/modules/weather.c | 4 +-- 5 files changed, 65 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41aaabaaf..ea760f60c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -516,6 +516,7 @@ elseif(MSYS) PRIVATE "opengl32" PRIVATE "gdi32" PRIVATE "iphlpapi" + PRIVATE "ws2_32" ) endif() diff --git a/src/common/networking.c b/src/common/networking.c index 4558f7f8e..d3685a543 100644 --- a/src/common/networking.c +++ b/src/common/networking.c @@ -1,13 +1,43 @@ +#if defined(_WIN32) || defined(__MSYS__) + #include + #include + #include + + static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context) + { + (void)once; + (void)param; + static WSADATA wsaData; + *context = &wsaData; + return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0; + } + + //Types of winsock2 are full of mess. Disable warnings for them and keep clean for posix + #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wsign-conversion" +#else + #include + #include + #include + #include + + #define closesocket close +#endif + +//Must be included after #include "fastfetch.h" #include "common/networking.h" -#include -#include -#include -#include - -int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout) +FFSockType ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout) { + #if defined(_WIN32) || defined(__MSYS__) + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + WSADATA* pData; + if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData)) + return INVALID_SOCKET; + #endif + struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, @@ -16,13 +46,13 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* struct addrinfo* addr; if(getaddrinfo(host, "80", &hints, &addr) != 0) - return -1; + return INVALID_SOCKET; - int sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if(sockfd == -1) + FFSockType sockfd = (FFSockType)socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if(sockfd == INVALID_SOCKET) { freeaddrinfo(addr); - return -1; + return INVALID_SOCKET; } if(timeout > 0) @@ -35,9 +65,9 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* if(connect(sockfd, addr->ai_addr, addr->ai_addrlen) == -1) { - close(sockfd); + closesocket(sockfd); freeaddrinfo(addr); - return -1; + return INVALID_SOCKET; } freeaddrinfo(addr); @@ -55,14 +85,14 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* if(send(sockfd, command.chars, command.length, 0) == -1) { ffStrbufDestroy(&command); - close(sockfd); - return -1; + closesocket(sockfd); + return INVALID_SOCKET; } ffStrbufDestroy(&command); return sockfd; } -bool ffNetworkingRecvHttpResponse(int sockfd, FFstrbuf* buffer) +bool ffNetworkingRecvHttpResponse(FFSockType sockfd, FFstrbuf* buffer) { ssize_t received = recv(sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0); @@ -72,14 +102,14 @@ bool ffNetworkingRecvHttpResponse(int sockfd, FFstrbuf* buffer) buffer->chars[buffer->length] = '\0'; } - close(sockfd); + closesocket(sockfd); return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n"); } bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer) { - int sockfd = ffNetworkingSendHttpRequest(host, path, headers, timeout); - if(sockfd > 0) + FFSockType sockfd = ffNetworkingSendHttpRequest(host, path, headers, timeout); + if(sockfd != INVALID_SOCKET) return ffNetworkingRecvHttpResponse(sockfd, buffer); return false; } diff --git a/src/common/networking.h b/src/common/networking.h index 145493ce7..f64288066 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -5,8 +5,18 @@ #include "util/FFstrbuf.h" -int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout); -bool ffNetworkingRecvHttpResponse(int sock, FFstrbuf* buffer); +#if defined(_WIN32) || defined(__MSYS__) + typedef uintptr_t FFSockType; //SOCKET, unsigned + #ifndef INVALID_SOCKET //Don't conflict with + #define INVALID_SOCKET ((uintptr_t)~0) + #endif +#else + typedef int FFSockType; // signed + #define INVALID_SOCKET (-1) +#endif + +FFSockType ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout); +bool ffNetworkingRecvHttpResponse(FFSockType sockfd, FFstrbuf* buffer); bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer); #endif diff --git a/src/modules/publicip.c b/src/modules/publicip.c index fe77e30f6..019f13dfb 100644 --- a/src/modules/publicip.c +++ b/src/modules/publicip.c @@ -5,7 +5,7 @@ #define FF_PUBLICIP_MODULE_NAME "Public IP" #define FF_PUBLICIP_NUM_FORMAT_ARGS 1 -static int sockfd; +static FFSockType sockfd; void ffPreparePublicIp(FFinstance* instance) { @@ -39,7 +39,7 @@ void ffPrintPublicIp(FFinstance* instance) if(sockfd == 0) ffPreparePublicIp(instance); - if(sockfd < 0) + if(sockfd == INVALID_SOCKET) { ffPrintError(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIP, "Failed to connect to an IP detection server"); return; diff --git a/src/modules/weather.c b/src/modules/weather.c index 43c1d56fd..11dc9748e 100644 --- a/src/modules/weather.c +++ b/src/modules/weather.c @@ -5,7 +5,7 @@ #define FF_WEATHER_MODULE_NAME "Weather" #define FF_WEATHER_NUM_FORMAT_ARGS 1 -static int sockfd; +static FFSockType sockfd; void ffPrepareWeather(FFinstance* instance) { @@ -21,7 +21,7 @@ void ffPrintWeather(FFinstance* instance) if(sockfd == 0) ffPrepareWeather(instance); - if(sockfd < 0) + if(sockfd == INVALID_SOCKET) { ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather, "Failed to connect to 'wttr.in'"); return;