sbd

package module
v0.0.0-...-f4e91f3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2019 License: MIT Imports: 10 Imported by: 0

README

pipeline status coverage report

Short Burst Data (Iridium)

Short Burst Data (SBD) is used by Iridium to send data from their datacenter to your service. This repository contains a library and a service to receive such data. You can use the library in your code, you can start the directipserver by starting the service standalone (or via docker) or you can deploy the directipserver as a kubernetes controller in your cluster.

Library

This repository implements a Go parser for Iridiums Short Bust Data. To use it you can import it and call the GetElements function with a reader:

data = "\x01\x008\x01\x00\x1cp\xec\ai300234063904190\x00\x00K\x00\x00U\x9e\xba,\x02\x00\x0ctest message"

el, err := sbd.GetElements(bytes.NewBufferString(data))

The result is an InformationBucket which contains field for the header, location and payload. The latitude and longitude is also transmitted in a location field where the values are transformed to positive and negative values.

Distribution service

If you do not want to use this code as an embedded library, you can use the bundled distribution service. This service needs a configuration for IMEI patterns and backend URL's. When the distributor receives a new SBD packet it will search for all matches of the IMEI in the packet and push a JSON data struct to the configured backend URL's. The JSON data contains all the data from the SBD packet, so its up to the receiver to transform the data to a custom format.

The distributor can be run as a standalone binary or as a controller inside a kubernetes cluster. If you are using it as a controller, it must be run with a serviceaccount which has enough rights to watch services. Take a look at the spec file in the 'kubernetes' folder as an example.

If you have deployed the controller, you can annotate your services like this:

apiVersion: v1
kind: Service
metadata:
  name: myservice
  labels:
    run: myservice
  annotations:
    protegear.io/directip-imei: ".*"
    protegear.io/directip-port: "8080"
    protegear.io/directip-path: "/"
spec:
  type: ClusterIP
  ports:
  - port: 8080
    protocol: TCP
  selector:
    app: myservice

The controller will match the imei of incoming messages with the annotated regexp protegear.io/directip-imei and if it matches, the controller will post the message as a JSON formatted message. The port and the path can also be annotated; if they are missing the port will be 8080 and the path will be /.

You can annotate as many services as you want; you can also annotate them with specific IMEI's. It's up to you.

Standalone service

First of all you have to compile the service. You need at least Go 1.11 installed. Simply type make so build a binary in the cmd/directipserver/bin directory.

You can use the service as a standalone daemon. In this case you have to write a configuration file for example:

- imeipattern: 30.*
  backend: http://localhost:8080/service1
- imeipattern: .*
  backend: https://localhost:8443/service2
  skiptls: true
  header:
    mytoken: 1234

This configuration would post all IMEI's which start with 30 to be posted to the URL http://localhost:8080/service1. All other IMEI's will be posted to the URL https://localhost:8443/service2 and the distribution service will not check the TLS certificate (use this only in development!). Additional Headers can also be added here.

Now start the distribution service:

$ ./directipserver -config ~/tmp/test.yaml -logformat term 0.0.0.0:8123
INFO[09-02|16:42:23] start service                            stage=test revision=29fb44a3 builddate="2018-09-02 16:30:51+02:00" listen=0.0.0.0:8123 caller=main.go:51
INFO[09-02|16:42:23] start distributor service                worker=1 caller=distributor.go:117
INFO[09-02|16:42:23] start distributor service                worker=3 caller=distributor.go:117
INFO[09-02|16:42:23] start distributor service                worker=2 caller=distributor.go:117
INFO[09-02|16:42:23] start distributor service                worker=0 caller=distributor.go:117
INFO[09-02|16:42:23] change configuration                     stage=test targets="[{ID: IMEIPattern:30.* Backend:http://localhost:8080/service1 SkipTLS:false Header:map[] imeipattern:<nil> client:<nil>} {ID: IMEIPattern:.* Backend:https://localhost:8443/service2 SkipTLS:true Header:map[mytoken:1234] imeipattern:<nil> client:<nil>}]" caller=main.go:71
INFO[09-02|16:42:23] no incluster config, assume standalone mode stage=test caller=main.go:77
INFO[09-02|16:42:23] start distributor service                worker=4 caller=distributor.go:117
INFO[09-02|16:42:23] set config                               config="[{ID: IMEIPattern:30.* Backend:http://localhost:8080/service1 SkipTLS:false Header:map[] imeipattern:0xc00008d2c0 client:0xc000087e30} {ID: IMEIPattern:.* Backend:https://localhost:8443/service2 SkipTLS:true Header:map[mytoken:1234] imeipattern:0xc00008d400 client:0xc000087ec0}]" worker=1 caller=distributor.go:124

You can omit the -logformat option to use json logging.

Important notice

The sbd service always sends an OK-acknowledge back to iridium if the post to the HTTP service was successful. It is up to the receiver of the webservice to store and forward the message. If the service returns a successfull HTTP response code and crashes, the message will be lost because iridium will receive a successfull ack.

Documentation

Index

Constants

View Source
const (

	// SBD Session Status
	StCompleted             = SessionStatus(0)
	StMTTooLarge            = SessionStatus(1)
	StLocationUnacceptable  = SessionStatus(2)
	StTimeout               = SessionStatus(10)
	StIMEITooLarge          = SessionStatus(12)
	StRFLinkLoss            = SessionStatus(13)
	StIMEIProtocolAnomaly   = SessionStatus(14)
	StIMEIProhibitedGateway = SessionStatus(15)

	NE = Orientation(0)
	NW = Orientation(1)
	SE = Orientation(2)
	SW = Orientation(3)
)

Variables

This section is empty.

Functions

func AssignMTMSN

func AssignMTMSN(rq *DirectIPRequest)

AssignMTMSN sets the corresponding disposition flag.

func FlushMTQueue

func FlushMTQueue(rq *DirectIPRequest)

FlushMTQueue sets the corresponding disposition flag.

func HighPriorityMessage

func HighPriorityMessage(rq *DirectIPRequest)

HighPriorityMessage sets the corresponding disposition flag.

func NewService

func NewService(log log15.Logger, address string, h Handler, proxyprotocol bool) error

NewService starts a listener on the given *address* and dispatches every short burst data packet to the given handler. If the handler returns a non-nil error, the service will send a negative response, otherwise the responsestatus will be ok.

func SendRingAlertNoMTM

func SendRingAlertNoMTM(rq *DirectIPRequest)

SendRingAlertNoMTM sets the corresponding disposition flag.

func UpdateSSDLocation

func UpdateSSDLocation(rq *DirectIPRequest)

UpdateSSDLocation sets the corresponding disposition flag.

Types

type Confirmation

type Confirmation struct {
	UniqueClientMsgID [4]byte  `json:"uniqueclientmsgid`
	IMEI              [15]byte `json:"imei"`
	AutoIDReference   uint32   `json:"autoidreference"`
	MessageStatus     int16    `json:"messagestatus"`
}

A Confirmation is returned when a directip call is invoked.

type DIPHandler

type DIPHandler func(mg *MessageHeader, dih *DirectIPHeader, payload []byte, priority *int) Confirmation

type DIPServer

type DIPServer struct {
	Handle  DIPHandler
	OnError func(error)
	// contains filtered or unexported fields
}

A DIPServer is a server which can listen on an given tcp address and parses the incoming directip messages. Set the Handler-Field to implement your wanted behaviour. The default is simply logging.

func NewDIPServer

func NewDIPServer(address string) (*DIPServer, error)

NewDIPServer returns a new directip server listening on the given address.

func (*DIPServer) Close

func (ts *DIPServer) Close()

Close closes the server so it does not accept any more connections.

func (*DIPServer) Start

func (ts *DIPServer) Start()

Start starts listening. This function will block!

type DirectIPHeader

type DirectIPHeader struct {
	UniqueClientMsgID [4]byte  `json:"uniqueclientmsgid"`
	IMEI              [15]byte `json:"imei"`
	DispositionFlags  uint16   `json:"dispositionflags"`
}

type DirectIPRequest

type DirectIPRequest struct {
	// contains filtered or unexported fields
}

A DirectIPRequest encapsulates the data needed for a directip message.

func NewRequest

func NewRequest() *DirectIPRequest

NewRequest returns a new request to the given address.

func (*DirectIPRequest) Do

func (rq *DirectIPRequest) Do(serverAddress string) (*Confirmation, error)

func (*DirectIPRequest) With

func (rq *DirectIPRequest) With(opts ...DirectOption) *DirectIPRequest

With can be used to set some request options.

type DirectOption

type DirectOption func(rq *DirectIPRequest)

DirectOption is the type for configuring the request

func ClientMsgID

func ClientMsgID(msg string) DirectOption

ClientMsgID sets the clientmsgi in the header. only the first 4 bytes are used!

func IMEI

func IMEI(imei string) DirectOption

IMEI sets the imei in the header.

func Payload

func Payload(payload []byte) DirectOption

Payload sets payload, so a payload information element will be added.

func PriorityLevel

func PriorityLevel(lvl int) DirectOption

PriorityLevel sets the prio level so a priority information element will be added.

type ElementID

type ElementID byte

func (ElementID) TargetType

func (eid ElementID) TargetType() interface{}

type Handler

type Handler interface {
	Handle(data *InformationBucket) error
}

A Handler is called by the service when a new *Short Burst Data* packet comes in. The handler will get an *InformationBucket* where all the packet data is bundled. If this handler returns nil, the server will send a positiv acknowledge back otherwise the packet will not be acknowledged.

func Logger

func Logger(log log15.Logger, next Handler) Handler

Logger is a middleware function which wraps a handler with logging capabilities.

type HandlerFunc

type HandlerFunc func(data *InformationBucket) error

A HandlerFunc makes a handler from a function.

func (HandlerFunc) Handle

func (f HandlerFunc) Handle(data *InformationBucket) error

Handle implements the required interface for *Handler*.

type Header struct {
	ID            ElementID `json:"id"`
	ElementLength uint16    `json:"elementlength"`
}

An Header is sent before every information element and specifies the ID (aka type) and length of the element.

type InformationBucket

type InformationBucket struct {
	Header   *MODirectIPHeader      `json:"header"`
	Payload  []byte                 `json:"payload"`
	Location *MOLocationInformation `json:"location"`
	Position *Location              `json:"position"`
}

InformationElements is a wrapper type for the InformationElement's which are in a bundled bucket

func GetElements

func GetElements(in io.Reader) (*InformationBucket, error)

GetElements parses the given stream and returns an array of found elements.

type InformationElement

type InformationElement struct {
	Header `json:"header"`
	Data   interface{} `json:"data"`
}

An InformationElement contains a header and the data which can have different types. You have to inspect the header's ID field to get the type.

func NewPayload

func NewPayload(b []byte) *InformationElement

NewPayload returns an element which contains the given bytes as payload.

func (*InformationElement) UnmarshalJSON

func (u *InformationElement) UnmarshalJSON(data []byte) error

type Location

type Location struct {
	Latitude  float64
	Longitude float64
}

type LocationData

type LocationData struct {
	OrientationCode Orientation `json:"orientationcode"`
	LatDegree       byte        `json:"latdegree"`
	LatMinute       uint16      `json:"latminute"`
	LngDegree       byte        `json:"lngdegree"`
	LngMinute       uint16      `json:"lngminute"`
}

LocationData contains an orientation as well as the latitude and longitude in degree's and minutes.

type MOConfirmationMessage

type MOConfirmationMessage struct {
	Status byte `json:"status"`
}

A MOConfirmationMessage contains the confirmation status.

func (*MOConfirmationMessage) Success

func (ch *MOConfirmationMessage) Success() bool

Success checks if the confirmation was successfull.

type MODirectIPHeader

type MODirectIPHeader struct {
	CDRReference  uint32        `json:"cdrreference"`
	IMEI          [15]byte      `json:"imei"`
	SessionStatus SessionStatus `json:"sessionstatus"`
	MOMSN         uint16        `json:"momsn"`
	MTMSN         uint16        `json:"mtmsn"`
	TimeOfSession uint32        `json:"timeofsession"`
}

The MODirectIPHeader contains some information about the message itself.

func (*MODirectIPHeader) GetIMEI

func (dih *MODirectIPHeader) GetIMEI() string

GetIMEI returns the imei as a string

func (*MODirectIPHeader) GetTime

func (dih *MODirectIPHeader) GetTime() time.Time

GetTime returns the time which is specified by the TimeOfSession field

func (*MODirectIPHeader) MarshalJSON

func (u *MODirectIPHeader) MarshalJSON() ([]byte, error)

func (*MODirectIPHeader) UnmarshalJSON

func (u *MODirectIPHeader) UnmarshalJSON(data []byte) error

type MOLocationInformation

type MOLocationInformation struct {
	Position  LocationData `json:"position"`
	CEPRadius uint32       `json:"cepradius"`
}

MOLocationInformation contains location information and the cep radius in km.

func (*MOLocationInformation) GetCEPRadius

func (loc *MOLocationInformation) GetCEPRadius() int

GetCEPRadius simply returns the radius as an int value

func (*MOLocationInformation) GetLatLng

func (loc *MOLocationInformation) GetLatLng() (float64, float64)

GetLatLng converts the location information to latitude/longitude values which can be used by other systems. The orientiation is used to convert the values to positive or negative vals.

type MOPayload

type MOPayload struct {
	Payload []byte `json:"payload"`
}

MOPayload is a wrapper around some blob data.

type MessageHeader

type MessageHeader struct {
	ProtocolRevision byte
	MessageLength    uint16
}

A MessageHeader defines the revision and the whole message length.

type Orientation

type Orientation byte

func (Orientation) LatLng

func (o Orientation) LatLng(lat, lng float64) (float64, float64)

type SessionStatus

type SessionStatus byte

Directories

Path Synopsis
cmd
Package mux provides a service to split incoming directip messages to backend HTTP services.
Package mux provides a service to split incoming directip messages to backend HTTP services.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL