github.com/la5nta/wl2k-go@v0.11.8/transport/ax25/beacon_linux.go (about)

     1  // Copyright 2015 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
     2  // Use of this source code is governed by the MIT-license that can be
     3  // found in the LICENSE file.
     4  
     5  //go:build libax25 && cgo
     6  // +build libax25,cgo
     7  
     8  package ax25
     9  
    10  //#include <sys/socket.h>
    11  import "C"
    12  
    13  import (
    14  	"fmt"
    15  	"net"
    16  	"syscall"
    17  	"time"
    18  	"unsafe"
    19  )
    20  
    21  func NewAX25Beacon(axPort, mycall, dest, message string) (Beacon, error) {
    22  	if err := checkPort(axPort); err != nil {
    23  		return nil, err
    24  	}
    25  
    26  	localAddr := newAX25Addr(mycall)
    27  	if err := localAddr.setPort(axPort); err != nil {
    28  		return nil, err
    29  	}
    30  	remoteAddr := newAX25Addr(dest)
    31  
    32  	return &ax25Beacon{localAddr, remoteAddr, message}, nil
    33  }
    34  
    35  type ax25Beacon struct {
    36  	localAddr  ax25Addr
    37  	remoteAddr ax25Addr
    38  	message    string
    39  }
    40  
    41  func (b *ax25Beacon) Message() string      { return b.message }
    42  func (b *ax25Beacon) LocalAddr() net.Addr  { return AX25Addr{b.localAddr} }
    43  func (b *ax25Beacon) RemoteAddr() net.Addr { return AX25Addr{b.remoteAddr} }
    44  
    45  func (b *ax25Beacon) Every(d time.Duration) error {
    46  	for {
    47  		if err := b.Now(); err != nil {
    48  			return err
    49  		}
    50  		time.Sleep(d)
    51  	}
    52  }
    53  
    54  func (b *ax25Beacon) Now() error {
    55  	// Create file descriptor
    56  	// REVIEW: Should we keep it for next beacon?
    57  	var socket fd
    58  	if f, err := syscall.Socket(syscall.AF_AX25, syscall.SOCK_DGRAM, 0); err != nil {
    59  		return err
    60  	} else {
    61  		socket = fd(f)
    62  	}
    63  	defer socket.close()
    64  
    65  	if err := socket.bind(b.localAddr); err != nil {
    66  		return fmt.Errorf("bind: %s", err)
    67  	}
    68  
    69  	msg := C.CString(b.message)
    70  	_, err := C.sendto(
    71  		C.int(socket),
    72  		unsafe.Pointer(msg),
    73  		C.size_t(len(b.message)),
    74  		0,
    75  		(*C.struct_sockaddr)(unsafe.Pointer(&b.remoteAddr)),
    76  		C.socklen_t(unsafe.Sizeof(b.remoteAddr)),
    77  	)
    78  
    79  	return err
    80  }