Skip to content
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

[Http] Implement sceHttp library #18003

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft

[Http] Implement sceHttp library #18003

wants to merge 11 commits into from

Conversation

anr2me
Copy link
Collaborator

@anr2me anr2me commented Aug 28, 2023

This is what i was working on before Mega Man Powered Up official server shutdown in November 2022.

This code is still experimental (just to get things to work), but my implementation is kinda wrong compared to JPCSP implementation.
My implementation is to use the parent simply as a template/base to initialize it's contents (ie. headers, userAgent, etc), thus any changes (ie. cookies, userAgent, etc) to the parent won't reflects existing children.
But later, i find out that JPCSP implementation is id-based relationship between parent-child similar to database's records relationship) and changes on the parent will reflects on it's children, thus cookies can be shared on multiple children (like a multi-tabs on most browsers).

So, this PR will need to be rewritten (probably using naett to support HTTPS too in the future), also need to do communication in a background thread to avoid stuttering the emulation.
So leaving this as a draft until i had the time to rewrite it (in case i lost my local copy due to bad sector).

Tested to work on:

  • Mega Man Powered Up (before the official server shutdown)
  • Yu-Gi-Oh! DX Tag Force 2 & Monster Hunter games - partially fixes [Feature Request] Support in-game web browser #14637
  • PSP Browser (UTST99281) - partially working (no HTTPS support, and images doesn't shows up, not sure whether it's cross-origin issue or not) - not sure whether it works properly on JPCSP or not as i can't get pass the NetConfig dialog on JPCSP.

@hrydgard hrydgard added this to the Future-Prio milestone Aug 28, 2023
@anr2me
Copy link
Collaborator Author

anr2me commented Aug 28, 2023

Btw how do i clean up temporary/intermediate files that was used during ./b.sh ? as i'm running out of free space after building.

@Anuskuss
Copy link
Contributor

Yu-Gi-Oh! GX: Tag Force 2

39:35:260 ehscript     E[SCENET]: HLE/sceNet.cpp:798 UNIMPL sceNetInetInit()
39:35:260 ehscript     E[SCENET]: HLE/sceNet.cpp:1389 UNIMPL sceNetResolverInit()
39:35:260 ehscript     E[SCENET]: HLE/sceHttp.cpp:537 UNIMPL sceHttpsInit(0, 0, 0, 0)
39:35:260 ehscript     E[SCENET]: HLE/sceHttp.cpp:704 UNIMPL sceHttpLoadDefaultCert(0, 0)
39:35:260 ehscript     E[SCENET]: HLE/sceHttp.cpp:709 UNIMPL sceHttpLoadSystemCookie()
39:35:260 ehscript     E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceUtilityHtmlViewerInitStart
39:35:276 ehscript     E[SCENET]: HLE/sceHttp.cpp:699 UNIMPL sceHttpSaveSystemCookie()
39:35:276 ehscript     E[SCENET]: HLE/sceHttp.cpp:549 UNIMPL sceHttpsEnd()
39:35:276 ehscript     E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverTerm
39:35:276 ehscript     E[SCENET]: HLE/sceNet.cpp:806 UNIMPL sceNetInetTerm()

What am I doing wrong?

@anr2me
Copy link
Collaborator Author

anr2me commented Aug 29, 2023

The unimplemented sceUtilityHtmlViewerInitStart (which made the game think that something is wrong) probably triggering the sceHttp to ends.

The menu you're trying to open is probably the "Go to the Yu-Gi-Oh! website" which supposed to open a web browser/view through sceUtilityHtmlViewerInitStart (most-likely in a dialog form), which is not part of sceHttp library.

Sorry, i forgot that Yu-Gi-Oh uses sceUtilityHtmlViewerInitStart, while this PR only works on games that renders the web page (ie. simple html & images) them self (ie. Mega Man Powered Up)

@unknownbrackets
Copy link
Collaborator

Btw how do i clean up temporary/intermediate files that was used during ./b.sh ? as i'm running out of free space after building.

Basically just remove build/CMakeFiles iirc. Or you can just remove all of build/.

-[Unknown]

Copy link
Collaborator

@unknownbrackets unknownbrackets left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't look at everything, just a few quick conments from a quick skim of some funcs.

-[Unknown]

@@ -329,7 +329,7 @@ int Client::SendRequestWithData(const char *method, const RequestParams &req, co
return 0;
}

int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector<std::string> &responseHeaders, net::RequestProgress *progress) {
int Client::ReadResponseHeaders(net::Buffer *readbuf, std::vector<std::string> &responseHeaders, net::RequestProgress *progress, std::string * httpCode) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Would prefer statusLine rather than httpCode which isn't very clear. Also would prefer * next to the name, as is the convention used elsewhere. It's nice to dream that C+ would make pointer part of the type, but it isn't. int* foo, bar is not two pointers, so the * is objectively in the wrong place.

-[Unknown]

Copy link
Collaborator Author

@anr2me anr2me Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think VS2022 inserted that space when i copy-paste it while fixing the conflict during merge 🤔 because i never put spaces on both sides of * except for multiplication, it supposed to be *httpCode and missed the changes done by VS, but yeah the naming is odd when i read it again😅

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, VS2022 seems to have some weird default formatting settings, like that ugly else formatting...

-[Unknown]

const std::string& s = httpLine_ + delim + imploded.str();
u32 sz = (u32)s.size();

u32* headerAddr = (u32*)Memory::GetPointerUnchecked(headerAddrPtr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should validate these pointers and at least not crash...

-[Unknown]


entityLength_ = -1;
for (std::string& line : responseHeaders_) {
if (startsWithNoCase(line, "Content-Length:")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's valid to use Content-Length : 42 FWIW.

-[Unknown]


std::lock_guard<std::mutex> guard(httpLock);
httpObjects.clear();
// Reserve at least 1 element to prevent ::begin() from returning null when no element has been added yet
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not really what reserve does? You'd need to resize(1) for that. reserve just makes sure it's ready to have that much memory. I don't know if an empty container is actually required to have a valid pointer return for [0].

-[Unknown]

Copy link
Collaborator Author

@anr2me anr2me Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resize(1) will make count/size resulting to 1 isn't?
i only need to allocate the space without increasing the number of elements, so begin() can return an iterator object which matches end() when empty, without it apparently returned null instead of an iterator object.
The reason it must not be null is because on some part of the code the iterator object being increased using +1 or +id i think (i haven't re-read the whole code while fixing the conflict), thus could cause access violation.
So i'm using reserve just to ensure that begin() on an empty vector will always returns a valid iterator object where i can use + index_number without problem (as long not exceeding the number of elements).

And as i remembered it doesn't have this issue when the httpObjects is freshly created (ie. begin() of an empty vector returns an iteration object as in most c++ examples), only happened when reused i think (or was it the opposite, i kinda forgot😅 was getting a crash because of that null), may be i erased the elements the wrong way🤔 most of the one-liner code that dealt with vectors was taken from stackoverflow 😅

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, we should really should have a bool then or something. Trying to rely on whether there's memory at &x[0] when empty just seems like asking for trouble.

-[Unknown]

@Beyley
Copy link

Beyley commented Sep 2, 2023

With this PR applied it lets LBP PSP get further in its networking, although it still does not send any requests to a custom server.

here is the log after i try to connect from LBP PSP
image
(that unknown syscall is spammed afterward, and the game seems to freeze)

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

With this PR applied it lets LBP PSP get further in its networking, although it still does not send any requests to a custom server.

here is the log after i try to connect from LBP PSP image (that unknown syscall is spammed afterward, and the game seems to freeze)

Which menu did you choose to for this logs to appear?
i saw there are more than one menu that can trigger online activity, the "Go Online" menu seems to use sceNp library (which will probably won't be fully implemented as it communicates with Sony's server, currently just being faked to by pass it)

Also, do you know any private server i can test it with?

@Beyley
Copy link

Beyley commented Sep 2, 2023

Which menu did you choose to for this logs to appear? i saw there are more than one menu that can trigger online activity, the "Go Online" menu seems to use sceNp library (which will probably won't be fully implemented as it communicates with Sony's server, currently just being faked to by pass it)

Also, do you know any private server i can test it with?

I chose "go online" from the community moon, and even with faked sceNp, it should at least attempt to make a connection to a server, all you need to do is decrypt the EBOOT.BIN, patch the 2 URLs (search for http: in the EBOOT) to http://localhost/lbp and then just spin up some random http server and see if you can get any requests when you boot the game and go online, its possible a DNS redirect would work for the PSP game (it does not work for the PS3 games due to them using HTTPS and enforcing the certificate), but the PS3 games have advanced enough patching tools (that ive made work with PSP) where it was the easiest path for testing right now

There is no functional LBP PSP private server right now, thats what i am trying to work on, but the real hardware is not cooperating

update: i used the most recent version of the game, and after patching i get this message

11:06:060 user_main    E[SCENET]: HLE/sceParseUri.cpp:48 ffffffff=sceUriParse(08ed889c, http://[ip_redacted]:10061/LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 08ed69b0, 00000000, 101): invalid arg

Even though the URL is 100% valid

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

Which menu did you choose to for this logs to appear? i saw there are more than one menu that can trigger online activity, the "Go Online" menu seems to use sceNp library (which will probably won't be fully implemented as it communicates with Sony's server, currently just being faked to by pass it)
Also, do you know any private server i can test it with?

I chose "go online" from the community moon, and even with faked sceNp, it should at least attempt to make a connection to a server, all you need to do is decrypt the EBOOT.BIN, patch the 2 URLs (search for http: in the EBOOT) to http://localhost/lbp and then just spin up some random http server and see if you can get any requests when you boot the game and go online, its possible a DNS redirect would work for the PSP game (it does not work for the PS3 games due to them using HTTPS and enforcing the certificate), but the PS3 games have advanced enough patching tools (that ive made work with PSP) where it was the easiest path for testing right now

There is no functional LBP PSP private server right now, thats what i am trying to work on, but the real hardware is not cooperating

You will need the test build from here #14256 (comment) which have a lot of the sceNetInet* syscalls being implemented for infrastructure support.
But that test build still have socket id issue on Windows, the Linux/Android builds might worked better.

PS: Those test builds were based on an older version of PPSSPP, so you will need to use a matching assests files if it only came with the binary file.

@Beyley
Copy link

Beyley commented Sep 2, 2023

You will need the test build from here #14256 (comment) which have a lot of the sceNetInet* syscalls being implemented for infrastructure support. But that test build still have socket id issue on Windows, the Linux/Android builds might worked better.

PS: Those test builds were based on an older version of PPSSPP, so you will need to use a matching assests files if it only came with the binary file.

I was testing on this PR rebased to master, but that branch doesnt seem to get any further,

23:56:125 user_main    E[SCENET]: HLE/sceNet.cpp:1866 UNIMPL sceNetInetInit()
23:56:125 user_main    E[SCENET]: HLE/sceNet.cpp:3220 UNIMPL sceNetResolverInit()
23:56:875 user_main    E[SCENET]: HLE/sceHttp.cpp:54 UNIMPL sceHttpInit(153600)
23:56:875 user_main    E[SCENET]: HLE/sceHttp.cpp:154 UNIMPL sceHttpsInit(1, 167769456, 0, 0)
23:56:875 user_main    E[SCENET]: HLE/sceHttp.cpp:258 UNIMPL sceHttpLoadDefaultCert(0, 0)
23:56:875 user_main    E[HLE]: HLE/HLE.cpp:736 Unimplemented HLE function sceHttpsEnableOption
23:56:876 user_main    E[HLE]: HLE/HLE.cpp:736 Unimplemented HLE function sceHttpsDisableOption
23:56:876 user_main    E[HLE]: HLE/HLE.cpp:736 Unimplemented HLE function sceHttpsDisableOption
23:56:876 user_main    E[SCENET]: HLE/sceHttp.cpp:263 UNIMPL sceHttpLoadSystemCookie()
24:06:040 user_main    E[SCENET]: HLE/sceNp.cpp:107 UNIMPL sceNpInit()
24:06:040 user_main    E[SCENET]: HLE/sceNp.cpp:279 UNIMPL sceNpAuthInit(16384, 15360, 50)
24:06:041 user_main    E[SCENET]: HLE/sceNp.cpp:522 UNIMPL sceNpServiceInit(00004000, 00004000, 00000032)
24:11:145 ApctlThread  E[SCENET]: HLE/sceNp.cpp:378 UNIMPL sceNpAuthGetTicket(1, 09596472, 248) at 088930cc
24:11:177 user_main    E[SCENET]: HLE/sceHttp.cpp:200 UNIMPL sceHttpSetMallocFunction(8883ca8, 8883cb0, 8883cc8)
24:11:178 user_main    E[SCENET]: HLE/sceHttp.cpp:268 UNIMPL sceHttpCreateTemplate(LBPPSP CLIENT, 1, 1)
24:11:178 user_main    E[SCENET]: HLE/sceHttp.cpp:119 UNIMPL sceHttpSetConnectTimeout(1, 15000000)
24:11:178 user_main    E[SCENET]: HLE/sceHttp.cpp:124 UNIMPL sceHttpSetSendTimeout(1, 15000000)
24:11:178 user_main    E[SCENET]: HLE/sceHttp.cpp:284 UNIMPL sceHttpSetRecvTimeOut(1, 15000000)
24:11:178 user_main    E[SCENET]: HLE/sceHttp.cpp:144 UNIMPL sceHttpDisableCookie(1)
24:11:312 user_main    E[HLE]: HLE/HLE.cpp:736 Unimplemented HLE function sceUriParse

With this PR i was at least getting to the URI parasing part (see my edit to this comment), but this other infrastructure branch seems to fail way earlier

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

update: i used the most recent version of the game, and after patching i get this message

11:06:060 user_main    E[SCENET]: HLE/sceParseUri.cpp:48 ffffffff=sceUriParse(08ed889c, http://[ip_redacted]:10061/LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 08ed69b0, 00000000, 101): invalid arg

Even though the URL is 100% valid

It seems to came from 2nd argument from behind, it will get invalid args if the value is not a valid address, i guess it's allow null ptr O.o may be not expecting any output.

@Beyley
Copy link

Beyley commented Sep 2, 2023

dirty_patch.txt
heres a quick patch i cooked up to get past that, it gets further now, but now the game seems to be initting and such, then giving up and deiniting afterward

33:11:190 user_main    E[SCENET]: HLE/sceNet.cpp:798 UNIMPL sceNetInetInit()
33:11:190 user_main    E[SCENET]: HLE/sceNet.cpp:1389 UNIMPL sceNetResolverInit()
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:537 UNIMPL sceHttpsInit(1, 167769456, 0, 0)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:704 UNIMPL sceHttpLoadDefaultCert(0, 0)
33:11:307 user_main    E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceHttpsEnableOption
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:555 UNIMPL sceHttpsDisableOption(4)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:555 UNIMPL sceHttpsDisableOption(16)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:709 UNIMPL sceHttpLoadSystemCookie()
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:110 UNIMPL sceNpInit()
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:290 UNIMPL sceNpAuthInit(16384, 15360, 50)
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:535 UNIMPL sceNpServiceInit(00004000, 00004000, 00000032)
33:22:906 ApctlThread  E[SCENET]: HLE/sceNp.cpp:391 UNIMPL sceNpAuthGetTicket(1, 09595f72, 248) at 088930cc
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:635 UNIMPL sceHttpSetMallocFunction(8883ca8, 8883cb0, 8883cc8)
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:498 UNIMPL sceHttpSetSendTimeout(1, 15000000)
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:526 UNIMPL sceHttpDisableCookie(1)
33:23:079 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:574 UNIMPL sceNpRosterCreateRequest(09a92f30) at 0888cb98
33:23:080 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:587 UNIMPL sceNpRosterGetFriendListEntry(1, 00000032, 00000000, 09f811a4, 09f811a8, 09a92f30, 00000000) at 0888cbf8
33:23:080 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:599 UNIMPL sceNpRosterDeleteRequest(1) at 0888cc6c
33:23:080 08ED96E0 svo E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverCreate
33:23:080 08ED96E0 svo E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverStartNtoA
33:23:193 user_main    E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverDelete
33:23:241 user_main    E[SCENET]: HLE/sceNet.cpp:1207 UNIMPL sceNetApctlDisconnect()
33:23:242 user_main    E[SCENET]: HLE/sceHttp.cpp:699 UNIMPL sceHttpSaveSystemCookie()
33:23:243 user_main    E[SCENET]: HLE/sceHttp.cpp:549 UNIMPL sceHttpsEnd()
33:23:243 user_main    E[SCENET]: HLE/sceNet.cpp:1395 UNIMPL sceNetResolverTerm()
33:23:243 user_main    E[SCENET]: HLE/sceNet.cpp:806 UNIMPL sceNetInetTerm()

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

With this PR i was at least getting to the URI parasing part (see my edit to this comment), but this other infrastructure branch seems to fail way earlier

Oops, those test build probably didn't have this PR included yet, although the one i had on my laptop already included it but i haven't update the test build yet (due to low free space i can only build the Windows version).

@Beyley
Copy link

Beyley commented Sep 2, 2023

Oops, those test build probably didn't have this PR included yet, although the one i had on my laptop already included it but i haven't update the test build yet (due to low free space i can only build the Windows version).

If theres an open branch to pull from i can do the rebase/build myself

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

dirty_patch.txt heres a quick patch i cooked up to get past that, it gets further now, but now the game seems to be initting and such, then giving up and deiniting afterward

33:11:190 user_main    E[SCENET]: HLE/sceNet.cpp:798 UNIMPL sceNetInetInit()
33:11:190 user_main    E[SCENET]: HLE/sceNet.cpp:1389 UNIMPL sceNetResolverInit()
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:537 UNIMPL sceHttpsInit(1, 167769456, 0, 0)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:704 UNIMPL sceHttpLoadDefaultCert(0, 0)
33:11:307 user_main    E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceHttpsEnableOption
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:555 UNIMPL sceHttpsDisableOption(4)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:555 UNIMPL sceHttpsDisableOption(16)
33:11:307 user_main    E[SCENET]: HLE/sceHttp.cpp:709 UNIMPL sceHttpLoadSystemCookie()
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:110 UNIMPL sceNpInit()
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:290 UNIMPL sceNpAuthInit(16384, 15360, 50)
33:17:802 user_main    E[SCENET]: HLE/sceNp.cpp:535 UNIMPL sceNpServiceInit(00004000, 00004000, 00000032)
33:22:906 ApctlThread  E[SCENET]: HLE/sceNp.cpp:391 UNIMPL sceNpAuthGetTicket(1, 09595f72, 248) at 088930cc
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:635 UNIMPL sceHttpSetMallocFunction(8883ca8, 8883cb0, 8883cc8)
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:498 UNIMPL sceHttpSetSendTimeout(1, 15000000)
33:22:936 user_main    E[SCENET]: HLE/sceHttp.cpp:526 UNIMPL sceHttpDisableCookie(1)
33:23:079 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:574 UNIMPL sceNpRosterCreateRequest(09a92f30) at 0888cb98
33:23:080 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:587 UNIMPL sceNpRosterGetFriendListEntry(1, 00000032, 00000000, 09f811a4, 09f811a8, 09a92f30, 00000000) at 0888cbf8
33:23:080 08ED96E0 svo E[SCENET]: HLE/sceNp.cpp:599 UNIMPL sceNpRosterDeleteRequest(1) at 0888cc6c
33:23:080 08ED96E0 svo E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverCreate
33:23:080 08ED96E0 svo E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverStartNtoA
33:23:193 user_main    E[HLE]: HLE/HLE.cpp:738 Unimplemented HLE function sceNetResolverDelete
33:23:241 user_main    E[SCENET]: HLE/sceNet.cpp:1207 UNIMPL sceNetApctlDisconnect()
33:23:242 user_main    E[SCENET]: HLE/sceHttp.cpp:699 UNIMPL sceHttpSaveSystemCookie()
33:23:243 user_main    E[SCENET]: HLE/sceHttp.cpp:549  sceHttpsEnd()
33:23:243 user_main    E[SCENET]: HLE/sceNet.cpp:1395 UNIMPL sceNetResolverTerm()
33:23:243 user_main    E[SCENET]: HLE/sceNet.cpp:806 UNIMPL sceNetInetTerm()

Unimplemented HLE function in the logs may trigger the game to terminates everything as it returned an error (-1) by default, the game may think something went wrong, unlike the stub function with UNIMPL which returns a faked success (ie. 0 or positive number) which made the game progressed (except when the game was expecting an output data from it)

Based on the logs, it probably expecting an output data from sceNpRosterGetFriendListEntry, not sure how the list should be formatted tho, will need to see the output from a real PSP during that call (or use JPCSP with prx files to dump the output, i think JPCSP can login to PSN when using prx files from official firmware)

@Beyley
Copy link

Beyley commented Sep 2, 2023

Unimplemented HLE function in the logs may trigger the game to terminates everything as it returned an error (-1) by default, the game may think something went wrong, unlike the stub function with UNIMPL which returns a faked success (ie. 0 or positive number) which made the game progressed (except when the game was expecting an output data from it)

That makes sense, i'll just stub it out and see what happens

@Beyley
Copy link

Beyley commented Sep 2, 2023

Stubbing out a bunch of unimplemented things to just return 0 seems to have made a bit of progress, but now its dying due to it trying to parse a URL that is only the second half?

57:45:841 user_main    E[SCENET]: HLE/sceNp.cpp:110 UNIMPL sceNpInit()
57:45:841 user_main    E[SCENET]: HLE/sceNp.cpp:290 UNIMPL sceNpAuthInit(16384, 15360, 50)
57:45:841 user_main    E[SCENET]: HLE/sceNp.cpp:535 UNIMPL sceNpServiceInit(00004000, 00004000, 00000032)
57:50:946 ApctlThread  E[SCENET]: HLE/sceNp.cpp:391 UNIMPL sceNpAuthGetTicket(1, 09595f72, 248) at 088930cc
57:50:978 user_main    E[SCENET]: HLE/sceHttp.cpp:635 UNIMPL sceHttpSetMallocFunction(8883ca8, 8883cb0, 8883cc8)
57:50:978 user_main    E[SCENET]: HLE/sceHttp.cpp:498 UNIMPL sceHttpSetSendTimeout(1, 15000000)
57:50:978 user_main    E[SCENET]: HLE/sceHttp.cpp:526 UNIMPL sceHttpDisableCookie(1)
57:51:126 08ED96F0 svo E[SCENET]: HLE/sceNp.cpp:574 UNIMPL sceNpRosterCreateRequest(09a92f30) at 0888cb98
57:51:126 08ED96F0 svo E[SCENET]: HLE/sceNp.cpp:587 UNIMPL sceNpRosterGetFriendListEntry(1, 00000032, 00000000, 09f811a4, 09f811a8, 09a92f30, 00000000) at 0888cbf8
57:51:127 08ED96F0 svo E[SCENET]: HLE/sceNp.cpp:599 UNIMPL sceNpRosterDeleteRequest(1) at 0888cc6c
57:51:127 08ED96F0 svo E[SCENET]: HLE/sceNet.cpp:1413 UNIMPL sceNetResolverCreate()
57:51:127 08ED96F0 svo E[SCENET]: HLE/sceNet.cpp:1401 UNIMPL sceNetResolverStartNtoA()
57:51:127 08ED96F0 svo E[SCENET]: HLE/sceNet.cpp:1419 UNIMPL sceNetInetInetNtop()
57:51:129 08ED96F0 svo E[IO]: Net/URL.cpp:13 Invalid URL: /LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1
57:51:231 user_main    E[SCENET]: HLE/sceNet.cpp:1407 UNIMPL sceNetResolverDelete()
57:51:281 user_main    E[SCENET]: HLE/sceNet.cpp:1207 UNIMPL sceNetApctlDisconnect()
57:51:282 user_main    E[SCENET]: HLE/sceHttp.cpp:699 UNIMPL sceHttpSaveSystemCookie()
57:51:283 user_main    E[SCENET]: HLE/sceHttp.cpp:549 UNIMPL sceHttpsEnd()
57:51:283 user_main    E[SCENET]: HLE/sceNet.cpp:1395 UNIMPL sceNetResolverTerm()
57:51:283 user_main    E[SCENET]: HLE/sceNet.cpp:806 UNIMPL sceNetInetTerm()

It seems to be calling into sceNetInet now before it fails, i believe the missing sceNetInetInetNtop is what would be filling in the domain into the string there (which is why it is invalid)

I believe what its trying to do is use sceNetResolverStartNtoA to get the IP, then print that ip directly into the URL, instead of passing the domain into the URL stuff

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 2, 2023

Oops, those test build probably didn't have this PR included yet, although the one i had on my laptop already included it but i haven't update the test build yet (due to low free space i can only build the Windows version).

If theres an open branch to pull from i can do the rebase/build myself

It's currently a pile of stashed code as i haven't had the time to separate it into smaller commits, or at least separate it by library as things can get tangled each other (especially the constant/definitions)

@Beyley
Copy link

Beyley commented Sep 2, 2023

It's currently a pile of stashed code as i haven't had the time to separate it into smaller commits, or at least separate it by library as things can get tangled each other (especially the constant/definitions)

I would very appreciate if you were to push that stash to a separate branch as just a single "big commit" when/if you get the time. I can work out how to get it working on my machine, and im willing to implement anything more missing to get LBP PSP at least making requests to a server, and i'll send any patches i make over (i mainly just dont want to duplicate any existing work as i poke at this to get it going)

@Beyley
Copy link

Beyley commented Sep 3, 2023

Using these patches half-stable-patch.txt i am able to semi-consistently get in-game and connect to a custom server, if you would like more details on how to setup said custom server for testing, you can find me on discord with the username baebey and we can chat there

explanation of the patches:

HTTPClient.cpp: Make all socket work synchronous, without this all requests that would get out would send no data and just silently disconnect, giving the "connection refused" errno
sceHttp.cpp: Dont delay in sceHttpReadData (this seems to prevent some crashes), manually prefix all URLs with http://localhost:10061 due to missing sceNetInetInetNtop and resolvers
sceNet.cpp: Stub out things to make the client not get mad
sceParseHttp.cpp: Implement the bare minimum for sceParseHttpResponseHeader for the client to be happy (needs to be properly implemented, this is just a stub to trick the client)

remaining bugs: the client loves to send extra garbage data after requests, and the game loves to crash trying to access address 0x0 (this is maybe caused by a half-implemented server, but its hard to be 100% certain)

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 3, 2023

What kind of crash did you get? game crash (Blue/Purple screen on PPSSPP) or PPSSPP crash (in case another issue where current thread is null)?

For sceNetInetInetNtop you can use this:

// Address families
#define	PSP_NET_INET_AF_UNSPEC		0		// unspecified 
#define	PSP_NET_INET_AF_LOCAL		1		// local to host (pipes, portals) 
#define	PSP_NET_INET_AF_UNIX		PSP_NET_INET_AF_LOCAL	// backward compatibility 
#define	PSP_NET_INET_AF_INET		2		// internetwork: UDP, TCP, etc. 

int convertSocketDomainPSP2Host(int domain) {
	switch (domain) {
	case PSP_NET_INET_AF_UNSPEC:
		return AF_UNSPEC;
	case PSP_NET_INET_AF_LOCAL:
		return AF_UNIX;
	case PSP_NET_INET_AF_INET:
		return AF_INET;
	}
	return hleLogError(SCENET, domain, "Unknown Socket Domain");
}

// TODO: Need to find out whether it's possible to get partial output or not, since Coded Arms Contagion is using a small bufsize(4)
static u32 sceNetInetInetNtop(int af, u32 srcInAddrPtr, u32 dstBufPtr, u32 bufsize) {
	WARN_LOG(SCENET, "UNTESTED sceNetInetInetNtop(%i, %08x, %08x, %d)", af, srcInAddrPtr, dstBufPtr, bufsize);
	if (!Memory::IsValidAddress(srcInAddrPtr)) {
		return hleLogError(SCENET, 0, "invalid arg");
	}
	if (!Memory::IsValidAddress(dstBufPtr) || bufsize < 1/*8*/) { // usually 8 or 16, but Coded Arms Contagion is using bufsize = 4
		inetLastErrno = ENOSPC;
		return hleLogError(SCENET, 0, "invalid arg");
	}

	if (inet_ntop(convertSocketDomainPSP2Host(af), Memory::GetCharPointer(srcInAddrPtr), (char*)Memory::GetCharPointer(dstBufPtr), bufsize) == NULL) {
		//return hleLogDebug(SCENET, 0, "invalid arg?"); // Temporarily commented out in case it's allowed to have partial output
	}
	return hleLogSuccessX(SCENET, dstBufPtr, "%s", safe_string(Memory::GetCharPointer(dstBufPtr)));
}

I also have the resolvers library working (which i use on my test builds), but i won't include them in this PR as it's a separate library (will create a different PR for it later)

For sceParseHttpResponseHeader you can try following JPCSP implementation https://github.com/jpcsp/jpcsp/blob/master/src/jpcsp/HLE/modules/sceParseHttp.java
As my understanding of java is a bit mediocre, i haven't figured out what kind of output it generates, but based on the arguments types, it seems to be used to get the value of a key in headers' key:value pairs (the input headers might be the one outputted from getAllResponseHeaders/sceHttpGetAllHeader)

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 3, 2023

Hmm.. based on this logs i'm getting:

11:11:762 user_main    W[SCENET]: HLE\sceParseUri.cpp:43 UNTESTED sceUriParse(0, https://lbppsp.online.scee.com:10061/LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 0, 9fff280, 0) at 0887cfa8
11:11:762 user_main    D[SCENET]: HLE\sceParseUri.cpp:57 0=sceUriParse(00000000, https://lbppsp.online.scee.com:10061/LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 00000000, 09fff280, 0): workAreaSize: 105, 0
11:11:762 user_main    W[SCENET]: HLE\sceParseUri.cpp:43 UNTESTED sceUriParse(8e71e3c, https://lbppsp.online.scee.com:10061/LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 8e72090, 0, 105) at 0887cfe0
11:11:777 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:579 UNTESTED sceHttpCreateConnection(1, lbppsp.online.scee.com, https, 10061, 1)
11:11:778 08E72200 svo D[SCENET]: HLE\sceHttp.cpp:589 2=sceHttpCreateConnection(1, lbppsp.online.scee.com, https, 0000274d, 1)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:604 UNTESTED sceHttpAddExtraHeader(2, Content-Type, application/octet-stream, 0)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:604 UNTESTED sceHttpAddExtraHeader(2, accept-encoding, deflate, 0)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:604 UNTESTED sceHttpAddExtraHeader(2, X-exe-v, 100, 0)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:604 UNTESTED sceHttpAddExtraHeader(2, HOST, lbppsp.online.scee.com, 0)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:561 UNTESTED sceHttpCreateRequest(2, 1, /LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, f8)
11:11:778 08E72200 svo D[SCENET]: HLE\sceHttp.cpp:574 3=sceHttpCreateRequest(2, 1, /LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1, 00000000000000f8)
11:11:778 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:433 UNTESTED sceHttpSendRequest(3, 8e726d0, f8)
11:11:778 08E72200 svo E[IO]: Net\URL.cpp:13 Invalid URL: /LITTLEBIGPLANETPSP_XML/login?applicationID=22234&languageID=1
11:11:778 08E72200 svo D[SCENET]: HLE\sceHttp.cpp:446 80433060=sceHttpSendRequest(3, 08e726d0, 000000f8)
11:11:779 08E72200 svo W[SCENET]: HLE\sceHttp.cpp:450 UNTESTED sceHttpDeleteRequest(3)

The input URL without the host domain, should be valid if there is a "HOST" header, and should probably constructed into a fully qualified URI using the information used in sceHttpCreateConnection before parsing it or sending the request.

Anyway, since LBP is using HTTPS, it won't be covered on this PR (may be until i replaced HTTPClient with naett)

@Beyley
Copy link

Beyley commented Sep 3, 2023

What kind of crash did you get? game crash (Blue/Purple screen on PPSSPP) or PPSSPP crash (in case another issue where current thread is null)?

many many crashes like this
image

@Beyley
Copy link

Beyley commented Sep 3, 2023

Anyway, since LBP is using HTTPS, it won't be covered on this PR (may be until i replaced HTTPClient with naett)

I have a game patch which forces HTTP, which is how im doing testing

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 3, 2023

The blue screen i got always have unknown module/syscall occurrence, so it probably related to that module/syscall

27:31:773 user_main    W[SCENET]: HLE\sceHttp.cpp:340 UNTESTED sceHttpInit(153600) at 08889228
27:31:773 user_main    E[SCENET]: HLE\sceHttp.cpp:543 UNIMPL sceHttpsInit(0, 0, 0, 0)
27:31:773 user_main    E[SCENET]: HLE\sceHttp.cpp:710 UNIMPL sceHttpLoadDefaultCert(0, 0)
27:31:773 user_main    E[SCENET]: HLE\sceHttp.cpp:561 UNIMPL sceHttpsDisableOption(1)
27:31:773 user_main    E[SCENET]: HLE\sceHttp.cpp:715 UNIMPL sceHttpLoadSystemCookie()
27:31:773 user_main    E[HLE]: HLE\HLE.cpp:675 Unknown syscall: Module: (unknown) (module: 255 func: 4095)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:949 sceUtilityGetNetParamLatestID(09fff510)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 1, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 2, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 3, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 4, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 5, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 6, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 7, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 13, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 14, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 15, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 18, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 19, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 20, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 22, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 21, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 8, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 9, 09fff514)
27:31:773 user_main    D[SCEUTIL]: HLE\sceUtility.cpp:739 sceUtilityGetNetParam(1, 10, 09fff514)
27:31:773 user_main    W[MEMMAP]: Core\Core.cpp:470 CPU Jump: Invalid exec address 00000000 PC 08889afc LR 00000000

PS: Trying to reset the game (through Emulation Menu) while in this blue screen seems to cause Invalid access flooding in the logs and locks up unable to do anything until... PPSSPP crashed (when running PPSSPP through VS2022)

@Beyley
Copy link

Beyley commented Sep 3, 2023

The latest patch did not seem to help, as it looks like the game is sending in a blank string for hostString
image

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 3, 2023

Is there any other syscall before sceHttpCreateConnection that shows a valid domain?
If there are no other way to find the host domain, the game shouldn't put an empty string there, unless it was taken out from a parser where the parser failed to provide the information on it's output.

@Beyley
Copy link

Beyley commented Sep 3, 2023

Is there any other syscall before sceHttpCreateConnection that shows a valid domain? If there are no other way to find the host domain, the game shouldn't put an empty string there, unless it was taken out from a parser where the parser failed to provide the information on it's output.

aha, i had forgotten to replace sceNetInetInetNtop, with that, its now slightly more correct behaviour, and its actually pinging my localhost server (in the EBOOT i patched to localhost)

45:44:246 08ED8380 svo E[SCENET]: HLE/sceHttp.cpp:594 UNTESTED sceHttpCreateConnection(1, 0.0.0.0, http, 10061, 1)
45:44:247 08ED8380 svo E[SCENET]: HLE/sceHttp.cpp:229 CONNECTING TO URL http://0.0.0.0:10061/lbp/login?applicationID=22234&languageID=1 hostString 0.0.0.0
45:44:247 08ED8380 svo E[SCENET]: Net/HTTPClient.cpp:122 Connected to sock 42
45:44:247 08ED8380 svo E[SCENET]: Net/HTTPClient.cpp:337 POST /lbp/login?applicationID=22234&languageID=1 HTTP/1.0

0.0.0.0 feels wrong, but it seems to connect fine

@Beyley
Copy link

Beyley commented Sep 3, 2023

And i did just confirm that removing hleDelayResult from sceHttp::sceHttpReadData makes the handshake (/login, /news, /announce) 100% consistent, while with hleDelayResult in read data it will usually crash immediately after 1-3 requests, although sometimes ittl get through. Not sure whats up there tbh

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 3, 2023

The delay itself isn't much, but it could trigger another PSP thread to run, and if that other thread also use HTTPClient to download something else .. it might conflicts with the delayed HLE (not sure whether HTTPClient can be used by more than 1 PSP thread at the same time or not tho)

@Beyley
Copy link

Beyley commented Sep 3, 2023

The delay itself isn't much, but it could trigger another PSP thread to run, and if that other thread also use HTTPClient to download something else .. it might conflicts with the delayed HLE (not sure whether HTTPClient can be used by more than 1 PSP thread at the same time or not tho)

Thats plausible, the game seems to be doing networking things from multiple threads (theres the announce thread, online news thread, para poster, and user_main, all of which seem to call into networking things at some point)

@Beyley
Copy link

Beyley commented Sep 4, 2023

I implemented sceParseHttpResponseHeader properly to replace my hack. Heres my current set of patches that makes LBP work
working-tree.txt
this implementation is imperfect, but it should be a very good starting point if you havent already done so yourself
(also fixed some constants, which seemed to have been defined wrong?)

This leaves my working tree to get LBP PSP connecting as such:
make sockets synchronous
dont fake latency in sceHttpReadData
fix wrong constants in sceHttp
stub out sceNetResolverStartNtoA, sceNetResolverDelete, sceNetResolverCreate
implement sceNetInetInetNtop and sceParseHttpResponseHeader

All this combined makes the initial login process 100% consistent (eg. im able to get to the community moon)

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 4, 2023

May i know where you get the definition for SCE_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432060 ?
i can only find references from Vita and PS4 on the internet, where on both the vita and ps4 have the value of 0x80432025 (which is also used by JPCSP)
it would be nice if i can get a link for PSP references as some vita definitions can be slightly different than PSP.

@Beyley
Copy link

Beyley commented Sep 4, 2023

May i know where you get the definition for SCE_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432060 ? i can only find references from Vita and PS4 on the internet, where on both the vita and ps4 have the value of 0x80432025 (which is also used by JPCSP) it would be nice if i can get a link for PSP references as some vita definitions can be slightly different than PSP.

Someone just told me the constants over discord, and i realized that the constants they sent me did not match what was in the source code as is, so i assumed the ones they sent me were correct, since they also gave a detailed description about the method in question (seems to be worded like it was pulled from some docs somewhere?) and seemed knowledgable, and the game seems to react better when i use the updated constants

@anr2me
Copy link
Collaborator Author

anr2me commented Sep 7, 2023

@Beyley you can try using resolver from this PR #18090
Not sure whether LBP will try to create more than one resolvers at the same time or not tho (which isn't supported yet)

@Beyley
Copy link

Beyley commented Sep 7, 2023

@Beyley you can try using resolver from this PR #18090 Not sure whether LBP will try to create more than one resolvers at the same time or not tho (which isn't supported yet)

That resolver does seem to work yes, at least the game does not regress at all connection wise, everything still works

@anr2me
Copy link
Collaborator Author

anr2me commented Dec 20, 2023

Looks like httpVersion_ have been removed on the latest master, not sure what's the best approach to implement syscalls that have httpVer argument, like int sceHttpCreateTemplate(const char *userAgent, int httpVer, int autoProxyConf) for example.

@xiaolang0668
Copy link

It would be great if we could achieve cross platform discovery of room lists online that supports both the IPv6 server and client.
The current online mode is not suitable for intranet users.

@anr2me
Copy link
Collaborator Author

anr2me commented Mar 17, 2024

PSP only support/know IPv4 if i'm not mistaken.
But if you can convert IPv6 to IPv4 and feeds the IPv4 to a PSP's app/game it should works too.

@xiaolang0668
Copy link

PSP only support/know IPv4 if i'm not mistaken. But if you can convert IPv6 to IPv4 and feeds the IPv4 to a PSP's app/game it should works too.

It would be great if the simulator could have a built-in function of creating rooms and adding rooms. Both mobile phones and computers can be online. At present, no teammates can be seen in Chinese Mainland, so it can only be realized by third-party software. We have created an online tool for online use.

@xiaolang0668
Copy link

QQ截图20240418181757
Temporarily solve online problems with friends.

@anr2me
Copy link
Collaborator Author

anr2me commented Apr 18, 2024

QQ截图20240418181757 Temporarily solve online problems with friends.

If you're talking about the ProOnline of AdHoc multiplayer, it's out of the scope of sceHttp library (which is part of Infrastructure networking and unrelated to AdHoc networking)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants