First public version
This commit is contained in:
parent
6c4e7843e6
commit
8eede5e66b
|
@ -0,0 +1,26 @@
|
|||
project(brokenithm LANGUAGES CXX)
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include/")
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE Release)
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
IF (NOT WIN32)
|
||||
MESSAGE(FATAL_ERROR "This is not supposed to be run on non-Windows platforms!")
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF (NOT MSVC)
|
||||
ADD_COMPILE_OPTIONS(-Wall -Wextra -Wno-unused-parameter -Wno-unused-result)
|
||||
ELSE()
|
||||
ADD_COMPILE_OPTIONS(/W4)
|
||||
ENDIF()
|
||||
|
||||
ADD_EXECUTABLE(brokenithm
|
||||
src/main.cpp)
|
||||
INCLUDE_DIRECTORIES(src)
|
||||
LINK_DIRECTORIES(${CMAKE_SOURCE_DIR})
|
||||
|
||||
TARGET_LINK_LIBRARIES(brokenithm ws2_32)
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DEFER_H_INCLUDED
|
||||
#define DEFER_H_INCLUDED
|
||||
|
||||
#define CONCAT(a,b) a ## b
|
||||
#define DO_CONCAT(a,b) CONCAT(a,b)
|
||||
template <typename T> class __defer_struct final {private: T fn; bool __cancelled = false; public: explicit __defer_struct(T func) : fn(std::move(func)) {} ~__defer_struct() {if(!__cancelled) fn();} void cancel() {__cancelled = true;} };
|
||||
//#define defer(x) std::unique_ptr<void> DO_CONCAT(__defer_deleter_,__LINE__) (nullptr, [&](...){x});
|
||||
#define defer(x) __defer_struct DO_CONCAT(__defer_deleter,__LINE__) ([&](...){x;});
|
||||
|
||||
#endif // DEFER_H_INCLUDED
|
|
@ -0,0 +1,385 @@
|
|||
#include <string>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "socket.h"
|
||||
#include "defer.h"
|
||||
#include <windows.h>
|
||||
|
||||
std::string remote_address;
|
||||
uint16_t remote_port = 52468;
|
||||
uint16_t server_port = 52468;
|
||||
bool tcp_mode = false;
|
||||
|
||||
std::atomic_bool EXIT_FLAG {false}, CONNECTED {false};
|
||||
|
||||
int setTimeout(SOCKET s, int timeout)
|
||||
{
|
||||
int ret = -1;
|
||||
#ifdef _WIN32
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int));
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(int));
|
||||
#else
|
||||
struct timeval timeo = {timeout / 1000, (timeout % 1000) * 1000};
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeo, sizeof(timeo));
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeo, sizeof(timeo));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int socket_bind(SOCKET sHost, long addr, uint16_t port)
|
||||
{
|
||||
sockaddr_in srcaddr = {};
|
||||
memset(&srcaddr, 0, sizeof(srcaddr));
|
||||
srcaddr.sin_family = AF_INET;
|
||||
srcaddr.sin_addr.s_addr = addr;
|
||||
srcaddr.sin_port = htons(port);
|
||||
return bind(sHost, reinterpret_cast<sockaddr*>(&srcaddr), sizeof(srcaddr));
|
||||
}
|
||||
|
||||
int udp_broadcast(SOCKET sHost, uint16_t port, const std::string &data)
|
||||
{
|
||||
struct sockaddr_in addr = {};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||
addr.sin_port = htons(port);
|
||||
return sendto(sHost, data.data(), data.size(), 0, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
|
||||
}
|
||||
|
||||
int udp_send(SOCKET sHost, const std::string &dst_host, uint16_t dst_port, const std::string &data)
|
||||
{
|
||||
struct sockaddr_in addr = {};
|
||||
addr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, dst_host.data(), (struct in_addr *)&addr.sin_addr.s_addr);
|
||||
addr.sin_port = htons(dst_port);
|
||||
return sendto(sHost, data.data(), data.size(), 0, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
|
||||
}
|
||||
|
||||
void UDPLEDBroadcast(SOCKET sHost, const char* memory)
|
||||
{
|
||||
static std::string previous_status;
|
||||
static int skip_count = 0;
|
||||
static std::string head = "\x63LED";
|
||||
while(!EXIT_FLAG)
|
||||
{
|
||||
if(!CONNECTED) {
|
||||
Sleep(50);
|
||||
continue;
|
||||
}
|
||||
std::string current_status;
|
||||
current_status.assign(reinterpret_cast<const char*>(memory + 6 + 32), 32 * 3);
|
||||
bool same = true;
|
||||
if(!previous_status.empty())
|
||||
{
|
||||
for(int i = 0; i < 32 * 3; i++)
|
||||
{
|
||||
if(previous_status[i] != current_status[i])
|
||||
{
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
same = false;
|
||||
previous_status = current_status;
|
||||
if(!same)
|
||||
{
|
||||
current_status.insert(0, head);
|
||||
//if(udp_broadcast(sHost, server_port, current_status) < 0)
|
||||
if(udp_send(sHost, remote_address, remote_port, current_status) < 0)
|
||||
{
|
||||
//std::cerr<<"cannot send broadcast: error " + std::to_string(GetLastError()) + "\n";
|
||||
fprintf(stderr, "cannot send packet: error %lu\n", GetLastError());
|
||||
}
|
||||
skip_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(++skip_count > 50)
|
||||
{
|
||||
current_status.insert(0, head);
|
||||
//if(udp_broadcast(sHost, server_port, current_status) < 0)
|
||||
if(udp_send(sHost, remote_address, remote_port, current_status) < 0)
|
||||
{
|
||||
//std::cerr<<"cannot send broadcast: error " + std::to_string(GetLastError()) + "\n";
|
||||
fprintf(stderr, "cannot send packet: error %lu\n", GetLastError());
|
||||
}
|
||||
skip_count = 0;
|
||||
}
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
void TCPLEDBroadcast(SOCKET sHost, const char* memory)
|
||||
{
|
||||
static std::string previous_status;
|
||||
static int skip_count = 0;
|
||||
static std::string head = "\x63LED";
|
||||
while(!EXIT_FLAG)
|
||||
{
|
||||
if(!CONNECTED) {
|
||||
Sleep(50);
|
||||
continue;
|
||||
}
|
||||
std::string current_status;
|
||||
current_status.assign(reinterpret_cast<const char*>(memory + 6 + 32), 32 * 3);
|
||||
bool same = true;
|
||||
if(!previous_status.empty())
|
||||
{
|
||||
for(int i = 0; i < 32 * 3; i++)
|
||||
{
|
||||
if(previous_status[i] != current_status[i])
|
||||
{
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
same = false;
|
||||
previous_status = current_status;
|
||||
if(!same)
|
||||
{
|
||||
current_status.insert(0, head);
|
||||
if(send(sHost, current_status.data(), current_status.size(), 0) < 0)
|
||||
{
|
||||
fprintf(stderr, "cannot send packet: error %lu\n", GetLastError());
|
||||
if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Device disconnected!");
|
||||
CONNECTED = false;
|
||||
EXIT_FLAG = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(++skip_count > 50)
|
||||
{
|
||||
current_status.insert(0, head);
|
||||
if(udp_send(sHost, remote_address, remote_port, current_status) < 0)
|
||||
{
|
||||
fprintf(stderr, "cannot send packet: error %lu\n", GetLastError());
|
||||
if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Device disconnected!\n");
|
||||
CONNECTED = false;
|
||||
EXIT_FLAG = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
skip_count = 0;
|
||||
}
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
FUNCTION_COIN = 1,
|
||||
FUNCTION_CARD
|
||||
};
|
||||
|
||||
void InputReceive(SOCKET sHost, char *memory)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
while(!EXIT_FLAG)
|
||||
{
|
||||
int recv_len;
|
||||
if((recv_len = recvfrom(sHost, buffer, BUFSIZ - 1, 0, NULL, NULL)) == -1)
|
||||
continue;
|
||||
int real_len = buffer[0];
|
||||
if(real_len > recv_len)
|
||||
continue;
|
||||
if(real_len >= 3 + 6 + 32 && buffer[1] == 'I' && buffer[2] == 'N' && buffer[3] == 'P')
|
||||
{
|
||||
memcpy(memory, buffer + 4, 6 + 32);
|
||||
if(real_len > 3 + 6 + 32)
|
||||
{
|
||||
memcpy(memory + 6 + 32 + 96, buffer + 4 + 6 + 32, real_len - (3 + 6 + 32));
|
||||
}
|
||||
}
|
||||
if(real_len >= 4 && buffer[1] == 'F' && buffer[2] == 'N' && buffer[3] == 'C')
|
||||
{
|
||||
switch(buffer[4])
|
||||
{
|
||||
case FUNCTION_COIN:
|
||||
*(memory + 6 + 32 + 96 + 2) = 1;
|
||||
break;
|
||||
case FUNCTION_CARD:
|
||||
*(memory + 6 + 32 + 96 + 3) = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(real_len >= 23 && buffer[1] == 'C' && buffer[2] == 'O' && buffer[3] == 'N')
|
||||
{
|
||||
remote_address.assign(buffer + 4, 15);
|
||||
auto epos = remote_address.find_last_not_of('\0');
|
||||
if(epos == std::string::npos)
|
||||
continue;
|
||||
remote_address.erase(epos + 1);
|
||||
std::string port;
|
||||
port.assign(buffer + 4 + 15, 5);
|
||||
remote_port = std::stoi(port);
|
||||
//std::cout << "Device " << remote_address << ":" << remote_port << " connected." <<std::endl;
|
||||
printf("Device %s:%d connected.\n", remote_address.data(), remote_port);
|
||||
CONNECTED = true;
|
||||
}
|
||||
if(real_len >= 3 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S')
|
||||
{
|
||||
CONNECTED = false;
|
||||
if(tcp_mode)
|
||||
{
|
||||
EXIT_FLAG = true;
|
||||
printf("Device disconnected!\n");
|
||||
break;
|
||||
}
|
||||
if(!remote_address.empty())
|
||||
{
|
||||
printf("Device %s:%d disconnected.\n", remote_address.data(), remote_port);
|
||||
//std::cout << "Device " << remote_address << ":" << remote_port << " disconnected." << std::endl;
|
||||
remote_address.clear();
|
||||
}
|
||||
}
|
||||
if(real_len >= 11 && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N')
|
||||
{
|
||||
if(!CONNECTED)
|
||||
continue;
|
||||
std::string response;
|
||||
response.assign(buffer, 12);
|
||||
response.replace(2, 1, "O");
|
||||
udp_send(sHost, remote_address, remote_port, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printInfo()
|
||||
{
|
||||
printf("=================================================\n");
|
||||
printf("= Brokenithm-Evolved-Android: =\n");
|
||||
printf("= Brokenithm with full IO over network =\n");
|
||||
printf("= v0.1 by XTindy =\n");
|
||||
printf("= Original: esterTion =\n");
|
||||
printf("=================================================\n\n");
|
||||
}
|
||||
|
||||
void checkArgs(int argc, char* argv[])
|
||||
{
|
||||
int opt;
|
||||
while((opt = getopt(argc, argv, "p:T")) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'p':
|
||||
server_port = atoi(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
tcp_mode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
checkArgs(argc, argv);
|
||||
SetConsoleTitle("Brokenithm-Evolved-Android Server");
|
||||
printInfo();
|
||||
|
||||
WSAData wsaData;
|
||||
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
{
|
||||
//std::cerr << "WSA startup failed!\n";
|
||||
fprintf(stderr, "WSA startup failed!\n");
|
||||
return -1;
|
||||
}
|
||||
const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER";
|
||||
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, memFileName);
|
||||
if(hMapFile == NULL)
|
||||
{
|
||||
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 1024, memFileName);
|
||||
if(hMapFile == NULL)
|
||||
{
|
||||
//std::cerr << "CreateFileMapping failed! Error " + std::to_string(GetLastError());
|
||||
fprintf(stderr, "CreateFileMapping failed! error: %lu\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
defer(CloseHandle(hMapFile))
|
||||
char *memory = reinterpret_cast<char*>(MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL));
|
||||
if(memory == nullptr)
|
||||
{
|
||||
//std::cerr << "Cannot get view of memory map! Error " + std::to_string(GetLastError());
|
||||
fprintf(stderr, "Cannot get view of memory map! error: %lu\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
if(!tcp_mode)
|
||||
{
|
||||
printf("Mode: UDP\n");
|
||||
SOCKET sHost = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
defer(closesocket(sHost))
|
||||
setTimeout(sHost, 2000);
|
||||
int broadcastEnable = 1;
|
||||
setsockopt(sHost, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&broadcastEnable), sizeof(broadcastEnable));
|
||||
socket_bind(sHost, htonl(INADDR_ANY), server_port);
|
||||
//std::cout << "Waiting for device on port " << server_port << "..." << std::endl;
|
||||
printf("Waiting for device on port %d...\n", server_port);
|
||||
auto LEDThread = std::thread(UDPLEDBroadcast, sHost, memory);
|
||||
auto InputThread = std::thread(InputReceive, sHost, memory);
|
||||
while(_getwch() != L'q');
|
||||
//std::cout << "Exiting gracefully..." << std::endl;
|
||||
printf("Exiting gracefully...\n");
|
||||
EXIT_FLAG = true;
|
||||
LEDThread.join();
|
||||
InputThread.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Mode: TCP\n");
|
||||
SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
defer(closesocket(sHost));
|
||||
setTimeout(sHost, 50);
|
||||
socket_bind(sHost, htonl(INADDR_ANY), server_port);
|
||||
listen(sHost, 10);
|
||||
while(true)
|
||||
{
|
||||
printf("Waiting for device on port %d...\n", server_port);
|
||||
struct sockaddr_in user_socket = {};
|
||||
socklen_t sock_size = sizeof(struct sockaddr_in);
|
||||
SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size);
|
||||
defer(closesocket(acc_socket));
|
||||
char buffer[20] = {};
|
||||
const char* user_address = inet_ntop(AF_INET, &user_socket.sin_addr, buffer, 20);
|
||||
if(user_address != NULL)
|
||||
{
|
||||
printf("Device %s:%d connected.\n", user_address, user_socket.sin_port);
|
||||
}
|
||||
CONNECTED = true;
|
||||
EXIT_FLAG = false;
|
||||
auto LEDThread = std::thread(TCPLEDBroadcast, acc_socket, memory);
|
||||
auto InputThread = std::thread(InputReceive, acc_socket, memory);
|
||||
while(_getwch() != L'q');
|
||||
//std::cout << "Exiting gracefully..." << std::endl;
|
||||
printf("Exiting gracefully...\n");
|
||||
EXIT_FLAG = true;
|
||||
CONNECTED = false;
|
||||
LEDThread.join();
|
||||
InputThread.join();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef SOCKET_H_INCLUDED
|
||||
#define SOCKET_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0501
|
||||
#endif // WINVER
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
//translate windows functions to linux functions
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define closesocket close
|
||||
#define SOCKADDR_IN sockaddr_in
|
||||
#define ZeroMemory(d,l) memset((d), 0, (l))
|
||||
#define ioctlsocket ioctl
|
||||
#ifndef SA_INTERRUPT
|
||||
#define SA_INTERRUPT 0 //ignore this setting
|
||||
#endif
|
||||
#define SD_BOTH SHUT_RDWR
|
||||
#ifndef __hpux
|
||||
#include <sys/select.h>
|
||||
#endif /* __hpux */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
typedef sockaddr *LPSOCKADDR;
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // SOCKET_H_INCLUDED
|
Loading…
Reference in New Issue