attempt at betterer wifi

* add preliminary sync mechanism
* fix gaps in wifi implementation
This commit is contained in:
Arisotura
2022-08-18 19:47:01 +02:00
parent b5073e6014
commit ab15d7402a
7 changed files with 864 additions and 127 deletions

View File

@ -55,6 +55,7 @@
#include "ROMManager.h"
#include "LAN_Socket.h"
#include "LAN_PCap.h"
#include "SPI.h"
#include <string>
#ifndef INVALID_SOCKET
@ -65,16 +66,17 @@
std::string EmuDirectory;
void emuStop();
extern u16 zanf;
namespace Platform
{
socket_t MPSocket;
sockaddr_t MPSendAddr;
u32 MPUniqueID;
socket_t MPSocket[2];
sockaddr_t MPSendAddr[2];
u8 PacketBuffer[2048];
#define NIFI_VER 1
#define NIFI_VER 2
void Init(int argc, char** argv)
@ -386,10 +388,38 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen
}
void _logpacket(bool tx, u8* data, int len)
{return;
char path[256];
sprintf(path, "framelog_%08X.log", MPUniqueID);
static FILE* f = nullptr;
if (!f) f = fopen(path, "a");
/*fprintf(f, "---- %s PACKET LEN=%d ----\n", tx?"SENDING":"RECEIVING", len);
for (int y = 0; y < len; y+=16)
{
fprintf(f, "%04X: ", y);
int linelen = 16;
if ((y+linelen) > len) linelen = len-y;
for (int x = 0; x < linelen; x++)
{
fprintf(f, " %02X", data[y+x]);
}
fprintf(f, "\n");
}
fprintf(f, "-------------------------------------\n\n\n");*/
fprintf(f, "%s PACKET: LEN=%0.4d FC=%04X SN=%04X CL=%04X/%04X\n", tx?"TX":"RX",
len, *(u16*)&data[12], *(u16*)&data[12+22], *(u16*)&data[12+24], *(u16*)&data[12+26]);
fflush(f);
}
bool MP_Init()
{
int opt_true = 1;
int res;
int res0, res1;
#ifdef __WIN32__
WSADATA wsadata;
@ -399,26 +429,40 @@ bool MP_Init()
}
#endif // __WIN32__
MPSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (MPSocket < 0)
MPSocket[0] = socket(AF_INET, SOCK_DGRAM, 0);
if (MPSocket[0] < 0)
{
return false;
}
res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int));
if (res < 0)
MPSocket[1] = socket(AF_INET, SOCK_DGRAM, 0);
if (MPSocket[1] < 0)
{
closesocket(MPSocket);
MPSocket = INVALID_SOCKET;
closesocket(MPSocket[0]);
MPSocket[0] = INVALID_SOCKET;
return false;
}
res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int));
res1 = setsockopt(MPSocket[1], SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int));
if (res0 < 0 || res1 < 0)
{
closesocket(MPSocket[0]);
MPSocket[0] = INVALID_SOCKET;
closesocket(MPSocket[1]);
MPSocket[1] = INVALID_SOCKET;
return false;
}
#if defined(BSD) || defined(__APPLE__)
res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
if (res < 0)
res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
res0 = setsockopt(MPSocket[1], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
if (res0 < 0 || res1 < 0)
{
closesocket(MPSocket);
MPSocket = INVALID_SOCKET;
closesocket(MPSocket[0]);
MPSocket[0] = INVALID_SOCKET;
closesocket(MPSocket[1]);
MPSocket[1] = INVALID_SOCKET;
return false;
}
#endif
@ -427,33 +471,51 @@ bool MP_Init()
saddr.sa_family = AF_INET;
*(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK);
*(u16*)&saddr.sa_data[0] = htons(7064);
res = bind(MPSocket, &saddr, sizeof(sockaddr_t));
if (res < 0)
res0 = bind(MPSocket[0], &saddr, sizeof(sockaddr_t));
*(u16*)&saddr.sa_data[0] = htons(7065);
res1 = bind(MPSocket[1], &saddr, sizeof(sockaddr_t));
if (res0 < 0 || res1 < 0)
{
closesocket(MPSocket);
MPSocket = INVALID_SOCKET;
closesocket(MPSocket[0]);
MPSocket[0] = INVALID_SOCKET;
closesocket(MPSocket[1]);
MPSocket[1] = INVALID_SOCKET;
return false;
}
res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
if (res < 0)
res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
res1 = setsockopt(MPSocket[1], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
if (res0 < 0 || res1 < 0)
{
closesocket(MPSocket);
MPSocket = INVALID_SOCKET;
closesocket(MPSocket[0]);
MPSocket[0] = INVALID_SOCKET;
closesocket(MPSocket[1]);
MPSocket[1] = INVALID_SOCKET;
return false;
}
MPSendAddr.sa_family = AF_INET;
*(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST);
*(u16*)&MPSendAddr.sa_data[0] = htons(7064);
MPSendAddr[0].sa_family = AF_INET;
*(u32*)&MPSendAddr[0].sa_data[2] = htonl(INADDR_BROADCAST);
*(u16*)&MPSendAddr[0].sa_data[0] = htons(7064);
MPSendAddr[1].sa_family = AF_INET;
*(u32*)&MPSendAddr[1].sa_data[2] = htonl(INADDR_BROADCAST);
*(u16*)&MPSendAddr[1].sa_data[0] = htons(7065);
u8* mac = SPI_Firmware::GetWifiMAC();
MPUniqueID = *(u32*)&mac[0];
MPUniqueID ^= *(u32*)&mac[2];
printf("local MP unique ID: %08X\n", MPUniqueID);
return true;
}
void MP_DeInit()
{
if (MPSocket >= 0)
closesocket(MPSocket);
if (MPSocket[0] >= 0)
closesocket(MPSocket[0]);
if (MPSocket[1] >= 0)
closesocket(MPSocket[1]);
#ifdef __WIN32__
WSACleanup();
@ -462,10 +524,10 @@ void MP_DeInit()
int MP_SendPacket(u8* data, int len)
{
if (MPSocket < 0)
if (MPSocket[0] < 0)
return 0;
if (len > 2048-8)
if (len > 2048-12)
{
printf("MP_SendPacket: error: packet too long (%d)\n", len);
return 0;
@ -475,57 +537,216 @@ int MP_SendPacket(u8* data, int len)
PacketBuffer[4] = NIFI_VER;
PacketBuffer[5] = 0;
*(u16*)&PacketBuffer[6] = htons(len);
memcpy(&PacketBuffer[8], data, len);
*(u32*)&PacketBuffer[8] = MPUniqueID;
memcpy(&PacketBuffer[12], data, len);
int slen = sendto(MPSocket, (const char*)PacketBuffer, len+8, 0, &MPSendAddr, sizeof(sockaddr_t));
if (slen < 8) return 0;
return slen - 8;
_logpacket(true, data, len);
int slen = sendto(MPSocket[0], (const char*)PacketBuffer, len+12, 0, &MPSendAddr[0], sizeof(sockaddr_t));
if (slen < 12) return 0;
return slen - 12;
}
int MP_RecvPacket(u8* data, bool block)
{
if (MPSocket < 0)
if (MPSocket[0] < 0)
return 0;
fd_set fd;
struct timeval tv;
FD_ZERO(&fd);
FD_SET(MPSocket, &fd);
tv.tv_sec = 0;
tv.tv_usec = block ? 5000 : 0;
if (!select(MPSocket+1, &fd, 0, 0, &tv))
for (;;)
{
FD_ZERO(&fd);
FD_SET(MPSocket[0], &fd);
tv.tv_sec = 0;
//tv.tv_usec = block ? 5000 : 0;
tv.tv_usec = block ? 500*1000 : 0;
if (!select(MPSocket[0]+1, &fd, 0, 0, &tv))
{
return 0;
}
sockaddr_t fromAddr;
socklen_t fromLen = sizeof(sockaddr_t);
int rlen = recvfrom(MPSocket[0], (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen);
if (rlen < 12+24)
{
continue;
}
rlen -= 12;
if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E)
{
continue;
}
if (PacketBuffer[4] != NIFI_VER || PacketBuffer[5] != 0)
{
continue;
}
if (ntohs(*(u16*)&PacketBuffer[6]) != rlen)
{
continue;
}
if (*(u32*)&PacketBuffer[8] == MPUniqueID)
{
continue;
}
zanf = *(u16*)&PacketBuffer[12+6];
_logpacket(false, &PacketBuffer[12], rlen);
memcpy(data, &PacketBuffer[12], rlen);
return rlen;
}
}
bool MP_SendSync(u16 clientmask, u16 type, u64 val)
{
u8 syncbuf[32];
if (MPSocket[1] < 0)
return false;
int len = 16;
*(u32*)&syncbuf[0] = htonl(0x4946494E); // NIFI
syncbuf[4] = NIFI_VER;
syncbuf[5] = 1;
*(u16*)&syncbuf[6] = htons(len);
*(u16*)&syncbuf[8] = htons(type);
*(u16*)&syncbuf[10] = htons(clientmask);
*(u32*)&syncbuf[12] = MPUniqueID;
*(u32*)&syncbuf[16] = htonl((u32)val);
*(u32*)&syncbuf[20] = htonl((u32)(val>>32));
int slen = sendto(MPSocket[1], (const char*)syncbuf, len+8, 0, &MPSendAddr[1], sizeof(sockaddr_t));
return slen == len+8;
}
bool MP_WaitSync(u16 clientmask, u16* type, u64* val)
{
u8 syncbuf[32];
if (MPSocket[1] < 0)
return false;
fd_set fd;
struct timeval tv;
for (;;)
{
FD_ZERO(&fd);
FD_SET(MPSocket[1], &fd);
tv.tv_sec = 0;
tv.tv_usec = 500*1000;
if (!select(MPSocket[1]+1, &fd, 0, 0, &tv))
{printf("sync fail\n");
return false;
}
sockaddr_t fromAddr;
socklen_t fromLen = sizeof(sockaddr_t);
int rlen = recvfrom(MPSocket[1], (char*)syncbuf, 32, 0, &fromAddr, &fromLen);
if (rlen != 8+16)
continue;
rlen -= 8;
if (ntohl(*(u32*)&syncbuf[0]) != 0x4946494E)
continue;
if (syncbuf[4] != NIFI_VER || syncbuf[5] != 1)
continue;
if (ntohs(*(u16*)&syncbuf[6]) != rlen)
continue;
if (*(u32*)&syncbuf[12] == MPUniqueID)
continue;
u16 clientval = ntohs(*(u16*)&syncbuf[10]);
if (!(clientmask & clientval))
continue;
// check the sync val, it should be ahead of the current sync val
u64 syncval = ntohl(*(u32*)&syncbuf[16]) | (((u64)ntohl(*(u32*)&syncbuf[20])) << 32);
//if (syncval <= curval)
// continue;
if (type) *type = ntohs(*(u16*)&syncbuf[8]);
if (val) *val = syncval;
return true;
}
}
u16 MP_WaitMultipleSyncs(u16 type, u16 clientmask, u64 curval)
{
u8 syncbuf[32];
if (!clientmask)
return 0;
if (MPSocket[1] < 0)
return 0;
fd_set fd;
struct timeval tv;
for (;;)
{
FD_ZERO(&fd);
FD_SET(MPSocket[1], &fd);
tv.tv_sec = 0;
tv.tv_usec = 500*1000;
if (!select(MPSocket[1]+1, &fd, 0, 0, &tv))
{printf("[sync3] nope :(\n");
return clientmask;
}
sockaddr_t fromAddr;
socklen_t fromLen = sizeof(sockaddr_t);
int rlen = recvfrom(MPSocket[1], (char*)syncbuf, 32, 0, &fromAddr, &fromLen);
if (rlen != 8+16)
continue;
rlen -= 8;
if (ntohl(*(u32*)&syncbuf[0]) != 0x4946494E)
continue;
if (syncbuf[4] != NIFI_VER || syncbuf[5] != 1)
continue;
//printf("[sync3] atleast header is good\n");
if (ntohs(*(u16*)&syncbuf[6]) != rlen)
continue;
if (*(u32*)&syncbuf[12] == MPUniqueID)
continue;
if (ntohs(*(u16*)&syncbuf[8]) != type)
continue;
u16 clientval = ntohs(*(u16*)&syncbuf[10]);
//printf("[sync3] good rlen/type %04X %04X, clientmask=%04X \n", ntohs(*(u16*)&syncbuf[6]), ntohs(*(u16*)&syncbuf[8]), clientval);
if (!(clientmask & clientval))
continue;
// check the sync val, it should be ahead of the current sync val
u64 syncval = ntohl(*(u32*)&syncbuf[12]) | (((u64)ntohl(*(u32*)&syncbuf[16])) << 32);
//if (syncval <= curval)
// continue;
//printf("[sync3] good\n");
clientmask &= ~clientval;
//if (!clientmask)
return 0;
}
sockaddr_t fromAddr;
socklen_t fromLen = sizeof(sockaddr_t);
int rlen = recvfrom(MPSocket, (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen);
if (rlen < 8+24)
{
return 0;
}
rlen -= 8;
if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E)
{
return 0;
}
if (PacketBuffer[4] != NIFI_VER)
{
return 0;
}
if (ntohs(*(u16*)&PacketBuffer[6]) != rlen)
{
return 0;
}
memcpy(data, &PacketBuffer[8], rlen);
return rlen;
return clientmask;
}

View File

@ -25,6 +25,7 @@
#include <string>
#include <algorithm>
#include <QProcess>
#include <QApplication>
#include <QMessageBox>
#include <QMenuBar>
@ -1475,6 +1476,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actTitleManager = menu->addAction("Manage DSi titles");
connect(actTitleManager, &QAction::triggered, this, &MainWindow::onOpenTitleManager);
// TEST!!
menu->addSeparator();
actTest = menu->addAction("Fart");
connect(actTest, &QAction::triggered, this, &MainWindow::onTest);
}
{
QMenu* menu = menubar->addMenu("Config");
@ -1828,7 +1834,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
if (event->isAutoRepeat()) return;
// TODO!! REMOVE ME IN RELEASE BUILDS!!
//if (event->key() == Qt::Key_F11) NDS::debug(0);
if (event->key() == Qt::Key_F11) NDS::debug(0);
Input::KeyPress(event);
}
@ -2602,6 +2608,17 @@ void MainWindow::onOpenTitleManager()
TitleManagerDialog* dlg = TitleManagerDialog::openDlg(this);
}
void MainWindow::onTest()
{
//QProcess::startDetached(QApplication::applicationFilePath());
QProcess ass;
ass.setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args)
{
args->flags |= CREATE_NEW_CONSOLE;
});
ass.startDetached(QApplication::applicationFilePath());
}
void MainWindow::onOpenEmuSettings()
{
emuThread->emuPause();
@ -3180,12 +3197,13 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho
if (argv_w) LocalFree(argv_w);
/*if (AttachConsole(ATTACH_PARENT_PROCESS))
//if (AttachConsole(ATTACH_PARENT_PROCESS))
if (AllocConsole())
{
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
printf("\n");
}*/
}
int ret = main(argc, argv);

View File

@ -255,6 +255,7 @@ private slots:
void onROMInfo();
void onRAMInfo();
void onOpenTitleManager();
void onTest();
void onOpenEmuSettings();
void onEmuSettingsDialogFinished(int res);
@ -344,6 +345,7 @@ public:
QAction* actROMInfo;
QAction* actRAMInfo;
QAction* actTitleManager;
QAction* actTest;
QAction* actEmuSettings;
QAction* actPowerManagement;