From c34b81ad6c6a55cf8afcb0f5e20172c0a036b808 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 6 Jan 2017 22:24:16 -1000 Subject: [PATCH] Win32 compatibility fixes --- CMakeLists.txt | 6 ++++ include/jbus/Endpoint.hpp | 3 +- include/jbus/Listener.hpp | 1 + include/jbus/Socket.hpp | 74 ++++++++++++++++++++++++++++++++------- lib/Common.cpp | 18 ++++++++++ lib/Endpoint.cpp | 8 +++-- lib/Listener.cpp | 8 ++--- tools/joyboot.cpp | 5 ++- 8 files changed, 101 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9a304..eab0798 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.0) project(jbus) +if(WIN32) +set(JBUS_PLAT_LIBS Ws2_32) +endif() + include_directories(include) add_library(jbus include/jbus/optional.hpp @@ -8,5 +12,7 @@ add_library(jbus lib/Common.cpp include/jbus/Common.hpp lib/Endpoint.cpp include/jbus/Endpoint.hpp lib/Listener.cpp include/jbus/Listener.hpp) +target_link_libraries(jbus ${JBUS_PLAT_LIBS}) + add_executable(joyboot tools/joyboot.cpp) target_link_libraries(joyboot jbus) diff --git a/include/jbus/Endpoint.hpp b/include/jbus/Endpoint.hpp index fb9bf55..dc426a6 100644 --- a/include/jbus/Endpoint.hpp +++ b/include/jbus/Endpoint.hpp @@ -5,6 +5,7 @@ #include "Socket.hpp" #include "optional.hpp" #include +#include namespace jbus { @@ -165,7 +166,7 @@ class Endpoint static u64 getTransferTime(u8 cmd); void clockSync(); void send(const u8* buffer); - size_t seceive(u8* buffer); + size_t receive(u8* buffer); size_t runBuffer(u8* buffer, u64& remTicks, EWaitResp resp); bool idleGetStatus(u64& remTicks); void transferProc(); diff --git a/include/jbus/Listener.hpp b/include/jbus/Listener.hpp index f4f966e..cc7c672 100644 --- a/include/jbus/Listener.hpp +++ b/include/jbus/Listener.hpp @@ -5,6 +5,7 @@ #include "Socket.hpp" #include #include +#include namespace jbus { diff --git a/include/jbus/Socket.hpp b/include/jbus/Socket.hpp index 7c12557..55e3a2a 100644 --- a/include/jbus/Socket.hpp +++ b/include/jbus/Socket.hpp @@ -1,15 +1,21 @@ #ifndef JBUS_SOCKET_HPP #define JBUS_SOCKET_HPP -#include +#ifndef _WIN32 #include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#else +#include +#include +#endif + +#include +#include #include #include "Common.hpp" @@ -52,10 +58,10 @@ class IPAddress else { /* Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") */ - uint32_t ip = inet_addr(address.c_str()); - if (ip != INADDR_NONE) + struct in_addr addr; + if (inet_pton(AF_INET, address.c_str(), &addr) == 1) { - m_address = ip; + m_address = addr.s_addr; m_valid = true; } else @@ -69,9 +75,9 @@ class IPAddress { if (result) { - ip = reinterpret_cast(result->ai_addr)->sin_addr.s_addr; + addr = reinterpret_cast(result->ai_addr)->sin_addr; freeaddrinfo(result); - m_address = ip; + m_address = addr.s_addr; m_valid = true; } } @@ -96,7 +102,12 @@ public: /** Server-oriented TCP socket class derived from SFML */ class Socket { - int m_socket = -1; +#ifndef _WIN32 + using SocketTp = int; +#else + using SocketTp = SOCKET; +#endif + SocketTp m_socket = -1; bool m_isBlocking; static sockaddr_in createAddress(uint32_t address, unsigned short port) @@ -119,7 +130,7 @@ class Socket if (isOpen()) return false; - m_socket = socket(PF_INET, SOCK_STREAM, 0); + m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_socket == -1) { fprintf(stderr, "Can't allocate socket\n"); @@ -152,6 +163,20 @@ public: Busy }; +#ifdef _WIN32 + static EResult LastWSAError() + { + switch (WSAGetLastError()) + { + case WSAEWOULDBLOCK: + case WSAEALREADY: + return EResult::Busy; + default: + return EResult::Error; + } + } +#endif + Socket(bool blocking) : m_isBlocking(blocking) {} ~Socket() { close(); } @@ -175,11 +200,16 @@ public: void setBlocking(bool blocking) { m_isBlocking = blocking; +#ifndef _WIN32 int status = fcntl(m_socket, F_GETFL); if (m_isBlocking) fcntl(m_socket, F_SETFL, status & ~O_NONBLOCK); else fcntl(m_socket, F_SETFL, status | O_NONBLOCK); +#else + u_long b = blocking ? 0 : 1; + ioctlsocket(m_socket, FIONBIO, &b); +#endif } bool isOpen() const { return m_socket != -1; } @@ -218,9 +248,15 @@ public: /* Check for errors */ if (remoteSocket == -1) { +#ifndef _WIN32 EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error; if (res == EResult::Error) fprintf(stderr, "Failed to accept incoming connection: %s\n", strerror(errno)); +#else + EResult res = LastWSAError(); + if (res == EResult::Error) + fprintf(stderr, "Failed to accept incoming connection\n"); +#endif return res; } @@ -252,7 +288,11 @@ public: { if (!isOpen()) return; +#ifndef _WIN32 ::close(m_socket); +#else + closesocket(m_socket); +#endif m_socket = -1; } @@ -266,7 +306,7 @@ public: return EResult::Error; /* Loop until every byte has been sent */ - ssize_t result = 0; + int result = 0; for (size_t sent = 0; sent < len; sent += result) { /* Send a chunk of data */ @@ -274,7 +314,11 @@ public: /* Check for errors */ if (result < 0) +#ifndef _WIN32 return (errno == EAGAIN) ? EResult::Busy : EResult::Error; +#else + return LastWSAError(); +#endif } transferred = len; @@ -303,7 +347,11 @@ public: int result = ::recv(m_socket, static_cast(buf), static_cast(len), _flags); if (result < 0) +#ifndef _WIN32 return (errno == EAGAIN) ? EResult::Busy : EResult::Error; +#else + return LastWSAError(); +#endif else if (result == 0) return EResult::Error; diff --git a/lib/Common.cpp b/lib/Common.cpp index 9faefec..31194d5 100644 --- a/lib/Common.cpp +++ b/lib/Common.cpp @@ -8,6 +8,7 @@ #define WIN32_LEAN_AND_MEAN #endif #include +#include #endif #include "jbus/Common.hpp" @@ -18,6 +19,8 @@ namespace jbus #if __APPLE__ static u64 MachToDolphinNum; static u64 MachToDolphinDenom; +#elif _WIN32 +static LARGE_INTEGER PerfFrequency; #endif u64 GetGCTicks() @@ -29,6 +32,12 @@ u64 GetGCTicks() clock_gettime(CLOCK_MONOTONIC, &tp); return u64((tp.tv_sec * 1000000000ull) + tp.tv_nsec) * GetGCTicksPerSec() / 1000000000ull; +#elif _WIN32 + LARGE_INTEGER perf; + QueryPerformanceCounter(&perf); + perf.QuadPart *= GetGCTicksPerSec(); + perf.QuadPart /= PerfFrequency.QuadPart; + return perf.QuadPart; #else return 0; #endif @@ -36,10 +45,15 @@ u64 GetGCTicks() void WaitGCTicks(u64 ticks) { +#ifndef _WIN32 struct timeval tv = {}; tv.tv_sec = ticks / GetGCTicksPerSec(); tv.tv_usec = (ticks % GetGCTicksPerSec()) * 1000000 / GetGCTicksPerSec(); select(0, NULL, NULL, NULL, &tv); +#else + Sleep(ticks * 1000 / GetGCTicksPerSec() + + (ticks % GetGCTicksPerSec()) * 1000 / GetGCTicksPerSec()); +#endif } void Initialize() @@ -49,6 +63,10 @@ void Initialize() mach_timebase_info(&timebase); MachToDolphinNum = GetGCTicksPerSec() * timebase.numer; MachToDolphinDenom = 1000000000ull * timebase.denom; +#elif _WIN32 + WSADATA initData; + WSAStartup(MAKEWORD(2, 2), &initData); + QueryPerformanceFrequency(&PerfFrequency); #endif } diff --git a/lib/Endpoint.cpp b/lib/Endpoint.cpp index 63b4694..54f2db1 100644 --- a/lib/Endpoint.cpp +++ b/lib/Endpoint.cpp @@ -1,6 +1,6 @@ #include "jbus/Endpoint.hpp" -#define LOG_TRANSFER 0 +#define LOG_TRANSFER 1 namespace jbus { @@ -418,6 +418,7 @@ void Endpoint::clockSync() TickDelta = u32(u64(TickDelta) * 16777216 / GetGCTicksPerSec()); m_lastGCTick = GetGCTicks(); TickDelta = SBig(TickDelta); + m_clockSocket.setBlocking(false); if (m_clockSocket.send(&TickDelta, 4) == net::Socket::EResult::Error) m_running = false; } @@ -428,6 +429,7 @@ void Endpoint::send(const u8* buffer) net::Socket::EResult result; size_t sentBytes; + m_dataSocket.setBlocking(false); if (m_lastCmd == CMD_WRITE) result = m_dataSocket.send(buffer, 5, sentBytes); else @@ -451,7 +453,7 @@ void Endpoint::send(const u8* buffer) m_timeCmdSent = GetGCTicks(); } -size_t Endpoint::seceive(u8* buffer) +size_t Endpoint::receive(u8* buffer) { if (!m_dataSocket) { @@ -523,7 +525,7 @@ size_t Endpoint::runBuffer(u8* buffer, u64& remTicks, EWaitResp resp) if (m_waitingResp != EWaitResp::NoWait && m_dataReceivedBytes == 0) { - m_dataReceivedBytes = seceive(buffer); + m_dataReceivedBytes = receive(buffer); } u64 ticksSinceSend = GetGCTicks() - m_timeSent; diff --git a/lib/Listener.cpp b/lib/Listener.cpp index 0e20a61..adbf7f1 100644 --- a/lib/Listener.cpp +++ b/lib/Listener.cpp @@ -1,7 +1,7 @@ #include "jbus/Listener.hpp" #include "jbus/Endpoint.hpp" -#define LOG_LISTENER 0 +#define LOG_LISTENER 1 namespace jbus { @@ -25,7 +25,7 @@ void Listener::listenerProc() #if LOG_LISTENER printf("data open failed %s; will retry\n", strerror(errno)); #endif - sleep(1); + WaitGCTicks(GetGCTicksPerSec()); } else { @@ -42,7 +42,7 @@ void Listener::listenerProc() #if LOG_LISTENER printf("clock open failed %s; will retry\n", strerror(errno)); #endif - sleep(1); + WaitGCTicks(GetGCTicksPerSec()); } else { @@ -77,7 +77,7 @@ void Listener::listenerProc() m_endpointQueue.push(std::make_unique( chan++, std::move(acceptData), std::move(acceptClock))); } - sleep(1); + WaitGCTicks(GetGCTicksPerSec()); } m_dataServer.close(); diff --git a/tools/joyboot.cpp b/tools/joyboot.cpp index 588f05c..207ba7a 100644 --- a/tools/joyboot.cpp +++ b/tools/joyboot.cpp @@ -1,6 +1,7 @@ #include #include "jbus/Listener.hpp" #include "jbus/Endpoint.hpp" +#include static void clientPadComplimentCheck(jbus::u8* buffer) { @@ -83,7 +84,9 @@ int main(int argc, char** argv) jbus::u8 status; if (endpoint->GBAJoyBootAsync(2, 2, data.get(), fsize, - &status, JoyBootDone) != jbus::GBA_READY) + &status, std::bind(JoyBootDone, + std::placeholders::_1, + std::placeholders::_2)) != jbus::GBA_READY) { fprintf(stderr, "Unable to start JoyBoot\n"); return 1;