From 7be2b0da6e89ddf61b78b3fa0b9ff952d52594c4 Mon Sep 17 00:00:00 2001 From: luigi__ Date: Fri, 24 Sep 2010 22:34:20 +0000 Subject: [PATCH] Wifi: for the Adhoc interface, generate a MAC address from the computer's IP and the process ID as to prevent MAC collisions in any case. --- desmume/src/driver.h | 2 ++ desmume/src/firmware.cpp | 6 ++++++ desmume/src/firmware.h | 1 + desmume/src/wifi.cpp | 18 ++++++++++++++---- desmume/src/windows/main.cpp | 29 +++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/desmume/src/driver.h b/desmume/src/driver.h index 073cedbdb..3e1b7d08f 100644 --- a/desmume/src/driver.h +++ b/desmume/src/driver.h @@ -49,6 +49,8 @@ public: virtual bool WIFI_SocketsAvailable() { return true; } virtual bool WIFI_PCapAvailable() { return false; } + virtual void WIFI_GetUniqueMAC(u8* mac) {} + virtual bool WIFI_WFCWarning() { return false; } virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return -1; } diff --git a/desmume/src/firmware.cpp b/desmume/src/firmware.cpp index 9456bcf4d..8d50dd35e 100644 --- a/desmume/src/firmware.cpp +++ b/desmume/src/firmware.cpp @@ -869,3 +869,9 @@ void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config) { fw_config->touch_cal[1].screen_x = 0xe0 + 1; fw_config->touch_cal[1].screen_y = 0x80 + 1; } + +void NDS_PatchFirmwareMAC() +{ + memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac)); + (*(u16*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138); +} diff --git a/desmume/src/firmware.h b/desmume/src/firmware.h index 2db38fe3e..2a4888544 100644 --- a/desmume/src/firmware.h +++ b/desmume/src/firmware.h @@ -80,6 +80,7 @@ public: int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data); int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings); void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config); +void NDS_PatchFirmwareMAC(); #endif diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index 07eebd479..79027a8ad 100644 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -1631,10 +1631,9 @@ typedef struct _Adhoc_FrameHeader bool Adhoc_Init() { + BOOL opt_true = TRUE; int res; - Adhoc.usecCounter = 0; - if (!driver->WIFI_SocketsAvailable()) { WIFI_LOG(1, "Ad-hoc: failed to initialize sockets.\n"); @@ -1650,6 +1649,10 @@ bool Adhoc_Init() return false; } + // Enable the socket to be bound to an address/port that is already in use + // This enables us to communicate with another DeSmuME instance running on the same computer. + res = setsockopt(wifi_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(BOOL)); + // Bind the socket to any address on port 7000 sockaddr_t saddr; saddr.sa_family = AF_INET; @@ -1665,8 +1668,7 @@ bool Adhoc_Init() // Enable broadcast mode // Not doing so results in failure when sendto'ing to broadcast address - BOOL opt = TRUE; - res = setsockopt(wifi_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(BOOL)); + res = setsockopt(wifi_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(BOOL)); if (res < 0) { WIFI_LOG(1, "Ad-hoc: failed to enable broadcast mode.\n"); @@ -1679,6 +1681,8 @@ bool Adhoc_Init() *(u32*)&sendAddr.sa_data[2] = htonl(INADDR_BROADCAST); *(u16*)&sendAddr.sa_data[0] = htons(BASEPORT); + Adhoc_Reset(); + WIFI_LOG(1, "Ad-hoc: initialization successful.\n"); return true; @@ -1693,6 +1697,12 @@ void Adhoc_DeInit() void Adhoc_Reset() { Adhoc.usecCounter = 0; + + driver->WIFI_GetUniqueMAC(FW_Mac); + NDS_PatchFirmwareMAC(); + + printf("WIFI: ADHOC: MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + FW_Mac[0], FW_Mac[1], FW_Mac[2], FW_Mac[3], FW_Mac[4], FW_Mac[5]); } void Adhoc_SendPacket(u8* packet, u32 len) diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index b23ccdca2..972f83211 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -2256,6 +2256,35 @@ class WinDriver : public BaseDriver virtual bool WIFI_SocketsAvailable() { return bSocketsAvailable; } virtual bool WIFI_PCapAvailable() { return bWinPCapAvailable; } + virtual void WIFI_GetUniqueMAC(u8* mac) + { + if (mac == NULL) return; + + char hostname[256]; + if (gethostname(hostname, 256) != 0) + strncpy(hostname, "127.0.0.1", 256); + + hostent* he = gethostbyname(hostname); + unsigned long ipaddr; + if (he == NULL) + ipaddr = 0x0100007F; // 127.0.0.1 + else + ipaddr = *(unsigned long*)he->h_addr_list[0]; + + unsigned long pid = GetCurrentProcessId(); + + unsigned long hash = pid; + while ((hash & 0xFF000000) == 0) + hash <<= 1; + hash >>= 1; + hash += ipaddr >> 8; + hash &= 0x00FFFFFF; + + mac[3] = hash >> 16; + mac[4] = (hash >> 8) & 0xFF; + mac[5] = hash & 0xFF; + } + virtual bool WIFI_WFCWarning() { return MessageBox(NULL, "You are trying to connect to the Nintendo WFC servers.\n"