<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gtw_rtr_udp

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"net"
)

type Adapter struct {
	Logger log.Logger
	conn   *net.UDPConn
}

// Ack implements the core.Adapter interface. It expects only one param "port" as a
// uint
func (a *Adapter) Listen(router core.Router, options interface{}) error {
	// Parse options
	var port uint
	switch options.(type) {
	case uint:
		port = options.(uint)
	default:
		return fmt.Errorf("Unreckognized options %+v\n", options)

	}

	// Create the udp connection and start listening with a goroutine
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		return err
	}
	a.conn, err = net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}
	go a.listen(router) // NOTE: There is no way to stop properly the adapter and thus this goroutine for now.
	return nil
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Ack(router core.Router, packet semtech.Packet, gateway core.GatewayAddress) {
	if a.conn == nil {
		a.log("Connection not established. Connect the adaptor first.")
		router.HandleError(core.ErrAck(fmt.Errorf("Connection not established. Connect the adaptor first.")))
		return
	}

	a.log("Acks packet %+v", packet)

	addr, err := net.ResolveUDPAddr("udp", string(gateway))

	if err != nil {
		a.log("Unable to retrieve gateway address")
		router.HandleError(core.ErrAck(err))
		return
	}

	raw, err := semtech.Marshal(packet)

	if err != nil {
		a.log("Unable to marshal given packet")
		router.HandleError(core.ErrAck(err))
		return
	}

	_, err = a.conn.WriteToUDP(raw, addr)

	if err != nil {
		a.log("Unable to send udp message")
		router.HandleError(core.ErrAck(err))
		return
	}
}

// listen Handle incoming packets and forward them to the router
func (a *Adapter) listen(router core.Router) {
	for {
		buf := make([]byte, 1024)
		n, addr, err := a.conn.ReadFromUDP(buf)
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}
		a.log("Incoming datagram %x", buf[:n])<commit_msg>[router] Impact changes caused by error handling refactor + test suite on gateway <-> router adapter<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package gtw_rtr_udp

import (
	"fmt"
	"github.com/thethingsnetwork/core"
	"github.com/thethingsnetwork/core/lorawan/semtech"
	"github.com/thethingsnetwork/core/utils/log"
	"net"
)

type Adapter struct {
	Logger log.Logger
	conn   *net.UDPConn
}

// Ack implements the core.Adapter interface. It expects only one param "port" as a
// uint
func (a *Adapter) Listen(router core.Router, options interface{}) error {
	// Parse options
	var port uint
	switch options.(type) {
	case uint:
		port = options.(uint)
	default:
		a.log("Invalid option provided: %+v", options)
		return core.ErrBadOptions
	}

	// Create the udp connection and start listening with a goroutine
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", port))
	if a.conn, err = net.ListenUDP("udp", addr); err != nil {
		a.log("Unable to establish the connection: %v", err)
		return core.ErrBadOptions
	}
	go a.listen(router) // NOTE: There is no way to stop properly the adapter and thus this goroutine for now.
	return nil
}

// Ack implements the core.GatewayRouterAdapter interface
func (a *Adapter) Ack(router core.Router, packet semtech.Packet, gateway core.GatewayAddress) {
	if a.conn == nil {
		a.log("Connection not established. Connect the adaptor first.")
		router.HandleError(core.ErrAck(fmt.Errorf("Connection not established. Connect the adaptor first.")))
		return
	}

	a.log("Acks packet %+v", packet)

	addr, err := net.ResolveUDPAddr("udp", string(gateway))

	if err != nil {
		a.log("Unable to retrieve gateway address")
		router.HandleError(core.ErrAck(err))
		return
	}

	raw, err := semtech.Marshal(packet)

	if err != nil {
		a.log("Unable to marshal given packet")
		router.HandleError(core.ErrAck(err))
		return
	}

	_, err = a.conn.WriteToUDP(raw, addr)

	if err != nil {
		a.log("Unable to send udp message")
		router.HandleError(core.ErrAck(err))
		return
	}
}

// listen Handle incoming packets and forward them to the router
func (a *Adapter) listen(router core.Router) {
	defer a.conn.Close()
	for {
		buf := make([]byte, 1024)
		n, addr, err := a.conn.ReadFromUDP(buf)
		if err != nil {
			a.log("Error: %v", err)
			go router.HandleError(core.ErrUplink(err))
			continue
		}
		a.log("Incoming datagram %x", buf[:n])
{'fraction_non_alphanumeric': 0.12708681135225375, 'fraction_numerical': 0.005008347245409015, 'mean_word_length': 3.9058341862845447, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1054783', 'n_tokens_mistral': 1705, 'n_tokens_neox': 1612, 'n_words': 500}