Commit 39754b91 authored by Orne Brocaar's avatar Orne Brocaar
Browse files

Support async NS<>JS API. Truncate GWInfoElement ID to 4 bytes.

parent 9d3eee7b
......@@ -815,6 +815,12 @@ resolve_domain_suffix="{{ .JoinServer.ResolveDomainSuffix }}"
# # for the JoinEUI associated with this server.
# server="https://example.com:1234/join/endpoint"
# # Use the async API scheme.
# async=false
# # Async request timeout.
# async_timeout="1s"
# # CA certificate (optional).
# #
# # Set this to validate the join-server server certificate (e.g. when the
......@@ -834,6 +840,8 @@ resolve_domain_suffix="{{ .JoinServer.ResolveDomainSuffix }}"
[[join_server.servers]]
server="{{ $element.Server }}"
join_eui="{{ $element.JoinEUI }}"
async={{ $element.Async }}
async_timeout="{{ $element.AsyncTimeout }}"
ca_cert="{{ $element.CACert }}"
tls_cert="{{ $element.TLSCert }}"
tls_key="{{ $element.TLSKey }}"
......@@ -849,6 +857,12 @@ resolve_domain_suffix="{{ .JoinServer.ResolveDomainSuffix }}"
# This API is provided by ChirpStack Application Server.
server="{{ .JoinServer.Default.Server }}"
# # Use the async API scheme.
async={{ .JoinServer.Default.Async }}
# # Async request timeout.
async_timeout="{{ .JoinServer.Default.AsyncTimeout }}"
# ca certificate used by the default join-server client (optional)
ca_cert="{{ .JoinServer.Default.CACert }}"
......
......@@ -8,7 +8,7 @@ require (
github.com/Azure/azure-service-bus-go v0.9.1
github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5
github.com/brocaar/chirpstack-api/go/v3 v3.11.1
github.com/brocaar/lorawan v0.0.0-20211025085338-61c36dbfb10a
github.com/brocaar/lorawan v0.0.0-20211122090658-49524ce5fb5b
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/go-redis/redis/v8 v8.8.3
github.com/gofrs/uuid v3.2.0+incompatible
......
......@@ -14,6 +14,7 @@ import (
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/brocaar/chirpstack-network-server/v3/internal/backend/joinserver"
"github.com/brocaar/chirpstack-network-server/v3/internal/band"
"github.com/brocaar/chirpstack-network-server/v3/internal/config"
downdata "github.com/brocaar/chirpstack-network-server/v3/internal/downlink/data"
......@@ -139,37 +140,74 @@ func (a *API) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
// validate ReceiverID
if basePL.ReceiverID != a.netID.String() {
// Parse Receiver ID (NetID).
var receiverID lorawan.NetID
if err := receiverID.UnmarshalText([]byte(basePL.ReceiverID)); err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"receiver_id": basePL.ReceiverID,
"net_id": a.netID.String(),
}).Error("roaming: ReceiverID does not match NetID of network-server")
}).WithError(err).Error("api/roaming: unmarshal ReceiverID as NetID error")
w.WriteHeader(http.StatusBadRequest)
return
}
// Get NetID from SenderID
var netID lorawan.NetID
if err := netID.UnmarshalText([]byte(basePL.SenderID)); err != nil {
// validate ReceiverID
if receiverID.String() != a.netID.String() {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: unmarshal SenderID as NetID error")
"ctx_id": ctx.Value(logging.ContextIDKey),
"receiver_id": basePL.ReceiverID,
"net_id": a.netID.String(),
}).Error("roaming: ReceiverID does not match NetID of network-server")
w.WriteHeader(http.StatusBadRequest)
return
}
// Get ClientID for NetID
client, err := roaming.GetClientForNetID(netID)
if err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: get client for NetID error")
w.WriteHeader(http.StatusInternalServerError)
return
var client backend.Client
if len(basePL.SenderID) >= 16 {
// Parse Sender ID (NetID).
var senderID lorawan.EUI64
if err := senderID.UnmarshalText([]byte(basePL.SenderID)); err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: unmarshal SenderID as EUI64 error")
w.WriteHeader(http.StatusBadRequest)
return
}
// Get ClientID for Sender ID (JoinEUI)
client, err = joinserver.GetClientForJoinEUI(senderID)
if err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: get client for JoinEUI error")
w.WriteHeader(http.StatusInternalServerError)
return
}
} else {
// Parse Sender ID (NetID).
var senderID lorawan.NetID
if err := senderID.UnmarshalText([]byte(basePL.SenderID)); err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: unmarshal SenderID as NetID error")
w.WriteHeader(http.StatusBadRequest)
return
}
// Get ClientID for Sender ID (NetID)
client, err = roaming.GetClientForNetID(senderID)
if err != nil {
log.WithFields(log.Fields{
"ctx_id": ctx.Value(logging.ContextIDKey),
"sender_id": basePL.SenderID,
}).WithError(err).Error("api/roaming: get client for NetID error")
w.WriteHeader(http.StatusInternalServerError)
return
}
}
log.WithFields(log.Fields{
......@@ -288,6 +326,8 @@ func (a *API) handleRequest(ctx context.Context, client backend.Client, basePL b
ans, err = a.handleXmitDataReq(ctx, basePL, b)
case backend.XmitDataAns:
err = a.handleXmitDataAns(ctx, client, basePL, b)
case backend.HomeNSAns:
err = a.handleHomeNSAns(ctx, client, basePL, b)
default:
ans = a.getBasePayloadResult(basePL, backend.MalformedRequest, fmt.Sprintf("MessageType %s is not expected", basePL.MessageType))
}
......@@ -483,6 +523,19 @@ func (a *API) handleXmitDataAns(ctx context.Context, client backend.Client, base
return nil
}
func (a *API) handleHomeNSAns(ctx context.Context, client backend.Client, basePL backend.BasePayload, b []byte) error {
var pl backend.HomeNSAnsPayload
if err := json.Unmarshal(b, &pl); err != nil {
return errors.Wrap(err, "unmarshal json error")
}
if err := client.HandleAnswer(ctx, pl); err != nil {
return errors.Wrap(err, "handle answer error")
}
return nil
}
func (a *API) handleXmitDataReq(ctx context.Context, basePL backend.BasePayload, b []byte) (backend.Answer, error) {
var pl backend.XmitDataReqPayload
if err := json.Unmarshal(b, &pl); err != nil {
......
......@@ -6,11 +6,14 @@ import (
"net"
"net/url"
"strings"
"time"
"github.com/go-redis/redis/v8"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/brocaar/chirpstack-network-server/v3/internal/config"
"github.com/brocaar/chirpstack-network-server/v3/internal/storage"
"github.com/brocaar/lorawan"
"github.com/brocaar/lorawan/backend"
)
......@@ -31,6 +34,8 @@ var (
defaultCACert string
defaultTLSCert string
defaultTLSKey string
defaultRedisClient redis.UniversalClient
defaultAsyncTimeout time.Duration
)
// Setup sets up the joinserver backend.
......@@ -45,6 +50,10 @@ func Setup(c config.Config) error {
defaultTLSKey = c.JoinServer.Default.TLSKey
resolveJoinEUI = c.JoinServer.ResolveJoinEUI
resolveDomainSuffix = c.JoinServer.ResolveDomainSuffix
if c.JoinServer.Default.Async {
defaultRedisClient = storage.RedisClient()
}
defaultAsyncTimeout = c.JoinServer.Default.AsyncTimeout
for _, s := range conf.Servers {
var joinEUI lorawan.EUI64
......@@ -56,14 +65,22 @@ func Setup(c config.Config) error {
s.Server = joinEUIToServer(joinEUI, resolveDomainSuffix)
}
var redisClient redis.UniversalClient
if s.Async {
redisClient = storage.RedisClient()
}
fmt.Println("FOOOO")
client, err := backend.NewClient(backend.ClientConfig{
Logger: log.StandardLogger(),
SenderID: c.NetworkServer.NetID.String(),
ReceiverID: joinEUI.String(),
Server: s.Server,
CACert: s.CACert,
TLSCert: s.TLSCert,
TLSKey: s.TLSKey,
Logger: log.StandardLogger(),
SenderID: c.NetworkServer.NetID.String(),
ReceiverID: joinEUI.String(),
Server: s.Server,
CACert: s.CACert,
TLSCert: s.TLSCert,
TLSKey: s.TLSKey,
RedisClient: redisClient,
AsyncTimeout: s.AsyncTimeout,
})
if err != nil {
return errors.Wrap(err, "new backend client error")
......@@ -125,13 +142,15 @@ func resolveClient(joinEUI lorawan.EUI64) (backend.Client, error) {
}
client, err := backend.NewClient(backend.ClientConfig{
Logger: log.StandardLogger(),
SenderID: netID.String(),
ReceiverID: joinEUI.String(),
Server: server,
CACert: defaultCACert,
TLSCert: defaultTLSCert,
TLSKey: defaultTLSKey,
Logger: log.StandardLogger(),
SenderID: netID.String(),
ReceiverID: joinEUI.String(),
Server: server,
CACert: defaultCACert,
TLSCert: defaultTLSCert,
TLSKey: defaultTLSKey,
RedisClient: defaultRedisClient,
AsyncTimeout: defaultAsyncTimeout,
})
if err != nil {
return nil, errors.Wrap(err, "joinserver: new client error")
......@@ -142,13 +161,15 @@ func resolveClient(joinEUI lorawan.EUI64) (backend.Client, error) {
func getDefaultClient(joinEUI lorawan.EUI64) (backend.Client, error) {
defaultClient, err := backend.NewClient(backend.ClientConfig{
Logger: log.StandardLogger(),
SenderID: netID.String(),
ReceiverID: joinEUI.String(),
Server: defaultServer,
CACert: defaultCACert,
TLSCert: defaultTLSCert,
TLSKey: defaultTLSKey,
Logger: log.StandardLogger(),
SenderID: netID.String(),
ReceiverID: joinEUI.String(),
Server: defaultServer,
CACert: defaultCACert,
TLSCert: defaultTLSCert,
TLSKey: defaultTLSKey,
RedisClient: defaultRedisClient,
AsyncTimeout: defaultAsyncTimeout,
})
if err != nil {
return nil, errors.Wrap(err, "joinserver: new default client error")
......
......@@ -166,18 +166,22 @@ type Config struct {
ResolveDomainSuffix string `mapstructure:"resolve_domain_suffix"`
Servers []struct {
Server string `mapstructure:"server"`
JoinEUI string `mapstructure:"join_eui"`
CACert string `mapstructure:"ca_cert"`
TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"`
Server string `mapstructure:"server"`
JoinEUI string `mapstructure:"join_eui"`
Async bool `mapstructure:"async"`
AsyncTimeout time.Duration `mapstructure:"async_timeout"`
CACert string `mapstructure:"ca_cert"`
TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"`
} `mapstructure:"servers"`
Default struct {
Server string `mapstructure:"server"`
CACert string `mapstructure:"ca_cert"`
TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"`
Server string `mapstructure:"server"`
Async bool `mapstructure:"async"`
AsyncTimeout time.Duration `mapstructure:"async_timeout"`
CACert string `mapstructure:"ca_cert"`
TLSCert string `mapstructure:"tls_cert"`
TLSKey string `mapstructure:"tls_key"`
} `mapstructure:"default"`
KEK struct {
......
......@@ -120,8 +120,13 @@ func RXInfoToGWInfo(rxInfo []*gw.UplinkRXInfo) ([]backend.GWInfoElement, error)
return nil, errors.Wrap(err, "marshal rxinfo error")
}
id := backend.HEXBytes(rxInfo[i].GatewayId)
if len(id) == 8 {
id = id[4:]
}
e := backend.GWInfoElement{
ID: backend.HEXBytes(rxInfo[i].GatewayId),
ID: id,
FineRecvTime: fineRecvTime,
RSSI: &rssi,
SNR: &rxInfo[i].LoraSnr,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment