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

Network socket changes: socket_lib_finish() shouldn't be a stub function #169

Closed
V10lator opened this issue Apr 23, 2021 · 2 comments
Closed

Comments

@V10lator
Copy link
Contributor

V10lator commented Apr 23, 2021

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();
}
@fincs
Copy link
Member

fincs commented Apr 25, 2021

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.

@fincs
Copy link
Member

fincs commented Sep 18, 2021

See eb03061

socket_lib_init/finish are no longer stubs.

@fincs fincs closed this as completed Sep 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants