-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement UDS service with example #156
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great PR! A bit long for my liking, but I saw you followed our standards for the public API. Sadly, I have no way to thoroughly test the changes since I can't make a local network (I only have one 3DS). Is there any way I can test things out, maybe with an emulator?
@@ -150,7 +150,7 @@ impl IrUser { | |||
shared_mem.shared_memory_layout, | |||
); | |||
|
|||
Ok(()) | |||
Ok::<_, Error>(()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AzureMarker Ehm, do you remember why a closure is used here? It doesn't seem to be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was done so I could use ?
, like the unstable try
block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change was the easiest way to fix a compile error introduced by my implementation of FromResidual
. If I handle errors a different way, this change can be reverted.
ctru-rs/src/services/uds.rs
Outdated
|
||
/// Returns the current [`ctru_sys::udsConnectionStatus`] struct. | ||
/// | ||
/// TODO: should this return an error if not connected? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so, the internal ctru_sys::udsConnectionStatus
contains informations specific to an existing network.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like calling it when not connected actually returns success. On New 3DS, I get
ConnectionStatus {
status: 3,
unk_x4: 0,
cur_node_id: 2,
unk_xa: 0,
unk_xc: [0, 0, 0, 0, 0, 0, 0, 0],
total_nodes: 0,
max_nodes: 0,
node_bitmask: 0,
}
and on Old 3DS I get
ConnectionStatus {
status: 3,
unk_x4: 0,
cur_node_id: 0,
unk_xa: 0,
unk_xc: [0, 0, 0, 0, 0, 0, 0, 0],
total_nodes: 0,
max_nodes: 0,
node_bitmask: 0,
}
consistently (they're identical besides cur_node_id
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. At this point I wonder whether the status
member itself specifies whether or not the client is connected to a network. We should probably try to understand its meaning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
libctru
doesn't describe it at all, so it would very much be a reverse-engineering effort. From my 20 seconds of experimentation, it looks like a value of 6 represents connected. Presumably it's a bitfield.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I found some details, seems like it's more of a weird enum with sparse value choices? https://www.3dbrew.org/wiki/NWMUDS:GetConnectionStatus#Status_values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO
doc comment should be removed now that it's fixed.
I've looked a little bit into it and I think it's maybe possible to connect to a 3DS's network with another device, but it'd require more knowledge about how Wi-Fi works than I have. |
Functions left to implement:
So, only about 5½ that would be actually useful, and they're mostly trivial. |
ctru-rs/src/services/uds.rs
Outdated
|
||
/// Returns the current [`ctru_sys::udsConnectionStatus`] struct. | ||
/// | ||
/// TODO: should this return an error if not connected? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I found some details, seems like it's more of a weird enum with sparse value choices? https://www.3dbrew.org/wiki/NWMUDS:GetConnectionStatus#Status_values
!= ctru_sys::MAKERESULT( | ||
ctru_sys::RL_STATUS as _, | ||
ctru_sys::RS_OUTOFRESOURCE as _, | ||
ctru_sys::RM_UDS as _, | ||
ctru_sys::RD_BUSY as _, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this status represent? it still seems like it would be an error of some kind but we
return Ok
for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See libctru and the UDS example. There's probably a nicer way to handle this, but this does work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so this error code basically means a packet was still sent but some other error occurred, I guess? Seems fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, something like that. Maybe it'd be a good idea to hardcode it as a constant somewhere rather than calling it in the function, though - MAKERESULT
presumably isn't const
so it'd have to be a magic number with some explanation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it isn't const
, we probably can/should make it const
, same for any of those other helper functions that just do bit operations on Result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably, this would need to be changed in ctru_sys. Once somebody does that, I'll change this to be a little more elegant.
Doh Co-authored-by: Ian Chamberlain <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this is a pretty intense example but it seems necessary given how many features there are in the uds
service. I was wondering if some of this functionality could go onto Uds
itself instead of just in this example, but honestly on first read I don't see any obvious things that make sense, so 👍 good with me
|
||
println!("UDS initialised"); | ||
|
||
enum State { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a lot like a manually implemented future state machine. could this have worked better with async?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very possibly! I'm scared of async
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done some basic reading about futures, and I don't understand how this could be done with async. Could you explain how that would work? It would definitely be nice to clean up the code if it's possible.
ctru-rs/src/services/uds.rs
Outdated
|
||
/// Returns the current [`ctru_sys::udsConnectionStatus`] struct. | ||
/// | ||
/// TODO: should this return an error if not connected? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO
doc comment should be removed now that it's fixed.
This PR adds basic local networking functionality with the
UDS
service.It's very much not feature-complete, but enough is implemented to be able to interface with the devkitPRO local networking example - i.e. joining a network, creating a network, sending and pulling packets, and basic configuration. This is probably enough functionality for most homebrew applications, and I plan to try and implement a Download Play sniffer with it.
Todo: finish implementing the rest of the functions; test properly; cleanup code?
An example is included (
local-networking.rs
; this is a mostly-but-not-entirely-complete port of the devkitPRO local networking example).