aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/qt_sdl
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2020-07-27 16:01:55 +0200
committerGitHub <noreply@github.com>2020-07-27 16:01:55 +0200
commitdff14ca80ada883870131c7ff17d85866254ccc0 (patch)
treec15926879ed78d68d313c75e4cb7d764cb4c1fea /src/frontend/qt_sdl
parent17ce4d2a73770ecd8c5f0ff036636b5453cb86c9 (diff)
parent6a682a8ef0d1cc3aa35eaa70c4f7a7d106b25b06 (diff)
Merge pull request #682 from nadiaholmquist/slirp-merge
Merge slirp branch into master
Diffstat (limited to 'src/frontend/qt_sdl')
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt11
-rw-r--r--src/frontend/qt_sdl/LAN_Socket.cpp1058
-rw-r--r--src/frontend/qt_sdl/main.cpp6
3 files changed, 243 insertions, 832 deletions
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index ea7849f..05c42d1 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -46,7 +46,9 @@ set(CMAKE_AUTORCC ON)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
+find_package(Iconv REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
+pkg_check_modules(SLIRP REQUIRED slirp)
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release))
add_executable(melonDS WIN32 ${SOURCES_QT_SDL})
@@ -57,15 +59,20 @@ endif()
target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS})
+target_include_directories(melonDS PRIVATE ${SLIRP_INCLUDE_DIRS})
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..")
target_link_libraries(melonDS core)
if (BUILD_STATIC)
- target_link_libraries(melonDS -static ${SDL2_LIBRARIES})
+ target_link_libraries(melonDS -static ${SDL2_STATIC_LIBRARIES} ${SLIRP_STATIC_LIBRARIES})
else()
- target_link_libraries(melonDS ${SDL2_LIBRARIES})
+ target_link_libraries(melonDS ${SDL2_LIBRARIES} ${SLIRP_LIBRARIES})
+endif()
+
+if (NOT Iconv_IS_BUILT_IN)
+ target_link_libraries(melonDS iconv)
endif()
if (UNIX)
diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp
index c6fbd4b..458c931 100644
--- a/src/frontend/qt_sdl/LAN_Socket.cpp
+++ b/src/frontend/qt_sdl/LAN_Socket.cpp
@@ -21,30 +21,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "../Wifi.h"
+#include "Wifi.h"
#include "LAN_Socket.h"
-#include "../Config.h"
+#include "Config.h"
+#include "FIFO.h"
+
+#include <slirp/libslirp.h>
#ifdef __WIN32__
- #include <winsock2.h>
#include <ws2tcpip.h>
- #define socket_t SOCKET
- #define sockaddr_t SOCKADDR
#else
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/select.h>
#include <sys/socket.h>
#include <netdb.h>
- #define socket_t int
- #define sockaddr_t struct sockaddr
- #define closesocket close
-#endif
-
-#ifndef INVALID_SOCKET
-#define INVALID_SOCKET (socket_t)-1
+ #include <poll.h>
+ #include <time.h>
#endif
@@ -57,85 +47,192 @@ const u32 kDNSIP = kSubnet | 0x02;
const u32 kClientIP = kSubnet | 0x10;
const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44};
-const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55};
-u8 PacketBuffer[2048];
-int PacketLen;
-volatile int RXNum;
+FIFO<u32>* RXBuffer = nullptr;
+
+u32 IPv4ID;
+
+Slirp* Ctx = nullptr;
+
+/*const int FDListMax = 64;
+struct pollfd FDList[FDListMax];
+int FDListSize;*/
+
+
+#ifdef __WIN32__
+
+#define poll WSAPoll
+
+// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
+
+struct timespec { long tv_sec; long tv_nsec; };
+#define CLOCK_MONOTONIC 1312
+
+int clock_gettime(int, struct timespec *spec)
+{
+ __int64 wintime;
+ GetSystemTimeAsFileTime((FILETIME*)&wintime);
+ wintime -=116444736000000000LL; //1jan1601 to 1jan1970
+ spec->tv_sec = wintime / 10000000LL; //seconds
+ spec->tv_nsec = wintime % 10000000LL * 100; //nano-seconds
+ return 0;
+}
+
+#endif // __WIN32__
+
+
+void RXEnqueue(const void* buf, int len)
+{
+ int alignedlen = (len + 3) & ~3;
+ int totallen = alignedlen + 4;
+
+ if (!RXBuffer->CanFit(totallen >> 2))
+ {
+ printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n");
+ return;
+ }
+
+ u32 header = (alignedlen & 0xFFFF) | (len << 16);
+ RXBuffer->Write(header);
+ for (int i = 0; i < alignedlen; i += 4)
+ RXBuffer->Write(((u32*)buf)[i>>2]);
+}
-u16 IPv4ID;
+ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque)
+{
+ if (len > 2048)
+ {
+ printf("slirp: packet too big (%d)\n", len);
+ return 0;
+ }
+ printf("slirp: response packet of %d bytes, type %04X\n", len, ntohs(((u16*)buf)[6]));
-// TODO: UDP sockets
-// * use FIFO list
-// * assign new socket when seeing new IP/port
+ RXEnqueue(buf, len);
+ return len;
+}
-typedef struct
+void SlirpCbGuestError(const char* msg, void* opaque)
{
- u8 DestIP[4];
- u16 SourcePort;
- u16 DestPort;
+ printf("SLIRP: error: %s\n", msg);
+}
- u32 SeqNum; // sequence number for incoming frames
- u32 AckNum;
+int64_t SlirpCbClockGetNS(void* opaque)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+}
- // 0: unused
- // 1: connected
- u8 Status;
+void* SlirpCbTimerNew(SlirpTimerCb cb, void* cb_opaque, void* opaque)
+{
+ return nullptr;
+}
- socket_t Backend;
+void SlirpCbTimerFree(void* timer, void* opaque)
+{
+}
-} TCPSocket;
+void SlirpCbTimerMod(void* timer, int64_t expire_time, void* opaque)
+{
+}
-typedef struct
+void SlirpCbRegisterPollFD(int fd, void* opaque)
{
- u8 DestIP[4];
- u16 SourcePort;
- u16 DestPort;
+ printf("Slirp: register poll FD %d\n", fd);
+
+ /*if (FDListSize >= FDListMax)
+ {
+ printf("!! SLIRP FD LIST FULL\n");
+ return;
+ }
+
+ for (int i = 0; i < FDListSize; i++)
+ {
+ if (FDList[i].fd == fd) return;
+ }
- socket_t Backend;
- struct sockaddr_in BackendAddr;
+ FDList[FDListSize].fd = fd;
+ FDListSize++;*/
+}
-} UDPSocket;
+void SlirpCbUnregisterPollFD(int fd, void* opaque)
+{
+ printf("Slirp: unregister poll FD %d\n", fd);
-TCPSocket TCPSocketList[16];
-UDPSocket UDPSocketList[4];
+ /*if (FDListSize < 1)
+ {
+ printf("!! SLIRP FD LIST EMPTY\n");
+ return;
+ }
-int UDPSocketID = 0;
+ for (int i = 0; i < FDListSize; i++)
+ {
+ if (FDList[i].fd == fd)
+ {
+ FDListSize--;
+ FDList[i] = FDList[FDListSize];
+ }
+ }*/
+}
+void SlirpCbNotify(void* opaque)
+{
+ printf("Slirp: notify???\n");
+}
+
+SlirpCb cb =
+{
+ .send_packet = SlirpCbSendPacket,
+ .guest_error = SlirpCbGuestError,
+ .clock_get_ns = SlirpCbClockGetNS,
+ .timer_new = SlirpCbTimerNew,
+ .timer_free = SlirpCbTimerFree,
+ .timer_mod = SlirpCbTimerMod,
+ .register_poll_fd = SlirpCbRegisterPollFD,
+ .unregister_poll_fd = SlirpCbUnregisterPollFD,
+ .notify = SlirpCbNotify
+};
bool Init()
{
- // TODO: how to deal with cases where an adapter is unplugged or changes config??
- //if (PCapLib) return true;
+ IPv4ID = 0;
+
+ //FDListSize = 0;
+ //memset(FDList, 0, sizeof(FDList));
- //Lib = NULL;
- PacketLen = 0;
- RXNum = 0;
+ RXBuffer = new FIFO<u32>(0x8000 >> 2);
- IPv4ID = 1;
+ SlirpConfig cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.version = 1;
- memset(TCPSocketList, 0, sizeof(TCPSocketList));
- memset(UDPSocketList, 0, sizeof(UDPSocketList));
+ cfg.in_enabled = true;
+ *(u32*)&cfg.vnetwork = htonl(kSubnet);
+ *(u32*)&cfg.vnetmask = htonl(0xFFFFFF00);
+ *(u32*)&cfg.vhost = htonl(kServerIP);
+ cfg.vhostname = "melonServer";
+ *(u32*)&cfg.vdhcp_start = htonl(kClientIP);
+ *(u32*)&cfg.vnameserver = htonl(kDNSIP);
- UDPSocketID = 0;
+ Ctx = slirp_new(&cfg, &cb, nullptr);
return true;
}
void DeInit()
{
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
+ if (Ctx)
{
- TCPSocket* sock = &TCPSocketList[i];
- if (sock->Backend) closesocket(sock->Backend);
+ slirp_cleanup(Ctx);
+ Ctx = nullptr;
}
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (RXBuffer)
{
- UDPSocket* sock = &UDPSocketList[i];
- if (sock->Backend) closesocket(sock->Backend);
+ delete RXBuffer;
+ RXBuffer = nullptr;
}
}
@@ -179,165 +276,6 @@ void FinishUDPFrame(u8* data, int len)
*(u16*)&udpheader[6] = htons(tmp);
}
-void FinishTCPFrame(u8* data, int len)
-{
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- // lengths
- *(u16*)&ipheader[2] = htons(len - 0xE);
-
- // IP checksum
- u32 tmp = 0;
-
- for (int i = 0; i < 20; i += 2)
- tmp += ntohs(*(u16*)&ipheader[i]);
- while (tmp >> 16)
- tmp = (tmp & 0xFFFF) + (tmp >> 16);
- tmp ^= 0xFFFF;
- *(u16*)&ipheader[10] = htons(tmp);
-
- u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14;
-
- // TCP checksum
- tmp = 0;
- tmp += ntohs(*(u16*)&ipheader[12]);
- tmp += ntohs(*(u16*)&ipheader[14]);
- tmp += ntohs(*(u16*)&ipheader[16]);
- tmp += ntohs(*(u16*)&ipheader[18]);
- tmp += ntohs(0x0600);
- tmp += tcplen;
- for (u8* i = tcpheader; i < &tcpheader[tcplen-1]; i += 2)
- tmp += ntohs(*(u16*)i);
- if (tcplen & 1)
- tmp += ntohs((u_short)tcpheader[tcplen-1]);
- while (tmp >> 16)
- tmp = (tmp & 0xFFFF) + (tmp >> 16);
- tmp ^= 0xFFFF;
- *(u16*)&tcpheader[16] = htons(tmp);
-}
-
-
-void HandleDHCPFrame(u8* data, int len)
-{
- u8 type = 0xFF;
-
- u32 transid = *(u32*)&data[0x2E];
-
- u8* options = &data[0x11A];
- for (;;)
- {
- if (options >= &data[len]) break;
- u8 opt = *options++;
- if (opt == 255) break;
-
- u8 len = *options++;
- switch (opt)
- {
- case 53: // frame type
- type = options[0];
- break;
- }
-
- options += len;
- }
-
- if (type == 0xFF)
- {
- printf("DHCP: bad frame\n");
- return;
- }
-
- printf("DHCP: frame type %d, transid %08X\n", type, transid);
-
- if (type == 1 || // discover
- type == 3) // request
- {
- u8 resp[512];
- u8* out = &resp[0];
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x11; // protocol (UDP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = htonl(kServerIP); out += 4; // source IP
- if (type == 1)
- {
- *(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP
- }
- else if (type == 3)
- {
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
- }
-
- // UDP
- u8* udpheader = out;
- *(u16*)out = htons(67); out += 2; // source port
- *(u16*)out = htons(68); out += 2; // destination port
- *(u16*)out = 0; out += 2; // length
- *(u16*)out = 0; out += 2; // checksum
-
- // DHCP
- u8* body = out;
- *out++ = 0x02;
- *out++ = 0x01;
- *out++ = 0x06;
- *out++ = 0x00;
- *(u32*)out = transid; out += 4;
- *(u16*)out = 0; out += 2; // seconds elapsed
- *(u16*)out = 0; out += 2;
- *(u32*)out = htonl(0x00000000); out += 4; // client IP
- *(u32*)out = htonl(kClientIP); out += 4; // your IP
- *(u32*)out = htonl(kServerIP); out += 4; // server IP
- *(u32*)out = htonl(0x00000000); out += 4; // gateway IP
- memcpy(out, &data[6], 6); out += 6;
- memset(out, 0, 10); out += 10;
- memset(out, 0, 192); out += 192;
- *(u32*)out = 0x63538263; out += 4; // DHCP magic
-
- // DHCP options
- *out++ = 53; *out++ = 1;
- *out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack
- *out++ = 1; *out++ = 4;
- *(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask
- *out++ = 3; *out++ = 4;
- *(u32*)out = htonl(kServerIP); out += 4; // router
- *out++ = 51; *out++ = 4;
- *(u32*)out = htonl(442030); out += 4; // lease time
- *out++ = 54; *out++ = 4;
- *(u32*)out = htonl(kServerIP); out += 4; // DHCP server
- *out++ = 6; *out++ = 4;
- *(u32*)out = htonl(kDNSIP); out += 4; // DNS (hax)
-
- *out++ = 0xFF;
- memset(out, 0, 20); out += 20;
-
- u32 framelen = (u32)(out - &resp[0]);
- if (framelen & 1) { *out++ = 0; framelen++; }
- FinishUDPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
- }
-}
-
void HandleDNSFrame(u8* data, int len)
{
u8* ipheader = &data[0xE];
@@ -458,12 +396,13 @@ void HandleDNSFrame(u8* data, int len)
while (p)
{
struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr;
- /*printf(" -> %d.%d.%d.%d",
- addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2,
- addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4);*/
-
- //addr_res = addr->sin_addr.S_un.S_addr;
addr_res = *(u32*)&addr->sin_addr;
+
+ printf(" -> %d.%d.%d.%d",
+ addr_res & 0xFF, (addr_res >> 8) & 0xFF,
+ (addr_res >> 16) & 0xFF, addr_res >> 24);
+
+ break;
p = p->ai_next;
}
}
@@ -490,653 +429,116 @@ void HandleDNSFrame(u8* data, int len)
if (framelen & 1) { *out++ = 0; framelen++; }
FinishUDPFrame(resp, framelen);
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
+ RXEnqueue(resp, framelen);
}
-void UDP_BuildIncomingFrame(UDPSocket* sock, u8* data, int len)
-{
- u8 resp[2048];
- u8* out = &resp[0];
-
- if (len > 1536) return;
-
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x11; // protocol (UDP)
- *(u16*)out = 0; out += 2; // checksum
- memcpy(out, sock->DestIP, 4); out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // UDP
- u8* resp_tcpheader = out;
- *(u16*)out = htons(sock->DestPort); out += 2; // source port
- *(u16*)out = htons(sock->SourcePort); out += 2; // destination port
- *(u16*)out = htons(len+8); out += 2; // length of header+data
- *(u16*)out = 0; out += 2; // checksum
-
- memcpy(out, data, len); out += len;
-
- u32 framelen = (u32)(out - &resp[0]);
- FinishUDPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-}
-
-void HandleUDPFrame(u8* data, int len)
+int SendPacket(u8* data, int len)
{
- u8* ipheader = &data[0xE];
- u8* udpheader = &data[0x22];
-
- // debug
- /*for (int j = 0; j < len; j += 16)
- {
- int rem = len - j;
- if (rem > 16) rem = 16;
- for (int i = 0; i < rem; i++)
- {
- printf("%02X ", data[i+j]);
- }
- printf("\n");
- }*/
-
- u16 srcport = ntohs(*(u16*)&udpheader[0]);
- u16 dstport = ntohs(*(u16*)&udpheader[2]);
+ if (!Ctx) return 0;
- int sockid = -1;
- UDPSocket* sock;
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (len > 2048)
{
- sock = &UDPSocketList[i];
- if (sock->Backend != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- sockid = i;
- break;
- }
+ printf("LAN_SendPacket: error: packet too long (%d)\n", len);
+ return 0;
}
- if (sockid == -1)
- {
- sockid = UDPSocketID;
- sock = &UDPSocketList[sockid];
-
- UDPSocketID++;
- if (UDPSocketID >= (sizeof(UDPSocketList)/sizeof(UDPSocket)))
- UDPSocketID = 0;
+ u16 ethertype = ntohs(*(u16*)&data[0xC]);
- if (sock->Backend != 0)
+ if (ethertype == 0x800)
+ {
+ u8 protocol = data[0x17];
+ if (protocol == 0x11) // UDP
{
- printf("LANMAGIC: closing previous UDP socket #%d\n", sockid);
- closesocket(sock->Backend);
+ u16 dstport = ntohs(*(u16*)&data[0x24]);
+ if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS
+ {
+ HandleDNSFrame(data, len);
+ return len;
+ }
}
-
- sock->Backend = socket(AF_INET, SOCK_DGRAM, 0);
-
- memcpy(sock->DestIP, &ipheader[16], 4);
- sock->SourcePort = srcport;
- sock->DestPort = dstport;
-
- memset(&sock->BackendAddr, 0, sizeof(sock->BackendAddr));
- sock->BackendAddr.sin_family = AF_INET;
- sock->BackendAddr.sin_port = htons(dstport);
- memcpy(&sock->BackendAddr.sin_addr, &ipheader[16], 4);
- /*if (bind(sock->Backend, (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)) == -1)
- {
- printf("bind() shat itself :(\n");
- }*/
-
- printf("LANMAGIC: opening UDP socket #%d to %d.%d.%d.%d:%d, srcport %d\n",
- sockid,
- ipheader[16], ipheader[17], ipheader[18], ipheader[19],
- dstport, srcport);
}
- u16 udplen = ntohs(*(u16*)&udpheader[4]) - 8;
-
- printf("UDP: socket %d sending %d bytes\n", sockid, udplen);
- sendto(sock->Backend, (char*)&udpheader[8], udplen, 0,
- (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr));
-}
-
-void TCP_SYNACK(TCPSocket* sock, u8* data, int len)
-{
- u8 resp[128];
- u8* out = &resp[0];
-
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- u32 seqnum = htonl(*(u32*)&tcpheader[4]);
- seqnum++;
- sock->AckNum = seqnum;
-
- //printf("SYNACK SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum);
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = *(u32*)&ipheader[16]; out += 4; // source IP
- *(u32*)out = *(u32*)&ipheader[12]; out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = *(u16*)&tcpheader[2]; out += 2; // source port
- *(u16*)out = *(u16*)&tcpheader[0]; out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; sock->SeqNum++; // seq number
- *(u32*)out = htonl(seqnum); out += 4; // ack seq number
- *(u16*)out = htons(0x8012); out += 2; // flags (SYN+ACK)
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- // TCP options
- *out++ = 0x02; *out++ = 0x04; // max segment size
- *(u16*)out = htons(0x05B4); out += 2;
- *out++ = 0x01;
- *out++ = 0x01;
- *out++ = 0x04; *out++ = 0x02; // SACK permitted
- *out++ = 0x01;
- *out++ = 0x03; *out++ = 0x03; // window size
- *out++ = 0x08;
-
- u32 framelen = (u32)(out - &resp[0]);
- //if (framelen & 1) { *out++ = 0; framelen++; }
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-}
-
-void TCP_ACK(TCPSocket* sock, bool fin)
-{
- u8 resp[64];
- u8* out = &resp[0];
-
- u16 flags = 0x5010;
- if (fin) flags |= 0x0001;
-
- //printf("%sACK SEQ=%08X|%08X\n", fin?"FIN":" ", sock->SeqNum, sock->AckNum);
-
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = *(u32*)&sock->DestIP; out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = htonl(sock->DestPort); out += 2; // source port
- *(u16*)out = htonl(sock->SourcePort); out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number
- *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number
- *(u16*)out = htons(flags); out += 2; // flags
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- u32 framelen = (u32)(out - &resp[0]);
- //if (framelen & 1) { *out++ = 0; framelen++; }
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
+ slirp_input(Ctx, data, len);
+ return len;
}
-void TCP_BuildIncomingFrame(TCPSocket* sock, u8* data, int len)
-{
- u8 resp[2048];
- u8* out = &resp[0];
-
- if (len > 1536) return;
-//printf("INCOMING SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum);
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- memcpy(out, sock->DestIP, 4); out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = htons(sock->DestPort); out += 2; // source port
- *(u16*)out = htons(sock->SourcePort); out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number
- *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number
- *(u16*)out = htons(0x5018); out += 2; // flags (ACK, PSH)
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- memcpy(out, data, len); out += len;
-
- u32 framelen = (u32)(out - &resp[0]);
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-
- sock->SeqNum += len;
-}
+const int PollListMax = 64;
+struct pollfd PollList[PollListMax];
+int PollListSize;
-void HandleTCPFrame(u8* data, int len)
+int SlirpCbAddPoll(int fd, int events, void* opaque)
{
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- u16 srcport = ntohs(*(u16*)&tcpheader[0]);
- u16 dstport = ntohs(*(u16*)&tcpheader[2]);
- u16 flags = ntohs(*(u16*)&tcpheader[12]);
-
- u32 tcpheaderlen = 4 * (flags >> 12);
- u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14;
- u32 tcpdatalen = tcplen - tcpheaderlen;
-
- /*printf("tcpflags=%04X header=%d data=%d seq=%08X|%08X\n",
- flags, tcpheaderlen, tcpdatalen,
- ntohl(*(u32*)&tcpheader[4]),
- ntohl(*(u32*)&tcpheader[8]));*/
-
- if (flags & 0x002) // SYN
+ if (PollListSize >= PollListMax)
{
- int sockid = -1;
- TCPSocket* sock;
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- printf("LANMAGIC: duplicate TCP socket\n");
- sockid = i;
- break;
- }
- }
-
- if (sockid == -1)
- {
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status == 0)
- {
- sockid = i;
- break;
- }
- }
- }
-
- if (sockid == -1)
- {
- printf("LANMAGIC: !! TCP SOCKET LIST FULL\n");
- return;
- }
-
- printf("LANMAGIC: opening TCP socket #%d to %d.%d.%d.%d:%d, srcport %d\n",
- sockid,
- ipheader[16], ipheader[17], ipheader[18], ipheader[19],
- dstport, srcport);
-
- // keep track of it
- sock->Status = 1;
- memcpy(sock->DestIP, &ipheader[16], 4);
- sock->DestPort = dstport;
- sock->SourcePort = srcport;
- sock->SeqNum = 0x13370000;
- sock->AckNum = 0;
-
- // open backend socket
- if (!sock->Backend)
- {
- sock->Backend = socket(AF_INET, SOCK_STREAM, 0);
- }
-
- struct sockaddr_in conn_addr;
- memset(&conn_addr, 0, sizeof(conn_addr));
- conn_addr.sin_family = AF_INET;
- memcpy(&conn_addr.sin_addr, &ipheader[16], 4);
- conn_addr.sin_port = htons(dstport);
- if (connect(sock->Backend, (sockaddr*)&conn_addr, sizeof(conn_addr)) == -1)
- {
- printf("connect() shat itself :(\n");
- }
- else
- {
- // acknowledge it
- TCP_SYNACK(sock, data, len);
- }
+ printf("slirp: POLL LIST FULL\n");
+ return -1;
}
- else
- {
- int sockid = -1;
- TCPSocket* sock;
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- sockid = i;
- break;
- }
- }
- if (sockid == -1)
- {
- printf("LANMAGIC: bad TCP packet\n");
- return;
- }
+ int idx = PollListSize++;
- // TODO: check those
- u32 seqnum = ntohl(*(u32*)&tcpheader[4]);
- u32 acknum = ntohl(*(u32*)&tcpheader[8]);
- sock->SeqNum = acknum;
- sock->AckNum = seqnum + tcpdatalen;
+ //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events);
- // send data over the socket
- if (tcpdatalen > 0)
- {
- u8* tcpdata = &tcpheader[tcpheaderlen];
+ u16 evt = 0;
- printf("TCP: socket %d sending %d bytes (flags=%04X)\n", sockid, tcpdatalen, flags);
- send(sock->Backend, (char*)tcpdata, tcpdatalen, 0);
+ if (events & SLIRP_POLL_IN) evt |= POLLIN;
+ if (events & SLIRP_POLL_OUT) evt |= POLLWRNORM;
- // kind of a hack, there
- TCP_ACK(sock, false);
- }
+#ifndef __WIN32__
+ // CHECKME
+ if (events & SLIRP_POLL_PRI) evt |= POLLPRI;
+ if (events & SLIRP_POLL_ERR) evt |= POLLERR;
+ if (events & SLIRP_POLL_HUP) evt |= POLLHUP;
+#endif // !__WIN32__
- if (flags & 0x001) // FIN
- {
- // TODO: timeout etc
- printf("TCP: socket %d closing\n", sockid);
+ PollList[idx].fd = fd;
+ PollList[idx].events = evt;
- sock->Status = 0;
- closesocket(sock->Backend);
- sock->Backend = 0;
- }
- }
+ return idx;
}
-void HandleARPFrame(u8* data, int len)
+int SlirpCbGetREvents(int idx, void* opaque)
{
- u16 protocol = ntohs(*(u16*)&data[0x10]);
- if (protocol != 0x0800) return;
-
- u16 op = ntohs(*(u16*)&data[0x14]);
- u32 targetip = ntohl(*(u32*)&data[0x26]);
-
- // TODO: handle ARP to the client
- // this only handles ARP to the DHCP/router
-
- if (op == 1)
- {
- // opcode 1=req 2=reply
- // sender MAC
- // sender IP
- // target MAC
- // target IP
-
- const u8* targetmac;
- if (targetip == kServerIP) targetmac = kServerMAC;
- else if (targetip == kDNSIP) targetmac = kDNSMAC;
- else return;
-
- u8 resp[64];
- u8* out = &resp[0];
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0806); out += 2;
-
- // ARP
- *(u16*)out = htons(0x0001); out += 2; // hardware type
- *(u16*)out = htons(0x0800); out += 2; // protocol
- *out++ = 6; // MAC address size
- *out++ = 4; // IP address size
- *(u16*)out = htons(0x0002); out += 2; // opcode
- memcpy(out, targetmac, 6); out += 6;
- *(u32*)out = htonl(targetip); out += 4;
- memcpy(out, &data[0x16], 6+4); out += 6+4;
-
- u32 framelen = (u32)(out - &resp[0]);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
- }
- else
- {
- printf("wat??\n");
- }
-}
+ if (idx < 0 || idx >= PollListSize)
+ return 0;
-void HandlePacket(u8* data, int len)
-{
- u16 ethertype = ntohs(*(u16*)&data[0xC]);
+ //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents);
- if (ethertype == 0x0800) // IPv4
- {
- u8 protocol = data[0x17];
- if (protocol == 0x11) // UDP
- {
- u16 srcport = ntohs(*(u16*)&data[0x22]);
- u16 dstport = ntohs(*(u16*)&data[0x24]);
- if (srcport == 68 && dstport == 67) // DHCP
- {
- printf("LANMAGIC: DHCP packet\n");
- return HandleDHCPFrame(data, len);
- }
- else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS
- {
- printf("LANMAGIC: DNS packet\n");
- return HandleDNSFrame(data, len);
- }
+ u16 evt = PollList[idx].revents;
+ int ret = 0;
- printf("LANMAGIC: UDP packet %d->%d\n", srcport, dstport);
- return HandleUDPFrame(data, len);
- }
- else if (protocol == 0x06) // TCP
- {
- printf("LANMAGIC: TCP packet\n");
- return HandleTCPFrame(data, len);
- }
- else
- printf("LANMAGIC: unsupported IP protocol %02X\n", protocol);
- }
- else if (ethertype == 0x0806) // ARP
- {
- printf("LANMAGIC: ARP packet\n");
- return HandleARPFrame(data, len);
- }
- else
- printf("LANMAGIC: unsupported ethernet type %04X\n", ethertype);
-}
+ if (evt & POLLIN) ret |= SLIRP_POLL_IN;
+ if (evt & POLLWRNORM) ret |= SLIRP_POLL_OUT;
+ if (evt & POLLPRI) ret |= SLIRP_POLL_PRI;
+ if (evt & POLLERR) ret |= SLIRP_POLL_ERR;
+ if (evt & POLLHUP) ret |= SLIRP_POLL_HUP;
-int SendPacket(u8* data, int len)
-{
- if (len > 2048)
- {
- printf("LAN_SendPacket: error: packet too long (%d)\n", len);
- return 0;
- }
-
- HandlePacket(data, len);
- return len;
+ return ret;
}
int RecvPacket(u8* data)
{
+ if (!Ctx) return 0;
+
int ret = 0;
- if (RXNum > 0)
- {
- memcpy(data, PacketBuffer, PacketLen);
- ret = PacketLen;
- RXNum = 0;
- }
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
+ //if (PollListSize > 0)
{
- TCPSocket* sock = &TCPSocketList[i];
- if (sock->Status != 1) continue;
-
- fd_set fd;
- struct timeval tv;
-
- FD_ZERO(&fd);
- FD_SET(sock->Backend, &fd);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (!select(sock->Backend+1, &fd, 0, 0, &tv))
- {
- continue;
- }
-
- u8 recvbuf[1024];
- int recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0);
- if (recvlen < 1)
- {
- if (recvlen == 0)
- {
- // socket has closed from the other side
- printf("TCP: socket %d closed from other side\n", i);
- sock->Status = 2;
- TCP_ACK(sock, true);
- }
- continue;
- }
-
- printf("TCP: socket %d receiving %d bytes\n", i, recvlen);
- TCP_BuildIncomingFrame(sock, recvbuf, recvlen);
-
- // debug
- /*for (int j = 0; j < recvlen; j += 16)
- {
- int rem = recvlen - j;
- if (rem > 16) rem = 16;
- for (int k = 0; k < rem; k++)
- {
- printf("%02X ", recvbuf[k+j]);
- }
- printf("\n");
- }*/
-
- //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0);
- //if (recvlen == 0) printf("it closed immediately after\n");
+ u32 timeout = 0;
+ PollListSize = 0;
+ slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr);
+ int res = poll(PollList, PollListSize, timeout);
+ slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr);
}
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (!RXBuffer->IsEmpty())
{
- UDPSocket* sock = &UDPSocketList[i];
- if (sock->Backend == 0) continue;
-
- fd_set fd;
- struct timeval tv;
-
- FD_ZERO(&fd);
- FD_SET(sock->Backend, &fd);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (!select(sock->Backend+1, &fd, 0, 0, &tv))
- {
- continue;
- }
-
- u8 recvbuf[1024];
- sockaddr_t fromAddr;
- socklen_t fromLen = sizeof(sockaddr_t);
- int recvlen = recvfrom(sock->Backend, (char*)recvbuf, 1024, 0, &fromAddr, &fromLen);
- if (recvlen < 1) continue;
+ u32 header = RXBuffer->Read();
+ u32 len = header & 0xFFFF;
- if (fromAddr.sa_family != AF_INET) continue;
- struct sockaddr_in* fromAddrIn = (struct sockaddr_in*)&fromAddr;
- if (memcmp(&fromAddrIn->sin_addr, sock->DestIP, 4)) continue;
- if (ntohs(fromAddrIn->sin_port) != sock->DestPort) continue;
+ for (int i = 0; i < len; i += 4)
+ ((u32*)data)[i>>2] = RXBuffer->Read();
- printf("UDP: socket %d receiving %d bytes\n", i, recvlen);
- UDP_BuildIncomingFrame(sock, recvbuf, recvlen);
+ ret = header >> 16;
}
return ret;
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index de6887c..47b3490 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -1285,6 +1285,8 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
{
if (event->isAutoRepeat()) return;
+ if (event->key() == Qt::Key_F11) NDS::debug(0);
+
Input::KeyPress(event);
}
@@ -2083,12 +2085,12 @@ 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))
{
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
printf("\n");
- }
+ }*/
int ret = main(argc, argv);