This is to give a comprehensive overview on the recent progress made in NXv3 (aka nx-libs) development.
The upstream sources of nx-libs can be found at / viewed on / cloned from Github:
https://github.com/ArcticaProject/nx-libs
A great portion of the current work is sponsored by the Qindel Group [1] in Spain (QINDEL FORMACIÓN Y SERVICIOS, S.L.). Thanks for making this possible.
Planned release date: 2nd July, 2016
We aim at releasing a completely tidied up nx-libs code tree versioned 3.6.0 on July 2nd, 2016. There is still a whole bunch of work to do for this, but I am positive that we can make this release date.
Goals of our Efforts
There are basically two major goals for spending a considerable amount of time, money and energy on NXv3 hacking:
- make this beast long-term maintainable
- make it work with latest X11 desktop environments and applications
The efforts undertaken always have the various existing use cases in mind (esp. the framework of the coming-up Arctica Project, TheQVD and X2Go).
Overview on Recent Development Progress
General Code Cleanups
Making this beast maintainable means first of all: identifying code redundancies, unused code passages, etc. and remove them.
This is where we came from (NoMachine's NX 3.5.x, including nxcomp, nxcompext, nxcompshad, nx-X11 and nxagent): 1,757,743 lines of C/C++ code.
[mike@minobo nx-libs.35 (3.5.0.x)]$ cloc --match-f '.*\.(c|cpp|h)$' . 5624 text files. 5614 unique files. 2701 files ignored. http://cloc.sourceforge.net v 1.60 T=18.59 s (302.0 files/s, 132847.4 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C 3134 231180 252893 1326393 C/C++ Header 2274 78062 116132 349743 C++ 206 20037 13312 81607 ------------------------------------------------------------------------------- SUM: 5614 329279 382337 1757743 -------------------------------------------------------------------------------
On the current 3.6.x branch of nx-libs (at commit 6c6b6b9), this is where we are now: 662,635 lines of C/C++ code, amount of code reduced to a third of the original code lines.
[mike@minobo nx-libs (3.6.x)]$ cloc --match-f '.*\.(c|cpp|h)' . 2012 text files. 2011 unique files. 1898 files ignored. http://cloc.sourceforge.net v 1.60 T=5.63 s (341.5 files/s, 161351.5 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C 1015 74605 81625 463244 C/C++ Header 785 26992 34354 138063 C++ 122 16984 10804 61328 ------------------------------------------------------------------------------- SUM: 1922 118581 126783 662635 -------------------------------------------------------------------------------
The latest development branch currently has these statistics: 619,353 lines of C/C++ code, another 40,000 lines could be dropped.
[mike@minobo nx-libs (pr/libnx-xext-drop-unused-extensions)]$ cloc --match-f '.*\.(c|cpp|h)' . 1932 text files. 1931 unique files. 1898 files ignored. http://cloc.sourceforge.net v 1.60 T=5.66 s (325.4 files/s, 150598.1 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C 983 69474 77186 426564 C/C++ Header 738 25616 33048 131599 C++ 121 16984 10802 61190 ------------------------------------------------------------------------------- SUM: 1842 112074 121036 619353 -------------------------------------------------------------------------------
Dropping various libNX_X* shared libraries (and using X.org shared client libraries instead)
At first, various bundled libraries could be dropped from the nx-X11 code tree. Secondly, several of the bundled X.org libraries could be dropped, because we managed to build against those libraries as provided system-wide.
Then, and this undertaking is much trickier, we could drop nearly all Xlib extension libraries that are used by nxagent with its role of being an X11 client.
We could sucessfully drop these Xlib extension libraries from nx-X11, because we managed to build nxagent against the matching libraries in X.org: libNX_Xdmcp, libNX_Xfixes, libNX_XComposite, libNX_Xdamage, libNX_Xtst, libNX_Xinerama, libNX_Xfont, libNX_xkbui, and various others. All these droppings happened without a loss of functionality.
However, some shared X client libraries are not easy to remove without loss of functionality, or rather not removable at all.
Dropping libNX_Xrender
We recently dropped libNX_Xrender [2] and now build nxagent against X.org's libXrender. However, this cost us a compression feature in NX. The libNX_Xrender code has passages that do zero padding of the unused memory portions in non-32bit-depth glyphs (the NX_RENDER_CLEANUP feature). However, we have hope for being able to reintroduce that feature again later, but current efforts [3] still fail at run-time.
Dropping libNX_Xext is not possible...
...the libNX_Xext / Xserver Xext code has been cleaned up instead.
Quite an amount of research and testing has been spent on removing the libNX_Xext library from the build workflow of nxagent. However, it seems that building against X.org's libXext will require us to update the Xext part of the nxagent Xserver at the same time. While taking this deep look into Xext code, we dropped various Xext extensions from the nx-X11 Xserver code. The extensions that got dropped [5] are all extensions that already have been dropped from X.org's Xserver code, as well.
Further investigation, however, showed, that actually the only used client side extension code from libNX_Xext is the XShape extension. Thus, all other client side extension got dropped now in a very recent pull request [4].
Dropping libNX_X11 not easy, research summary given here
For the sake of dropping the Xlib library bundled with nx-libs, we have attempted at writing a shared library called libNX_Xproxy. This library is supposed to contain a subset of the NXtrans related Xlib code that NoMachine patched into X.org's libX11 (and libxtrans).
Results of this undertaking [6] so far:
- We managed to build nxagent against Xlib from X.org
- Local nxagent sessions (using the normal X11 transport) worked and seemed to perform better than sessions running under the original Xlib library (libNX_X11) bundled with nx-libs.
- NXtrans support in libNX_Xproxy is half implemented but far from being finished, yet. The referenced branch [6] is a work-in-progress branch. Don't expect it to work. Expect force-pushes no that branch, too, please.
Over the weekend, I thought this all through once more and I am pretty sure right now, that we can actually make libNX_Xproxy work and drop all of libNX_X11 from nx-libs soon. Although we have to port (i.e. copy) various functions related to the NX transport from libNX_X11 into libNX_Xproxy, this change will allow us to drop all Xlib drawing routines and use those provided by X.org's Xlib shared library directly.
Composite extension backport in nxagent to version 0.4
Mihai Moldovan looked at what it needs to make the Composite extension functional in nxagent. Unfortunately, the exact answer cannot be given, yet. As a start, Mihai backported latest Composite extension (v0.4) code from X.org's Xserver into the nxagent Xserver [7]. The currently shipped Composite extension version in nxagent is v0.2.
Work on the NX Compression shared library (aka nxcomp v3)
Fernando Carvajal and Salvador Fandiño from the Qindel Group [1] filed three pull requests against the nxcomp part of nx-libs recently, two of them have been code cleanups (done by Fernando), the third one is a feature enhancement regarding channels in nxcomp (provided by Salva).
Protocol clean-up: drop pre-3.5 support
With the release of nx-libs 3.6.x, we will drop support for nxcomp versions earlier than 3.5. Thus, if you are still on nxcomp 3.4, be prepared for upgrading at least to version 3.5.x.
The code removal had been issued as pull request #111 ("Remove compatibility code for nxcomp before 3.5.0") [8]. The PR has already been reviewed and merged.
Fernando filed another code cleanup PR (#119 [9]) against nx-libs that also already got merged into the 3.6.x branch.
UNIX Socket Support for Channels
The nxcomp library (and thus, nxproxy) provides a feature called "channels". Channels in nxcomp can be used for forwarding traffic between NX client side and the NX server side (along the graphical X11 transport that nxcomp is designed for). Until version 3.5.x, nxcomp was only able to use local TCP sockets for providing / connecting to channel endpoints. We consider local TCP sockets as insecure and aim at adding UNIX file socket support to nxcomp whereever a connection is established.
Salva provided a patch against nxcomp that provides UNIX socket support to channel endpoints. The initial use case for this patch is: connect to client side pulseaudio socket file and avoid enabling the TCP listening socket in pulseaudio. The traffic then is channeled to the server side, so that pulse clients can connect to a UNIX socket file rather than to a local TCP port.
The channel support patch has already been reviewed and merged into the 3.6.x branch of nx-libs.
Rebasing nxagent against latest X.org
Ulrich Sibiller spent a considerable amount of time and energy on providing a build chain that allows building nxagent against a modularized X.org 7.0 (rather than against the monolithic build tree of X.org 6.9, like we still do in nx-libs 3.6.x). We plan to adapt and minimize this build workflow for nx-libs 3.7.x (scheduled for summer 2017).
A short howto that shows how to build nxagent with that new workflow will be posted on this blog within the next days. So stay tuned.
Further work accomplished
Quite a lot of code cleanup PRs have been filed by myself against nx-libs. Most of them target at removal of unnecessary code from the nx-X11 Xserver code base and the nxagent DDX:
- Amend all issues generating compiler warnings in progams/Xserver/hw/nxagent/. (PR #102 [10], not yet merged).
- nx-X11's Xserver: Drop outdated Xserver extensions. (PR #106 [11], not yet merged).
- nxagent: drop duplicate Xserver code and include original Xserver code in nxagent code files. (PR #120 [12], not yet merged).
- libNX_Xext: Drop unused extensions. (PR #121 [4], not yet merged).
The third one (PR #120) in the list requires some detailled explanation:
We discovered that nxagent ships overrides some symbols from the original Xserver code base. These overrides are induced by copies of some files from some Xserver sub-directory placed into the hw/nxagent/ DDX path. All those files' names match the pattern NX*.c. These copies of code are done in a way that the C compiler suppresses throwing its 'symbol "
The approach taken, however, requires to have quite a few 10.000 lines of redundant code in hw/nxagent/NX*.c that also gets shipped in some Xserver sub-directory (mostly dix/ and render/).
With pull request #120, we have identified all code passages in hw/nxagent/NX*.c that must be considered as NX'ish. We differentiated the NX'ish functions from functions that never got changed by NoMachine when developing nxagent.
I then came up with four different approaches ([13,14,15,16]) of dropping redundant code from those hw/nxagent/NX*.c files. We (Mihai Moldovan and myself) discussed the various approaches and favoured the disable-Xserver-code-and-include-into-NX*.c variant [14] over the others for the following reasons:
- It requires the least invasive change in Xserver code files.
- It pulls in Xserver code (MIT/X11) into nxagent code (GPL-2) at build time (vs. [13]).
- It does not require weakening symbols, static symbols can stay static symbols [15].
- We don't have to use the hacky interception approach as shown in [16].
In the long run, the Xserver portion of the patches provided via this pull request #120 are required to be upstreamed into X.org's Xserver. The discussion around this will be started when we fully dive into rebasing nxagent's Xserver code base against latest X.org Xserver.
Tasks ahead before the 3.6.x Release
Various tasks we face before 3.6.x can be released. Here is a probably incomplete list:
- Drop libNX_X11 from nx-libs (2nd attempt)
- Drop libNX_Xau from nx-libs
- Fully fix the Composite extension in nxagent (hopefully)
- Several QA pull requests to close several of the open issues
- Upgrade XRandR extension in the nxagent Xserver to 1.4
- Attempt fixing KDE5 launch-up inside nxagent and recent GNOME application failures (due to missing Xinput2 extension in nxagent)
- More UNIX file socket support in nxcomp
- Fix reparenting in nxagent
- Make nxagent run smoothly in x11vnc when suspended
Tasks ahead after the 3.6.x Release (i.e., for 3.7.x)
Here is an even rougher and probably highly incomplete list for tasks after the 3.6.x release:
- Rename nx-libs to a new name that does not remind us of the original authoring company (NoMachine) that much.
- Generalize the channel support in nxcomp (make it possible to fire-up an arbitrary amount of channels with TCP and/or UNIX file socket endpoints.
- Proceed with the X.org Rebasing Effort.
Credits
Some people have to be named here that give their heart and love to this project. Thank you guys for supporting the development efforts around nx-libs and the Arctica Project:
Thanks to Nico Arenas Alonso from and on behalf of the Qindel Group for coordinating the current funding project around nx-libs.
Thanks to Ulrich Sibiller for giving a great amount of spare time to working on the nxagent-rebase-against-X.org effort.
Thanks to Mihai Moldovan for doing endless code reviews and being available for contracted work via BAUR-ITCS UG [17] on NXv3, as well.
Thanks to Mario Becroft for providing a patch that allows us to hook into nxagent X11 sessions with VNC and have the session fully available over VNC while the NX transport is in suspended state. Also Mario is pouring some fancy UDP ideas into the re-invention of remote desktop computing process performed in the Arctica Project. Mario has been an NX supporter for years, I am glad to have him still around after so many years (although he was close to abandoning NX usage at least once).
Thanks to Fernando Carvajal from Qindel (until April 2016) for cleaning up nxcomp code.
Thanks to Orion Poplawski from the Fedora Project for working on the first bundled libraries removal patches and being a resource on RPM packaging.
Thanks to my friend Lee for working behind the scenes on the Arctica Core code and constantly pouring various of his ideas into my head. Thanks for regularly reminding me on benchmarking things.
Folks, thanks to all of you for all your various efforts on this huge beast of software. You are a great resource of expertise and it's a pleasure and honour working with you all.
New Faces
Last but not least, I'd like to let everyone know that the Qindel Group sponsors another developer joining in on NXv3 development: Vadim Troshchinskiy (aka vatral on Github). Vadim has worked on NXv3 before and we are looking forward to having him and his skills in the team soon (probably end of May 2016).
Welcome on board of the team, Vadim.
[1] http://www.qindel.com
[2] https://github.com/ArcticaProject/nx-libs/pull/93
[3] https://github.com/sunweaver/nx-libs/commit/be41bde7efc46582b442706dfb85...
[4] https://github.com/ArcticaProject/nx-libs/pull/121
[5] https://github.com/ArcticaProject/nx-libs/pull/106
[6] https://github.com/sunweaver/nx-libs/tree/wip/libnx-x11-full-removal
[7] https://github.com/sunweaver/nx-libs/tree/pr/composite-0_4
[8] https://github.com/ArcticaProject/nx-libs/pull/111
[9] https://github.com/ArcticaProject/nx-libs/pull/119
[10] https://github.com/ArcticaProject/nx-libs/pull/102
[11] https://github.com/ArcticaProject/nx-libs/pull/106
[12] https://github.com/ArcticaProject/nx-libs/pull/120
[13] https://github.com/sunweaver/nx-libs/commit/9692e6a7045b3ab5cb0daaed187e... (include NX'ish code into Xserver)
[14] https://github.com/sunweaver/nx-libs/commit/3d359bfc2b6d021c1ae9c6e19e96... (include Xserver code into NX*.c)
[15] https://github.com/sunweaver/nx-libs/commit/af72ee5624a15d21c610528e37b6... (use weak symbols and non-static symbols)
[16] https://github.com/sunweaver/nx-libs/commit/7205bb8848c49ee3e78a82fde906... (override symbols with interceptions)
[17] http://www.baur-itcs.de/20-x2go/20-x2gosupport/