Skip to content

Commit

Permalink
Refactor the initial raw decoding
Browse files Browse the repository at this point in the history
* clean up the Raw HTTP route, move code to raw_decoder.
* move device location tracking to its own package/struct
* create a map of method -> decode function, minimum level required
  * we don't need level 30 for everything
  * map will be more efficient than big switch/case
  * decode functions take in the proto and its metadata like
    device uuid, account, etc. This will allow us to pass
    information deeper for things like shiny stats which will
    require tracking accounts.
  • Loading branch information
comstud committed Oct 21, 2023
1 parent 5415262 commit 2a4b37a
Show file tree
Hide file tree
Showing 6 changed files with 562 additions and 499 deletions.
54 changes: 0 additions & 54 deletions deviceList.go

This file was deleted.

64 changes: 64 additions & 0 deletions device_tracker/device_tracker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package device_tracker

import (
"time"

"github.com/jellydator/ttlcache/v3"
)

type DeviceTracker interface {
UpdateDeviceLocation(deviceId string, lat, lon float64, scanContext string)
GetAllDevices() map[string]ApiDeviceLocation
}

type ApiDeviceLocation struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
LastUpdate int64 `json:"last_update"`
ScanContext string `json:"scan_context"`
}

type DeviceLocation struct {
Latitude float64
Longitude float64
LastUpdate int64
ScanContext string
}

type deviceTracker struct {
maxDeviceTTL time.Duration
deviceLocation *ttlcache.Cache[string, DeviceLocation]
}

func (tracker *deviceTracker) UpdateDeviceLocation(deviceId string, lat, lon float64, scanContext string) {
if lat == 0 || lon == 0 || deviceId == "" {
return
}
tracker.deviceLocation.Set(deviceId, DeviceLocation{
Latitude: lat,
Longitude: lon,
LastUpdate: time.Now().Unix(),
ScanContext: scanContext,
}, tracker.maxDeviceTTL)
}

func (tracker *deviceTracker) GetAllDevices() map[string]ApiDeviceLocation {
locations := map[string]ApiDeviceLocation{}
for _, key := range tracker.deviceLocation.Items() {
deviceLocation := key.Value()
locations[key.Key()] = ApiDeviceLocation(deviceLocation)
}
return locations
}

func NewDeviceTracker(maxDeviceTTLHours int) DeviceTracker {
maxDeviceTTL := time.Hour * time.Duration(maxDeviceTTLHours)
tracker := &deviceTracker{
maxDeviceTTL: maxDeviceTTL,
deviceLocation: ttlcache.New[string, DeviceLocation](
ttlcache.WithTTL[string, DeviceLocation](maxDeviceTTL),
),
}
go tracker.deviceLocation.Start()
return tracker
}
56 changes: 4 additions & 52 deletions grpc_server_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"context"
"golbat/config"
pb "golbat/grpc"

_ "google.golang.org/grpc/encoding/gzip" // Install the gzip compressor
"google.golang.org/grpc/metadata"
"time"
)

// server is used to implement helloworld.GreeterServer.
Expand All @@ -24,59 +24,11 @@ func (s *grpcRawServer) SubmitRawProto(ctx context.Context, in *pb.RawProtoReque
}
}

uuid := in.DeviceId
account := in.Username
level := int(in.TrainerLevel)
scanContext := ""
if in.ScanContext != nil {
scanContext = *in.ScanContext
}

latTarget, lonTarget := float64(in.LatTarget), float64(in.LonTarget)
globalHaveAr := in.HaveAr
var protoData []ProtoData

for _, v := range in.Contents {

inboundRawData := ProtoData{
Method: int(v.Method),
Account: account,
Level: level,
ScanContext: scanContext,
Lat: latTarget,
Lon: lonTarget,
Data: v.ResponsePayload,
Request: v.RequestPayload,
Uuid: uuid,
HaveAr: func() *bool {
if v.HaveAr != nil {
return v.HaveAr
}
return globalHaveAr
}(),
}

protoData = append(protoData, inboundRawData)
}

protoData := rawProtoDecoder.GetProtoDataFromGRPC(in)
// Process each proto in a packet in sequence, but in a go-routine
go func() {
timeout := 5 * time.Second
if config.Config.Tuning.ExtendedTimeout {
timeout = 30 * time.Second
}
go rawProtoDecoder.Decode(context.Background(), protoData, decode)

for _, entry := range protoData {
// provide independent cancellation contexts for each proto decode
ctx, cancel := context.WithTimeout(context.Background(), timeout)
decode(ctx, entry.Method, &entry)
cancel()
}
}()

if latTarget != 0 && lonTarget != 0 && uuid != "" {
UpdateDeviceLocation(uuid, latTarget, lonTarget, scanContext)
}
deviceTracker.UpdateDeviceLocation(protoData.Uuid, protoData.Lat(), protoData.Lon(), protoData.ScanContext)

return &pb.RawProtoResponse{Message: "Processed"}, nil
}
Loading

0 comments on commit 2a4b37a

Please sign in to comment.