Network Protocol/STATUS
This pages is related to MKWii Network Protocol and describes the record type STATUS.
The status packages are from one client to another in 3 different ways:
- Direct client to client communication
- Client to Server MS to Server MASTER to client communication. Server MASTER itself prefixes the message by a master message of type 06.
- Client to Server GPCM to client communication using a GPCM90vMAT message. The message header is omitted. This is used for known friends.
The used data structure is identical for all 3 communication ways, only the header is different. The members itself are mainly stored as little endian data.
Basic Message Header
All status records start with a 20 bytes long message header:
Offset | Name | Size | Endian | Description |
---|---|---|---|---|
0x00 | identifier | 4 | ? | The magic, always 0xbb49cc4d (big endian) = 0x4dcc49bb (little endian) |
0x04 | version | 4 | little | Always 90, maybe the »dwc_mver«. |
0x08 | command | 1 | — | The status type. |
0x09 | size | 1 | — | The length of the appended data. |
0x0a | qr2Port | 2 | little | The public port of the sender client. |
0x0c | qr2IP | 4 | 4 bytes | The public IPv4 of the sender client, byte by byte (similar to big endian). |
0x10 | profileID | 4 | little | The profile id of the sender client. |
0x14 | data | size | — | The status type dependent extent. |
The total record length is the length of the header plus extent (20+ELEN). For GPCM90vMAT messages this header is omitted.
Type | Size | Transport | Name | Description |
---|---|---|---|---|
0x01 | 0x24 | GPCM90vMAT MS+MASTER |
RESERVATION | NAT negotiation reservation request |
0x02 | 0x34 | GPCM90vMAT MS+MASTER |
RESV_OK | NAT negotiation reservation completion |
0x03 | 0x04 | GPCM90vMAT MS+MASTER |
RESV_DENY | NAT negotiation reservation refusal |
0x04 | 0x00 | GPCM90vMAT MS+MASTER |
RESV_WAIT | NAT negotiation reservation wait request |
0x05 | 0x00 | GPCM90vMAT MS+MASTER |
RESV_CANCEL | NAT negotiation reservation cancellation request |
0x06 | 0x08 | GPCM90vMAT | TELL_ADDR | NN starting address notification (NAT negotiation unnecessary) |
0x07 | 0x08 | client to client | NEW_PID_AID | New connection client profile ID and AID notification |
0x08 | 0x08 | client to client | LINK_CLS_REQ | Not used by MKWii. Request for connection between clients |
0x09 | 0x04 | client to client | LINK_CLS_SUC | Not used by MKWii. Notification of successful connection between clients |
0x0a | ? | ? | CLOSE_LINK | Not used by MKWii. Notification of closed connection when connection is established |
0x0b | ? | ? | RESV_PRIOR | Not used by MKWii. NAT negotiation priority reservation request |
0x0c | 0x04 | client to client | CANCEL | matchmaking cancel command |
0x0d | 0x04 | client to client | CANCEL_SYN | SYN for matchmaking cancellation synchronization |
0x0e | 0x00 | client to client | CANCEL_SYN_ACK | SYN-ACK for matchmaking cancellation synchronization |
0x0f | 0x00 | client to client | CANCEL_ACK | ACK for matchmaking cancellation synchronization |
0x10 | 0x04 * n | GPCM90vMAT MS+MASTER client to client |
SC_CLOSE_CL | Notification of unintentional disconnect for already connected clients. Host disconnects n players (contains all their PIDs) |
0x11 | 0x00 | ? | POLL_TIMEOUT | Not used by MKWii. OPTION_MIN_COMPLETE timeout polling |
0x12 | 0x04 | ? | POLL_TO_ACK | Not used by MKWii. ACK to OPTION_MIN_COMPLETE timeout polling |
0x13 | ? | ? | SC_CONN_BLOCK | Not used by MKWii. Reservation denied due to block by OPTION_SC_CONNECT_BLOCK |
0x20 | 0x04 | ? | FRIEND_ACCEPT | Not used by MKWii. new connection friend permission from client |
0x40 | 0x00 | ? | CL_WAIT_POLL | Not used by MKWii. client standby timeout polling |
0x41 | 0x00 | ? | SV_KA_TO_CL | Not used by MKWii. server keep-alive for the above polling |
0x52 | 0x04 | client to client | SVDOWNQUERY | Somehow related to host negotiations - who will be the new host. Still need to look into how exactly these work. |
0x53 | 0x00 | client to client | SVDOWN_ACK | |
0x54 | 0x00 | client to client | SVDOWN_NAK | |
0x55 | 0x04 | client to client | SVDOWN_KEEP | |
0x82 | 0x08 0x10 |
MS+MASTER client to client |
SUSPEND_MATCH | SUSPEND flag control, guests can request a suspend value, host sets it |
0x83 | 0x0c | MS+MASTER client to client |
Unknown | Contains a slot usage list. Sent by the host every 15 seconds (ServerPolling). |
Naming
- knocker
- A player who wants to enter a room.
- (room) player
- A player of a room.
- host
- The host of a room. Exact one room player is host, all others are guests.
- guest
- All room players except the host.
Protocol
New Player enters room
When a new player enters a room, he connects to all players, one after another. To do so, either the joining client or a client that is already in the room (that seems to be random) sends a ST-01 (connection request) packet to the other. Then, the other player either answers with a ST-02, the players do NATNEG, connect to eachother, and continue with other players; or he sends a ST-04 (busy), gets a ST-05 as reply, and tries again later.
Traceable public IP
The value "traceable public IP" means the last reachable host on the route to the client. Do a traceroute on publicip and put the farthest reachable host here. This is the behaviour of the official server, but probably it'd be enough to simply put the public IP here.
Message Types
RESERVATION (01): Connection request
This status packet is send from a knocker to each room player, when the knocker will enter the room or group. There are 2 ways to transmit the message:
- For known friends, the message is send as a GPCM90vMAT message of type 0x01 using Server GPCM. In this case, the message header is omitted.
- For all others, Server MS and Server MASTER are used for transmission.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | DWC_MATCH_TYPE. 0 = anybody, 1 = friend, 2 = SC_SV, 3 = SC_CL |
0x04 | 4 | 4 bytes | Traceable public IPv4 of the sender, byte by byte (similar to big endian). |
0x08 | 4 | little | Public port of the sender. Always the same value as the public port of the header. |
0x0c | 4 | 4 bytes | Local IPv4 of the sender, byte by byte (similar to big endian). |
0x10 | 4 | little | Local port of the sender. |
0x14 | 4 | little | Unknown. Always 1. CTGP uses the highest byte for custom data. |
0x18 | 4 | little | Player's Friend. 0 or 1. |
0x1c | 4 | little | Number of players at the console (1 or 2) |
0x20 | 4 | little | Unique identfication number of this status packet (resvCheckValue). The reply of the player (status type 0x02) use the same ID. |
0x24 | End of the packet, 36 bytes total. |
RESV_OK (02): Allow connection
This status packet is send from the room player to the knocker as reply of a type 0x01 message to confirm the entrance of the guest. There are 2 ways to transmit the message:
- For known friends, the message is send as a GPCM90vMAT message of type 0x02 using Server GPCM. In this case, the message header is omitted.
- For all others, Server MS and Server MASTER are used for transmission.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | Parameter »maxplayers« (not 100% sure) = Number of possible guests. Always 11. |
0x04 | 4 | little | Most likely the client slot index of the sender (zero based, not player count). |
0x08 | 4 | little | Parameter »dwc_pid«. It is the same as the profile id of the header. |
0x0c | 4 | 4 bytes | Traceable public IPv4 of the sender, byte by byte (similar to big endian). |
0x10 | 4 | little | Public port of the sender. Always the same value as the public port of the header. |
0x14 | 4 | 4 bytes | Local IPv4 of the sender, byte by byte (similar to big endian). |
0x18 | 4 | little | Local port of the sender. |
0x1c | 4 | little | Unknown, always 1 |
0x20 | 4 | little | Number of players at the room player's console. |
0x24 | 4 | little | Parameter »dwc_groupid« (not 100% sure). |
0x28 | 4 | little | Most likely the client slot index of the receiver (zero based, not player count). |
0x2c | 4 | little | Most likely the client/console count already in the room. |
0x30 | 4 | little | The identfication number (resvCheckValue) send by the other player (status type 0x01). |
0x34 | End of the packet, 52 bytes total. |
RESV_DENY (02): Room full
This status packet is sent from the room player to the knocker when access is denied.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | Error ID. 0x10 = room is full (but not on suspend) (never seen in-game, but is implemented in the game code) 0x11 = Room has already started playing since you tried joining 0x12 = Room is on suspend. |
0x04 | End of the packet, 4 bytes total. |
RESV_WAIT (04): Busy doing NATNEG
0x04 is sent by a player as answer to 0x01 to deny a join request because the player is busy doing NATNEG.
RESV_CANCEL (05): Abort connection
0x05 is sent by a player to another player to abort an ongoing NATNEG attempt with the target. It is commonly seen as a response to 0x04, but can also be triggered in other circumstances too, for instance, if the player receives a 0x07 packet from the host.
TELL_ADDR (06): Same Network (Skip NATNEG)
This packet contains the local IP of the player. This packet is sent after a received STATUS-02 to skip NATNEG for Wiis that are on the same network as each other.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | 4-byte | Local IP. |
0x04 | 4 | little | Local port. |
0x08 | End of the packet, 8 bytes total. |
NEW_PID_AID (07): New client
Send by host when there joins a new player.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of new guest |
0x04 | 4 | little | slot ID of new guest |
0x08 | End of the packet, 8 bytes total. |
CANCEL (0c): Cancels a connection attempt
Sent under special circumstances when aborting a connection attempt. Cancel type/reason is only used for DWC Logs.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | Cancel type/reason |
0x04 | End of the packet, 4 bytes total. |
CANCEL_SYN (0d): Cancel SYN
This contains a little-endian PID and is sent by the host when a player tried to join, only connected partially, and then disconnected again. He hasn't done a full Natneg, so he can't send a disconnect himself, so the host sends a ST0D packet.
CANCEL_SYN_ACK (0e): Cancel SYN ACK
Other players acknowlegde a 0x0d with a 0x0e packet.
CANCEL_ACK (0f): Cancel ACK
Type 0F is sent by the host after receiving all 0x0e packets to confirm the disconnection of the half-connected player.
SC_CLOSE_CL (10): Host disconnect?
Disconnects one or many players. Can contain multiple PIDs after another.
Offset | Size | Endian | Description |
---|---|---|---|
0x04 * n | 4 | little | PID to disconnect |
0x04 * n+1 | End of the packet. |
Seems to be sent by the host when he disconected joining player(s) because the room doesn't go on suspend.
SVDOWNQUERY (52): New host request
This packet is sent by a player when the current host disconnects. The wii which has been in the room for the longest (Dolphin may cause problems and room splits due to its wrong time ...) sends a ST52 record to every other Wii, with the only parameter being the time (minutes? seconds? races?) how long it has already been in the race.
SVDOWN_ACK (53): New host request reply: Maybe
When a Wii sends a ST52 request, the other Wiis may respond with ST53 or ST54. Responding with ST53 means "I don't know if you should be the host", and then they receive another ST53 as acknowledgement.
The new host then replys with ST55 to tell the Wii that he is now the new host.
SVDOWN_NAK (54): New host request reply: Yes
When a Wii sends a ST52 request, the other Wiis may respond with ST53 or ST54. Responding with ST54 means "Yes, you are now the new host, I don't know any better candidate".
The new host then replys with another ST52 just to acknowledge, which is again acknowledged with a ST53.
SVDOWN_KEEP (55): I am the new host
ST55 is sent by the new host to every Wii which answered the host request with ST53.
SUSPEND_MATCH (82): SUSPEND flag control
This status types are being used by the players to control and coordinate the SUSPEND status of the current room. The guests tell the host the status they want the room to be in, and the host tells the guests what status he is going to set the room to.
Guest requests SUSPEND = 1
This is sent by every guest when he wants to enable SUSPEND
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of host. |
0x04 | 4 | little | host flag. 0 for this record type, since this is sent by guests. |
0x08 | 4 | little | 1, the wanted suspend value |
0x0c | 4 | little | Slot of guest |
0x10 | End of the packet, 16 bytes total. |
Host sets SUSPEND = 1
The host has received requests from every client to enable suspend, confirms SUSPEND has been enabled.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of host. |
0x04 | 4 | little | Host flag, 1 as this is sent by the host |
0x08 | 4 | little | 1, to indicate the wanted SUSPEND value |
0x0c | 4 | little | slot usage mask. bit 1 for used slot, bit 0 for empty slot |
0x10 | End of the packet, 16 bytes total. |
Guests request SUSPEND = 0
Guest is ready to disable SUSPEND.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of host. |
0x04 | 4 | little | Host flag - 0, because it's sent by guests |
0x08 | 4 | little | 0 to indicate the guest wants to turn off SUSPEND |
0x0c | 4 | little | Client slot |
0x10 | End of the packet, 16 bytes total. |
Host sets SUSPEND = 0
This is sent by the host to indicate he is turning off suspend.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of host. |
0x04 | 4 | little | Host value, always 1 |
0x08 | 4 | little | 0, the new suspend value |
0x0c | 4 | little | slot usage mask. bit 1 for used slot, bit 0 for empty slot |
0x10 | End of the packet, 16 bytes total. |
Client acknowledge
This is just an acknowledge to a client's request, sent by the host.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of host. |
0x04 | 4 | little | host flag, so, 1. |
0x08 | End of the packet, 8 bytes total. |
Type 83: Polling
This packet is sent by the host to every other player every 15 seconds. It contains a list of used slots.
Offset | Size | Endian | Description |
---|---|---|---|
0x00 | 4 | little | PID of player. |
0x04 | 4 | little | Slot usage mask (12 bit data, 20 bit padding) |
0x08 | 4 | ? | unknown ID, changes when new client joins |
0x0c | End of the packet, 12 bytes total. |
Statistics
This is a summary of all status packages of 286 dumps (mostly private room versus races).
---------------------------------- msg status count type type+size ---------------------------------- 9126 GPCM90 01 24 by-server 704 STATUS 01 24 by-server 3669 GPCM90 02 34 by-server 327 STATUS 02 34 by-server 195 GPCM90 03 04 by-server 41 STATUS 03 04 by-server 4887 GPCM90 04 00 by-server 376 STATUS 04 00 by-server 3203 GPCM90 05 00 by-server 503 STATUS 05 00 by-server 4 GPCM90 06 08 by-server 7105 STATUS 07 08 peer-to-peer 1151 STATUS 0d 04 peer-to-peer 1191 STATUS 0e 00 peer-to-peer 1169 STATUS 0f 00 peer-to-peer 3 GPCM90 10 00 by-server 13 STATUS 10 00 peer-to-peer 7 GPCM90 10 04 by-server 22 STATUS 10 04 peer-to-peer 1 GPCM90 10 08 by-server 3 STATUS 10 08 peer-to-peer 262 STATUS 52 04 peer-to-peer 436 STATUS 53 00 peer-to-peer 31 STATUS 54 00 peer-to-peer 23 STATUS 55 04 peer-to-peer 13 STATUS 82 08 by-server 19987 STATUS 82 08 peer-to-peer 20 STATUS 82 10 by-server 29343 STATUS 82 10 peer-to-peer 237 STATUS 83 0c by-server 320349 STATUS 83 0c peer-to-peer
Old data structures
This is the old data structure in GNU C notation used by mkw-ana from the beginning. It is deprecated and will be removed later.
typedef struct udp_status_t { /*00*/ u32 record_id; // always 0xbb49cc4d (be) /*04*/ u32 unknown_04; // always 0x5a000000 (be) /*08*/ u8 subtype_id; // indicating the record sub type /*09*/ u8 ext_len; // length of record extension // total_record_len := '0x14 + ext_len' /*0a*/ u16 user_id[3]; // unique user id for this session ? /*10*/ u32 cid; // client id: // last 4 bytes of FC in reverse order /*14*/ union { struct // send by host, any anouncement? { /*14*/ u32 obj_cid; // client id of object /*18*/ } s04; struct // assign slot // => exception 'x x 7100 0514' found in 2013-01-24-ct-24h { /*14*/ u32 obj_cid; // client id of object /*18*/ u8 slot; // assign slot to 'obj_cid' /*19*/ u8 padding_19[3]; // always 0 /*1c*/ } s08; struct // send by host, client mask { /*14*/ u32 copy_of_cid; // copy of 'cid' above /*18*/ u16 slot_mask; // slot usage mask in little endian // each 1-bit represents one active client /*1a*/ u16 unknown_1a; // always 0 /*1e*/ u32 unknown_1c; // any checksum or random token? /*20*/ } s0c; struct // to host, verify assigned slot? { /*14*/ u32 obj_cid; // copy of 'cid' above /*18*/ u16 unknown_18; // always 0x0000|0x0100 (be) /*1a*/ u16 unknown_1a; // always 0 /*1c*/ u16 unknown_1c; // always 0x0000|0x0100 (be) /*1e*/ u16 unknown_1e; // always 0 /*20*/ u8 slot; // assigned slot of 'obj_cid' // or 0x1f or 0xff /*21*/ u8 padding_21[3]; // always 0 /*22*/ } s10; }; } __attribute__ ((packed)) udp_status_t;