Skip to content

Reworking cluster interface - #546

Draft
zcsahok wants to merge 34 commits into
Tlf:masterfrom
zcsahok:rework_cluster
Draft

zcsahok wants to merge 34 commits into
Tlf:masterfrom
zcsahok:rework_cluster

Conversation

@zcsahok

@zcsahok zcsahok commented Oct 27, 2026

Copy link
Copy Markdown
Member

The motivations for reworking the cluster interface are:

  • Slow start-up: addressing the annoying "still there...not dead" messages that eventually block the system if the cluster is inaccessible.
  • Sporadic cluster messages: random cluster messages were appearing on the UI sporadically.
    I decided it was easier to just rewrite the code than to try and untangle the mess of UI and backend logic, especially since most of the current code is just dead and isn't even being used.
  • Unintuitive cluster CLI: the cluster split-screen command line interface is difficult to exit,
    particularly when accidentally entered it by typing a colon in the call input field.

The new design moves cluster handling to its own dedicated thread.
To ensure no UI actions occur within this thread, communication with the rest of the TLF (main and background threads) is performed via thread-safe queues. The main RX queue is fed with lines read from the network, serial, or FIFO device, while a similar TX queue is used for sending messages into the cluster.

The tasks of the cluster thread are to:

  • Connect to the configured endpoint.
  • Read available data and post it into the RX queue line-by-line.
  • Check the TX queue and send its contents.
  • Upon a connection break wait and restart the process.

Cluster-related features like band map or spotting are not affected.
Current cluster information is shown on :INFo screen.

I've been using the code locally for several months, but there may still be some rough edges.
These will be addressed along the way.

Starting with a quick cleanup of an unused define. After this, I'll remove splitscreen.c and sockserv.c and begin incrementally rebuilding the functionality.

@zcsahok

zcsahok commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

Commented-out parts marked with CFIXME.

introduced add_cluster_text() and add_other_text() for the specific use cases.

also changed argument of bm_add() and send_lan_message() to 'const char *'
@zcsahok

zcsahok commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

The logic for forwarding cluster messages to LAN nodes is as follows:

Source Forward to LAN
cluster yes, as CLUSTERMSG, but see Note1
CLUSTERMSG from LAN no (old code for some reason did call addtext() with lanspotflg=false, maybe relying on cl_send_inhibit)
internal spot (Ctrl-A or BMAUTOADD) yes, as TLFSPOT via add_local_spot()+add_to_spots()
manual cluster spot (Ctrl-B) no (but see Note2), calls add_cluster_spot()+send_to_cluster()
TLFSPOT from LAN no

Note1: upon receiving a CLUSTERMSG, a node stops transmitting further
CLUSTERMSG messages by setting cl_send_inhibit = true.
This ensures that only a single node acts as the cluster source.

Note2: manually generated cluster spots follow the standard cluster data path:
they are submitted to the cluster, received back through the cluster interface,
and processed using the normal cluster spot handling logic.

The previous implementation relied on the global lanspotflg (setting it to true suppresses forwarding), shared between the main and background threads, creating a potential race condition. This has been replaced by the thread-safe functions add_cluster_text() and add_other_text().

@zcsahok

zcsahok commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

Now TLF starts up with the new cluster thread, spots are shown on the band map.

also always init cluster queues, even if cluster is not explicitly configured,
as there could be traffic coming via LAN
reason: now all cluster messages are passed via rx_queue,
the direct injection using addtext() has been removed.
so rx_queue has to be checked, even if (local) cluster is not configured.
was clearing one record too much
use symbolic FILTER_x constants in getclusterinfo()
streamline cluster display code
@dl1jbe

dl1jbe commented Oct 29, 2026

Copy link
Copy Markdown
Member

Reworking the interface is really an appreciated and needed step.

Some comments as a start:

* Slow start-up: addressing the annoying "still there...not dead" messages that eventually block the system if the cluster is inaccessible.

It would be good besides :info to get a quick information during startup if the cluster gets connected.

  I decided it was easier to just rewrite the code than to try and untangle the mess of UI and backend logic, especially since most of the current code is just dead and isn't even being used.

Strongly supported.

The new design moves cluster handling to its own dedicated thread. To ensure no UI actions occur within this thread, communication with the rest of the TLF (main and background threads) is performed via thread-safe queues. The main RX queue is fed with lines read from the network, serial, or FIFO device, while a similar TX queue is used for sending messages into the cluster.

  • The network connect does not work here. Some first checks showed that the cluster used here needs an \n after the 'clusterlogin' message. Without it the login process seems stuck (at the server side) and no spots were send to us.

  • To keep a terminal like cluster interface would be a good idea in the long run. I use the feature often to change cluster filtering, asking for www/wcy data or similar.

  • If I have looked it up correctly 'stdatomic.h' is supported from C11 on. While most modern compilers use C11 or newer by default we should somewhere state the requirement or force it via configure.ac or similar.

@zcsahok

zcsahok commented Oct 29, 2026

Copy link
Copy Markdown
Member Author

Please check if the logging in into your cluster (I assume via telnet) works now.

@dl1jbe

dl1jbe commented Oct 30, 2026

Copy link
Copy Markdown
Member

Checked with 4 different clusters. I does not work for any of it - neither with the added \n nor without.

It seems that all 4 clusters give me a 'login:' text without a following '\n' or '\r' and waits for the callsign. After some time without getting a response the connection gets closed and TLF starts tries it again.

So maybe we have to wait for the 'login:' before sending out call.

@zcsahok

zcsahok commented Oct 30, 2026 •

Copy link
Copy Markdown
Member Author

Interesting. Could you please try this cluster, just to rule out any local issue:
TELNETHOST=cluster.lz7aa.com
TELNETPORT=7300

It works for me, even with just \r line ending.

The code now doesn't wait for login. It sends user name right in the first iteration. Normally this means after a read of up to READ_SIZE (1k) bytes. I could add a bit of logic to ensure that this read was actually done and some time (~half sec) has elapsed since then.

@dl1jbe

dl1jbe commented Oct 30, 2026

Copy link
Copy Markdown
Member

Interesting. Could you please try this cluster, just to rule out any local issue: TELNETHOST=cluster.lz7aa.com TELNETPORT=7300

That works without problems.

The code now doesn't wait for login. It sends user name right in the first iteration. Normally this means after a read of up to READ_SIZE (1k) bytes. I could add a bit of logic to ensure that this read was actually done and some time (~half sec) has elapsed since then.

Seems the different cluster versions out there behave differently. My failing test are with the following clusters:

dxc.pi4cc.nl
oz5bbs.dk
dxfun.com
dxc.middlebrook.ca

All on port 8000.

Maybe we should have a look into the old code how they handled the login process.

@zcsahok

zcsahok commented Oct 30, 2026

Copy link
Copy Markdown
Member Author

ok, was sending just CR out of CR+LF, fixed. I was able to see the issue with some .de clusters and it is now resolved.

@dl1jbe

dl1jbe commented Oct 30, 2026

Copy link
Copy Markdown
Member

That was the problem, nice :-). Works fine now with all clusters tested.

@zcsahok

zcsahok commented Oct 30, 2026

Copy link
Copy Markdown
Member Author

Glad to hear it worked. Startup is now instantaneous, and the connection is established in the cluster thread. There’s no explicit notification of whether the connection succeeded or what the error was; that was also the case before, but now at least :INFo gives some indication of the connection state.

We could add a basic connection-error notification by checking the cluster state in the background process, similarly to the “Fldigi: lost connection!” warning. I’m not sure it would add much value, though. No new spots is a fairly clear indirect indication that something has gone wrong.

I just realized that atomics have been used in audio.c since #317, when the VK thread was introduced. GCC has supported C11 for about ten years, so we could add a check, but it probably isn’t worth it. In fact, we could also check other uses of atomics, since other variables are also shared between the threads.

I’m still working on the cluster-terminal concept. We’ll see how it goes.

probably this check guards against line noise; not what one sees
on a tcp connection...
In case of no radio control frequencies show actually bands.
This works for other nodes, but own frequency was not converted to Hz units
and thus when scaling to kHz the result was 0.
before it was: clearing all node lines and then writing freq
now: for each node clearing and writing freq
@zcsahok

zcsahok commented Nov 1, 2026

Copy link
Copy Markdown
Member Author

The new cluster terminal is available the same way as the old one: type :PACket or simply : (colon). To return to the log, press Esc or type any command beginning with :.
The upper part has a fixed size; the lower part adjusts to the terminal size.
All background activities continue running while the terminal is active.

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.

2 participants