Network socket changes: socket_lib_finish() shouldn't be a stub function
Closed this issue · 2 comments
If one calls somemopt the homebrew will never be able to exit as somemopt blocks untill socket_lib_finish is called which can't be done if said function is replaced by a stub.
Now you might ask "why call somemopt in the first place?" - the answer is simple: Performance reasons. You'll get much faster up-/downloads by using I/O buffers in userspace and the way to set these buffers is somemopt (socket memory option).
Example code to show the issue:
#define DLBGT_STACK_SIZE 0x2000
#define SOCKET_BUFSIZE (128 * 1024)
#define SOCKLIB_BUFSIZE (SOCKET_BUFSIZE * 4) // For send & receive + double buffering
static OSThread dlbgThread;
static uint8_t *dlbgThreadStack;
int dlbgThreadMain(int argc, const char **argv)
{
void *buf = MEMAllocFromDefaultHeapEx(SOCKLIB_BUFSIZE, 64);
if(buf == NULL)
return 1;
if(somemopt(0x01, buf, SOCKLIB_BUFSIZE, 0) == -1 && socketlasterr() != 50) // This will block untill socket_lib_finish() is called
return 1;
MEMFreeToDefaultHeap(buf);
return 0;
}
bool initDownloader()
{
dlbgThreadStack = MEMAllocFromDefaultHeapEx(DLBGT_STACK_SIZE, 8);
if(dlbgThreadStack == NULL || !OSCreateThread(&dlbgThread, dlbgThreadMain, 0, NULL, dlbgThreadStack + DLBGT_STACK_SIZE, DLBGT_STACK_SIZE, 0, OS_THREAD_ATTRIB_AFFINITY_ANY))
return false;
OSSetThreadName(&dlbgThread, "DL background thread");
OSResumeThread(&dlbgThread);
return true;
}
void deinitDownloader()
{
socket_lib_finish();
int ret;
OSJoinThread(&dlbgThread, &ret);
MEMFreeToDefaultHeap(dlbgThreadStack);
socket_lib_init();
}
static curl_off_t initSocket(void *ptr, curl_socket_t socket, curlsocktype type)
{
int o = 1;
// Activate userspace buffer (fom somemopt)
if(setsockopt(socket, SOL_SOCKET, 0x10000, &o, sizeof(o)) != 0)
return 1;
o = SOCKET_BUFSIZE;
// Set send buffersize
if(setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &o, sizeof(o)) != 0)
return 1;
// Set receive buffersize
if(setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &o, sizeof(o)) != 0)
return 1;
return 0;
}
int main()
{
initDownloader();
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, (curl_sockopt_callback)initSocket);
// Do something, like a download...
curl_easy_cleanup(curl);
deinitDownloader();
}
I've created a branch: https://github.com/devkitPro/wut/tree/socket-init
This branch makes it possible to call socket_lib_init/finalize again, which now performs refcounting and handles devoptab registration/etc. However, the main addition is the ability to override the socket initialization/deinitialization logic, so that it can be customized to do things such as setting up somemopt. E.g.
void __init_wut_socket()
{
socket_lib_init();
// somemopt thread creation goes here
// wait for somemopt to be initialized? dunno how that's done
// AC initialization/connection goes here
}
void __fini_wut_socket()
{
// AC deinitialization goes here
socket_lib_finish();
// somemopt thread teardown goes here
}
Please test this branch, and see if the changes suit your use case.