la5nta / wl2k-go

A Winlink framework for Go.
https://getpat.io
MIT License
50 stars 20 forks source link

Linux NetROM support #72

Open drboone opened 2 years ago

drboone commented 2 years ago

I'm interested in having NetROM support for outbound connections. I'm really not a go programmer, so some of the knowledge I'd need to start this project are missing -- building pat + wl2k-go with local mods, etc.

From a brief investigation, I think the changes would mostly consist of using AF_NETROM for the socket, calling nr_config_loadports instead of the ax version, adding a netrom: url scheme, not using digis. Not sure whether this would be better done as a separate transport, or as conditionals in the ax25 path.

Thoughts?

martinhpedersen commented 2 years ago

Sounds interesting 🙂

With regards to SoC I think a new package and URL scheme (netrom://) are in order. Possibly re-using some functionality from the ax25 package (which will require some refactoring).

I'm not familiar with Net/ROM, so I can't help you with those aspects. What I can tell you is that writing such low-level code in Go can be a challenging task depending on how familiar you are with the language, Cgo and/or the unsafe and syscall packages.

But to get you going, you will need to clone both wl2k-go and pat into adjecent folders and use the replace directive in go.mod to tell the Go toolchain to use your local copy of wl2k-go when compiling Pat. Something like this:

replace github.com/la5nta/wl2k-go => ../wl2k-go

More on replace here: https://thewebivore.com/using-replace-in-go-mod-to-point-to-your-local-module/

martinhpedersen commented 2 years ago

By the way, there is a Wiki page explaining how to implement a new transport driver here: https://github.com/la5nta/pat/wiki/Adding-transports

drboone commented 2 years ago

Aha! Thanks, I'll see how far I can get with this.

martinhpedersen commented 2 years ago

Good luck 🙂 Don't hesitate to reach out if you find yourself stuck down the road!

drboone commented 2 years ago

Stuck!

In the setPort() function, I need to call ax25_aton. The second argument to be passed is a, a pointer to a type ax25Addr C.struct_full_sockaddr_ax25, which (lack of go knowledge here?) seems to be the return value. This type is the same as in the ax25 transport. From the C header files:

int ax25_aton(const char *cp, struct full_sockaddr_ax25 *fsap);

This is the struct from the C header files:

struct full_sockaddr_ax25
  {
    struct sockaddr_ax25 fsa_ax25;
    ax25_address fsa_digipeater[AX25_MAX_DIGIS];
  };

The problem seems to be that the bare a variable, which is a pointer to:

type ax25Addr C.struct_full_sockaddr_ax25

isn't the same type as the required pointer to the C struct. I suspect I'm up against something interesting about the cgo stuff. If I wanted to pass a pointer to a subcomponent, that seems to be possible, as in the ax25 transport.

How do I pass a pointer to the whole thing?

setPort(), barely different from the ax25 transport version, looks like this:

func (a *ax25Addr) setPort(port string) (err error) {
// FIXME
    C.ax25_aton(
        C.nr_config_get_addr(C.CString(port)),
        a,
    )
    return
}

Sorry, this note is a bit upside down, it's late. ;)

martinhpedersen commented 2 years ago

Hmm.. 🤔 It's been a while since I had to struggle with Cgo.

But could it be as simple as C.ax25_aton(..., &a)?

martinhpedersen commented 2 years ago

Probably not. See this: https://github.com/la5nta/wl2k-go/blob/8d29296b6e7a36f0f9756289c7ce03ca58e432ba/transport/ax25/ax25_linux.go#L353.

Looks like you have to use unsafe.Pointer and an explicit type cast 🙂

func (a *ax25Addr) setPort(port string) (err error) {
    C.ax25_aton(
        C.nr_config_get_addr(C.CString(port)),
        (*C.struct_full_sockaddr_ax25)(unsafe.Pointer(&a)),
    )
    return
}
drboone commented 2 years ago

Thank you. That got it to compile, at least.

drboone commented 2 years ago

The Pat session:

ozymandias 19 # ./pat connect netrom://kb8zqz-14@nrnino/n8hee-10
2022/02/26 15:36:57 Connecting to N8HEE-10 (netrom)...
DialNetROMTimeout: socket call succeeded
DialNetROMTimeout: bind call succeeded
2022/02/26 15:37:01 Connected to N8HEE-10 (NetROM)
Trying ec2-54-243-159-239.compute-1.amazonaws.com
*** KB8ZQZ-14 Connected to CMS
[WL2K-5.0-B2FWIHJM$]
;PQ: 58761336
CMS via N8HEE-10 >
>FF
FQ
2022/02/26 15:37:18 Disconnected.

The axlisten output during the Pat session:

nino: fm KB8ZQZ-14 to MISEOC-2 ctl I00^ pid=CF(NET/ROM) len 192 15:36:57.051240

NET/ROM: KB8ZQZ-14->N8HEE-10 ttl 15
         conn rqst: my ckt 01/06 wnd 4 KB8ZQZ-14@KB8ZQZ-14 timeout 120
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I10+ pid=CF(NET/ROM) len 21 15:37:01.582841 
NET/ROM: N8HEE-10->KB8ZQZ-14 ttl 24
         conn ack: ur ckt 01/06 my ckt 04/F7 wnd 4
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR1- 15:37:01.583446 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I11^ pid=CF(NET/ROM) len 70 15:37:03.597099 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 0 rxseq 0
0000  Trying ec2-54-243-159-239.compute-1.amazonaws.comM
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I12+ pid=CF(NET/ROM) len 51 15:37:04.763059 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 1 rxseq 0
0000  *** KB8ZQZ-14 Connected to CMSM
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR3- 15:37:04.763692 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I13^ pid=CF(NET/ROM) len 41 15:37:06.856894 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 2 rxseq 0
0000  [WL2K-5.0-B2FWIHJM$]M
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I14+ pid=CF(NET/ROM) len 34 15:37:07.993476 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 3 rxseq 0
0000  ;PQ: 58761336M
nino: fm KB8ZQZ-14 to MISEOC-2 ctl I51^ pid=CF(NET/ROM) len 192 15:37:07.994059

NET/ROM: KB8ZQZ-14->N8HEE-10 ttl 15
         info ack: ur ckt 04/F7 rxseq 4
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR5- 15:37:08.028897 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl RR1+ 15:37:11.434659 
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR5- 15:37:11.435249 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I25+ pid=CF(NET/ROM) len 39 15:37:12.627891 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 4 rxseq 0
0000  CMS via N8HEE-10 >M
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR6- 15:37:12.628482 
nino: fm KB8ZQZ-14 to MISEOC-2 ctl I62^ pid=CF(NET/ROM) len 91 15:37:12.628815 
NET/ROM: KB8ZQZ-14->N8HEE-10 ttl 15
         info: ur ckt 04/F7 txseq 0 rxseq 5
0000  ;FW: KB8ZQZM[Pat-0.12.1-B2FHMG$]M;PR: 48032496M; N8HEE-10 DE KB8
0040  ZQZ ()M
nino: fm KB8ZQZ-14 to MISEOC-2 ctl I63+ pid=CF(NET/ROM) len 23 15:37:12.645297 
NET/ROM: KB8ZQZ-14->N8HEE-10 ttl 15
         info: ur ckt 04/F7 txseq 1 rxseq 5
0000  FFM
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I25+ pid=CF(NET/ROM) len 39 15:37:14.431367 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 4 rxseq 0
0000  CMS via N8HEE-10 >M
nino: fm KB8ZQZ-14 to MISEOC-2 ctl REJ6- 15:37:14.432033 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl RR4- 15:37:16.743102 
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I46+ pid=CF(NET/ROM) len 23 15:37:18.460874 
NET/ROM: N8HEE-5->KB8ZQZ-14 ttl 24
         info: ur ckt 01/06 txseq 5 rxseq 2
0000  FQM
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR7- 15:37:18.461589 
nino: fm KB8ZQZ-14 to MISEOC-2 ctl I74^ pid=CF(NET/ROM) len 192 15:37:18.461959

NET/ROM: KB8ZQZ-14->N8HEE-10 ttl 15
         disc: ur ckt 04/F7
nino: fm MISEOC-2 to KB8ZQZ-14 ctl I57+ pid=CF(NET/ROM) len 192 15:37:23.786319

NET/ROM: N8HEE-10->KB8ZQZ-14 ttl 24
         disc ack: ur ckt 01/06
nino: fm KB8ZQZ-14 to MISEOC-2 ctl RR0- 15:37:23.786899 

Clearly more testing is in order, as this was a minimal session, and there's some fiddly stuff required with the callsigns and such, but it basically worked!

drboone commented 2 years ago

I've been moving actual mail through this thing for a few days now without issues. I've moved binary attachments both directions, too. Next hacking session, I'll try to clean up the callsign/alias issues &c.