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

[web] Support libevent as WS server instead of libwebsockets #1818

Merged
merged 6 commits into from
Jan 18, 2025

Conversation

chme
Copy link
Collaborator

@chme chme commented Oct 3, 2024

The next planned minor release 2.2 of libevent will have support for running a websocket server. I thought, I give it a try and see if it works in OwnTone and check if it is something worth adding :-)

The changes in this PR add a libevent based websocket server, that accepts connections under the path /ws (and the same port as the web interface).

If libevent >= 2.2 is detected during configure and "websocket_port" == 0 in the config file, the libwebsocket implementation is disabled and instead the libevent websocket server is active.

The web interface was updated to attempt a WS connection to /ws if websocket_port == 0.

The advantages in using libevent are - if it proves to be reliable - that the libwebsocket dependency could be removed. Additionally, only having one port for the web interface, will make it easier to use a reverse proxy with OwnTone (especially if the reverse proxy is running on the same host).

I did some short tests, and it seems to be working fine, but more tests are required.
I tested it locally and by building an OwnTone container with libevent from git-master (https://github.com/chme/owntone-container/tree/feat/libevent-git). Also I am unsure how it will work with the multi threading support of the http server in OwnTone.

Currently only an alpha release of libevent 2.2 is available (https://github.com/libevent/libevent/releases/tag/release-2.2.1-alpha) . Note, that the libevent 2.2.1 alpha release contains a bug that prevents ws connections from Firefox (Chrome is working fine). The bug is already fixed in the master branch of libevent.

@ejurgensen
Copy link
Member

This looks great, I think it would be very good to have an alternative to libwebsockets. Maybe this can also be a way of solving issue #1699 and the problem mentioned in #1446.

I will try to check the http multithreading to see if this could cause any problems.

@hacketiwack
Copy link
Collaborator

Sounds really promising. Too bad that the libevent team is slow at releasing versions of their library; last commit was last year.

@chme
Copy link
Collaborator Author

chme commented Oct 6, 2024

Too bad that the libevent team is slow at releasing versions of their library; last commit was last year.

Yes, more frequent releases of libevent would be nice. Especially because it also takes quite a long time until all the distros pick up the new release.

Copy link
Member

@ejurgensen ejurgensen left a comment

Choose a reason for hiding this comment

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

Here's a few comments and suggestions. I think it should work with the multithreaded http server, at least as long as THREADPOOL_NTHREADS is 1, because then there is still only one httpd thread and one evhttp instance.

struct client *client = NULL;
char *reply = NULL;

for (client = clients; client; client = clients->next)
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't look thread safe to me since clients is a global? And is evws_send_text safe to call with ->evws, which looks like it belongs to the httpd thread's evhttp?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, thread safety is an issue. I reworked it. The listener callback now triggers a command executed in the httpd thread (hope I did it correctly). Required a bit of additional refactoring of the listener call back function.

The listener now supports passing an opaque pointer (context) when adding a listener. This pointer is then passed to each notify callback invocation.

return -1;
}

DPRINTF(E_DBG, L_WEB, "notify callback request: %s\n", json_object_to_json_string(request));
Copy link
Member

Choose a reason for hiding this comment

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

I suggest commenting this out, it's usually quite "noisy"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This log is only written once per websocket connection. It should not be that noisy.
I have reduced the log level for the "notify callback event received" log message to "spam". That seems to me noisier and not the helpful.

@@ -38,6 +38,7 @@
#include "logger.h"
#include "commands.h"
#include "httpd_internal.h"
#include "websocket_ev.h"
Copy link
Member

Choose a reason for hiding this comment

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

websocket_ev.c isn't that much code, and since it's tied to libevent's evhttp and not called from anywhere else, you could just add it here in httpd_libevent.c?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mmh .. generally I am not a fan of huge files, but given that with the changes to make it thread safe it is more tightly coupled with httpd_libevent.c, I moved the code now into httpd_libevent.c.

chme added 4 commits December 27, 2024 13:51
If libevent >= 2.2 is detected during configure and "websocket_port" == 0 in the config file, the libwebsocket implementation is disabled and instead the libevent http server offers the websocket connection. The connection to the websocket is then done with the path "/ws".
@chme chme force-pushed the feat/libevent-2.2-ws branch from 61d6945 to f2e4819 Compare December 27, 2024 12:55
@chme
Copy link
Collaborator Author

chme commented Dec 27, 2024

Thanks for taking the time to review this change and apologies for the lack of response from me.

I finally got around and rebased the changes on top of master and addressed the review comments. The thread safety issue required some rework (that now also effects a tiny bit other code parts).

I'll test this more over the coming weeks to see if it is stable (at least for my set up).

@ejurgensen
Copy link
Member

Excellent, you are welcome to merge it when you think it's ready. Looking forward to using this as the default, but I guess we have to wait for a libevent release.

It's fine to keep the version check of libevent instead of feature check, and I agree the map can wait.

@chme chme merged commit 8c2b44f into owntone:master Jan 18, 2025
6 checks passed
@chme chme deleted the feat/libevent-2.2-ws branch January 18, 2025 06:12
@chme
Copy link
Collaborator Author

chme commented Jan 18, 2025

I have merged it now. It is working stable for me for quite some time now (with libevent build from git).

Too bad, there is no progress on a new libevent release though. And given how long Debian release cycles are, it will probably take around three years, until this will be usable on Debian distros ...

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

Successfully merging this pull request may close these issues.

3 participants