Migration services: Difference between revisions

No edit summary
No edit summary
 
(9 intermediate revisions by one other user not shown)
Line 28: Line 28:
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)
| 201 || [7.0.0+] [[#ResumeUserMigrationClient|ResumeUserMigrationClient]] ([4.0.0-6.2.0] ResumeClient)
|-
|-
| 1001 || [8.0.0+] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]
| 1001 || [8.0.0-20.5.0] [[#GetSaveDataMigrationPolicyInfoAsync|GetSaveDataMigrationPolicyInfoAsync]]
|-
|-
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo
| 1010 || [7.0.0+] TryGetLastSaveDataMigrationInfo
Line 169: Line 169:
| 0 || GetUid
| 0 || GetUid
|-
|-
| 1 || GetServerProfile
| 1 || [[#GetServerProfile|GetServerProfile]]
|-
|-
| 100 || PrepareAsync
| 100 || PrepareAsync
Line 191: Line 191:
| 500 || Abort
| 500 || Abort
|}
|}
=== GetServerProfile ===
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].


== IClient ==
== IClient ==
Line 289: Line 292:
| 1 || [7.0.0-19.0.1] GetApplicationId
| 1 || [7.0.0-19.0.1] GetApplicationId
|-
|-
| 2 || GetServerProfile
| 2 || [[#GetServerProfile_2|GetServerProfile]]
|-
|-
| 3 || [17.0.0+] ListApplicationIds
| 3 || [17.0.0+] ListApplicationIds
Line 299: Line 302:
| 102 || [20.0.0+]
| 102 || [20.0.0+]
|-
|-
| 200 || WaitConnectionAsync
| 200 || [[#WaitConnectionAsync|WaitConnectionAsync]]
|-
|-
| 201 || GetClientProfile
| 201 || GetClientProfile
Line 308: Line 311:
|-
|-
| 210 || [8.0.0+] WaitAcceptanceAsync
| 210 || [8.0.0+] WaitAcceptanceAsync
|-
| 220 || [21.0.0+]
|-
|-
| 300 || ProcessTransferAsync
| 300 || ProcessTransferAsync
Line 315: Line 320:
| 500 || [7.0.0-19.0.1] Abort
| 500 || [7.0.0-19.0.1] Abort
|-
|-
| 510 || [19.0.0+]
| 510 || [19.0.0-20.5.0]
|-
| 511 || [21.0.0+]
|-
|-
| 998 || [8.0.0+] DebugTryGetState
| 998 || [8.0.0+] DebugTryGetState
Line 321: Line 328:
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync
| 999 || [8.0.0+] DebugWaitStateSynchronizationFinalizedAsync
|}
|}
=== GetServerProfile ===
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].


=== PrepareAsync ===
=== PrepareAsync ===
Line 328: Line 338:


[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].
[20.0.0+] The above policy functionality is no longer present. This now eventually uses network request [[Network|transfer_events/start]].
=== WaitConnectionAsync ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
The async task does the following:
* ...
* Initializes the data used for the AdvertiseData.
* Calls a func which:
** Calls a func which handles [[LDN_services|ldn]] initialization and network creation. SetProtocol is also used with a value from state.
** Calls a func which:
*** Handles setup for the server socket.
*** Uses [[LDN_services|SetAdvertiseData]] with the above AdvertiseData buffer.
*** Waits for a ldn Node to connect, with timeout etc handling.
*** Then [[LDN_services|SetStationAcceptPolicy]] is used with value 3 (WhiteList), and [[LDN_services|AddAcceptFilterEntry]] is used.
** Calls a func which waits for a socket connection (with timeout etc), and handles socket setup for it.
** Uses [[LDN_services|SetAdvertiseData]] with buf/size = 0 (empty AdvertiseData).
** Uses [[LDN_services|SetStationAcceptPolicy]] with value 1 (AlwaysReject).
** Enters a loop waiting for a state field to become value 0x3. Two funcs are called repeatedly in this loop, with cleanup and return being handled if these return error.
*** The first func receives socket data and handles it. The second func calls a func to get data for sending, then sends the socket data. Both have timeout etc handling.
** Updates state and returns 0.
* ...
=== Cmd510 ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].


== IClient ==
== IClient ==
Line 352: Line 388:
| 220 || [8.0.0+] AcceptAsync
| 220 || [8.0.0+] AcceptAsync
|-
|-
| 221 || [8.0.0+] DeclineAsync
| 221 || [8.0.0-20.5.0] DeclineAsync
|-
| 222 || [21.0.0+]  
|-
|-
| 300 || GetStorageShortfall
| 300 || GetStorageShortfall
Line 391: Line 429:
No input, returns an [[#IAsyncContext|IAsyncContext]].
No input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this uses network request [[Network|transfer_events/%lld/finish_transfer]].
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_transfer]].


== IServer ==
== IServer ==
Line 402: Line 440:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 ||  
| 0 || [[#GetServerProfile_3|GetServerProfile]]
|-
|-
| 10 ||  
| 10 ||  
Line 422: Line 460:
| 111 ||  
| 111 ||  
|-
|-
| 120 ||  
| 120 || [20.0.0-20.5.0]
|-
| 121 || [21.0.0+]
|-
|-
| 130 ||  
| 130 ||  
Line 436: Line 476:
| 400 ||  
| 400 ||  
|-
|-
| 510 ||  
| 510 || [20.0.0-20.5.0]
|-
| 511 || [21.0.0+]
|-
|-
| 900 ||  
| 900 ||  
|}
|}
=== GetServerProfile ===
Unofficial name.
Takes a type-0x1A output buffer containing a [[#ServerProfile|ServerProfile]].


=== Cmd230 ===
=== Cmd230 ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
No input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this uses network request [[Network|transfer_events/start]].
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].
 
=== Cmd510 ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
 
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_transfer]].


== IClient ==
== IClient ==
Line 535: Line 587:
| 90 ||  
| 90 ||  
|-
|-
| 100 ||  
| 100 || [20.0.0-20.5.0]
|-
| 101 || [21.0.0+]
|-
|-
| 310 ||  
| 310 ||  
Line 551: Line 605:
| 500 ||  
| 500 ||  
|-
|-
| 610 ||  
| 610 || [20.0.0-20.5.0]
|-
| 611 || [21.0.0+]
|-
|-
| 900 ||  
| 900 ||  
Line 559: Line 615:
No input, returns an [[#IAsyncContext|IAsyncContext]].
No input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this uses network request [[Network|transfer_events/start]].
Besides other functionality, this async task uses network request [[Network|transfer_events/start]].


=== Cmd500 ===
=== Cmd500 ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
No input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this uses network request [[Network|transfer_events/%lld/finish_upload]].
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_upload]].
 
=== Cmd610 ===
No input, returns an [[#IAsyncContext|IAsyncContext]].
 
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/abort_upload]].


=== Cmd900 ===
=== Cmd900 ===
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this may call the same network-request func as [[#Cmd500]].
Besides other functionality, this async task may call the same network-request func as [[#Cmd500]].


== IDownloader ==
== IDownloader ==
Line 597: Line 658:
|-
|-
| 330 ||  
| 330 ||  
|-
| 390 || [21.0.0+]
|-
|-
| 400 ||  
| 400 ||  
Line 612: Line 675:
No input, returns an [[#IAsyncContext|IAsyncContext]].
No input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this uses network request [[Network|transfer_events/%lld/finish_download]].
Besides other functionality, this async task uses network request [[Network|transfer_events/%lld/finish_download]].


=== Cmd900 ===
=== Cmd900 ===
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].
Takes a total of 4-bytes of input, returns an [[#IAsyncContext|IAsyncContext]].


Besides other functionality, this may call the same network-request func as [[#Cmd500_2|Cmd500]].
Besides other functionality, this async task may call the same network-request func as [[#Cmd500_2|Cmd500]].
 
= ServerProfile =
This is a 0x100-byte struct.
 
It's unknown whether user/savedata/device use the same struct (size is the same for these).
 
Any data here which is initialized is usually zeros?
 
= Protocol =
Once connected with [[LDN_services|ldn]], the client node connects to the server with TCP port 441.
 
The first byte of messages is the message-type.
 
Messages are encrypted with AES-128-GCM. The key is derived during the initial message-handling loop (WaitConnectionAsync).
 
= AdvertiseData =
These sections document the initial [[LDN_services|AdvertiseData]] used by migration.
 
The global constant used with hashing below is the same regardless of the AdvertiseData.
 
Later the server also sets the AdvertiseData to {0x10-byte Uuid previously used below}.
 
The Uuid used below is generated with <code>nn::util::GenerateUuid</code>.
 
== user ==
Used by nn::migration::user::*.
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x8 || AccountId
|-
| 0x8 || 0x58 || Unused
|-
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]
|-
| 0x160 || 0x20 || SHA256 hash
|}
 
The hash is calculated by using SHA256-update with each field separately, followed by global constant:
* AccountId
* ServerProfile
* 0x100-byte global constant
 
== savedata ==
Used by nn::migration::savedata::*.
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x8 || AccountId
|-
| 0x8 || 0x8 || ApplicationId
|-
| 0x10 || 0x50 || Unused
|-
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]
|-
| 0x160 || 0x20 || SHA256 hash
|}
 
The hash is calculated by using SHA256-update with each field separately, followed by global constant:
* AccountId
* ApplicationId
* ServerProfile
* 0x100-bytes global constant
 
[20.0.0+]:
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x10 || Uuid
|-
| 0x10 || 0x8 || AccountId
|-
| 0x18 || 0x8 || ApplicationId
|-
| 0x20 || 0x4 || [[Settings_services#GetProductModel|ProductModel]]
|-
| 0x24 || 0x4 || Padding
|-
| 0x28 || 0x100 || [[#ServerProfile|ServerProfile]]
|-
| 0x128 || 0x20 || SHA256 hash
|}
 
The hash is calculated by using SHA256-update with each field separately, followed by global constant:
* Uuid
* AccountId
* ApplicationId
* ProductModel
* ServerProfile
* 0x100-bytes global constant
 
== device ==
Used by nn::migration::device::*.
 
{| class="wikitable" border="1"
|-
! Offset || Size || Description
|-
| 0x0 || 0x10 || Uuid
|-
| 0x10 || 0x40 (0x8*0x8) || Array of u64s with the below count.
|-
| 0x50 || 0x4 || Count for the above array.
|-
| 0x54 || 0xC || Unused
|-
| 0x60 || 0x100 || [[#ServerProfile|ServerProfile]]
|-
| 0x160 || 0x20 || SHA256 hash
|}
 
The hash is calculated by using SHA256-update with each field separately, followed by global constant:
* Uuid
* +0x10 size 0x40-bytes
* +0x50 size 0x4-bytes
* ServerProfile
* 0x100-bytes global constant


= Notes =
= Notes =