107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package cdp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
|
|
"src.dualinventive.com/go/lib/dilog"
|
|
)
|
|
|
|
// Endpoint for T-Mobile CDP HTTP JSON
|
|
type Endpoint struct {
|
|
mux http.Handler
|
|
url string
|
|
log dilog.Logger
|
|
uplinkMsgReportHandler UplinkMsgReportHandlerFunc
|
|
basicAuth *endpointBasicAuth
|
|
}
|
|
|
|
// NewEndpoint create a new endpoint on url
|
|
func NewEndpoint(url string, opts ...EndpointOption) (*Endpoint, error) {
|
|
ep := &Endpoint{}
|
|
for _, option := range opts {
|
|
err := option(ep)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if ep.log == nil {
|
|
ep.log = dilog.Discard
|
|
}
|
|
ep.url = url
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/", ep.uplinkMsgDataHandler)
|
|
ep.mux = mux
|
|
return ep, nil
|
|
}
|
|
|
|
// ListenAndServe listens and serves the endpoint
|
|
func (ep *Endpoint) ListenAndServe() error {
|
|
return http.ListenAndServe(ep.url, ep.mux)
|
|
}
|
|
|
|
// uplinkMsgDataHandlerReadEndpointMessage reads the EndpointMessage from the http request
|
|
func uplinkMsgDataHandlerReadEndpointMessage(r *http.Request) (*EndpointMessage, error) {
|
|
data, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = r.Body.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
epMsg := &EndpointMessage{}
|
|
err = json.Unmarshal(data, epMsg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return epMsg, nil
|
|
}
|
|
|
|
func (ep *Endpoint) uplinkMsgDataHandler(w http.ResponseWriter, r *http.Request) {
|
|
if ep.uplinkMsgReportHandler == nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// When basic authentication option is set we validate the request
|
|
if ep.basicAuth != nil {
|
|
if !ep.basicAuth.IsRequestAuthenticated(r) {
|
|
ep.log.WithFields(dilog.Fields{
|
|
"ip": getIPAddress(r),
|
|
}).Error("client not authenticated")
|
|
w.Header().Set("WWW-Authenticate", "Basic")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
}
|
|
|
|
// It is possible the IoT portal probes if the URL is valid with an empty request
|
|
if r.ContentLength == 0 {
|
|
w.WriteHeader(http.StatusOK)
|
|
return
|
|
}
|
|
|
|
epMsg, err := uplinkMsgDataHandlerReadEndpointMessage(r)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
ep.log.WithError(err).Error("uplinkMsgDataHandlerReadEndpointMessage failed")
|
|
return
|
|
}
|
|
|
|
for _, report := range epMsg.Reports {
|
|
report := report
|
|
if report.ResourcePath != ResourcePathUplinkMsgData {
|
|
continue
|
|
}
|
|
|
|
ep.uplinkMsgReportHandler(&report)
|
|
}
|
|
}
|