forked from beerpsi/chuniio-brokenithm
Fixes timeouts causing disconnections (also helps with multi-client TCP support)
This commit is contained in:
parent
c9484640d0
commit
2e0010d374
349
src/chuniio.c
349
src/chuniio.c
@ -19,8 +19,8 @@
|
|||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//region Brokenithm
|
// region Brokenithm
|
||||||
struct IPCMemoryInfo* chuni_io_file_mapping;
|
struct IPCMemoryInfo *chuni_io_file_mapping;
|
||||||
|
|
||||||
const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER";
|
const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER";
|
||||||
|
|
||||||
@ -33,10 +33,7 @@ enum {
|
|||||||
CARD_FELICA,
|
CARD_FELICA,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum { FUNCTION_COIN = 1, FUNCTION_CARD };
|
||||||
FUNCTION_COIN = 1,
|
|
||||||
FUNCTION_CARD
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
@ -45,12 +42,12 @@ typedef struct {
|
|||||||
atomic_bool exit_flag;
|
atomic_bool exit_flag;
|
||||||
atomic_bool connected;
|
atomic_bool connected;
|
||||||
uint32_t last_input_packet_id;
|
uint32_t last_input_packet_id;
|
||||||
struct IPCMemoryInfo* memory;
|
struct IPCMemoryInfo *memory;
|
||||||
} thread_ctx;
|
} thread_ctx;
|
||||||
|
|
||||||
void socket_set_timeout(SOCKET sHost, int timeout) {
|
void socket_set_timeout(SOCKET sHost, int timeout) {
|
||||||
setsockopt(sHost, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int));
|
setsockopt(sHost, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(int));
|
||||||
setsockopt(sHost, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(int));
|
setsockopt(sHost, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_bind(SOCKET sHost, unsigned long addr, uint16_t port) {
|
int socket_bind(SOCKET sHost, unsigned long addr, uint16_t port) {
|
||||||
@ -59,14 +56,15 @@ int socket_bind(SOCKET sHost, unsigned long addr, uint16_t port) {
|
|||||||
srcaddr.sin_family = AF_INET;
|
srcaddr.sin_family = AF_INET;
|
||||||
srcaddr.sin_addr.s_addr = addr;
|
srcaddr.sin_addr.s_addr = addr;
|
||||||
srcaddr.sin_port = htons(port);
|
srcaddr.sin_port = htons(port);
|
||||||
return bind(sHost, (struct sockaddr*)&srcaddr, sizeof(srcaddr));
|
return bind(sHost, (struct sockaddr *)&srcaddr, sizeof(srcaddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_send_to(SOCKET sHost, const struct sockaddr_in* addr, const char* buf, int len) {
|
int socket_send_to(SOCKET sHost, const struct sockaddr_in *addr, const char *buf,
|
||||||
return sendto(sHost, buf, len, 0, (struct sockaddr*)&addr, sizeof(&addr));
|
int len) {
|
||||||
|
return sendto(sHost, buf, len, 0, (struct sockaddr *)&addr, sizeof(&addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_err(const char* fmt, ...) {
|
void print_err(const char *fmt, ...) {
|
||||||
time_t lt = time(NULL);
|
time_t lt = time(NULL);
|
||||||
struct tm *local = localtime(<);
|
struct tm *local = localtime(<);
|
||||||
char tmpbuf[32];
|
char tmpbuf[32];
|
||||||
@ -81,7 +79,8 @@ void print_err(const char* fmt, ...) {
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_socks_address(const struct PacketConnect* pkt, char* address, int address_len, uint16_t *port) {
|
void get_socks_address(const struct PacketConnect *pkt, char *address, int address_len,
|
||||||
|
uint16_t *port) {
|
||||||
if (!pkt || !address || !port) {
|
if (!pkt || !address || !port) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -89,32 +88,32 @@ void get_socks_address(const struct PacketConnect* pkt, char* address, int addre
|
|||||||
*port = ntohs(pkt->port);
|
*port = ntohs(pkt->port);
|
||||||
|
|
||||||
switch (pkt->addrType) {
|
switch (pkt->addrType) {
|
||||||
case 1:
|
case 1:
|
||||||
inet_ntop(AF_INET, pkt->addr.addr4.addr, address, address_len);
|
inet_ntop(AF_INET, pkt->addr.addr4.addr, address, address_len);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
inet_ntop(AF_INET6, pkt->addr.addr6, address, address_len);
|
inet_ntop(AF_INET6, pkt->addr.addr6, address, address_len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_packet_id(thread_ctx *ctx, uint32_t new_packet_id)
|
void update_packet_id(thread_ctx *ctx, uint32_t new_packet_id) {
|
||||||
{
|
|
||||||
if (ctx->last_input_packet_id > new_packet_id) {
|
if (ctx->last_input_packet_id > new_packet_id) {
|
||||||
print_err("[WARN] Packet #%" PRIu32 " came too late\n", new_packet_id);
|
print_err("[WARN] Packet #%" PRIu32 " came too late\n", new_packet_id);
|
||||||
} else if (new_packet_id > ctx->last_input_packet_id + 1) {
|
} else if (new_packet_id > ctx->last_input_packet_id + 1) {
|
||||||
print_err("[WARN] Packets between #%" PRIu32 " and #%" PRIu32 " total %" PRIu32 " packet(s) are missing, probably too late or dropped\n",
|
print_err("[WARN] Packets between #%" PRIu32 " and #%" PRIu32 " total %" PRIu32
|
||||||
ctx->last_input_packet_id, new_packet_id, new_packet_id - ctx->last_input_packet_id - 1);
|
" packet(s) are missing, probably too late or dropped\n",
|
||||||
|
ctx->last_input_packet_id, new_packet_id,
|
||||||
|
new_packet_id - ctx->last_input_packet_id - 1);
|
||||||
} else if (new_packet_id == ctx->last_input_packet_id) {
|
} else if (new_packet_id == ctx->last_input_packet_id) {
|
||||||
print_err("[WARN] Packet #%" PRIu32 " duplicated\n", new_packet_id);
|
print_err("[WARN] Packet #%" PRIu32 " duplicated\n", new_packet_id);
|
||||||
}
|
}
|
||||||
ctx->last_input_packet_id = new_packet_id;
|
ctx->last_input_packet_id = new_packet_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_bytes(const void *ptr, size_t nbytes, bool hex_string)
|
void dump_bytes(const void *ptr, size_t nbytes, bool hex_string) {
|
||||||
{
|
|
||||||
const uint8_t *bytes;
|
const uint8_t *bytes;
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -124,20 +123,20 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string)
|
|||||||
dprintf("\t--- Empty ---\n");
|
dprintf("\t--- Empty ---\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes = (const unsigned char*)ptr;
|
bytes = (const unsigned char *)ptr;
|
||||||
|
|
||||||
if (hex_string) {
|
if (hex_string) {
|
||||||
for (i = 0 ; i < nbytes ; i++) {
|
for (i = 0; i < nbytes; i++) {
|
||||||
dprintf("%02x", bytes[i]);
|
dprintf("%02x", bytes[i]);
|
||||||
}
|
}
|
||||||
dprintf("\n");
|
dprintf("\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < nbytes ; i += 16) {
|
for (i = 0; i < nbytes; i += 16) {
|
||||||
dprintf(" %08x:", (int) i);
|
dprintf(" %08x:", (int)i);
|
||||||
|
|
||||||
for (j = 0 ; i + j < nbytes && j < 16 ; j++) {
|
for (j = 0; i + j < nbytes && j < 16; j++) {
|
||||||
dprintf(" %02x", bytes[i + j]);
|
dprintf(" %02x", bytes[i + j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +147,7 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string)
|
|||||||
|
|
||||||
dprintf(" ");
|
dprintf(" ");
|
||||||
|
|
||||||
for (j = 0 ; i + j < nbytes && j < 16 ; j++) {
|
for (j = 0; i + j < nbytes && j < 16; j++) {
|
||||||
c = bytes[i + j];
|
c = bytes[i + j];
|
||||||
|
|
||||||
if (c < 0x20 || c >= 0x7F) {
|
if (c < 0x20 || c >= 0x7F) {
|
||||||
@ -166,20 +165,20 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string)
|
|||||||
|
|
||||||
void print_card_info(uint8_t card_type, uint8_t *card_id) {
|
void print_card_info(uint8_t card_type, uint8_t *card_id) {
|
||||||
switch (card_type) {
|
switch (card_type) {
|
||||||
case CARD_AIME:
|
case CARD_AIME:
|
||||||
print_err("[INFO] Card type: AiMe, ID: ");
|
print_err("[INFO] Card type: AiMe, ID: ");
|
||||||
dump_bytes(card_id, 10, true);
|
dump_bytes(card_id, 10, true);
|
||||||
break;
|
break;
|
||||||
case CARD_FELICA:
|
case CARD_FELICA:
|
||||||
print_err("[INFO] Card type: FeliCa, ID: ");
|
print_err("[INFO] Card type: FeliCa, ID: ");
|
||||||
dump_bytes(card_id, 8, true);
|
dump_bytes(card_id, 8, true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int make_ipv4_address(struct sockaddr_in* addr, char* host, uint16_t port) {
|
int make_ipv4_address(struct sockaddr_in *addr, char *host, uint16_t port) {
|
||||||
addr->sin_family = AF_INET;
|
addr->sin_family = AF_INET;
|
||||||
addr->sin_port = htons(port);
|
addr->sin_port = htons(port);
|
||||||
return inet_pton(AF_INET, host, (struct in_addr *)&addr->sin_addr.s_addr);
|
return inet_pton(AF_INET, host, (struct in_addr *)&addr->sin_addr.s_addr);
|
||||||
@ -190,10 +189,10 @@ bool has_previous_led_status = false;
|
|||||||
int skip_count = 0;
|
int skip_count = 0;
|
||||||
|
|
||||||
unsigned int __stdcall thread_led_broadcast(void *v) {
|
unsigned int __stdcall thread_led_broadcast(void *v) {
|
||||||
thread_ctx *ctx = (thread_ctx*)v;
|
thread_ctx *ctx = (thread_ctx *)v;
|
||||||
|
|
||||||
SOCKET sHost = ctx->sock;
|
SOCKET sHost = ctx->sock;
|
||||||
struct IPCMemoryInfo* memory = ctx->memory;
|
struct IPCMemoryInfo *memory = ctx->memory;
|
||||||
|
|
||||||
struct sockaddr_in addr = {};
|
struct sockaddr_in addr = {};
|
||||||
make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port);
|
make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port);
|
||||||
@ -206,7 +205,6 @@ unsigned int __stdcall thread_led_broadcast(void *v) {
|
|||||||
|
|
||||||
uint8_t current_led_status[3 * 32];
|
uint8_t current_led_status[3 * 32];
|
||||||
|
|
||||||
|
|
||||||
while (!atomic_load(&ctx->exit_flag)) {
|
while (!atomic_load(&ctx->exit_flag)) {
|
||||||
if (!atomic_load(&ctx->connected)) {
|
if (!atomic_load(&ctx->connected)) {
|
||||||
Sleep(50);
|
Sleep(50);
|
||||||
@ -233,14 +231,21 @@ unsigned int __stdcall thread_led_broadcast(void *v) {
|
|||||||
print_err("[ERROR] Cannot send packet: error %lu\n", GetLastError());
|
print_err("[ERROR] Cannot send packet: error %lu\n", GetLastError());
|
||||||
|
|
||||||
if (tcp_mode) {
|
if (tcp_mode) {
|
||||||
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||||
|
error == WSAETIMEDOUT) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
print_err("[INFO] Device disconnected!\n");
|
|
||||||
atomic_store(&ctx->connected, false);
|
|
||||||
atomic_store(&ctx->exit_flag, true);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_err("[INFO] Device disconnected (could not send packet), "
|
||||||
|
"error %d, os error %ld\n",
|
||||||
|
errno, error);
|
||||||
|
|
||||||
|
atomic_store(&ctx->connected, false);
|
||||||
|
atomic_store(&ctx->exit_flag, true);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,10 +261,10 @@ unsigned int __stdcall thread_led_broadcast(void *v) {
|
|||||||
uint8_t last_card_id[10];
|
uint8_t last_card_id[10];
|
||||||
|
|
||||||
unsigned int __stdcall thread_input_recv(void *v) {
|
unsigned int __stdcall thread_input_recv(void *v) {
|
||||||
thread_ctx *ctx = (thread_ctx*)v;
|
thread_ctx *ctx = (thread_ctx *)v;
|
||||||
|
|
||||||
SOCKET sHost = ctx->sock;
|
SOCKET sHost = ctx->sock;
|
||||||
struct IPCMemoryInfo* memory = ctx->memory;
|
struct IPCMemoryInfo *memory = ctx->memory;
|
||||||
|
|
||||||
char buffer[BUFSIZ];
|
char buffer[BUFSIZ];
|
||||||
|
|
||||||
@ -272,8 +277,9 @@ unsigned int __stdcall thread_input_recv(void *v) {
|
|||||||
while (!atomic_load(&ctx->exit_flag)) {
|
while (!atomic_load(&ctx->exit_flag)) {
|
||||||
if (!tcp_mode) {
|
if (!tcp_mode) {
|
||||||
/**
|
/**
|
||||||
on UDP mode data is sent as packets, so just receive into a buffer big enough for 1 packet
|
on UDP mode data is sent as packets, so just receive into a buffer big
|
||||||
each recvfrom call will only get 1 packet of data, the remaining data is discarded
|
enough for 1 packet each recvfrom call will only get 1 packet of data, the
|
||||||
|
remaining data is discarded
|
||||||
**/
|
**/
|
||||||
|
|
||||||
if ((recv_len = recvfrom(sHost, buffer, BUFSIZ - 1, 0, NULL, NULL)) == -1) {
|
if ((recv_len = recvfrom(sHost, buffer, BUFSIZ - 1, 0, NULL, NULL)) == -1) {
|
||||||
@ -289,8 +295,8 @@ unsigned int __stdcall thread_input_recv(void *v) {
|
|||||||
packet_len = real_len + 1;
|
packet_len = real_len + 1;
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
on TCP mode packets are length-prefixed, so we read in the first 4 bytes to
|
on TCP mode packets are length-prefixed, so we read in the first 4 bytes
|
||||||
figure out how much we need to read, then read in the full data.
|
to figure out how much we need to read, then read in the full data.
|
||||||
**/
|
**/
|
||||||
recv_len = 0;
|
recv_len = 0;
|
||||||
|
|
||||||
@ -298,90 +304,112 @@ unsigned int __stdcall thread_input_recv(void *v) {
|
|||||||
int read = recv(sHost, buffer + recv_len, 4 - recv_len, 0);
|
int read = recv(sHost, buffer + recv_len, 4 - recv_len, 0);
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||||
|
error == WSAETIMEDOUT) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
print_err("[INFO] Device disconnected!\n");
|
|
||||||
atomic_store(&ctx->connected, false);
|
|
||||||
atomic_store(&ctx->exit_flag, true);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_err("[INFO] Device disconnected (could not receive packet), "
|
||||||
|
"errno %d, os error %ld\n",
|
||||||
|
errno, error);
|
||||||
|
atomic_store(&ctx->connected, false);
|
||||||
|
atomic_store(&ctx->exit_flag, true);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_len = recv_len + read;
|
recv_len = recv_len + read;
|
||||||
}
|
}
|
||||||
|
|
||||||
real_len = buffer[0];
|
real_len = buffer[0];
|
||||||
packet_len = real_len + 1; // 1 for the packetSize
|
packet_len = real_len + 1; // 1 for the packetSize
|
||||||
|
|
||||||
while (recv_len < packet_len) {
|
while (recv_len < packet_len) {
|
||||||
int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0);
|
int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0);
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
|
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN ||
|
||||||
|
error == WSAETIMEDOUT) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
print_err("[INFO] Device disconnected!\n");
|
|
||||||
atomic_store(&ctx->connected, false);
|
|
||||||
atomic_store(&ctx->exit_flag, true);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_err("[INFO] Device disconnected (could not receive packet), "
|
||||||
|
"errno %d, os error %ld\n",
|
||||||
|
errno, error);
|
||||||
|
atomic_store(&ctx->connected, false);
|
||||||
|
atomic_store(&ctx->exit_flag, true);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_len = recv_len + read;
|
recv_len = recv_len + read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet_len >= sizeof(struct PacketInput) && buffer[1] == 'I' && buffer[2] == 'N' && buffer[3] == 'P') {
|
if (packet_len >= sizeof(struct PacketInput) && buffer[1] == 'I' &&
|
||||||
struct PacketInput* pkt = (struct PacketInput*)buffer;
|
buffer[2] == 'N' && buffer[3] == 'P') {
|
||||||
|
struct PacketInput *pkt = (struct PacketInput *)buffer;
|
||||||
|
|
||||||
memcpy(memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus));
|
memcpy(memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus));
|
||||||
memcpy(memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus));
|
memcpy(memory->sliderIoStatus, pkt->sliderIoStatus,
|
||||||
|
sizeof(pkt->sliderIoStatus));
|
||||||
memory->testBtn = pkt->testBtn;
|
memory->testBtn = pkt->testBtn;
|
||||||
memory->serviceBtn = pkt->serviceBtn;
|
memory->serviceBtn = pkt->serviceBtn;
|
||||||
|
|
||||||
update_packet_id(ctx, ntohl(pkt->packetId));
|
update_packet_id(ctx, ntohl(pkt->packetId));
|
||||||
} else if (packet_len >= sizeof(struct PacketInputNoAir) && buffer[1] == 'I' && buffer[2] == 'P' && buffer[3] == 'T') { // without air
|
} else if (packet_len >= sizeof(struct PacketInputNoAir) && buffer[1] == 'I' &&
|
||||||
struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer;
|
buffer[2] == 'P' && buffer[3] == 'T') { // without air
|
||||||
|
struct PacketInputNoAir *pkt = (struct PacketInputNoAir *)buffer;
|
||||||
|
|
||||||
memcpy(memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus));
|
memcpy(memory->sliderIoStatus, pkt->sliderIoStatus,
|
||||||
|
sizeof(pkt->sliderIoStatus));
|
||||||
memory->testBtn = pkt->testBtn;
|
memory->testBtn = pkt->testBtn;
|
||||||
memory->serviceBtn = pkt->serviceBtn;
|
memory->serviceBtn = pkt->serviceBtn;
|
||||||
|
|
||||||
update_packet_id(ctx, ntohl(pkt->packetId));
|
update_packet_id(ctx, ntohl(pkt->packetId));
|
||||||
} else if (packet_len >= sizeof(struct PacketFunction) && buffer[1] == 'F' && buffer[2] == 'N' && buffer[3] == 'C') {
|
} else if (packet_len >= sizeof(struct PacketFunction) && buffer[1] == 'F' &&
|
||||||
struct PacketFunction* pkt = (struct PacketFunction*)buffer;
|
buffer[2] == 'N' && buffer[3] == 'C') {
|
||||||
|
struct PacketFunction *pkt = (struct PacketFunction *)buffer;
|
||||||
|
|
||||||
switch (pkt->funcBtn) {
|
switch (pkt->funcBtn) {
|
||||||
case FUNCTION_COIN:
|
case FUNCTION_COIN:
|
||||||
memory->coinInsertion = 1;
|
memory->coinInsertion = 1;
|
||||||
break;
|
break;
|
||||||
case FUNCTION_CARD:
|
case FUNCTION_CARD:
|
||||||
memory->cardRead = 1;
|
memory->cardRead = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (packet_len >= sizeof(struct PacketConnect) && buffer[1] == 'C' && buffer[2] == 'O' && buffer[3] == 'N') {
|
} else if (packet_len >= sizeof(struct PacketConnect) && buffer[1] == 'C' &&
|
||||||
struct PacketConnect* pkt = (struct PacketConnect*)buffer;
|
buffer[2] == 'O' && buffer[3] == 'N') {
|
||||||
|
struct PacketConnect *pkt = (struct PacketConnect *)buffer;
|
||||||
|
|
||||||
get_socks_address(pkt, ctx->remote_address, BUFSIZ - 1, &ctx->remote_port);
|
get_socks_address(pkt, ctx->remote_address, BUFSIZ - 1, &ctx->remote_port);
|
||||||
print_err("[INFO] Device %s:%d connected.\n", ctx->remote_address, ctx->remote_port);
|
print_err("[INFO] Device %s:%d connected.\n", ctx->remote_address,
|
||||||
|
ctx->remote_port);
|
||||||
|
|
||||||
ctx->last_input_packet_id = 0;
|
ctx->last_input_packet_id = 0;
|
||||||
atomic_store(&ctx->connected, true);
|
atomic_store(&ctx->connected, true);
|
||||||
} else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S') {
|
} else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' &&
|
||||||
|
buffer[3] == 'S') {
|
||||||
atomic_store(&ctx->connected, false);
|
atomic_store(&ctx->connected, false);
|
||||||
|
|
||||||
if (tcp_mode) {
|
if (tcp_mode) {
|
||||||
atomic_store(&ctx->exit_flag, true);
|
atomic_store(&ctx->exit_flag, true);
|
||||||
print_err("[INFO] Device disconnected!\n");
|
print_err("[INFO] Device disconnected (clean disconnect)\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(ctx->remote_address)) {
|
if (strlen(ctx->remote_address)) {
|
||||||
print_err("[INFO] Device %s:%d disconnected.\n", ctx->remote_address, ctx->remote_port);
|
print_err("[INFO] Device %s:%d disconnected.\n", ctx->remote_address,
|
||||||
|
ctx->remote_port);
|
||||||
memset(ctx->remote_address, 0, BUFSIZ);
|
memset(ctx->remote_address, 0, BUFSIZ);
|
||||||
}
|
}
|
||||||
} else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N') {
|
} else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' &&
|
||||||
|
buffer[2] == 'I' && buffer[3] == 'N') {
|
||||||
if (!atomic_load(&ctx->connected)) {
|
if (!atomic_load(&ctx->connected)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -391,8 +419,9 @@ unsigned int __stdcall thread_input_recv(void *v) {
|
|||||||
response[2] = 'O';
|
response[2] = 'O';
|
||||||
|
|
||||||
socket_send_to(sHost, &addr, response, 13);
|
socket_send_to(sHost, &addr, response, 13);
|
||||||
} else if (packet_len >= sizeof(struct PacketCard) && buffer[1] == 'C' && buffer[2] == 'R' && buffer[3] == 'D') {
|
} else if (packet_len >= sizeof(struct PacketCard) && buffer[1] == 'C' &&
|
||||||
struct PacketCard* pkt = (struct PacketCard*)buffer;
|
buffer[2] == 'R' && buffer[3] == 'D') {
|
||||||
|
struct PacketCard *pkt = (struct PacketCard *)buffer;
|
||||||
|
|
||||||
if (pkt->remoteCardRead) {
|
if (pkt->remoteCardRead) {
|
||||||
if (memcmp(last_card_id, pkt->remoteCardId, 10) != 0) {
|
if (memcmp(last_card_id, pkt->remoteCardId, 10) != 0) {
|
||||||
@ -414,8 +443,8 @@ unsigned int __stdcall thread_input_recv(void *v) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int __stdcall server_thread_proc(void* ctx) {
|
unsigned int __stdcall server_thread_proc(void *ctx) {
|
||||||
struct IPCMemoryInfo* memory = (struct IPCMemoryInfo*)ctx;
|
struct IPCMemoryInfo *memory = (struct IPCMemoryInfo *)ctx;
|
||||||
|
|
||||||
if (!tcp_mode) {
|
if (!tcp_mode) {
|
||||||
print_err("[INFO] Mode: UDP\n");
|
print_err("[INFO] Mode: UDP\n");
|
||||||
@ -426,16 +455,16 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
|||||||
|
|
||||||
print_err("[INFO] Waiting for device on port %d...\n", server_port);
|
print_err("[INFO] Waiting for device on port %d...\n", server_port);
|
||||||
|
|
||||||
thread_ctx args = {
|
thread_ctx args = {.sock = sHost,
|
||||||
.sock = sHost,
|
.exit_flag = ATOMIC_VAR_INIT(false),
|
||||||
.exit_flag = ATOMIC_VAR_INIT(false),
|
.connected = ATOMIC_VAR_INIT(false),
|
||||||
.connected = ATOMIC_VAR_INIT(false),
|
.last_input_packet_id = 0,
|
||||||
.last_input_packet_id = 0,
|
.memory = memory};
|
||||||
.memory = memory
|
|
||||||
};
|
|
||||||
|
|
||||||
HANDLE led_thread = (HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
HANDLE led_thread =
|
||||||
HANDLE input_thread = (HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
(HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
||||||
|
HANDLE input_thread =
|
||||||
|
(HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
||||||
|
|
||||||
WaitForSingleObject(led_thread, INFINITE);
|
WaitForSingleObject(led_thread, INFINITE);
|
||||||
WaitForSingleObject(input_thread, INFINITE);
|
WaitForSingleObject(input_thread, INFINITE);
|
||||||
@ -458,24 +487,26 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
struct sockaddr_in user_socket = {};
|
struct sockaddr_in user_socket = {};
|
||||||
socklen_t sock_size = sizeof(struct sockaddr_in);
|
socklen_t sock_size = sizeof(struct sockaddr_in);
|
||||||
SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size);
|
SOCKET acc_socket =
|
||||||
|
accept(sHost, (struct sockaddr *)&user_socket, &sock_size);
|
||||||
|
|
||||||
char buffer[20] = {};
|
char buffer[20] = {};
|
||||||
const char* user_address = inet_ntop(AF_INET, &user_socket.sin_addr, buffer, 20);
|
const char *user_address =
|
||||||
|
inet_ntop(AF_INET, &user_socket.sin_addr, buffer, 20);
|
||||||
if (user_address != NULL) {
|
if (user_address != NULL) {
|
||||||
print_err("[INFO] Device %s:%d connected.\n", user_address, user_socket.sin_port);
|
print_err("[INFO] Device %s:%d connected.\n", user_address,
|
||||||
|
user_socket.sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_ctx args = {
|
thread_ctx *args = malloc(sizeof(thread_ctx));
|
||||||
.sock = acc_socket,
|
args->sock = acc_socket;
|
||||||
.exit_flag = ATOMIC_VAR_INIT(false),
|
args->exit_flag = ATOMIC_VAR_INIT(false);
|
||||||
.connected = ATOMIC_VAR_INIT(true),
|
args->connected = ATOMIC_VAR_INIT(true);
|
||||||
.last_input_packet_id = 0,
|
args->last_input_packet_id = 0;
|
||||||
.memory = memory
|
args->memory = memory;
|
||||||
};
|
|
||||||
|
|
||||||
_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
_beginthreadex(NULL, 0, thread_led_broadcast, args, 0, NULL);
|
||||||
_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
_beginthreadex(NULL, 0, thread_input_recv, args, 0, NULL);
|
||||||
}
|
}
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
@ -484,8 +515,10 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HRESULT server_start() {
|
HRESULT server_start() {
|
||||||
tcp_mode = GetPrivateProfileIntW(L"brokenithm", L"tcp", 0, L".\\segatools.ini") == 1;
|
tcp_mode =
|
||||||
server_port = GetPrivateProfileIntW(L"brokenithm", L"port", 52468, L".\\segatools.ini");
|
GetPrivateProfileIntW(L"brokenithm", L"tcp", 0, L".\\segatools.ini") == 1;
|
||||||
|
server_port =
|
||||||
|
GetPrivateProfileIntW(L"brokenithm", L"port", 52468, L".\\segatools.ini");
|
||||||
|
|
||||||
struct WSAData wsaData = {};
|
struct WSAData wsaData = {};
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
@ -496,18 +529,21 @@ HRESULT server_start() {
|
|||||||
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, memFileName);
|
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, memFileName);
|
||||||
|
|
||||||
if (hMapFile == NULL) {
|
if (hMapFile == NULL) {
|
||||||
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, memFileName);
|
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
|
||||||
|
1024, memFileName);
|
||||||
if (hMapFile == NULL) {
|
if (hMapFile == NULL) {
|
||||||
print_err("[ERROR] CreateFileMapping failed! error: %lu\n", GetLastError());
|
print_err("[ERROR] CreateFileMapping failed! error: %lu\n", GetLastError());
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IPCMemoryInfo* memory = (struct IPCMemoryInfo*)MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL);
|
struct IPCMemoryInfo *memory = (struct IPCMemoryInfo *)MapViewOfFileEx(
|
||||||
|
hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL);
|
||||||
chuni_io_file_mapping = memory;
|
chuni_io_file_mapping = memory;
|
||||||
|
|
||||||
if (memory == NULL) {
|
if (memory == NULL) {
|
||||||
print_err("[ERROR] Cannot get view of memory map! error: %lu\n", GetLastError());
|
print_err("[ERROR] Cannot get view of memory map! error: %lu\n",
|
||||||
|
GetLastError());
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,9 +552,9 @@ HRESULT server_start() {
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//endregion
|
// endregion
|
||||||
|
|
||||||
//region ChuniIO stuff
|
// region ChuniIO stuff
|
||||||
#ifdef ENV64BIT
|
#ifdef ENV64BIT
|
||||||
static HANDLE chuni_io_file_mapping_handle;
|
static HANDLE chuni_io_file_mapping_handle;
|
||||||
|
|
||||||
@ -528,13 +564,19 @@ void chuni_io_init_shared_memory() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((chuni_io_file_mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, sizeof(struct IPCMemoryInfo), memFileName)) == 0) {
|
if ((chuni_io_file_mapping_handle =
|
||||||
dprintf("chuni_io_init_shared_memory: could not create file mapping: %ld\n", GetLastError());
|
CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
|
||||||
|
sizeof(struct IPCMemoryInfo), memFileName)) == 0) {
|
||||||
|
dprintf("chuni_io_init_shared_memory: could not create file mapping: %ld\n",
|
||||||
|
GetLastError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((chuni_io_file_mapping = (struct IPCMemoryInfo*)MapViewOfFile(chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(struct IPCMemoryInfo))) == 0) {
|
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *)MapViewOfFile(
|
||||||
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n", GetLastError());
|
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
|
||||||
|
sizeof(struct IPCMemoryInfo))) == 0) {
|
||||||
|
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n",
|
||||||
|
GetLastError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +585,6 @@ void chuni_io_init_shared_memory() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
|
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
|
||||||
|
|
||||||
static bool chuni_io_coin;
|
static bool chuni_io_coin;
|
||||||
@ -553,9 +594,7 @@ static HANDLE chuni_io_slider_thread;
|
|||||||
static bool chuni_io_slider_stop_flag;
|
static bool chuni_io_slider_stop_flag;
|
||||||
static struct chuni_io_config chuni_io_cfg;
|
static struct chuni_io_config chuni_io_cfg;
|
||||||
|
|
||||||
uint16_t chuni_io_get_api_version() {
|
uint16_t chuni_io_get_api_version() { return 0x0102; }
|
||||||
return 0x0102;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT chuni_io_jvs_init() {
|
HRESULT chuni_io_jvs_init() {
|
||||||
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
|
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
|
||||||
@ -598,11 +637,13 @@ void chuni_io_jvs_read_coin_counter(uint16_t *out) {
|
|||||||
void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
|
void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if ((chuni_io_file_mapping && chuni_io_file_mapping->testBtn) || GetAsyncKeyState(chuni_io_cfg.vk_test)) {
|
if ((chuni_io_file_mapping && chuni_io_file_mapping->testBtn) ||
|
||||||
|
GetAsyncKeyState(chuni_io_cfg.vk_test)) {
|
||||||
*opbtn |= CHUNI_IO_OPBTN_TEST; /* Test */
|
*opbtn |= CHUNI_IO_OPBTN_TEST; /* Test */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((chuni_io_file_mapping && chuni_io_file_mapping->serviceBtn) || GetAsyncKeyState(chuni_io_cfg.vk_service)) {
|
if ((chuni_io_file_mapping && chuni_io_file_mapping->serviceBtn) ||
|
||||||
|
GetAsyncKeyState(chuni_io_cfg.vk_service)) {
|
||||||
*opbtn |= CHUNI_IO_OPBTN_SERVICE; /* Service */
|
*opbtn |= CHUNI_IO_OPBTN_SERVICE; /* Service */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,37 +657,30 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < 6 ; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if (chuni_io_hand_pos > i) {
|
if (chuni_io_hand_pos > i) {
|
||||||
*beams |= (1 << i);
|
*beams |= (1 << i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IR format is beams[5:0] = {b5,b6,b3,b4,b1,b2};
|
// IR format is beams[5:0] = {b5,b6,b3,b4,b1,b2};
|
||||||
for (i = 0 ; i < 3 ; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i*2])
|
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i * 2])
|
||||||
*beams |= (1 << (i*2+1));
|
*beams |= (1 << (i * 2 + 1));
|
||||||
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i*2+1])
|
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i * 2 + 1])
|
||||||
*beams |= (1 << (i*2));
|
*beams |= (1 << (i * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT chuni_io_slider_init() {
|
HRESULT chuni_io_slider_init() { return S_OK; }
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void chuni_io_slider_start(void* callback) {
|
void chuni_io_slider_start(void *callback) {
|
||||||
if (chuni_io_slider_thread != NULL) {
|
if (chuni_io_slider_thread != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chuni_io_slider_thread = (HANDLE) _beginthreadex(
|
chuni_io_slider_thread =
|
||||||
NULL,
|
(HANDLE)_beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
|
||||||
0,
|
|
||||||
chuni_io_slider_thread_proc,
|
|
||||||
callback,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chuni_io_slider_stop(void) {
|
void chuni_io_slider_stop(void) {
|
||||||
@ -668,14 +702,11 @@ void chuni_io_slider_set_leds(const uint8_t *rgb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT chuni_io_led_init(void) {
|
HRESULT chuni_io_led_init(void) { return S_OK; }
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {}
|
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {}
|
||||||
|
|
||||||
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx)
|
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
|
||||||
{
|
|
||||||
chuni_io_slider_callback_t callback;
|
chuni_io_slider_callback_t callback;
|
||||||
uint8_t pressure[32];
|
uint8_t pressure[32];
|
||||||
|
|
||||||
@ -695,7 +726,7 @@ static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//endregion
|
// endregion
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
Loading…
Reference in New Issue
Block a user