Win32 compatibility fixes

This commit is contained in:
Jack Andersen 2017-01-06 22:24:16 -10:00
parent ed1adfee0d
commit c34b81ad6c
8 changed files with 101 additions and 22 deletions

View File

@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(jbus) project(jbus)
if(WIN32)
set(JBUS_PLAT_LIBS Ws2_32)
endif()
include_directories(include) include_directories(include)
add_library(jbus add_library(jbus
include/jbus/optional.hpp include/jbus/optional.hpp
@ -8,5 +12,7 @@ add_library(jbus
lib/Common.cpp include/jbus/Common.hpp lib/Common.cpp include/jbus/Common.hpp
lib/Endpoint.cpp include/jbus/Endpoint.hpp lib/Endpoint.cpp include/jbus/Endpoint.hpp
lib/Listener.cpp include/jbus/Listener.hpp) lib/Listener.cpp include/jbus/Listener.hpp)
target_link_libraries(jbus ${JBUS_PLAT_LIBS})
add_executable(joyboot tools/joyboot.cpp) add_executable(joyboot tools/joyboot.cpp)
target_link_libraries(joyboot jbus) target_link_libraries(joyboot jbus)

View File

@ -5,6 +5,7 @@
#include "Socket.hpp" #include "Socket.hpp"
#include "optional.hpp" #include "optional.hpp"
#include <thread> #include <thread>
#include <mutex>
namespace jbus namespace jbus
{ {
@ -165,7 +166,7 @@ class Endpoint
static u64 getTransferTime(u8 cmd); static u64 getTransferTime(u8 cmd);
void clockSync(); void clockSync();
void send(const u8* buffer); void send(const u8* buffer);
size_t seceive(u8* buffer); size_t receive(u8* buffer);
size_t runBuffer(u8* buffer, u64& remTicks, EWaitResp resp); size_t runBuffer(u8* buffer, u64& remTicks, EWaitResp resp);
bool idleGetStatus(u64& remTicks); bool idleGetStatus(u64& remTicks);
void transferProc(); void transferProc();

View File

@ -5,6 +5,7 @@
#include "Socket.hpp" #include "Socket.hpp"
#include <thread> #include <thread>
#include <queue> #include <queue>
#include <mutex>
namespace jbus namespace jbus
{ {

View File

@ -1,15 +1,21 @@
#ifndef JBUS_SOCKET_HPP #ifndef JBUS_SOCKET_HPP
#define JBUS_SOCKET_HPP #define JBUS_SOCKET_HPP
#include <sys/types.h> #ifndef _WIN32
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#else
#include <winsock2.h>
#include <Ws2tcpip.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include <string> #include <string>
#include "Common.hpp" #include "Common.hpp"
@ -52,10 +58,10 @@ class IPAddress
else else
{ {
/* Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") */ /* Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx") */
uint32_t ip = inet_addr(address.c_str()); struct in_addr addr;
if (ip != INADDR_NONE) if (inet_pton(AF_INET, address.c_str(), &addr) == 1)
{ {
m_address = ip; m_address = addr.s_addr;
m_valid = true; m_valid = true;
} }
else else
@ -69,9 +75,9 @@ class IPAddress
{ {
if (result) if (result)
{ {
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr; addr = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr;
freeaddrinfo(result); freeaddrinfo(result);
m_address = ip; m_address = addr.s_addr;
m_valid = true; m_valid = true;
} }
} }
@ -96,7 +102,12 @@ public:
/** Server-oriented TCP socket class derived from SFML */ /** Server-oriented TCP socket class derived from SFML */
class Socket class Socket
{ {
int m_socket = -1; #ifndef _WIN32
using SocketTp = int;
#else
using SocketTp = SOCKET;
#endif
SocketTp m_socket = -1;
bool m_isBlocking; bool m_isBlocking;
static sockaddr_in createAddress(uint32_t address, unsigned short port) static sockaddr_in createAddress(uint32_t address, unsigned short port)
@ -119,7 +130,7 @@ class Socket
if (isOpen()) if (isOpen())
return false; return false;
m_socket = socket(PF_INET, SOCK_STREAM, 0); m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == -1) if (m_socket == -1)
{ {
fprintf(stderr, "Can't allocate socket\n"); fprintf(stderr, "Can't allocate socket\n");
@ -152,6 +163,20 @@ public:
Busy Busy
}; };
#ifdef _WIN32
static EResult LastWSAError()
{
switch (WSAGetLastError())
{
case WSAEWOULDBLOCK:
case WSAEALREADY:
return EResult::Busy;
default:
return EResult::Error;
}
}
#endif
Socket(bool blocking) Socket(bool blocking)
: m_isBlocking(blocking) {} : m_isBlocking(blocking) {}
~Socket() { close(); } ~Socket() { close(); }
@ -175,11 +200,16 @@ public:
void setBlocking(bool blocking) void setBlocking(bool blocking)
{ {
m_isBlocking = blocking; m_isBlocking = blocking;
#ifndef _WIN32
int status = fcntl(m_socket, F_GETFL); int status = fcntl(m_socket, F_GETFL);
if (m_isBlocking) if (m_isBlocking)
fcntl(m_socket, F_SETFL, status & ~O_NONBLOCK); fcntl(m_socket, F_SETFL, status & ~O_NONBLOCK);
else else
fcntl(m_socket, F_SETFL, status | O_NONBLOCK); 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; } bool isOpen() const { return m_socket != -1; }
@ -218,9 +248,15 @@ public:
/* Check for errors */ /* Check for errors */
if (remoteSocket == -1) if (remoteSocket == -1)
{ {
#ifndef _WIN32
EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error; EResult res = (errno == EAGAIN) ? EResult::Busy : EResult::Error;
if (res == EResult::Error) if (res == EResult::Error)
fprintf(stderr, "Failed to accept incoming connection: %s\n", strerror(errno)); 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; return res;
} }
@ -252,7 +288,11 @@ public:
{ {
if (!isOpen()) if (!isOpen())
return; return;
#ifndef _WIN32
::close(m_socket); ::close(m_socket);
#else
closesocket(m_socket);
#endif
m_socket = -1; m_socket = -1;
} }
@ -266,7 +306,7 @@ public:
return EResult::Error; return EResult::Error;
/* Loop until every byte has been sent */ /* Loop until every byte has been sent */
ssize_t result = 0; int result = 0;
for (size_t sent = 0; sent < len; sent += result) for (size_t sent = 0; sent < len; sent += result)
{ {
/* Send a chunk of data */ /* Send a chunk of data */
@ -274,7 +314,11 @@ public:
/* Check for errors */ /* Check for errors */
if (result < 0) if (result < 0)
#ifndef _WIN32
return (errno == EAGAIN) ? EResult::Busy : EResult::Error; return (errno == EAGAIN) ? EResult::Busy : EResult::Error;
#else
return LastWSAError();
#endif
} }
transferred = len; transferred = len;
@ -303,7 +347,11 @@ public:
int result = ::recv(m_socket, static_cast<char*>(buf), static_cast<int>(len), _flags); int result = ::recv(m_socket, static_cast<char*>(buf), static_cast<int>(len), _flags);
if (result < 0) if (result < 0)
#ifndef _WIN32
return (errno == EAGAIN) ? EResult::Busy : EResult::Error; return (errno == EAGAIN) ? EResult::Busy : EResult::Error;
#else
return LastWSAError();
#endif
else if (result == 0) else if (result == 0)
return EResult::Error; return EResult::Error;

View File

@ -8,6 +8,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#include <WinSock2.h>
#endif #endif
#include "jbus/Common.hpp" #include "jbus/Common.hpp"
@ -18,6 +19,8 @@ namespace jbus
#if __APPLE__ #if __APPLE__
static u64 MachToDolphinNum; static u64 MachToDolphinNum;
static u64 MachToDolphinDenom; static u64 MachToDolphinDenom;
#elif _WIN32
static LARGE_INTEGER PerfFrequency;
#endif #endif
u64 GetGCTicks() u64 GetGCTicks()
@ -29,6 +32,12 @@ u64 GetGCTicks()
clock_gettime(CLOCK_MONOTONIC, &tp); clock_gettime(CLOCK_MONOTONIC, &tp);
return u64((tp.tv_sec * 1000000000ull) + tp.tv_nsec) * GetGCTicksPerSec() / 1000000000ull; 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 #else
return 0; return 0;
#endif #endif
@ -36,10 +45,15 @@ u64 GetGCTicks()
void WaitGCTicks(u64 ticks) void WaitGCTicks(u64 ticks)
{ {
#ifndef _WIN32
struct timeval tv = {}; struct timeval tv = {};
tv.tv_sec = ticks / GetGCTicksPerSec(); tv.tv_sec = ticks / GetGCTicksPerSec();
tv.tv_usec = (ticks % GetGCTicksPerSec()) * 1000000 / GetGCTicksPerSec(); tv.tv_usec = (ticks % GetGCTicksPerSec()) * 1000000 / GetGCTicksPerSec();
select(0, NULL, NULL, NULL, &tv); select(0, NULL, NULL, NULL, &tv);
#else
Sleep(ticks * 1000 / GetGCTicksPerSec() +
(ticks % GetGCTicksPerSec()) * 1000 / GetGCTicksPerSec());
#endif
} }
void Initialize() void Initialize()
@ -49,6 +63,10 @@ void Initialize()
mach_timebase_info(&timebase); mach_timebase_info(&timebase);
MachToDolphinNum = GetGCTicksPerSec() * timebase.numer; MachToDolphinNum = GetGCTicksPerSec() * timebase.numer;
MachToDolphinDenom = 1000000000ull * timebase.denom; MachToDolphinDenom = 1000000000ull * timebase.denom;
#elif _WIN32
WSADATA initData;
WSAStartup(MAKEWORD(2, 2), &initData);
QueryPerformanceFrequency(&PerfFrequency);
#endif #endif
} }

View File

@ -1,6 +1,6 @@
#include "jbus/Endpoint.hpp" #include "jbus/Endpoint.hpp"
#define LOG_TRANSFER 0 #define LOG_TRANSFER 1
namespace jbus namespace jbus
{ {
@ -418,6 +418,7 @@ void Endpoint::clockSync()
TickDelta = u32(u64(TickDelta) * 16777216 / GetGCTicksPerSec()); TickDelta = u32(u64(TickDelta) * 16777216 / GetGCTicksPerSec());
m_lastGCTick = GetGCTicks(); m_lastGCTick = GetGCTicks();
TickDelta = SBig(TickDelta); TickDelta = SBig(TickDelta);
m_clockSocket.setBlocking(false);
if (m_clockSocket.send(&TickDelta, 4) == net::Socket::EResult::Error) if (m_clockSocket.send(&TickDelta, 4) == net::Socket::EResult::Error)
m_running = false; m_running = false;
} }
@ -428,6 +429,7 @@ void Endpoint::send(const u8* buffer)
net::Socket::EResult result; net::Socket::EResult result;
size_t sentBytes; size_t sentBytes;
m_dataSocket.setBlocking(false);
if (m_lastCmd == CMD_WRITE) if (m_lastCmd == CMD_WRITE)
result = m_dataSocket.send(buffer, 5, sentBytes); result = m_dataSocket.send(buffer, 5, sentBytes);
else else
@ -451,7 +453,7 @@ void Endpoint::send(const u8* buffer)
m_timeCmdSent = GetGCTicks(); m_timeCmdSent = GetGCTicks();
} }
size_t Endpoint::seceive(u8* buffer) size_t Endpoint::receive(u8* buffer)
{ {
if (!m_dataSocket) 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) if (m_waitingResp != EWaitResp::NoWait && m_dataReceivedBytes == 0)
{ {
m_dataReceivedBytes = seceive(buffer); m_dataReceivedBytes = receive(buffer);
} }
u64 ticksSinceSend = GetGCTicks() - m_timeSent; u64 ticksSinceSend = GetGCTicks() - m_timeSent;

View File

@ -1,7 +1,7 @@
#include "jbus/Listener.hpp" #include "jbus/Listener.hpp"
#include "jbus/Endpoint.hpp" #include "jbus/Endpoint.hpp"
#define LOG_LISTENER 0 #define LOG_LISTENER 1
namespace jbus namespace jbus
{ {
@ -25,7 +25,7 @@ void Listener::listenerProc()
#if LOG_LISTENER #if LOG_LISTENER
printf("data open failed %s; will retry\n", strerror(errno)); printf("data open failed %s; will retry\n", strerror(errno));
#endif #endif
sleep(1); WaitGCTicks(GetGCTicksPerSec());
} }
else else
{ {
@ -42,7 +42,7 @@ void Listener::listenerProc()
#if LOG_LISTENER #if LOG_LISTENER
printf("clock open failed %s; will retry\n", strerror(errno)); printf("clock open failed %s; will retry\n", strerror(errno));
#endif #endif
sleep(1); WaitGCTicks(GetGCTicksPerSec());
} }
else else
{ {
@ -77,7 +77,7 @@ void Listener::listenerProc()
m_endpointQueue.push(std::make_unique<Endpoint>( m_endpointQueue.push(std::make_unique<Endpoint>(
chan++, std::move(acceptData), std::move(acceptClock))); chan++, std::move(acceptData), std::move(acceptClock)));
} }
sleep(1); WaitGCTicks(GetGCTicksPerSec());
} }
m_dataServer.close(); m_dataServer.close();

View File

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include "jbus/Listener.hpp" #include "jbus/Listener.hpp"
#include "jbus/Endpoint.hpp" #include "jbus/Endpoint.hpp"
#include <functional>
static void clientPadComplimentCheck(jbus::u8* buffer) static void clientPadComplimentCheck(jbus::u8* buffer)
{ {
@ -83,7 +84,9 @@ int main(int argc, char** argv)
jbus::u8 status; jbus::u8 status;
if (endpoint->GBAJoyBootAsync(2, 2, data.get(), fsize, 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"); fprintf(stderr, "Unable to start JoyBoot\n");
return 1; return 1;