# Wiring

AI-generated

How `DirewolfMain` (`internal/direwolf/direwolf.go`) builds the components of `samoyed-direwolf`
and connects them.
No component reaches another through a package-level variable:
each is handed what it uses when it is made,
as a constructor argument.

Each arrow points from a component to something it uses,
and is labelled with what it is handed:
a function, often a method value such as `dataLinkQueue.RecFrame`,
or a small interface declared beside the code that uses it.
Dashed arrows are connections made after construction rather than at it.

The diagram leaves out what is plain configuration
(the parsed configuration file and the debug options,
and the `digipeater.Port` for each channel that `RadioConfig.digipeaterPorts` takes from it for the digipeaters)
and the services with only one user,
which `DirewolfMain` hands over in the same way:
the heard list (`mheard`) to the packet filter, the IGate, the beacon service and the received packet handler;
the packet filter to the IGate and the digipeaters;
the APRS log to the beacon service and the received packet handler;
the GPS to the beacon service and the waypoint sender;
and the waypoint sender and the APRS decoder to the received packet handler.

How a received frame gets from a sample to `recv_process`,
and what happens to it there,
is on the [Receive path](../receive-path/index.html.md) page.

## Construction order

`DirewolfMain` makes each component once what it is handed exists,
so the order of construction follows the arrows:

1. The audio devices, then the `DataLinkQueue`,
   which almost everything feeds.
2. The demodulators (`multi_modem_init`),
   handed a `radioSink` that passes their frames to the `DataLinkQueue`.
3. The network TNCs, the serial TNCs and the AXUDP channels.
   Their listeners start straight away and can hand the queue frames at once.
4. The `TransmitQueue`,
   which sends a packet for a network TNC, serial TNC or AXUDP channel straight there
   rather than queueing it.
5. The tone generators and the PTT.
6. The web interface and the AGW server.
   The web interface binds its port as it is made;
   with its port disabled, or taken, there is no hub,
   and the frames that would have gone to it go nowhere.
   The AGW server is made here,
   so that the transmit service can show its clients each frame sent,
   but only started once the transmit threads are running.
   It binds its port when it is made,
   so a port already in use is reported before the server starts,
   rather than once it is running.
   With the port disabled or taken,
   or when `-x` only sends calibration tones,
   there is no AGW server:
   what it would have been handed takes a nil one as having no clients.
7. The `XmitService`, which starts a transmit thread per radio channel.
8. The IGate and the two digipeaters,
   then the `AX25Link`, the KISS handler and its transports,
   the APRStt gateway and the beacon service.
9. The audio device goroutines (`recv_init`),
   and finally `recv_process`,
   which takes from the `DataLinkQueue` and hands each item to the `AX25Link` or the `recPacketHandler`.

Nothing is sent or received until the goroutines that do so are started,
so a component made later in this list can still be handed to one made earlier,
by a connection made after construction, before anything starts.
The next section lists those connections.

## Connections made after construction

**The PTT and the demodulators.**
The PTT mutes a channel’s receiver while it transmits (`Layer2Receiver.MuteInput`),
so it is made after the demodulators.
The demodulators in turn set the PTT’s DCD output (`radioSink.setDCD`)
and read its transmit inhibit input (`Layer2Receiver.txInhibited`),
so those two are set once the PTT exists.

**The transmit queue and the IGate.**
The IGate queues packets from APRS-IS for transmission,
and the transmit queue hands the IGate whatever is queued for the IGate’s own channel.
The queue is made first,
and handed the IGate’s `sendRecPacket` with `TransmitQueue.SetIGate` once the IGate exists.

**The KISS handler and the KISS TCP service.**
The handler copies a client’s data frames to the TCP clients with KISSCOPY,
so it is made after the `KissNetService` and handed it.
The service is handed the handler when it is started (`KissNetService.Start`),
rather than when it is made.
It binds its ports when it is made, though,
so a port already in use is reported before the service starts,
rather than once it is running.

**The audio devices and the demodulators.**
Each audio device’s statistics report its channels’ received audio levels,
which the demodulators keep,
so the devices are handed `Layer2Receiver.AudioLevel` with `AudioDevices.setAudioLevel` once the demodulators exist.
Unlike the others this is not a cycle:
the demodulators do not use the audio devices,
and are made after them only because `DirewolfMain` opens the devices first.

## Conventions

The shapes in the diagram follow the dependency conventions in `AGENTS.md`:

- A component that makes one call is handed a function,
  typed for what it does with it:
  `frameReceiver`, `dwcore.FrameSender`, `igateSender`, `seizeConfirmer`.
- A component that makes several calls is handed a small interface,
  declared beside it and holding only those calls:
  `linkClients`, `linkTransmitter`, `clientTransmitQueue`, `xmitQueue`, `agwDataLink`.
- `*TransmitQueue`, `*DataLinkQueue` and `*AGWServer` satisfy those interfaces without knowing about them.

## References

- `internal/direwolf/direwolf.go`: `DirewolfMain`, which makes and connects everything above,
  and `recPacketHandler`.
- The constructors, and the functions and interfaces they take,
  in `internal/direwolf`:
  `multi_modem.go` (`multi_modem_init`, `ReceiveSink`, `radioSink`),
  `dlq.go` (`frameReceiver`, `seizeConfirmer`),
  `tq.go` (`NewTransmitQueue`, `clientTransmitQueue`, `SetIGate`),
  `xmit.go` (`NewXmitService`, `xmitQueue`),
  `ax25_link.go` (`NewAX25Link`, `linkClients`, `linkTransmitter`),
  `server.go` (`NewAGWServer`, `agwDataLink`),
  `igate.go` (`NewIGate`, `igateSender`),
  `kiss_frame.go` (`NewKissHandler`),
  `kissnet.go` (`NewKissNetService`, `KissNetService.Start`),
  `aprs_tt.go` (`NewTTGateway`),
  `beacon.go` (`NewBeaconService`, `beaconIGate`),
  `audio.go` (`AudioDevices.setAudioLevel`),
  `channel_config.go` (`RadioConfig.digipeaterPorts`)
  and `recv.go` (`recv_init`, `recv_process`).
- `internal/direwolf/webui_source.go`: `webui_init`,
  and `internal/webui/server.go`: `NewServer`.
- `internal/ptt/ptt.go`: `New`,
  handed each channel’s configuration by `RadioConfig.pttChannels` (`internal/direwolf/channel_config.go`).
- The digipeaters’ constructors, and what they take,
  in `internal/digipeater`:
  `digipeater.go` (`New`, `Port`)
  and `cdigipeater.go` (`NewConnected`).
- `internal/dwcore/dwcore.go`: `FrameSender`,
  shared by everything that hands the transmit queue a frame.
- `AGENTS.md`, the “Dependencies” section.
