MKWii Network Protocol/Server

From Custom Mario Kart
< MKWii Network Protocol(Redirected from SAKE)
Jump to: navigation, search

The following table gives an overview about Nintendo's servers accessed by various DS(i)/Wii games, such as Mario Kart Wii.

Server Overview

If entering the WFC, Mario Kart Wii starts with a series of DNS queries to resolve 14 domain names. All of these names and some more are stored in the table. The different servers have different functionality, and some seems to be backup servers. It also seems, that each functionalities is assigned to exact one port and will use exact one network protocol.


Nintendo's Servers for Mario Kart Wii
DNS Name IP Address Port Protocol Description
gamestats.gs.nintendowifi.net
mariokartwii.gamestats.gs.nintendowifi.net
69.10.30.240 29920 N/A These are looked up, but never used.
gamestats2.gs.nintendowifi.net
mariokartwii.gamestats2.gs.nintendowifi.net
69.10.30.234 N/A TCP These are looked up, but never used.
gpcm.gs.nintendowifi.net 69.10.30.242 29900 TCP This connection is used to manage friends and to inform about one's status.
gpsp.gs.nintendowifi.net 69.10.30.241 29901 TCP The server exchanges profile ids into user nicks.
mariokartwii.available.gs.nintendowifi.net
mariokartwii.master.gs.nintendowifi.net
69.10.30.248 27900 UDP See pages
mariokartwii.ms19.gs.nintendowifi.net 69.10.30.247 28910 TCP This server handles database requests for online matchmaking.
mariokartwii.natneg1.gs.nintendowifi.net 69.10.30.254 27901 UDP NAT NEGotiation is a way to bypass NAT and firewalls.
mariokartwii.natneg2.gs.nintendowifi.net 69.10.30.253 27901 UDP NAT NEGotiation is a way to bypass NAT and firewalls.
mariokartwii.natneg3.gs.nintendowifi.net 69.10.30.252 27901 UDP NAT NEGotiation is a way to bypass NAT and firewalls.
mariokartwii.sake.gs.nintendowifi.net 69.10.24.119 443 TCP/HTTP(S) This server handles Mii exchange and Ghost up/downloads
naswii.nintendowifi.net 192.195.204.143
69.25.139.143
443 TCP/HTTP(S) The authority DNS server delivers randomly both IP addresses with a TTL (time to live) of 30s to support a kind of load balancing.
mariokartwii.race.gs.nintendowifi.net 69.10.24.125 443 TCP/HTTP(S) This server is used for time trial / competition leaderboards and the actual competition distribution.

mariokartwii.available.gs.nintendowifi.net

Available (0x09)

The Wii checks if the server is available.

09 00 00 00 00 6d 61 72 69 6f 6b 61 72 74 77 69 69 00
09 			is the record typ (AVAILABLE)
00 00 00 00		status ("disabled services" bit field)
6d 61 72 69 6f 6b \
61 72 74 77 69 69	gamename ("mariokartwii")
00 			end

if it is available, the bitfield is empty (all services are available):

fe fd 09 00 00 00 00
fe fd		Nintendo-Answer
09		Type (AVAILABLE)
00 00 00 00	status

When the server's down permanent, bit 1 is set:

fe fd 09 00 00 00 01
fe fd		Nintendo-Answer
09		Type (AVAILABLE)
00 00 00 01	status

(Results in "20110").

When the server's having maintenance (temporarily down), bit 2 is set:

fe fd 09 00 00 00 02
fe fd		Nintendo-Answer
09		Type (AVAILABLE)
00 00 00 02	status

(Results in "20101").

mariokartwii.sake.gs.nintendowifi.net

x.sake.gs.nintendowifi.net/SakeStorageServer/StorageServer.asmx
x is the internal game name, for example mariokartwii.

For Mii requesting, the game sends the following to /SakeStorageServer/StorageServer.asmx, with a header, SOAPAction: "http://gamespy.net/sake/GetMyRecords

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://gamespy.net/sake">
<SOAP-ENV:Body>
<ns1:GetMyRecords>
<ns1:gameid>1687</ns1:gameid>
<ns1:secretKey>9r3Rmy</ns1:secretKey>
<ns1:loginTicket>xxxxxxxx_YYYYYYYYYY__</ns1:loginTicket>
<ns1:tableid>FriendInfo</ns1:tableid>
<ns1:fields><ns1:string>info</ns1:string><ns1:string>recordid</ns1:string></ns1:fields>
</ns1:GetMyRecords>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Then it's sent back the PID it wants, along with the Mii data in base64, like so:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetMyRecordsResponse xmlns="http://gamespy.net/sake">
<GetMyRecordsResult>Success</GetMyRecordsResult>
<values><ArrayOfRecordValue>
<RecordValue><binaryDataValue><value>$mii</value></binaryDataValue></RecordValue>
<RecordValue><intValue><value>$pid</value></intValue></RecordValue>
</ArrayOfRecordValue></values>
</GetMyRecordsResponse>
</soap:Body>
</soap:Envelope>

$mii is the mii and $pid is the profile id.

naswii.nintendowifi.net

As you can see here, it is possible to force the Wii to use HTTP to connect to nas.nintendowifi.net instead of naswii.nintendowifi.net. By adding a simple ":81" to the URL in the main.dol it's also possible to force the Wii to use another port than 80/443.

While logging in, there is an SSL communication with naswii.nintendowifi.net.

There is base64 encoded information:

LOGIN (Wii to Nintendo):

action=login
gsbrcd=RMCJ2abcdef	The second part of the unique nick name. 
userid=1739273526102	The decoded first part of the unique nick name. 
ingamesn= n o   n a m e	For Wii its the Mii name, for DS its the User name
sdkver=001000		Always "1.0" for MKWii (two 3-char decimal numbers)
gamecd=RMCE		ID4 of Game
makercd=01		last two digits of ID6
unitcd=1		?
macadr=001712345678	The WLAN-MAC-Adress of the Wii
lang=01			A language code. English is 01, German is 02
devtime=140228160425	Wii date/time in Format YYMMDDhhmmss
csnum=LU123456789	Wii S/N
cfc=1234567890123456	Wii FC
region=01		Any region identifier. Maybe the same as the language code

ACCTCREATE (Wii to Nintendo)

action=acctcreate
sdkver=001000		Always "1.0" for MKWii (two 3-char decimal numbers)
gamecd=RMCP		ID4 of Game
makercd=01		last two digits of ID6
unitcd=1		?
macadr=001712345678	The Wiis WLAN-MAC-Adress
lang=02			A language code. English is 01, German is 02. 
devtime=140304203139	Wii date/time in Format YYMMDDhhmmss
csnum=LU123456789	Wii S/N
cfc=1234567890123456	Wii FC
region=02		Any region identifier. May be the same as the language code

Nintendo to Wii:

challenge=687TF0EG	Any challenge
locator=gamespy.com	?
retry=0			count of retries
returncd=00		returncode. Bigger than 99, lower than 1000: Error message 20XXX.
                        Bigger than 1000: Turn off Wii
token=...		Same token as during LOGIN
datetime=20140228210452	Server date/time in format YYYYMMDDhhmmss

In DS-Games there is also the following data from DS to Nintendo:

apinfo=XX-0000000-00	XX is 00 for the first WiFi-Connection, 01 for the second,
                        02 for the third and probably 03 for the Nintendo USB Connector
devname=...		Username in UTF16-LE
passwd=...		Unknown three-digit code
bssid=000d0bf85370	WLAN-MAC from WLAN-AP
birth=071b		Two bytes Birthdate. First byte is Month (July), second Day (27th)

mariokartwii.race.gs.nintendowifi.net

RACE is used for Top 10 in Mario Kart Wii, along with competitions (tournaments), and is paired with SAKE for downloading of ghosts.

For Top10 rankings, the game POSTs:

      <?xml version="1.0" encoding="UTF-8"?>
        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://gamespy.net/RaceService/">
          <SOAP-ENV:Body>
            <ns1:GetTopTenRankings>
              <ns1:gameid>1687</ns1:gameid>
              <ns1:regionid>$rid</ns1:regionid>
              <ns1:courseid>$cid</ns1:courseid>
            </ns1:GetTopTenRankings>
          </SOAP-ENV:Body>
        </SOAP-ENV:Envelope>

Where 1687 is Mario Kart Wii's unique gameID, $rid is the region ID (0 if worldwide), and $cid is courseID The server then responds:

      <?xml version="1.0" encoding="utf-8"?>
        <RankingDataResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://gamespy.net/RaceService/">
          <responseCode>0</responseCode>
          <dataArray>
            <numrecords>$amount</numrecords>
            <data>
              <RankingData>
                <ownerid>$pid</ownerid>
                <rank>1</rank>
                <time>$time</time>
                <userdata>$mii</userdata>
              </RankingData>
              <RankingData>
                <ownerid>$pid</ownerid>
                <rank>2</rank>
                <time>$time</time>
                <userdata>$mii</userdata>
              </RankingData>
              <RankingData>
                <ownerid>$pid</ownerid>
                <rank>3</rank>
                <time>$time</time>
                <userdata>$mii</userdata>
              </RankingData>
              <RankingData>
                <ownerid>$pid</ownerid>
                <rank>4</rank>
                <time>$time</time>
                <userdata>$mii/userdata>
              </RankingData>
              <RankingData>
                <ownerid>$pid</ownerid>
                <rank>5</rank>
                <time>$time</time>
                <userdata>$mii</userdata>
		</RankingData>
		<RankingData>
		<ownerid>$pid</ownerid>
		<rank>6</rank>
		<time>$time</time>
		<userdata>$mii</userdata>
		</RankingData>
		<RankingData>
		<ownerid>$pid</ownerid>
		<rank>7</rank>
		<time>$time</time>
		<userdata>$mii</userdata>
		</RankingData>
		<RankingData>
		<ownerid>$pid</ownerid>
		<rank>8</rank>
		<time>$time</time>
		<userdata>$mii</userdata>
		</RankingData>
		<RankingData>
		<ownerid>$pid</ownerid>
		<rank>9</rank>
		<time>$time</time>
		<userdata>$mii</userdata>
		</RankingData>
		<RankingData>
		<ownerid>$pid</ownerid>
		<rank>10</rank>
		<time>$time</time>
		<userdata>$mii</userdata>
		</RankingData>
		</data>
		  </dataArray>
</RankingDataResponse>

Where $amount is how many records (only give as many RankingData sections as needed per amount), $pid is the profile ID, $time is the time, and $mii is the Mii in BASE64.

dls1.nintendowifi.net

DLS1 is not used by Mario Kart Wii, however it is best to include it. An example of DLS1 usage is Pokemon DS Mystery Gifts.

Once authenticated via NAS, the game sends (in base64):

sdkver=002002
userid=2022983770208
passwd=172
bssid=A1B2C3D4E5F6
apinfo=01:0000000-00
gamecd=CPUE
makercd=01
unitcd=0
macadr=345678901234
lang=01
birth=MMDD
devtime=150813185742
devname=B i l l y   H
action=SVCLOC
svc=9000

Where bssid is your WiFi's BSSID, macadr is your MAC address, devname is your name in UTF-16, and APInfo is which access point it uses.

The server sends back:

retry=0
returncd=007
token=NDS/SVCLOC/TOKEN/123.456.789.000|abcdefghijkl
servicetoken=NDS/SVCLOC/TOKEN/123.456.789.000|abcdefghijkl
statusdata=Y
svchost=dls2.pokeacer.xyz
datetime=20150813195801

Where svchost is the DLS1 server to connect to (in this case PokeAcer's NDS server).


The client then sends a request to /download, saying:

gamecd=CPUE
rhgamecd=CPUE
passwd=DwuCXmdJfPVLBnKA
token=NDS/SVCLOC/TOKEN/123.456.789.000|abcdefghijkl
userid=2022983770208
macadr=345678901234
action=count
apinfo=01:0000000-00

Where action = count, which means to count how many files are on the server. In the case of Pokémon, however, the server must lie and pick either a random one in the folder (what public implementations do) or list the only file in the server (what Nintendo probably did).

The server then responds with how many (in this case, '1'), and then the client sends:

gamecd=CPUE
rhgamecd=CPUE
passwd=DwuCXmdJfPVLBnKA
token=NDS/SVCLOC/TOKEN/123.456.789.000|abcdefghijkl
userid=2022983770208
macadr=345678901234
action=list
apinfo=01:0000000-00
offset=0
num=10

And then the server responds with the file name, some NULL characters, then a number.

The game finally sends:

gamecd=CPUE
rhgamecd=CPUE
passwd=DwuCXmdJfPVLBnKA
token=NDS/SVCLOC/TOKEN/123.456.789.000|abcdefghijkl
userid=2022983770208
macadr=345678901234
action=contents
apinfo=01:0000000-00
contents=21dppUS.myg

To which the server sends the file.


Record Types
HEADERROOMSELECTUSER
RACEHEADER_1RACEHEADER_2RACEDATAITEMEVENT
NATNEGANNOUNCEQUITSTATUSPARAM-STRING
Related Infos
Nintendos ServersFriend Code & Player IDUser NickDumping Network Traffic
Wiimmfi Extensions
Online StatusConnection StatusWiimmfi packetsServer SV
Software
Wiimms mkw-ana
Forums Wiimmfi-Project