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)
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)

View File

@ -5,6 +5,7 @@
#include "Socket.hpp"
#include "optional.hpp"
#include <thread>
#include <mutex>
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();

View File

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

View File

@ -1,15 +1,21 @@
#ifndef JBUS_SOCKET_HPP
#define JBUS_SOCKET_HPP
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.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 "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<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
addr = reinterpret_cast<sockaddr_in*>(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<char*>(buf), static_cast<int>(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;

View File

@ -8,6 +8,7 @@
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <WinSock2.h>
#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
}

View File

@ -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;

View File

@ -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<Endpoint>(
chan++, std::move(acceptData), std::move(acceptClock)));
}
sleep(1);
WaitGCTicks(GetGCTicksPerSec());
}
m_dataServer.close();

View File

@ -1,6 +1,7 @@
#include <stdio.h>
#include "jbus/Listener.hpp"
#include "jbus/Endpoint.hpp"
#include <functional>
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;