WiFi: Significantly reduce the host-to-emulator latency of libpcap-sourced packets in Infrastructure mode by running RX packet receives on a separate thread, just like how socket-sourced packets in Ad-hoc mode do it.
- Also, Infrastructure mode can no longer "partially function." Now, it either works completely or not at all, just like how Ad-hoc mode does it.
This commit is contained in:
parent
71df3f4f28
commit
91526e6324
|
@ -506,6 +506,11 @@ public:
|
|||
|
||||
return _pcap_dispatch((pcap_t *)dev, num, (pcap_handler)callback, (u_char *)userdata);
|
||||
}
|
||||
|
||||
virtual void breakloop(void *dev)
|
||||
{
|
||||
_pcap_breakloop((pcap_t *)dev);
|
||||
}
|
||||
};
|
||||
|
||||
GPUEventHandlerWindows *WinGPUEvent = NULL;
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef void (__cdecl *T_pcap_close)(pcap_t* dev);
|
|||
typedef int (__cdecl *T_pcap_setnonblock)(pcap_t* dev, int nonblock, char* errbuf);
|
||||
typedef int (__cdecl *T_pcap_sendpacket)(pcap_t* dev, const u_char* data, int len);
|
||||
typedef int (__cdecl *T_pcap_dispatch)(pcap_t* dev, int num, pcap_handler callback, u_char* userdata);
|
||||
typedef int (__cdecl *T_pcap_breakloop)(pcap_t* dev);
|
||||
|
||||
T_pcap_findalldevs _pcap_findalldevs = NULL;
|
||||
T_pcap_freealldevs _pcap_freealldevs = NULL;
|
||||
|
@ -46,6 +47,7 @@ T_pcap_close _pcap_close = NULL;
|
|||
T_pcap_setnonblock _pcap_setnonblock = NULL;
|
||||
T_pcap_sendpacket _pcap_sendpacket = NULL;
|
||||
T_pcap_dispatch _pcap_dispatch = NULL;
|
||||
T_pcap_breakloop _pcap_breakloop = NULL;
|
||||
|
||||
|
||||
#define LOADSYMBOL(name) \
|
||||
|
@ -71,6 +73,7 @@ static void LoadWinPCap(bool &outResult)
|
|||
LOADSYMBOL(pcap_setnonblock);
|
||||
LOADSYMBOL(pcap_sendpacket);
|
||||
LOADSYMBOL(pcap_dispatch);
|
||||
LOADSYMBOL(pcap_breakloop);
|
||||
|
||||
result = true;
|
||||
outResult = result;
|
||||
|
|
|
@ -3090,24 +3090,9 @@ static const u8 SoftAP_DeauthFrame[] = {
|
|||
|
||||
static void SoftAP_RXPacketGet_Callback(u_char *userData, const pcap_pkthdr *pktHeader, const u_char *pktData)
|
||||
{
|
||||
WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io;
|
||||
const WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io;
|
||||
|
||||
if (userData == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the emulator header.
|
||||
DesmumeFrameHeader &emulatorHeader = (DesmumeFrameHeader &)userData[0];
|
||||
strncpy(emulatorHeader.frameID, DESMUME_EMULATOR_FRAME_ID, 8);
|
||||
emulatorHeader.version = DESMUME_EMULATOR_FRAME_CURRENT_VERSION;
|
||||
emulatorHeader.timeStamp = 0;
|
||||
emulatorHeader.emuPacketSize = 0;
|
||||
|
||||
emulatorHeader.packetAttributes.value = 0;
|
||||
emulatorHeader.packetAttributes.IsTXRate20 = 1;
|
||||
|
||||
if ( (pktData == NULL) || (pktHeader == NULL) )
|
||||
if ( (userData == NULL) || (pktData == NULL) || (pktHeader == NULL) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -3139,16 +3124,37 @@ static void SoftAP_RXPacketGet_Callback(u_char *userData, const pcap_pkthdr *pkt
|
|||
return;
|
||||
}
|
||||
|
||||
// Determine the NDS-compatible RX packet size and store in the emulator header.
|
||||
RXRawPacketData *rawPacket = (RXRawPacketData *)userData;
|
||||
u8 *targetPacket = &rawPacket->buffer[rawPacket->writeLocation];
|
||||
|
||||
// Generate the emulator header.
|
||||
DesmumeFrameHeader &emulatorHeader = (DesmumeFrameHeader &)targetPacket[0];
|
||||
strncpy(emulatorHeader.frameID, DESMUME_EMULATOR_FRAME_ID, 8);
|
||||
emulatorHeader.version = DESMUME_EMULATOR_FRAME_CURRENT_VERSION;
|
||||
emulatorHeader.timeStamp = 0;
|
||||
emulatorHeader.emuPacketSize = (pktHeader->len + (sizeof(WifiDataFrameHeaderDS2STA) + sizeof(WifiLLCSNAPHeader) - sizeof(EthernetFrameHeader)) + 3) & 0xFFFC;
|
||||
|
||||
emulatorHeader.packetAttributes.value = 0;
|
||||
emulatorHeader.packetAttributes.IsTXRate20 = 1;
|
||||
|
||||
WifiHandler::ConvertDataFrame8023To80211((u8 *)pktData, pktHeader->len, (u8 *)userData + sizeof(DesmumeFrameHeader));
|
||||
|
||||
rawPacket->writeLocation += emulatorHeader.emuPacketSize;
|
||||
rawPacket->count++;
|
||||
}
|
||||
|
||||
static void* WifiHandler_RXPacketGetAdhoc(void *arg)
|
||||
static void* Adhoc_RXPacketGetOnThread(void *arg)
|
||||
{
|
||||
WifiHandler *handler = (WifiHandler *)arg;
|
||||
handler->RXPacketGetAdhoc();
|
||||
AdhocCommInterface *commInterface = (AdhocCommInterface *)arg;
|
||||
commInterface->RXPacketGet();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* Infrastructure_RXPacketGetOnThread(void *arg)
|
||||
{
|
||||
SoftAPCommInterface *commInterface = (SoftAPCommInterface *)arg;
|
||||
commInterface->RXPacketGet();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3197,6 +3203,11 @@ int DummyPCapInterface::dispatch(void *dev, int num, void *callback, void *userd
|
|||
return -1;
|
||||
}
|
||||
|
||||
void DummyPCapInterface::breakloop(void *dev)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
#ifndef HOST_WINDOWS
|
||||
|
||||
int POSIXPCapInterface::findalldevs(void **alldevs, char *errbuf)
|
||||
|
@ -3239,11 +3250,44 @@ int POSIXPCapInterface::dispatch(void *dev, int num, void *callback, void *userd
|
|||
return pcap_dispatch((pcap_t *)dev, num, (pcap_handler)callback, (u_char *)userdata);
|
||||
}
|
||||
|
||||
void POSIXPCapInterface::breakloop(void *dev)
|
||||
{
|
||||
pcap_breakloop((pcap_t *)dev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
WifiCommInterface::WifiCommInterface()
|
||||
{
|
||||
_rxTask = new Task();
|
||||
_mutexRXThreadRunningFlag = slock_new();
|
||||
_isRXThreadRunning = false;
|
||||
_rawPacket = NULL;
|
||||
_wifiHandler = NULL;
|
||||
}
|
||||
|
||||
WifiCommInterface::~WifiCommInterface()
|
||||
{
|
||||
// Do nothing.
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
if (this->_isRXThreadRunning)
|
||||
{
|
||||
this->_isRXThreadRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
this->_rxTask->finish();
|
||||
delete this->_rxTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
free(this->_rawPacket);
|
||||
this->_rawPacket = NULL;
|
||||
this->_wifiHandler = NULL;
|
||||
|
||||
slock_free(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
AdhocCommInterface::AdhocCommInterface()
|
||||
|
@ -3264,20 +3308,12 @@ AdhocCommInterface::~AdhocCommInterface()
|
|||
free(this->_sendAddr);
|
||||
}
|
||||
|
||||
bool AdhocCommInterface::Start(WifiEmulationLevel emulationLevel)
|
||||
bool AdhocCommInterface::Start(WifiHandler *currentWifiHandler)
|
||||
{
|
||||
socket_t &thisSocket = *((socket_t *)this->_wifiSocket);
|
||||
int socketOptValueTrue = 1;
|
||||
int result = -1;
|
||||
|
||||
// Ad-hoc mode won't have a partial-functioning variant, and so just return
|
||||
// if the WiFi emulation level is Off.
|
||||
if (emulationLevel == WifiEmulationLevel_Off)
|
||||
{
|
||||
thisSocket = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create an UDP socket.
|
||||
thisSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (thisSocket < 0)
|
||||
|
@ -3350,6 +3386,18 @@ bool AdhocCommInterface::Start(WifiEmulationLevel emulationLevel)
|
|||
*(u32 *)&thisSendAddr.sa_data[2] = htonl(INADDR_BROADCAST);
|
||||
*(u16 *)&thisSendAddr.sa_data[0] = htons(BASEPORT);
|
||||
|
||||
// Start the RX packet thread.
|
||||
this->_wifiHandler = currentWifiHandler;
|
||||
this->_rawPacket = (RXRawPacketData *)calloc(1, sizeof(RXRawPacketData));
|
||||
|
||||
#ifdef DESMUME_COCOA
|
||||
this->_rxTask->start(false, 43);
|
||||
#else
|
||||
this->_rxTask->start(false);
|
||||
#endif
|
||||
this->_isRXThreadRunning = true;
|
||||
this->_rxTask->execute(&Adhoc_RXPacketGetOnThread, this);
|
||||
|
||||
WIFI_LOG(1, "Ad-hoc: Initialization successful.\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -3360,9 +3408,28 @@ void AdhocCommInterface::Stop()
|
|||
|
||||
if (thisSocket >= 0)
|
||||
{
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
if (this->_isRXThreadRunning)
|
||||
{
|
||||
this->_isRXThreadRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
this->_rxTask->finish();
|
||||
this->_rxTask->shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
closesocket(thisSocket);
|
||||
thisSocket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
free(this->_rawPacket);
|
||||
this->_rawPacket = NULL;
|
||||
this->_wifiHandler = NULL;
|
||||
}
|
||||
|
||||
size_t AdhocCommInterface::TXPacketSend(u8 *txTargetBuffer, size_t txLength)
|
||||
|
@ -3382,15 +3449,10 @@ size_t AdhocCommInterface::TXPacketSend(u8 *txTargetBuffer, size_t txLength)
|
|||
return txPacketSize;
|
||||
}
|
||||
|
||||
size_t AdhocCommInterface::RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber)
|
||||
int AdhocCommInterface::_RXPacketGetFromSocket(RXRawPacketData &rawPacket)
|
||||
{
|
||||
size_t rxPacketSize = 0;
|
||||
socket_t &thisSocket = *((socket_t *)this->_wifiSocket);
|
||||
|
||||
if ( (thisSocket < 0) || (rxTargetBuffer == NULL) )
|
||||
{
|
||||
return rxPacketSize;
|
||||
}
|
||||
int rxPacketSizeInt = 0;
|
||||
|
||||
fd_set fd;
|
||||
struct timeval tv;
|
||||
|
@ -3405,10 +3467,12 @@ size_t AdhocCommInterface::RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber)
|
|||
sockaddr_t fromAddr;
|
||||
socklen_t fromLen = sizeof(sockaddr_t);
|
||||
|
||||
int rxPacketSizeInt = recvfrom(thisSocket, (char *)rxTargetBuffer, WIFI_WORKING_PACKET_BUFFER_SIZE, 0, &fromAddr, &fromLen);
|
||||
u8 *targetPacket = &rawPacket.buffer[rawPacket.writeLocation];
|
||||
|
||||
rxPacketSizeInt = recvfrom(thisSocket, (char *)targetPacket, WIFI_WORKING_PACKET_BUFFER_SIZE, 0, &fromAddr, &fromLen);
|
||||
if (rxPacketSizeInt <= 0)
|
||||
{
|
||||
return rxPacketSize; // No packet data was received.
|
||||
return rxPacketSizeInt; // No packet data was received.
|
||||
}
|
||||
|
||||
// This is the smallest possible frame size there can be. As of this time:
|
||||
|
@ -3417,14 +3481,51 @@ size_t AdhocCommInterface::RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber)
|
|||
// 4 bytes - Size of the FCS at the end of every IEEE 802.11 frame
|
||||
if (rxPacketSizeInt <= (16 + 10 + 4))
|
||||
{
|
||||
return rxPacketSize; // The packet is too small to be of any use.
|
||||
rxPacketSizeInt = 0;
|
||||
return rxPacketSizeInt; // The packet is too small to be of any use.
|
||||
}
|
||||
|
||||
// Set the packet size to a non-zero value.
|
||||
rxPacketSize = (size_t)rxPacketSizeInt;
|
||||
DesmumeFrameHeader &emulatorHeader = (DesmumeFrameHeader &)targetPacket[0];
|
||||
rawPacket.writeLocation += emulatorHeader.emuPacketSize;
|
||||
rawPacket.count++;
|
||||
}
|
||||
|
||||
return rxPacketSize;
|
||||
return rxPacketSizeInt;
|
||||
}
|
||||
|
||||
void AdhocCommInterface::RXPacketGet()
|
||||
{
|
||||
socket_t &thisSocket = *((socket_t *)this->_wifiSocket);
|
||||
|
||||
if ( (thisSocket < 0) || (this->_rawPacket == NULL) || (this->_wifiHandler == NULL) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
while (this->_isRXThreadRunning)
|
||||
{
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
this->_rawPacket->writeLocation = 0;
|
||||
this->_rawPacket->count = 0;
|
||||
|
||||
int result = this->_RXPacketGetFromSocket(*this->_rawPacket);
|
||||
if (result <= 0)
|
||||
{
|
||||
this->_rawPacket->count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_wifiHandler->RXPacketRawToQueue<false>(*this->_rawPacket);
|
||||
}
|
||||
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
SoftAPCommInterface::SoftAPCommInterface()
|
||||
|
@ -3541,53 +3642,67 @@ void SoftAPCommInterface::SetBridgeDeviceIndex(int deviceIndex)
|
|||
this->_bridgeDeviceIndex = deviceIndex;
|
||||
}
|
||||
|
||||
bool SoftAPCommInterface::Start(WifiEmulationLevel emulationLevel)
|
||||
bool SoftAPCommInterface::Start(WifiHandler *currentWifiHandler)
|
||||
{
|
||||
const bool isPCapSupported = (this->_pcap != &dummyPCapInterface);
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
if (isPCapSupported && (emulationLevel != WifiEmulationLevel_Off))
|
||||
if (isPCapSupported)
|
||||
{
|
||||
this->_bridgeDevice = this->_GetBridgeDeviceAtIndex(this->_bridgeDeviceIndex, errbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_bridgeDevice = NULL;
|
||||
|
||||
if (!isPCapSupported)
|
||||
{
|
||||
WIFI_LOG(1, "SoftAP: No libpcap interface has been set.\n");
|
||||
}
|
||||
|
||||
if (emulationLevel == WifiEmulationLevel_Off)
|
||||
{
|
||||
WIFI_LOG(1, "SoftAP: Emulation level is OFF.\n");
|
||||
}
|
||||
WIFI_LOG(1, "SoftAP: No libpcap interface has been set.\n");
|
||||
}
|
||||
|
||||
// Set non-blocking mode
|
||||
if (this->_bridgeDevice != NULL)
|
||||
const bool hasBridgeDevice = (this->_bridgeDevice != NULL);
|
||||
if (hasBridgeDevice)
|
||||
{
|
||||
int result = this->_pcap->setnonblock(this->_bridgeDevice, 1, errbuf);
|
||||
if (result == -1)
|
||||
{
|
||||
this->_pcap->close(this->_bridgeDevice);
|
||||
this->_bridgeDevice = NULL;
|
||||
|
||||
WIFI_LOG(1, "SoftAP: libpcap failed to set non-blocking mode: %s\n", errbuf);
|
||||
}
|
||||
// Start the RX packet thread.
|
||||
this->_wifiHandler = currentWifiHandler;
|
||||
this->_rawPacket = (RXRawPacketData *)calloc(1, sizeof(RXRawPacketData));
|
||||
|
||||
#ifdef DESMUME_COCOA
|
||||
this->_rxTask->start(false, 43);
|
||||
#else
|
||||
this->_rxTask->start(false);
|
||||
#endif
|
||||
this->_isRXThreadRunning = true;
|
||||
this->_rxTask->execute(&Infrastructure_RXPacketGetOnThread, this);
|
||||
}
|
||||
|
||||
return true;
|
||||
return hasBridgeDevice;
|
||||
}
|
||||
|
||||
void SoftAPCommInterface::Stop()
|
||||
{
|
||||
if (this->_bridgeDevice != NULL)
|
||||
{
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
if (this->_isRXThreadRunning)
|
||||
{
|
||||
this->_isRXThreadRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
this->_pcap->breakloop(this->_bridgeDevice);
|
||||
this->_rxTask->finish();
|
||||
this->_rxTask->shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
this->_pcap->close(this->_bridgeDevice);
|
||||
this->_bridgeDevice = NULL;
|
||||
}
|
||||
|
||||
free(this->_rawPacket);
|
||||
this->_rawPacket = NULL;
|
||||
this->_wifiHandler = NULL;
|
||||
}
|
||||
|
||||
size_t SoftAPCommInterface::TXPacketSend(u8 *txTargetBuffer, size_t txLength)
|
||||
|
@ -3608,38 +3723,36 @@ size_t SoftAPCommInterface::TXPacketSend(u8 *txTargetBuffer, size_t txLength)
|
|||
return txPacketSize;
|
||||
}
|
||||
|
||||
size_t SoftAPCommInterface::RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber)
|
||||
void SoftAPCommInterface::RXPacketGet()
|
||||
{
|
||||
size_t rxPacketSize = 0;
|
||||
|
||||
if ( (this->_bridgeDevice == NULL) || (rxTargetBuffer == NULL) )
|
||||
if ( (this->_bridgeDevice == NULL) || (this->_rawPacket == NULL) || (this->_wifiHandler == NULL) )
|
||||
{
|
||||
return rxPacketSize;
|
||||
return;
|
||||
}
|
||||
|
||||
int result = this->_pcap->dispatch(this->_bridgeDevice, 1, (void *)&SoftAP_RXPacketGet_Callback, rxTargetBuffer);
|
||||
if (result <= 0)
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
while (this->_isRXThreadRunning)
|
||||
{
|
||||
return rxPacketSize;
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
|
||||
this->_rawPacket->writeLocation = 0;
|
||||
this->_rawPacket->count = 0;
|
||||
|
||||
int result = this->_pcap->dispatch(this->_bridgeDevice, 8, (void *)&SoftAP_RXPacketGet_Callback, (u_char *)this->_rawPacket);
|
||||
if (result <= 0)
|
||||
{
|
||||
this->_rawPacket->count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_wifiHandler->RXPacketRawToQueue<true>(*this->_rawPacket);
|
||||
}
|
||||
|
||||
slock_lock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
DesmumeFrameHeader &emulatorHeader = (DesmumeFrameHeader &)rxTargetBuffer[0];
|
||||
rxPacketSize = emulatorHeader.emuPacketSize;
|
||||
if (rxPacketSize == 0)
|
||||
{
|
||||
return rxPacketSize;
|
||||
}
|
||||
|
||||
// Update the sequence number.
|
||||
WifiDataFrameHeaderDS2STA &IEEE80211Header = (WifiDataFrameHeaderDS2STA &)rxTargetBuffer[sizeof(DesmumeFrameHeader)];
|
||||
IEEE80211Header.seqCtl.SequenceNumber = sequenceNumber;
|
||||
|
||||
// Write the FCS at the end of the frame.
|
||||
u32 &fcs = (u32 &)rxTargetBuffer[sizeof(DesmumeFrameHeader) + emulatorHeader.emuPacketSize];
|
||||
fcs = WIFI_calcCRC32(rxTargetBuffer + sizeof(DesmumeFrameHeader), emulatorHeader.emuPacketSize);
|
||||
emulatorHeader.emuPacketSize += sizeof(u32);
|
||||
|
||||
return rxPacketSize + sizeof(DesmumeFrameHeader);
|
||||
slock_unlock(this->_mutexRXThreadRunningFlag);
|
||||
}
|
||||
|
||||
WifiHandler::WifiHandler()
|
||||
|
@ -3653,15 +3766,10 @@ WifiHandler::WifiHandler()
|
|||
_selectedBridgeDeviceIndex = 0;
|
||||
|
||||
_workingTXBuffer = NULL;
|
||||
_workingRXAdhocBuffer = NULL;
|
||||
_workingRXSoftAPBuffer = NULL;
|
||||
|
||||
_rxTaskAdhoc = new Task();
|
||||
_mutexRXPacketQueue = slock_new();
|
||||
_mutexRXThreadAdhocRunningFlag = slock_new();
|
||||
_rxPacketQueue.clear();
|
||||
_rxCurrentQueuedPacketPosition = 0;
|
||||
_isRXThreadAdhocRunning = false;
|
||||
|
||||
_softAPStatus = APStatus_Disconnected;
|
||||
_softAPSequenceNumber = 0;
|
||||
|
@ -3682,24 +3790,11 @@ WifiHandler::WifiHandler()
|
|||
|
||||
WifiHandler::~WifiHandler()
|
||||
{
|
||||
slock_lock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_isRXThreadAdhocRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_rxTaskAdhoc->finish();
|
||||
delete this->_rxTaskAdhoc;
|
||||
slock_free(this->_mutexRXThreadAdhocRunningFlag);
|
||||
|
||||
slock_free(this->_mutexRXPacketQueue);
|
||||
|
||||
free(this->_workingTXBuffer);
|
||||
this->_workingTXBuffer = NULL;
|
||||
|
||||
free(this->_workingRXAdhocBuffer);
|
||||
this->_workingRXAdhocBuffer = NULL;
|
||||
|
||||
free(this->_workingRXSoftAPBuffer);
|
||||
this->_workingRXSoftAPBuffer = NULL;
|
||||
|
||||
delete this->_adhocCommInterface;
|
||||
delete this->_softAPCommInterface;
|
||||
}
|
||||
|
@ -4172,16 +4267,17 @@ bool WifiHandler::_SoftAPTrySendPacket(const TXPacketHeader &txHeader, const u8
|
|||
if ( WIFI_compareMAC(mgmtFrameHeader.BSSID, SoftAP_MACAddr) ||
|
||||
(WIFI_isBroadcastMAC(mgmtFrameHeader.BSSID) && (fc.Subtype == WifiFrameManagementSubtype_ProbeRequest)) )
|
||||
{
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
|
||||
RXQueuedPacket newRXPacket = this->_GenerateSoftAPMgmtResponseFrame((WifiFrameManagementSubtype)fc.Subtype, this->_softAPSequenceNumber, this->_wifi.usecCounter);
|
||||
if (newRXPacket.rxHeader.length > 0)
|
||||
{
|
||||
newRXPacket.latencyCount = 0;
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
this->_softAPSequenceNumber++;
|
||||
}
|
||||
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
isPacketHandled = true;
|
||||
}
|
||||
break;
|
||||
|
@ -4257,12 +4353,12 @@ bool WifiHandler::_SoftAPTrySendPacket(const TXPacketHeader &txHeader, const u8
|
|||
if (sendPacketSize > 0)
|
||||
{
|
||||
RXQueuedPacket newRXPacket = this->_GenerateSoftAPCtlACKFrame(IEEE80211FrameHeader, sendPacketSize);
|
||||
|
||||
newRXPacket.latencyCount = 0;
|
||||
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
this->_softAPSequenceNumber++;
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
|
||||
#if WIFI_SAVE_PCAP_TO_FILE
|
||||
// Store the packet in the PCAP file.
|
||||
|
@ -4427,16 +4523,7 @@ void WifiHandler::SetBridgeDeviceIndex(int deviceIndex)
|
|||
|
||||
bool WifiHandler::CommStart()
|
||||
{
|
||||
bool isAdhocCommStarted = false;
|
||||
bool isInfrastructureCommStarted = false;
|
||||
WifiEmulationLevel pendingEmulationLevel = this->_selectedEmulationLevel;
|
||||
|
||||
// Stop the current comm interface.
|
||||
slock_lock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_isRXThreadAdhocRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_rxTaskAdhoc->finish();
|
||||
|
||||
// Stop the current comm interfaces.
|
||||
this->_adhocCommInterface->Stop();
|
||||
this->_softAPCommInterface->Stop();
|
||||
|
||||
|
@ -4444,10 +4531,18 @@ bool WifiHandler::CommStart()
|
|||
this->_wifi.usecCounter = 0;
|
||||
this->_RXEmptyQueue();
|
||||
|
||||
FW_Mac[0] = MMU.fw.data.wifiInfo.MACAddr[0];
|
||||
FW_Mac[1] = MMU.fw.data.wifiInfo.MACAddr[1];
|
||||
FW_Mac[2] = MMU.fw.data.wifiInfo.MACAddr[2];
|
||||
FW_Mac[3] = MMU.fw.data.wifiInfo.MACAddr[3];
|
||||
FW_Mac[4] = MMU.fw.data.wifiInfo.MACAddr[4];
|
||||
FW_Mac[5] = MMU.fw.data.wifiInfo.MACAddr[5];
|
||||
|
||||
WIFI_LOG(1, "MAC Address = %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]);
|
||||
|
||||
// Allocate 16KB worth of memory per buffer for sending packets. Hopefully, this should be plenty.
|
||||
this->_workingTXBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
|
||||
this->_workingRXAdhocBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
|
||||
this->_workingRXSoftAPBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
|
||||
this->_softAPStatus = APStatus_Disconnected;
|
||||
this->_softAPSequenceNumber = 0;
|
||||
|
||||
|
@ -4455,58 +4550,33 @@ bool WifiHandler::CommStart()
|
|||
this->_softAPCommInterface->SetPCapInterface(this->_pcap);
|
||||
this->_softAPCommInterface->SetBridgeDeviceIndex(this->_selectedBridgeDeviceIndex);
|
||||
|
||||
// Start the new comm interface.
|
||||
if (this->_isSocketsSupported)
|
||||
if (this->_selectedEmulationLevel == WifiEmulationLevel_Off)
|
||||
{
|
||||
isAdhocCommStarted = this->_adhocCommInterface->Start(pendingEmulationLevel);
|
||||
if (!isAdhocCommStarted)
|
||||
{
|
||||
this->_adhocCommInterface->Stop();
|
||||
}
|
||||
WIFI_LOG(1, "Emulation level is OFF.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WIFI_LOG(1, "Ad-hoc mode requires sockets, but sockets are not supported on this system.\n");
|
||||
}
|
||||
|
||||
if (this->IsPCapSupported())
|
||||
{
|
||||
isInfrastructureCommStarted = this->_softAPCommInterface->Start(pendingEmulationLevel);
|
||||
if (!isInfrastructureCommStarted)
|
||||
// Start the new comm interfaces.
|
||||
if (this->_isSocketsSupported)
|
||||
{
|
||||
this->_softAPCommInterface->Stop();
|
||||
this->_adhocCommInterface->Start(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIFI_LOG(1, "Ad-hoc mode requires sockets, but sockets are not supported on this system.\n");
|
||||
}
|
||||
|
||||
if (this->IsPCapSupported())
|
||||
{
|
||||
this->_softAPCommInterface->Start(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIFI_LOG(1, "Infrastructure mode requires libpcap for full functionality,\n but libpcap is not available on this system. Network functions\n will be disabled for this session.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WIFI_LOG(1, "Infrastructure mode requires libpcap for full functionality,\n but libpcap is not available on this system. Network functions\n will be disabled for this session.\n");
|
||||
}
|
||||
|
||||
if (isAdhocCommStarted || isInfrastructureCommStarted)
|
||||
{
|
||||
FW_Mac[0] = MMU.fw.data.wifiInfo.MACAddr[0];
|
||||
FW_Mac[1] = MMU.fw.data.wifiInfo.MACAddr[1];
|
||||
FW_Mac[2] = MMU.fw.data.wifiInfo.MACAddr[2];
|
||||
FW_Mac[3] = MMU.fw.data.wifiInfo.MACAddr[3];
|
||||
FW_Mac[4] = MMU.fw.data.wifiInfo.MACAddr[4];
|
||||
FW_Mac[5] = MMU.fw.data.wifiInfo.MACAddr[5];
|
||||
|
||||
// Starting the comm interface was successful.
|
||||
// Report the MAC address to the user as confirmation.
|
||||
WIFI_LOG(1, "MAC Address = %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]);
|
||||
|
||||
#ifdef DESMUME_COCOA
|
||||
this->_rxTaskAdhoc->start(false, 43);
|
||||
#else
|
||||
this->_rxTaskAdhoc->start(false);
|
||||
#endif
|
||||
|
||||
this->_isRXThreadAdhocRunning = true;
|
||||
this->_rxTaskAdhoc->execute(&WifiHandler_RXPacketGetAdhoc, this);
|
||||
}
|
||||
|
||||
this->_currentEmulationLevel = pendingEmulationLevel;
|
||||
this->_currentEmulationLevel = this->_selectedEmulationLevel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4515,12 +4585,6 @@ void WifiHandler::CommStop()
|
|||
{
|
||||
this->_PacketCaptureFileClose();
|
||||
|
||||
slock_lock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_isRXThreadAdhocRunning = false;
|
||||
slock_unlock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
this->_rxTaskAdhoc->finish();
|
||||
this->_rxTaskAdhoc->shutdown();
|
||||
|
||||
this->_adhocCommInterface->Stop();
|
||||
this->_softAPCommInterface->Stop();
|
||||
|
||||
|
@ -4528,12 +4592,6 @@ void WifiHandler::CommStop()
|
|||
|
||||
free(this->_workingTXBuffer);
|
||||
this->_workingTXBuffer = NULL;
|
||||
|
||||
free(this->_workingRXAdhocBuffer);
|
||||
this->_workingRXAdhocBuffer = NULL;
|
||||
|
||||
free(this->_workingRXSoftAPBuffer);
|
||||
this->_workingRXSoftAPBuffer = NULL;
|
||||
}
|
||||
|
||||
void WifiHandler::CommSendPacket(const TXPacketHeader &txHeader, const u8 *IEEE80211PacketData)
|
||||
|
@ -4639,7 +4697,7 @@ void WifiHandler::CommTrigger()
|
|||
if (isTXSlotBusy)
|
||||
{
|
||||
IOREG_W_TXBUF_LOCATION *txBufLocation = NULL;
|
||||
TXPacketInfo &txPacketInfo = wifiHandler->GetPacketInfoAtSlot(txSlotIndex);
|
||||
TXPacketInfo &txPacketInfo = this->GetPacketInfoAtSlot(txSlotIndex);
|
||||
|
||||
switch (txSlotIndex)
|
||||
{
|
||||
|
@ -4675,7 +4733,7 @@ void WifiHandler::CommTrigger()
|
|||
txBufLocation->TransferRequest = 0;
|
||||
|
||||
TXPacketHeader &txHeader = (TXPacketHeader &)wifi.RAM[txBufLocation->HalfwordAddress << 1];
|
||||
wifiHandler->CommSendPacket(txHeader, &wifi.RAM[(txBufLocation->HalfwordAddress << 1) + sizeof(TXPacketHeader)]);
|
||||
this->CommSendPacket(txHeader, &wifi.RAM[(txBufLocation->HalfwordAddress << 1) + sizeof(TXPacketHeader)]);
|
||||
txHeader.txStatus = 0x0001;
|
||||
txHeader.UNKNOWN3 = 0;
|
||||
|
||||
|
@ -4747,39 +4805,17 @@ void WifiHandler::_AddPeriodicPacketsToRXQueue(const u64 usecCounter)
|
|||
{
|
||||
if ((usecCounter & 131071) == 0)
|
||||
{
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
|
||||
//zero sez: every 1/10 second? does it have to be precise? this is so costly..
|
||||
// Okay for 128 ms then
|
||||
RXQueuedPacket newRXPacket = this->_GenerateSoftAPBeaconFrame(this->_softAPSequenceNumber, this->_wifi.usecCounter);
|
||||
|
||||
newRXPacket.latencyCount = 0;
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
this->_softAPSequenceNumber++;
|
||||
}
|
||||
|
||||
// EXTREMELY EXPERIMENTAL packet receiving code
|
||||
// Can now receive 64 packets per millisecond. Completely arbitrary limit. Todo: tweak if needed.
|
||||
// But due to using non-blocking mode, this shouldn't be as slow as it used to be.
|
||||
if ((usecCounter & 15) == 0)
|
||||
{
|
||||
size_t rxBytes = this->_softAPCommInterface->RXPacketGet(this->_workingRXSoftAPBuffer, this->_softAPSequenceNumber);
|
||||
if (rxBytes > 0)
|
||||
{
|
||||
RXQueuedPacket newRXPacket;
|
||||
|
||||
const u8 *packetIEEE80211HeaderPtr = this->_RXPacketFilter(this->_workingRXSoftAPBuffer, rxBytes, newRXPacket.rxHeader);
|
||||
if (packetIEEE80211HeaderPtr != NULL)
|
||||
{
|
||||
memcpy(newRXPacket.rxData, packetIEEE80211HeaderPtr, newRXPacket.rxHeader.length);
|
||||
|
||||
newRXPacket.latencyCount = 0;
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
this->_softAPSequenceNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4857,33 +4893,45 @@ void WifiHandler::CommEmptyRXQueue()
|
|||
this->_RXEmptyQueue();
|
||||
}
|
||||
|
||||
void WifiHandler::RXPacketGetAdhoc()
|
||||
template <bool WILLADVANCESEQNO>
|
||||
void WifiHandler::RXPacketRawToQueue(const RXRawPacketData &rawPacket)
|
||||
{
|
||||
RXQueuedPacket newRXPacket;
|
||||
|
||||
slock_lock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
|
||||
while (this->_isRXThreadAdhocRunning)
|
||||
for (size_t i = 0, readLocation = 0; i < rawPacket.count; i++)
|
||||
{
|
||||
slock_unlock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
const u8 *currentPacket = &rawPacket.buffer[readLocation];
|
||||
const DesmumeFrameHeader &emulatorHeader = (DesmumeFrameHeader &)*currentPacket;
|
||||
readLocation += sizeof(DesmumeFrameHeader) + emulatorHeader.emuPacketSize;
|
||||
|
||||
size_t rxBytes = this->_adhocCommInterface->RXPacketGet(this->_workingRXAdhocBuffer, 0);
|
||||
if (rxBytes > 0)
|
||||
const u8 *packetIEEE80211HeaderPtr = this->_RXPacketFilter(currentPacket, sizeof(DesmumeFrameHeader) + emulatorHeader.emuPacketSize, newRXPacket.rxHeader);
|
||||
if (packetIEEE80211HeaderPtr != NULL)
|
||||
{
|
||||
const u8 *packetIEEE80211HeaderPtr = this->_RXPacketFilter(this->_workingRXAdhocBuffer, rxBytes, newRXPacket.rxHeader);
|
||||
if (packetIEEE80211HeaderPtr != NULL)
|
||||
memset(newRXPacket.rxData, 0, sizeof(newRXPacket.rxData));
|
||||
memcpy(newRXPacket.rxData, packetIEEE80211HeaderPtr, newRXPacket.rxHeader.length);
|
||||
newRXPacket.latencyCount = 0;
|
||||
|
||||
if (WILLADVANCESEQNO)
|
||||
{
|
||||
memcpy(newRXPacket.rxData, packetIEEE80211HeaderPtr, newRXPacket.rxHeader.length);
|
||||
// Update the sequence number.
|
||||
WifiDataFrameHeaderDS2STA &IEEE80211Header = (WifiDataFrameHeaderDS2STA &)newRXPacket.rxData[0];
|
||||
IEEE80211Header.seqCtl.SequenceNumber = this->_softAPSequenceNumber;
|
||||
this->_softAPSequenceNumber++;
|
||||
|
||||
newRXPacket.latencyCount = 0;
|
||||
slock_lock(this->_mutexRXPacketQueue);
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
// Write the FCS at the end of the frame.
|
||||
u32 &fcs = (u32 &)newRXPacket.rxData[newRXPacket.rxHeader.length];
|
||||
fcs = WIFI_calcCRC32(newRXPacket.rxData, newRXPacket.rxHeader.length);
|
||||
newRXPacket.rxHeader.length += sizeof(u32);
|
||||
}
|
||||
|
||||
// Add the packet to the RX queue.
|
||||
this->_rxPacketQueue.push_back(newRXPacket);
|
||||
}
|
||||
}
|
||||
|
||||
slock_unlock(this->_mutexRXThreadAdhocRunningFlag);
|
||||
slock_unlock(this->_mutexRXPacketQueue);
|
||||
}
|
||||
|
||||
bool WifiHandler::IsPCapSupported()
|
||||
|
|
|
@ -203,6 +203,7 @@
|
|||
|
||||
#define WIFI_WORKING_PACKET_BUFFER_SIZE (16 * 1024 * sizeof(u8)) // 16 KB size
|
||||
|
||||
class WifiHandler;
|
||||
class Task;
|
||||
struct slock;
|
||||
typedef slock slock_t;
|
||||
|
@ -3161,6 +3162,13 @@ typedef union
|
|||
};
|
||||
} RXQueuedPacket;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 buffer[(sizeof(DesmumeFrameHeader) + MAX_PACKET_SIZE_80211) * 16];
|
||||
size_t writeLocation;
|
||||
size_t count;
|
||||
} RXRawPacketData;
|
||||
|
||||
extern LegacyWifiSFormat legacyWifiSF;
|
||||
|
||||
/* wifimac io */
|
||||
|
@ -3204,6 +3212,7 @@ public:
|
|||
virtual int setnonblock(void *dev, int nonblock, char *errbuf) = 0;
|
||||
virtual int sendpacket(void *dev, const void *data, int len) = 0;
|
||||
virtual int dispatch(void *dev, int num, void *callback, void *userdata) = 0;
|
||||
virtual void breakloop(void *dev) = 0;
|
||||
};
|
||||
|
||||
class DummyPCapInterface : public ClientPCapInterface
|
||||
|
@ -3219,6 +3228,7 @@ public:
|
|||
virtual int setnonblock(void *dev, int nonblock, char *errbuf);
|
||||
virtual int sendpacket(void *dev, const void *data, int len);
|
||||
virtual int dispatch(void *dev, int num, void *callback, void *userdata);
|
||||
virtual void breakloop(void *dev);
|
||||
};
|
||||
|
||||
#ifndef HOST_WINDOWS
|
||||
|
@ -3233,6 +3243,7 @@ public:
|
|||
virtual int setnonblock(void *dev, int nonblock, char *errbuf);
|
||||
virtual int sendpacket(void *dev, const void *data, int len);
|
||||
virtual int dispatch(void *dev, int num, void *callback, void *userdata);
|
||||
virtual void breakloop(void *dev);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3241,14 +3252,21 @@ class WifiCommInterface
|
|||
{
|
||||
protected:
|
||||
WifiCommInterfaceID _commInterfaceID;
|
||||
WifiHandler *_wifiHandler;
|
||||
|
||||
Task *_rxTask;
|
||||
slock_t *_mutexRXThreadRunningFlag;
|
||||
volatile bool _isRXThreadRunning;
|
||||
RXRawPacketData *_rawPacket;
|
||||
|
||||
public:
|
||||
WifiCommInterface();
|
||||
~WifiCommInterface();
|
||||
|
||||
virtual bool Start(WifiEmulationLevel emulationLevel) = 0;
|
||||
virtual bool Start(WifiHandler *currentWifiHandler) = 0;
|
||||
virtual void Stop() = 0;
|
||||
virtual size_t TXPacketSend(u8 *txTargetBuffer, size_t txLength) = 0;
|
||||
virtual size_t RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber) = 0;
|
||||
virtual void RXPacketGet() = 0;
|
||||
};
|
||||
|
||||
class AdhocCommInterface : public WifiCommInterface
|
||||
|
@ -3261,10 +3279,12 @@ public:
|
|||
AdhocCommInterface();
|
||||
~AdhocCommInterface();
|
||||
|
||||
virtual bool Start(WifiEmulationLevel emulationLevel);
|
||||
int _RXPacketGetFromSocket(RXRawPacketData &rawPacket);
|
||||
|
||||
virtual bool Start(WifiHandler *currentWifiHandler);
|
||||
virtual void Stop();
|
||||
virtual size_t TXPacketSend(u8 *txTargetBuffer, size_t txLength);
|
||||
virtual size_t RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber);
|
||||
virtual void RXPacketGet();
|
||||
};
|
||||
|
||||
class SoftAPCommInterface : public WifiCommInterface
|
||||
|
@ -3287,10 +3307,10 @@ public:
|
|||
int GetBridgeDeviceIndex();
|
||||
void SetBridgeDeviceIndex(int deviceIndex);
|
||||
|
||||
virtual bool Start(WifiEmulationLevel emulationLevel);
|
||||
virtual bool Start(WifiHandler *currentWifiHandler);
|
||||
virtual void Stop();
|
||||
virtual size_t TXPacketSend(u8 *txTargetBuffer, size_t txLength);
|
||||
virtual size_t RXPacketGet(u8 *rxTargetBuffer, u16 sequenceNumber);
|
||||
virtual void RXPacketGet();
|
||||
};
|
||||
|
||||
class WifiHandler
|
||||
|
@ -3311,12 +3331,6 @@ protected:
|
|||
bool _didWarnWFCUser;
|
||||
|
||||
u8 *_workingTXBuffer;
|
||||
u8 *_workingRXAdhocBuffer;
|
||||
u8 *_workingRXSoftAPBuffer;
|
||||
|
||||
Task *_rxTaskAdhoc;
|
||||
slock_t *_mutexRXThreadAdhocRunningFlag;
|
||||
volatile bool _isRXThreadAdhocRunning;
|
||||
|
||||
slock_t *_mutexRXPacketQueue;
|
||||
std::deque<RXQueuedPacket> _rxPacketQueue;
|
||||
|
@ -3372,7 +3386,7 @@ public:
|
|||
void CommTrigger();
|
||||
void CommEmptyRXQueue();
|
||||
|
||||
void RXPacketGetAdhoc();
|
||||
template<bool WILLADVANCESEQNO> void RXPacketRawToQueue(const RXRawPacketData &rawPacket);
|
||||
|
||||
bool IsSocketsSupported();
|
||||
void SetSocketsSupported(bool isSupported);
|
||||
|
|
Loading…
Reference in New Issue