-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp-send.go
141 lines (107 loc) · 3 KB
/
http-send.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2017 Inca Roads LLC. All rights reserved.
// Use of this source code is governed by licenses granted by the
// copyright holder including that found in the LICENSE file.
// Inbound support for the "/send" HTTP topic
package main
import (
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
)
// Unpack common AppReq fields from an incoming TTGateReq
func newAppReqFromGateway(ttg *TTGateReq, Transport string) IncomingAppReq {
var AppReq IncomingAppReq
if ttg.Latitude != 0 {
AppReq.GwLatitude = &ttg.Latitude
AppReq.GwLongitude = &ttg.Longitude
alt := float64(ttg.Altitude)
AppReq.GwAltitude = &alt
}
if ttg.Snr != 0 {
AppReq.GwSnr = &ttg.Snr
}
if ttg.ReceivedAt != "" {
AppReq.GwReceivedAt = &ttg.ReceivedAt
}
if ttg.Location != "" {
AppReq.GwLocation = &ttg.Location
}
AppReq.SvTransport = Transport
return AppReq
}
// Handle inbound HTTP requests from the gateway or directly from the device
func inboundWebSendHandler(rw http.ResponseWriter, req *http.Request) {
stats.Count.HTTP++
body, err := io.ReadAll(req.Body)
if err != nil {
fmt.Printf("Error reading HTTP request body: \n%v\n", req)
return
}
switch req.UserAgent() {
// UDP messages that were relayed to the TTSERVE HTTP load balancer, JSON-formatted
case "TTSERVE":
{
var ttg TTGateReq
err = json.Unmarshal(body, &ttg)
if err != nil {
fmt.Printf("*** Received badly formatted HTTP request from %s: \n%v\n", req.UserAgent(), body)
return
}
// Use the TTGateReq to initialize a new AppReq
AppReq := newAppReqFromGateway(&ttg, ttg.Transport)
// Process it. Note there is no possibility of a reply.
go AppReqPushPayload(AppReq, ttg.Payload, "device directly")
stats.Count.HTTPRelay++
}
// Messages that come from TTGATE are JSON-formatted
case "TTGATE":
{
var ttg TTGateReq
err = json.Unmarshal(body, &ttg)
if err != nil {
return
}
// Figure out the transport based upon whether or not a gateway ID was included
requestor, _, abusive := getRequestorIPv4(req)
if abusive {
return
}
Transport := "lora-http:" + requestor
if ttg.GatewayID != "" {
Transport = "lora:" + ttg.GatewayID
}
// Use the TTGateReq to initialize a new AppReq
AppReq := newAppReqFromGateway(&ttg, Transport)
// Process it
go AppReqPushPayload(AppReq, ttg.Payload, "Lora gateway")
stats.Count.HTTPGateway++
}
// Messages directly from devices are hexified
case "TTNODE":
{
// After the single solarproto unit is upgraded, we can remove this.
buf, err := hex.DecodeString(string(body))
if err != nil {
fmt.Printf("Hex decoding error: %v\n%v\n", err, string(body))
return
}
// Initialize a new AppReq
AppReq := IncomingAppReq{}
requestor, _, abusive := getRequestorIPv4(req)
if abusive {
return
}
AppReq.SvTransport = "device-http:" + requestor
// Push it
go AppReqPushPayload(AppReq, buf, "device directly")
stats.Count.HTTPDevice++
}
default:
{
// A web crawler, etc.
return
}
}
}