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

Extensions - Add Linux support for the Mumble plugin #1218

Open
wants to merge 21 commits into
base: mumble-plugin
Choose a base branch
from

Conversation

DylanFrese
Copy link

  • Make some syntactic changes for other compilers

  • Update CMakelists for Linux compatibility

    This allows ACRE2Core, ACRE2Shared, and ACRE2Wine to be built under Linux toolchains.

  • Extend compat.h to provide Linux compat types

    Some Windows types and functions have been aliased for compilation on Linux.

  • Provide FAudio/x3daudio compatibility on Linux

    FilterPosition relies on x3daudio to do positional transformations. On Linux, we can use FAudio as an (almost) drop-in replacement.

  • Alias tbb concurrency modules on Linux

    Intel TBB is available as a library on Linux, under the tbb namespace, rather than the concurrency namespace as on Windows.

  • Update filesystem paths for building on Linux

    Use paths in ~ for ACRE config & temp files

  • Do not load AcreSettings in constructor

    If the default path baked into the constructor is not the same as one that is later loaded, the user would end up with two config files!

  • Reimplement NamedPipeServer on Linux

    This is the most involved change in this changeset.

    On Linux, Arma runs under WINE, but Mumble is native. There's no (known to me) way to do IPC between WINE processes and native processes.

    This solution uses a simple duplex network socket listening on localhost, with a default port of 19141. The Mumble side is responsible for setting up the server, and the Arma side connects.

  • Modify arma2ts to use sockets if running in Wine

    When running in Wine, ACRE2Arma.dll will mirror the changes to NamedPipeServer.cpp for Linux; instead of using named pipes, it will connect to the socket opened on the other side.

  • Add a Linux build job to CI

    Also, publish the resulting Linux/Mumble plugin

This PR adds support for building the ACRE Mumble plugin for native Linux, and modifies both it and the arma2ts DLL (when running in WINE) to communicate over network sockets instead of named pipes.

I've polished the commit log so that this changeset may be reviewed in a developmental manner on the command line with
git log -w -p --reverse origin/mumble-plugin..HEAD, rather than as one big diff (if you prefer).

I've also added and tested CI support (although I haven't tested the publishing steps, for obvious reasons) for the Linux plugin. CI has built this workshop item, if you'd like to test it.

Mostly trailing whitespace at the end of lines
Make some of the first steps to be able to build parts of ACRE on other
platforms (such as GCC).

Mostly, this amounts to differences in preprocessors, and some builtins.
This allows ACRE2Core, ACRE2Shared, and ACRE2Wine to be built under
Linux toolchains.

We gate DirectX inclusion to Windows only; on Linux, we include FAudio
as a drop in replacement for x3daudio. .pdb debugging symbols generated
on the Windows build are not copied on Linux. PIC has been flipped on
for Shared and Core on Linux.

ACRE2Arma, ACRE2TS, ACRE2Steam, and the utility modules are not built on
Linux, and it doesn't really make sense for them to be.
Some Windows types and functions have been aliased for compilation on
Linux.
FilterPosition relies on x3daudio to do positional transformations. On
Linux, we can use FAudio as an (almost) drop-in replacement.
Intel TBB is available as a library on Linux, under the `tbb` namespace,
rather than the `concurrency` namespace as on Windows.
ACRE's config file will be stored in $XDG_CONFIG_HOME (~/.config), as
per the XDG standard. Temporary files are stored in /tmp/acre-${USER},
and logs in $XDG_DATA_HOME (~/.local/share).

This tends to be Linux desktop users expect.
Replace some Windows specific string functions with cross-compatible
ones, and don't try to pop up message boxes on Linux.
An unused sddl.h include has also been removed
If the default path baked into the constructor is not the same as one
that is later loaded, the user will end up with two config files! Only
one will be used.

There is no need to load the config file in the constructor, however.
Hardcoded defaults are already set, and users of the class all load
config files explicitly.
This is the most involved change in this changeset.

On Linux, Arma runs under WINE, but Mumble is native. There's no (known
to me) way to do IPC between WINE processes and native processes; WINE
makes it (purposefully?) difficult.

It may be possible to use Windows 10+ Unix socket compatibility (if WINE
supports it), or some other mechanism. But this solution uses a simple
duplex network socket listening on localhost, with a default port of
19141. The Mumble side is responsible for setting up the server, and the
Arma side connects.

ACRE uses Windows named pipes in "message" mode, which means rather than
a stream of bytes, senders send a stream of messages and receivers
receive whole messages, not partial messages.

This is not the case with a TCP socket, and so a simple length encoding
is used. Whenever a sender has a message to send, they first send a four
byte unsigned integer that is the length of the message to come, and the
receiver first reads exactly four bytes, decodes the length of the
message, then reads exactly that many bytes.

The code is written to be tolerant (as in: will not crash, and will
simply drop the connection and wait for the otherside to reconnect) to
network faults and partial sends/receives. However, given that the
client and server are on the same networking stack, conditions are
ideal: sends and receives should match up exactly, and faults should be
impossible.

Since the port chosen could conflict with another server, possibly
another instance of Mumble/Acre/Arma, it is configurable. On the Mumble
side, it can be configured in the ACRE config file. On the Arma side, it
will be specified as a CBA setting and passed in to the extension via
a parameter to callExtension.
When running in Wine, ACRE2Arma.dll will mirror the changes to
NamedPipeServer.cpp for Linux; instead of using named pipes, it will
connect to the socket opened on the other side.

A helper function has been added to detect if running under Wine, by
checking for a function Wine defines in ntdll.
Also, publish the resulting Linux/Mumble plugin
@DylanFrese
Copy link
Author

This is currently marked as WIP because ACRE2Steam currently does not search for the Linux version of Mumble to copy plugins to. Wine, by default, maps Z: to /, so automatically adding/updating the plugin is certainly doable, I just have to get my head around what voip_plugin is doing.

The Linux plugin will also build as 32-bit, but there's no 32-bit image of Ubuntu, and Ubuntu 22 doesn't appear to have all the multiarch packages necessary.

You can view a successful CI run here: https://github.com/DylanFrese/acre2/actions/runs/2942274717

The scratch commit in that CI run has modified release.yml to compile on a non-release branch, and also trimmed out things like publishing and signing; it is not included in this PR.

This is how I intended it, but during a rewrite/rebase it got screwed
up.
@rautamiekka
Copy link
Contributor

Ubuntu 22 doesn't appear to have all the multiarch packages necessary.

As in, doesn't exist at all ? I seem to recall reading some being missing.

@DylanFrese
Copy link
Author

Ubuntu 22 doesn't appear to have all the multiarch packages necessary.

As in, doesn't exist at all ? I seem to recall reading some being missing.

I'm not 100% sure, I don't have a Ubuntu system myself to check on. I know Ubuntu 19 dropped 32-bit support to an extent. I'd went through the steps to enable multiarch in CI, and modify sources.list to grab i386 packages, but apt reported they weren't present.

I'm almost certain, though, that anyone running Arma under Wine/Proton is using 64-bit.

@rautamiekka
Copy link
Contributor

As in, doesn't exist at all ? I seem to recall reading some being missing.

modify sources.list to grab i386 packages, but apt reported they weren't present.

I'm almost certain, though, that anyone running Arma under Wine/Proton is using 64-bit.

Ya, x86_32 support ended after *Ubuntu 18.04 LTS "Bionic Beaver" (supported until April 2023) except for a very rare few derivatives, so those packages straight up don't exist.

^ According to this 2021 comment, likely way too many 32 multiarch libs just don't exist cuz ppl don't wanna do the work, and you likely are right about 64 'Arma' under Wine/Proton mostly, so indeed it's far better to make a 64 version 1st and try to make a 32 one if it ain't too much trouble, otherwise only a 64.

@DylanFrese
Copy link
Author

Again, to be clear, the 32-bit build works. I've built it on my system, running Debian. If there are any 32-bit users out there (which is more rare in the Linux desktop space than in the Windows space), they'd be able to build it themselves (which they're also more likely to know how to do than in the Windows space).

@jonpas
Copy link
Member

jonpas commented Aug 29, 2022

I don't see a reason to support 32-bit Linux.

The atof function is locale dependent. Specifically, it uses the
locale-specific decimal separator to convert floating-point strings;
that is, in a locale that uses commas as decimal separators, "0,5" will
convert to 0.5, whereas "0.5" will fail, and convert as 0.0. Strings
coming from Arma will always use a period as a decimal separator, this
causes myriad failures.

On Linux, on startup, we now set LC_NUMERIC to C, which has the behavior
we want.

I'm not certain why this isn't a problem on Win32. There may be a path
in Qt/Mumble that sets locale one way on Linux and another on Windows.
Instead of hardcoding the filenames of the destination files for
plugins, VOIPPlugin::handle_update_plugin will now use the basenames of
the x32 and x64 plugins paths passed into it.
If running under Wine, ACRE2Steam will now detect that and automatically
install the Linux Mumble plugin to the Linux version of Mumble, if it is
present.
@DylanFrese DylanFrese changed the title WIP: Extensions - Add Linux support for the Mumble plugin Extensions - Add Linux support for the Mumble plugin Sep 21, 2022

#define PIPE_COMMAND_OPEN 0
#define PIPE_COMMAND_CLOSE 1
#define PIPE_COMMAND_WRITE 2
#define PIPE_COMMAND_READ 3
#define PIPE_COMMAND_RESET 4
#define COMMAND_IS_WINE 99

#define WINE_SOCKET_PORT "19141"
Copy link
Author

Choose a reason for hiding this comment

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

if (getenv("XDG_DATA_HOME")) {
acrePluginLog = std::string(getenv("XDG_DATA_HOME")) + "/" + acrePluginLog;
} else {
acrePluginLog = std::string(getenv("HOME")) + "/.local/share/" + acrePluginLog;
Copy link
Author

Choose a reason for hiding this comment

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

Can crash if $HOME is unset, but that should never happen, and the user probably has bigger problems if that happens.

clock_gettime(CLOCK_MONOTONIC_RAW, &t);
g_pingTime = t.tv_sec;
#endif
vServer->sendMessage(CTextMessage::formatNewMessage("pong", "%f,", (float) g_pingTime));
Copy link
Author

Choose a reason for hiding this comment

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

MONOTIME is more 'correct' for computing time differences, but does not track walltime. I don't think it actually matters here.

@DylanFrese
Copy link
Author

I've pushed code that now copies over the Linux .so to the user's Mumble Plugins directory when running under Wine. I depends on the environment variable WINEHOMEDIR being set -- the home directory of the Linux user as mapped in Wine. This isn't documented anywhere, but Wine sets it and has for a long time (concluded after doing some git archaeology); there isn't really any other way to get this information. It also isn't guaranteed that the user's home directory is even mapped inside of Wine, but it almost always will be.

As for the rest of the PR, I've taken the approach of trying to alter as little behaviour as possible when it comes to the Windows builds of the extensions, mostly because I don't use Windows and am not really able to verify the correctness of any changes.

I don't have any substantial experience with C++, and so what I've written I've tried to blend in with surrounding code, but I'm sure a lot of it isn't idiomatic. I welcome a harsh review to improve it to a higher C++ standard; I simply don't know when there are better approaches available in the language or libraries.

@jonpas This is ready for review.

@DylanFrese
Copy link
Author

The Ubuntu runner builds against libtbb2, which is kind of old for newer distributions. It's not available in Debian Bookworm or Manjaro. I need to update the Ubuntu image or otherwise try to link against libtbb12

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.

3 participants