-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMatchCommand.cpp
156 lines (125 loc) · 5.74 KB
/
MatchCommand.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <common/Common.hpp>
#include <dwc/dwc_main.h>
#include <dwc/dwc_match.h>
#include <dwc/dwc_node.h>
#include <gs/gt2/gt2Main.h>
#include <gs/gt2/gt2Utility.h>
#include <platform/stdio.h>
#include <platform/string.h>
#include <revolutionex/net/NETDigest.h>
#include <wiimmfi/ConnectionMatrix.hpp>
#include <wiimmfi/MatchCommand.hpp>
namespace Wiimmfi {
namespace MatchCommand {
void ProcessRecvConnFailMtxCommand(int clientAPid, u32 clientAIP, u16 clientAPort, DWCMatchCommandConnFailMtx* data, int dataLen) {
// Only process the command if we are waiting
// This should also act as a host check since this state cannot be in use by a client (i think)
if (stpMatchCnt->state != DWC_MATCH_STATE_SV_WAITING) {
DEBUG_REPORT("[WIIMMFI_RECV] But ignored (invalid state)\n")
return;
}
// Ensure the data size is correct
if (DWC_MATCH_CMD_GET_ACTUAL_SIZE(dataLen) != sizeof(*data)) {
DEBUG_REPORT("[WIIMMFI_RECV] But ignored (invalid data size)\n")
return;
}
// Find a "client B" with a connection failure, as we can only send the commands once per function
// The loop is reversed in order to find the highest AID
int clientBAid = -1;
for (int i = 0xB; i >= 0; i--) {
if (data->connFailMtx >> i & 1) {
clientBAid = i;
break;
}
}
// If no "client B" was found, bail
if (clientBAid == -1) {
DEBUG_REPORT("[WIIMMFI_RECV] But ignored (no connection failures)\n")
return;
}
// Get node info for client A and client B
// Check for null and eventually bail
DWCNodeInfo* clientAInfo = DWCi_NodeInfoList_GetNodeInfoForProfileId(clientAPid);
DWCNodeInfo* clientBInfo = DWCi_NodeInfoList_GetNodeInfoForAid(clientBAid);
if (!clientAInfo || !clientBInfo) {
DEBUG_REPORT("[WIIMMFI_RECV] But ignored (invalid PID/AID)\n")
return;
}
// Copy the node info to the temporary new node
memcpy(&stpMatchCnt->tempNewNodeInfo, clientBInfo, sizeof(DWCNodeInfo));
// Set up the command for client B and send it
DWCMatchCommandNewPidAid cmd;
NETWriteSwappedBytes32(&cmd.pid, stpMatchCnt->tempNewNodeInfo.profileId);
NETWriteSwappedBytes32(&cmd.aid, stpMatchCnt->tempNewNodeInfo.aid);
DWCi_SendMatchCommand(DWC_MATCH_CMD_NEW_PID_AID, clientAPid, clientAIP, clientAPort,
&cmd, DWC_MATCH_CMD_GET_SIZE(sizeof(cmd)));
// Send a SYN packet to client A
DWCi_SendMatchSynPacket(clientAInfo->aid, DWC_MATCH_SYN_CMD_SYN);
// Reset node info and return
memset(&stpMatchCnt->tempNewNodeInfo, 0, sizeof(DWCNodeInfo));
}
void ProcessRecvConnMtxCommand(int srcPid, DWCMatchCommandConnMtx* data, int dataLen) {
// Ensure the data size is correct
if (DWC_MATCH_CMD_GET_ACTUAL_SIZE(dataLen) != sizeof(*data)) {
DEBUG_REPORT("[WIIMMFI_RECV] But ignored (invalid data size)\n")
return;
}
// If the profile id of the source client isn't found, reset the outdated matrices
DWCNodeInfo* node = DWCi_NodeInfoList_GetNodeInfoForProfileId(srcPid);
if (node) Wiimmfi::ConnectionMatrix::sRecvConnMtx[node->aid] = data->connMtx;
else Wiimmfi::ConnectionMatrix::ResetRecv();
}
bool ProcessRecvMatchCommand(u8 cmd, int profileId, u32 publicIp, u16 publicPort, void* cmdData, int dataLen) {
// Dispatch call to different functions depending on the command
// Use the original function as a fallback
switch(cmd) {
case DWC_MATCH_CMD_CONN_FAIL_MTX:
DEBUG_REPORT("[WIIMMFI_RECV] Received CONN_FAIL_MTX command\n")
ProcessRecvConnFailMtxCommand(profileId, publicIp, publicPort,
(DWCMatchCommandConnFailMtx*)cmdData, dataLen);
return true;
case DWC_MATCH_CMD_CONN_MTX:
DEBUG_REPORT("[WIIMMFI_RECV] Received CONN_MTX command\n")
ProcessRecvConnMtxCommand(profileId, (DWCMatchCommandConnMtx*)cmdData, dataLen);
return true;
default:
return false;
}
}
void SendConnFailMtxCommand(u32 aidsConnectedToHost, u32 aidsConnectedToMe) {
// Get the AIDs who haven't connected to me
DWCMatchCommandConnFailMtx cmd;
cmd.connFailMtx = aidsConnectedToHost & ~aidsConnectedToMe;
// If all AIDs are connected or i am waiting, bail
if (!cmd.connFailMtx || stpMatchCnt->state == DWC_MATCH_STATE_CL_WAITING)
return;
// Get the host's node info, with all the necessary failsaves
DWCNodeInfo* hostNodeInfo = DWCi_NodeInfoList_GetServerNodeInfo();
if (!hostNodeInfo || hostNodeInfo->profileId == 0)
return;
// Send the command
DEBUG_REPORT("[WIIMMFI_SEND] Sending CONN_MTX command with data %08X\n", cmd.connFailMtx)
DWCi_SendMatchCommand(DWC_MATCH_CMD_CONN_FAIL_MTX, hostNodeInfo->profileId, hostNodeInfo->publicip,
hostNodeInfo->publicport, &cmd, DWC_MATCH_CMD_GET_SIZE(sizeof(cmd)));
}
void SendConnMtxCommand(u32 aidsConnectedToMe) {
// Failsafe
if (stpMatchCnt->nodeInfoList.nodeCount == 0)
return;
// Set up the command
DWCMatchCommandConnMtx cmd;
cmd.connMtx = aidsConnectedToMe;
DEBUG_REPORT("[WIIMMFI_SEND] Sending CONN_FAIL_MTX command with data %08X\n", aidsConnectedToMe)
// Send the command to every node
for (int i = 0; i < stpMatchCnt->nodeInfoList.nodeCount; i++) {
// Get the node and check that it isn't me
DWCNodeInfo* node = &stpMatchCnt->nodeInfoList.nodeInfos[i];
if (node->profileId == stpMatchCnt->profileId)
continue;
// Send the command
DWCi_SendMatchCommand(DWC_MATCH_CMD_CONN_MTX, node->profileId, node->publicip, node->publicport,
&cmd, DWC_MATCH_CMD_GET_SIZE(sizeof(cmd)));
}
}
} // namespace Natneg
} // namespace Wiimmfi