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
IOS/KD: Add WiiLink as WC24 service provider by default #11903
Conversation
The changes look sane - I wonder if we should use a dropdown instead of a checkbox though, just in case we decide to add more WC24 service provider in the future. Also, I think it'd be nice to have a description of what WiiLink is in the tooltip text. |
Alternatively, let's add an INI override for the server names to e.g. make local testing/development of WiiLink style services easier |
d5ca6f2
to
f5e255d
Compare
Added an INI field as requested, as well as rename I have also added WiiLink URLs to the default INI. Nintendo Channel is also currently not in a complete state as main requests use SSL. |
82d0615
to
fa0f536
Compare
Looks like MSVC is unhappy about operator< being used on bools; this is a side effect of the wrong overload of TryParse getting selected. Consider adding a specialisation of TryParse for boolean enums: https://godbolt.org/z/xPn5dzzof // add this:
template <typename T> requires (detail::IsBooleanEnum<T>())
bool TryParse(T* output) {
bool value;
if (!TryParse(&value))
return false;
*output = static_cast<T>(value);
return true;
}
// and then change the integer/enum template to this:
template <typename T>
requires (std::is_integral_v<T> || (std::is_enum_v<T> && !detail::IsBooleanEnum<T>()))
bool TryParse(T* output); |
Just added the patches in the INI files for all regions of the Nintendo Channel. Should be good to merge now. |
Data/Sys/GameSettings/HAF.ini
Outdated
|
||
[WC24Patch] | ||
$Main | ||
weather.wapp.wii.com:fore.wiilink24.com:1 |
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.
Can you please add end-of-file newlines to all your inis?
Source/Core/Core/ConfigManager.cpp
Outdated
@@ -54,6 +54,7 @@ | |||
#include "Core/TitleDatabase.h" | |||
#include "VideoCommon/HiresTextures.h" | |||
|
|||
#include "Core/WC24PatchEngine.h" |
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 include should go into the block with the other Core includes. Maybe also add a newline between the Core block and the VideoCommon one while you're there.
u32 NWC24Dl::GetHighTitleID(u16 entry_index) const | ||
{ | ||
return Common::swap32(m_data.entries[entry_index].high_title_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.
This function doesn't seem to be used anywhere?
if (std::optional<std::string> patch = | ||
WC24PatchEngine::GetNetworkPatch(parts[2], WC24PatchEngine::IsKD{true})) | ||
{ | ||
url = ReplaceAll(url, parts[2], patch.value()); |
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 seems too broad, this would also replace instances outside the domain part.
Source/Core/Core/WC24PatchEngine.cpp
Outdated
if (source.find(patch.source) != std::string::npos && patch.is_kd != IsKD{true}) | ||
// We found the correct patch, return it! | ||
return ReplaceAll(std::string{source}, patch.source, patch.replacement); |
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 also seems too aggressive. You'd be replacing any instances outside the Host header, too.
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 on the other hand is still clearly wrong. You're targetting the Host:
part of the HTTP header here, yeah? https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages In that case, you should also only search in that area of the request. Basically, something like (untested if this actually works, you might want to write a unit test for the logic because it seems prone to off-by-one errors...)
size_t pos = 0;
while (pos < source.size())
{
if (source[pos] == '\n') // end of header
break;
if (source.substr(pos).starts_with("Host:"))
{
size_t end_of_line = source.find('\n', pos);
std::string_view domain =
source.substr(pos + 5, end_of_line == std::string_view::npos ? std::string_view::npos :
(end_of_line - pos - 5));
for (const NetworkPatch& patch : s_patches)
{
if (domain.trim() == patch.source)
{
return source.substr(0, pos) + "Host: " + patch.replacement +
(end_of_line == std::string_view::npos ? "" : source.substr(end_of_line));
}
}
}
else
{
size_t end_of_line = source.find('\n', pos);
if (end_of_line == std::string_view::npos)
break;
pos = end_of_line + 1;
}
}
return std::nullopt;
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 example was a big help. With some testing and looking at RFC2616, all HTTP messages have CRLF line endings, so I opted for checking for that instead of just \n
. Other than that and the return line, it works perfectly with my testing in the Nintendo Channel.
Aside from those this seems fine. I'll grant that it's not particularly likely that those domains would appear anywhere outside the specific places you're expecting them, but it still doesn't seem a great idea to run a blanket search-and-replace when you could be more targetted to what you're actually expecting. |
WC24PatchEngine::GetNetworkPatch(parts[2], WC24PatchEngine::IsKD{true})) | ||
{ | ||
const size_t index = url.find(parts[2]); | ||
url.replace(index, parts[2].size(), patch.value()); |
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 is better but I feel you could still trick this if you really tried to...
It's probably fine given typical input but if you feel motivated you might want to actually extract the host part of the URI based on https://www.rfc-editor.org/rfc/rfc3986 and just target that part.
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 you really want me to I can fix it, otherwise I might just defer it to another time.
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.
Eh... like I said, if you feel motivated. You'd have to actively try to abuse this, and to questionable effect.
@@ -241,6 +241,7 @@ const Info<bool> MAIN_ALLOW_SD_WRITES{{System::Main, "Core", "WiiSDCardAllowWrit | |||
const Info<bool> MAIN_ENABLE_SAVESTATES{{System::Main, "Core", "EnableSaveStates"}, false}; | |||
const Info<bool> MAIN_REAL_WII_REMOTE_REPEAT_REPORTS{ | |||
{System::Main, "Core", "RealWiiRemoteRepeatReports"}, true}; | |||
const Info<bool> MAIN_WII_WIILINK_ENABLE{{System::Main, "Core", "EnableWiiLink"}, true}; |
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 should probably default to off.
bfafb97
to
88b4ea3
Compare
Source/Core/Core/WC24PatchEngine.cpp
Outdated
if (source.substr(pos).starts_with("Host:")) | ||
{ | ||
size_t end_of_line = source.find("\r\n", pos); | ||
std::string_view domain = | ||
source.substr(pos + 6, end_of_line == std::string_view::npos ? std::string_view::npos : |
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 size_t end_of_line = source.find("\r\n", pos);
can be pulled out of the branch.
There's a mismatch here between the starts_with("Host:")
and .substr(pos + 6
, you're dropping a byte here. I'm not sure whether HTTP forces a space between the :
and the start of the data? Might be okay to just change to starts_with("Host: ")
?
Adding a few const
s to variables here wouldn't hurt either.
Common::IniFile ini; | ||
// If WiiLink is enabled then we load the Default Ini as that has the WiiLink URLs. | ||
if (Config::Get(Config::MAIN_WII_WIILINK_ENABLE)) | ||
ini = sconfig.LoadDefaultGameIni(); | ||
else | ||
ini = sconfig.LoadLocalGameIni(); |
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 logic here also feels a bit jank now that I think about it... I would expect user patches to apply in addition to the system ones, regardless of if the WiiLink option is enabled or not. Though I'd be okay with that being a follow-up by either you or someone else, I'm not expecting every user to suddenly start writing URL replacements into their INIs.
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 logic I was trying to get at here is that the WiiLink URL's will be contained within the INI's we pack. If Enable WiiLink is off, it would allow for users to put in their own replacement URL if they please. I just didn't want any conflicts between the INI's URL's
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.
Untested, but this looks reasonable enough to me now.
if (patch) | ||
{ | ||
data = patch->c_str(); | ||
BufferInSize = static_cast<u32>(patch->size()) - 2; |
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.
Upon reviewing payload sizes and how they look, all Nintendo Channel payloads were data_size - 2
. This is because the literal FR
was at the end of the string, not sure what it is for but it should not be sent through the socket.
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.
Oh, duh, yeah that's not a nullterminated string so we're treating it incorrectly. That explains your corruption. Please change it to
const std::optional<std::string> patch = WC24PatchEngine::GetNetworkPatchByPayload(
std::string_view(data, BufferInSize));
if (patch)
{
data = patch->c_str();
BufferInSize = static_cast<u32>(patch->size());
}
and see if it's correct then.
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.
Works like a charm.
As discussed, this PR has WiiLink as the default service for WiiConnect24 services by default (More are coming!)
Currently, there is a checkbox users can toggle in the config to disable or enable WiiLink. If enabled, it will reroute requests by a supportted channel to the WiiLink equivalent.
Image of the config option under
Wii
TODO:
Somewhere to put the Terms of Service visibly. JMC had the idea of having it popup much like the Analytics disclaimer.