Newer
Older
* Copyright (c) 2019 InterDigital Communications, Inc
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
package server
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
Kevin Di Lallo
committed
"os"
"strconv"
"strings"
"time"
sbi "github.com/InterDigitalInc/AdvantEDGE/go-apps/meep-loc-serv/sbi"
Kevin Di Lallo
committed
dkm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-key-mgr"
httpLog "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-http-logger"
Simon Pastor
committed
clientNotifOMA "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-loc-serv-notification-client"
log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis"
Simon Pastor
committed
"github.com/gorilla/mux"
)
Kevin Di Lallo
committed
const LocServBasePath = "/location/v1/"
Kevin Di Lallo
committed
const locServKey string = "loc-serv:"
const typeZone = "zone"
const typeAccessPoint = "accessPoint"
const typeUser = "user"
const typeZonalSubscription = "zonalsubs"
const typeUserSubscription = "usersubs"
const typeZoneStatusSubscription = "zonestatus"
const USER_TRACKING_AND_ZONAL_TRAFFIC = 1
const ZONE_STATUS = 2
Kevin Di Lallo
committed
type UeUserData struct {
queryZoneId string
queryApId string
userList *UserList
}
type ApUserData struct {
queryInterestRealm string
apList *AccessPointList
}
var nextZonalSubscriptionIdAvailable int
var nextUserSubscriptionIdAvailable int
Simon Pastor
committed
var nextZoneStatusSubscriptionIdAvailable int
var zonalSubscriptionEnteringMap = map[int]string{}
var zonalSubscriptionLeavingMap = map[int]string{}
var zonalSubscriptionTransferringMap = map[int]string{}
var zonalSubscriptionMap = map[int]string{}
var userSubscriptionEnteringMap = map[int]string{}
var userSubscriptionLeavingMap = map[int]string{}
var userSubscriptionTransferringMap = map[int]string{}
var userSubscriptionMap = map[int]string{}
Simon Pastor
committed
var zoneStatusSubscriptionMap = map[int]*ZoneStatusCheck{}
type ZoneStatusCheck struct {
ZoneId string
Serviceable bool
Unserviceable bool
Unknown bool
NbUsersInZoneThreshold int
NbUsersInAPThreshold int
}
Kevin Di Lallo
committed
var LOC_SERV_DB = 0
var redisAddr string = "meep-redis-master.default.svc.cluster.local:6379"
var influxAddr string = "http://meep-influxdb.default.svc.cluster.local:8086"
var postgisHost string = "meep-postgis.default.svc.cluster.local"
var postgisPort string = "5432"
Kevin Di Lallo
committed
var hostUrl *url.URL
Kevin Di Lallo
committed
var sandboxName string
Kevin Di Lallo
committed
var basePath string
Kevin Di Lallo
committed
var baseKey string
Simon Pastor
committed
// Init - Location Service initialization
func Init() (err error) {
sandboxNameEnv := strings.TrimSpace(os.Getenv("MEEP_SANDBOX_NAME"))
if sandboxNameEnv != "" {
sandboxName = sandboxNameEnv
}
if sandboxName == "" {
err = errors.New("MEEP_SANDBOX_NAME env variable not set")
log.Error(err.Error())
return err
}
log.Info("MEEP_SANDBOX_NAME: ", sandboxName)
Kevin Di Lallo
committed
Kevin Di Lallo
committed
// Retrieve Host URL from environment variable
hostUrl, err = url.Parse(strings.TrimSpace(os.Getenv("MEEP_HOST_URL")))
Kevin Di Lallo
committed
if err != nil {
Kevin Di Lallo
committed
hostUrl = new(url.URL)
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
log.Info("MEEP_HOST_URL: ", hostUrl)
// Set base path
basePath = "/" + sandboxName + LocServBasePath
Kevin Di Lallo
committed
Kevin Di Lallo
committed
// Get base storage key
baseKey = dkm.GetKeyRoot(sandboxName) + locServKey
Kevin Di Lallo
committed
// Connect to Redis DB
userTrackingReInit()
zonalTrafficReInit()
Simon Pastor
committed
zoneStatusReInit()
Kevin Di Lallo
committed
// Initialize SBI
sbiCfg := sbi.SbiCfg{
SandboxName: sandboxName,
RedisAddr: redisAddr,
PostgisHost: postgisHost,
PostgisPort: postgisPort,
Kevin Di Lallo
committed
UserInfoCb: updateUserInfo,
ZoneInfoCb: updateZoneInfo,
ApInfoCb: updateAccessPointInfo,
ScenarioNameCb: updateStoreName,
CleanUpCb: cleanUp,
}
err = sbi.Init(sbiCfg)
if err != nil {
log.Error("Failed initialize SBI. Error: ", err)
return err
}
log.Info("SBI Initialized")
return nil
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
func Run() (err error) {
return sbi.Run()
Simon Pastor
committed
func createClient(notifyPath string) (*clientNotifOMA.APIClient, error) {
// Create & store client for App REST API
Simon Pastor
committed
subsAppClientCfg := clientNotifOMA.NewConfiguration()
subsAppClientCfg.BasePath = notifyPath
Simon Pastor
committed
subsAppClient := clientNotifOMA.NewAPIClient(subsAppClientCfg)
if subsAppClient == nil {
log.Error("Failed to create Subscription App REST API client: ", subsAppClientCfg.BasePath)
err := errors.New("Failed to create Subscription App REST API client")
return nil, err
}
return subsAppClient, nil
}
Simon Pastor
committed
func deregisterZoneStatus(subsIdStr string) {
subsId, _ := strconv.Atoi(subsIdStr)
Simon Pastor
committed
}
func registerZoneStatus(zoneId string, nbOfUsersZoneThreshold int32, nbOfUsersAPThreshold int32, opStatus []OperationStatus, subsIdStr string) {
Simon Pastor
committed
subsId, _ := strconv.Atoi(subsIdStr)
var zoneStatus ZoneStatusCheck
if opStatus != nil {
for i := 0; i < len(opStatus); i++ {
switch opStatus[i] {
case SERVICEABLE:
zoneStatus.Serviceable = true
case UNSERVICEABLE:
zoneStatus.Unserviceable = true
case OPSTATUS_UNKNOWN:
zoneStatus.Unknown = true
default:
}
}
}
zoneStatus.NbUsersInZoneThreshold = (int)(nbOfUsersZoneThreshold)
zoneStatus.NbUsersInAPThreshold = (int)(nbOfUsersAPThreshold)
zoneStatus.ZoneId = zoneId
zoneStatusSubscriptionMap[subsId] = &zoneStatus
}
func deregisterZonal(subsIdStr string) {
subsId, _ := strconv.Atoi(subsIdStr)
zonalSubscriptionMap[subsId] = ""
zonalSubscriptionEnteringMap[subsId] = ""
zonalSubscriptionLeavingMap[subsId] = ""
zonalSubscriptionTransferringMap[subsId] = ""
func registerZonal(zoneId string, event []UserEventType, subsIdStr string) {
subsId, _ := strconv.Atoi(subsIdStr)
if event != nil {
for i := 0; i < len(event); i++ {
switch event[i] {
case ENTERING:
zonalSubscriptionEnteringMap[subsId] = zoneId
zonalSubscriptionLeavingMap[subsId] = zoneId
zonalSubscriptionTransferringMap[subsId] = zoneId
default:
}
}
} else {
zonalSubscriptionEnteringMap[subsId] = zoneId
zonalSubscriptionLeavingMap[subsId] = zoneId
zonalSubscriptionTransferringMap[subsId] = zoneId
}
zonalSubscriptionMap[subsId] = zoneId
}
func deregisterUser(subsIdStr string) {
subsId, _ := strconv.Atoi(subsIdStr)
userSubscriptionMap[subsId] = ""
userSubscriptionEnteringMap[subsId] = ""
userSubscriptionLeavingMap[subsId] = ""
userSubscriptionTransferringMap[subsId] = ""
func registerUser(userAddress string, event []UserEventType, subsIdStr string) {
subsId, _ := strconv.Atoi(subsIdStr)
if event != nil {
for i := 0; i < len(event); i++ {
switch event[i] {
case ENTERING:
userSubscriptionEnteringMap[subsId] = userAddress
userSubscriptionLeavingMap[subsId] = userAddress
userSubscriptionTransferringMap[subsId] = userAddress
default:
}
}
} else {
userSubscriptionEnteringMap[subsId] = userAddress
userSubscriptionLeavingMap[subsId] = userAddress
userSubscriptionTransferringMap[subsId] = userAddress
}
userSubscriptionMap[subsId] = userAddress
}
func checkNotificationRegistrations(checkType int, param1 string, param2 string, param3 string, param4 string, param5 string) {
switch checkType {
case USER_TRACKING_AND_ZONAL_TRAFFIC:
//params are the following => newZoneId:oldZoneId:newAccessPointId:oldAccessPointId:userAddress
checkNotificationRegisteredUsers(param1, param2, param3, param4, param5)
checkNotificationRegisteredZones(param1, param2, param3, param4, param5)
case ZONE_STATUS:
//params are the following => zoneId:accessPointId:nbUsersInAP:nbUsersInZone
checkNotificationRegisteredZoneStatus(param1, param2, param3, param4)
default:
Simon Pastor
committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
}
}
func checkNotificationRegisteredZoneStatus(zoneId string, apId string, nbUsersInAPStr string, nbUsersInZoneStr string) {
//check all that applies
for subsId, zoneStatus := range zoneStatusSubscriptionMap {
if zoneStatus.ZoneId == zoneId {
nbUsersInZone := 0
nbUsersInAP := -1
zoneWarning := false
apWarning := false
if nbUsersInZoneStr != "" {
nbUsersInZone, _ = strconv.Atoi(nbUsersInZoneStr)
if nbUsersInZone >= zoneStatus.NbUsersInZoneThreshold {
zoneWarning = true
}
}
if nbUsersInAPStr != "" {
nbUsersInAP, _ = strconv.Atoi(nbUsersInAPStr)
if nbUsersInAP >= zoneStatus.NbUsersInAPThreshold {
apWarning = true
}
}
if zoneWarning || apWarning {
subsIdStr := strconv.Itoa(subsId)
Kevin Di Lallo
committed
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeZoneStatusSubscription+":"+subsIdStr, ".")
Simon Pastor
committed
if jsonInfo == "" {
return
}
subscription := convertJsonToZoneStatusSubscription(jsonInfo)
var zoneStatusNotif clientNotifOMA.ZoneStatusNotification
zoneStatusNotif.ZoneId = zoneId
if apWarning {
zoneStatusNotif.AccessPointId = apId
zoneStatusNotif.NumberOfUsersInAP = (int32)(nbUsersInAP)
Simon Pastor
committed
}
if zoneWarning {
zoneStatusNotif.NumberOfUsersInZone = (int32)(nbUsersInZone)
Simon Pastor
committed
}
Simon Pastor
committed
zoneStatusNotif.Timestamp = time.Now()
sendStatusNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zoneStatusNotif)
Simon Pastor
committed
if apWarning {
log.Info("Zone Status Notification" + "(" + subsIdStr + "): " + "For event in zone " + zoneId + " which has " + nbUsersInAPStr + " users in AP " + apId)
} else {
log.Info("Zone Status Notification" + "(" + subsIdStr + "): " + "For event in zone " + zoneId + " which has " + nbUsersInZoneStr + " users in total")
}
}
}
}
}
func checkNotificationRegisteredUsers(oldZoneId string, newZoneId string, oldApId string, newApId string, userId string) {
//if a zone is null, means going in/out of the 3gpp network, so no notification
if newZoneId == "" || oldZoneId == "" {
return
}
//check all that applies
for subsId, value := range userSubscriptionMap {
if value == userId {
subsIdStr := strconv.Itoa(subsId)
Kevin Di Lallo
committed
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeUserSubscription+":"+subsIdStr, ".")
if jsonInfo == "" {
return
}
subscription := convertJsonToUserSubscription(jsonInfo)
Simon Pastor
committed
var zonal clientNotifOMA.TrackingNotification
Simon Pastor
committed
zonal.Timestamp = time.Now()
zonal.CallbackData = subscription.ClientCorrelator
if newZoneId != oldZoneId {
if userSubscriptionEnteringMap[subsId] != "" {
zonal.ZoneId = newZoneId
zonal.CurrentAccessPointId = newApId
Simon Pastor
committed
event := new(clientNotifOMA.UserEventType)
Simon Pastor
committed
zonal.UserEventType = event
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("User Notification" + "(" + subsIdStr + "): " + "Entering event in zone " + newZoneId + " for user " + userId)
}
if userSubscriptionLeavingMap[subsId] != "" {
zonal.ZoneId = oldZoneId
zonal.CurrentAccessPointId = oldApId
event := new(clientNotifOMA.UserEventType)
*event = clientNotifOMA.LEAVING_UserEventType
zonal.UserEventType = event
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("User Notification" + "(" + subsIdStr + "): " + "Leaving event in zone " + oldZoneId + " for user " + userId)
}
} else {
if newApId != oldApId {
if userSubscriptionTransferringMap[subsId] != "" {
zonal.ZoneId = newZoneId
zonal.CurrentAccessPointId = newApId
zonal.PreviousAccessPointId = oldApId
Simon Pastor
committed
event := new(clientNotifOMA.UserEventType)
Simon Pastor
committed
zonal.UserEventType = event
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("User Notification" + "(" + subsIdStr + "): " + " Transferring event within zone " + newZoneId + " for user " + userId + " from Ap " + oldApId + " to " + newApId)
}
}
Simon Pastor
committed
func sendNotification(notifyUrl string, ctx context.Context, subscriptionId string, notification clientNotifOMA.TrackingNotification) {
client, err := createClient(notifyUrl)
if err != nil {
log.Error(err)
return
}
jsonNotif, err := json.Marshal(notification)
if err != nil {
log.Error(err.Error())
}
resp, err := client.NotificationsApi.PostTrackingNotification(ctx, subscriptionId, notification)
_ = httpLog.LogTx(notifyUrl, "POST", string(jsonNotif), resp, startTime)
Kevin Di Lallo
committed
if err != nil {
log.Error(err)
return
}
Simon Pastor
committed
func sendStatusNotification(notifyUrl string, ctx context.Context, subscriptionId string, notification clientNotifOMA.ZoneStatusNotification) {
Simon Pastor
committed
client, err := createClient(notifyUrl)
if err != nil {
log.Error(err)
return
}
jsonNotif, err := json.Marshal(notification)
if err != nil {
log.Error(err.Error())
}
resp, err := client.NotificationsApi.PostZoneStatusNotification(ctx, subscriptionId, notification)
_ = httpLog.LogTx(notifyUrl, "POST", string(jsonNotif), resp, startTime)
Kevin Di Lallo
committed
if err != nil {
log.Error(err)
return
}
Simon Pastor
committed
}
func checkNotificationRegisteredZones(oldZoneId string, newZoneId string, oldApId string, newApId string, userId string) {
//if a zone is null, means going in/out of the 3gpp network, so no notification
if newZoneId == "" || oldZoneId == "" {
return
}
//check all that applies
for subsId, value := range zonalSubscriptionMap {
if value == newZoneId {
if newZoneId != oldZoneId {
if zonalSubscriptionEnteringMap[subsId] != "" {
subsIdStr := strconv.Itoa(subsId)
Kevin Di Lallo
committed
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeZonalSubscription+":"+subsIdStr, ".")
if jsonInfo != "" {
subscription := convertJsonToZonalSubscription(jsonInfo)
Simon Pastor
committed
var zonal clientNotifOMA.TrackingNotification
zonal.ZoneId = newZoneId
zonal.CurrentAccessPointId = newApId
zonal.Address = userId
Simon Pastor
committed
event := new(clientNotifOMA.UserEventType)
Simon Pastor
committed
zonal.UserEventType = event
zonal.Timestamp = time.Now()
zonal.CallbackData = subscription.ClientCorrelator
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("Zonal Notify Entering event in zone " + newZoneId + " for user " + userId)
}
}
} else {
if newApId != oldApId {
if zonalSubscriptionTransferringMap[subsId] != "" {
subsIdStr := strconv.Itoa(subsId)
Kevin Di Lallo
committed
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeZonalSubscription+":"+subsIdStr, ".")
if jsonInfo != "" {
subscription := convertJsonToZonalSubscription(jsonInfo)
Simon Pastor
committed
var zonal clientNotifOMA.TrackingNotification
zonal.ZoneId = newZoneId
zonal.CurrentAccessPointId = newApId
zonal.PreviousAccessPointId = oldApId
zonal.Address = userId
Simon Pastor
committed
event := new(clientNotifOMA.UserEventType)
Simon Pastor
committed
zonal.UserEventType = event
zonal.Timestamp = time.Now()
zonal.CallbackData = subscription.ClientCorrelator
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("Zonal Notify Transferring event in zone " + newZoneId + " for user " + userId + " from Ap " + oldApId + " to " + newApId)
}
}
}
} else {
if value == oldZoneId {
if zonalSubscriptionLeavingMap[subsId] != "" {
subsIdStr := strconv.Itoa(subsId)
Kevin Di Lallo
committed
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeZonalSubscription+":"+subsIdStr, ".")
if jsonInfo != "" {
subscription := convertJsonToZonalSubscription(jsonInfo)
Simon Pastor
committed
var zonal clientNotifOMA.TrackingNotification
zonal.ZoneId = oldZoneId
zonal.CurrentAccessPointId = oldApId
zonal.Address = userId
Simon Pastor
committed
event := new(clientNotifOMA.UserEventType)
Simon Pastor
committed
zonal.UserEventType = event
zonal.Timestamp = time.Now()
zonal.CallbackData = subscription.ClientCorrelator
sendNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zonal)
log.Info("Zonal Notify Leaving event in zone " + oldZoneId + " for user " + userId)
}
}
}
}
}
}
func usersGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Kevin Di Lallo
committed
var userData UeUserData
Kevin Di Lallo
committed
// Retrieve query parameters
u, _ := url.Parse(r.URL.String())
log.Info("url: ", u.RequestURI())
q := u.Query()
Kevin Di Lallo
committed
userData.queryZoneId = q.Get("zoneId")
userData.queryApId = q.Get("accessPointId")
Kevin Di Lallo
committed
// Get user list from DB
Kevin Di Lallo
committed
userList.ResourceURL = hostUrl.String() + basePath + "users"
response.UserList = &userList
Kevin Di Lallo
committed
userData.userList = &userList
Kevin Di Lallo
committed
keyName := baseKey + typeUser + ":*"
err := rc.ForEachJSONEntry(keyName, populateUserList, &userData)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Kevin Di Lallo
committed
// Send response
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
Kevin Di Lallo
committed
func populateUserList(key string, jsonInfo string, userData interface{}) error {
// Get query params & userlist from user data
data := userData.(*UeUserData)
if data == nil || data.userList == nil {
return errors.New("userList not found in userData")
}
Kevin Di Lallo
committed
// Retrieve user info from DB
var userInfo UserInfo
err := json.Unmarshal([]byte(jsonInfo), &userInfo)
if err != nil {
return err
}
Kevin Di Lallo
committed
// Ignore entries with no zoneID or AP ID
if userInfo.ZoneId == "" || userInfo.AccessPointId == "" {
return nil
Kevin Di Lallo
committed
// Filter using query params
if data.queryZoneId != "" && userInfo.ZoneId != data.queryZoneId {
return nil
Kevin Di Lallo
committed
if data.queryApId != "" && userInfo.AccessPointId != data.queryApId {
return nil
Kevin Di Lallo
committed
// Add user info to list
data.userList.User = append(data.userList.User, userInfo)
return nil
}
func usersGetById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
var userInfo UserInfo
response.UserInfo = &userInfo
Kevin Di Lallo
committed
jsonUserInfo, _ := rc.JSONGetEntry(baseKey+typeUser+":"+vars["userId"], ".")
if jsonUserInfo == "" {
w.WriteHeader(http.StatusNotFound)
return
}
err := json.Unmarshal([]byte(jsonUserInfo), &userInfo)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func zonesByIdGetAps(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Kevin Di Lallo
committed
var userData ApUserData
vars := mux.Vars(r)
// Retrieve query parameters
u, _ := url.Parse(r.URL.String())
log.Info("url: ", u.RequestURI())
q := u.Query()
Kevin Di Lallo
committed
userData.queryInterestRealm = q.Get("interestRealm")
Kevin Di Lallo
committed
// Get user list from DB
var apList AccessPointList
apList.ZoneId = vars["zoneId"]
Kevin Di Lallo
committed
apList.ResourceURL = hostUrl.String() + basePath + "zones/" + vars["zoneId"] + "/accessPoints"
Kevin Di Lallo
committed
response.AccessPointList = &apList
userData.apList = &apList
keyName := baseKey + typeZone + ":" + vars["zoneId"] + ":*"
err := rc.ForEachJSONEntry(keyName, populateApList, &userData)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Kevin Di Lallo
committed
// Send response
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func zonesByIdGetApsById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
var apInfo AccessPointInfo
response.AccessPointInfo = &apInfo
Kevin Di Lallo
committed
jsonApInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+vars["zoneId"]+":"+typeAccessPoint+":"+vars["accessPointId"], ".")
if jsonApInfo == "" {
w.WriteHeader(http.StatusNotFound)
return
}
err := json.Unmarshal([]byte(jsonApInfo), &apInfo)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func zonesGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Kevin Di Lallo
committed
zoneList.ResourceURL = hostUrl.String() + basePath + "zones"
response.ZoneList = &zoneList
Kevin Di Lallo
committed
keyName := baseKey + typeZone + ":*"
err := rc.ForEachJSONEntry(keyName, populateZoneList, &zoneList)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func zonesGetById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
var zoneInfo ZoneInfo
response.ZoneInfo = &zoneInfo
Kevin Di Lallo
committed
jsonZoneInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+vars["zoneId"], ".")
if jsonZoneInfo == "" {
w.WriteHeader(http.StatusNotFound)
return
}
err := json.Unmarshal([]byte(jsonZoneInfo), &zoneInfo)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
Kevin Di Lallo
committed
func populateZoneList(key string, jsonInfo string, userData interface{}) error {
zoneList := userData.(*ZoneList)
var zoneInfo ZoneInfo
// Format response
err := json.Unmarshal([]byte(jsonInfo), &zoneInfo)
if err != nil {
return err
}
if zoneInfo.ZoneId != "" {
zoneList.Zone = append(zoneList.Zone, zoneInfo)
}
return nil
}
Kevin Di Lallo
committed
func populateApList(key string, jsonInfo string, userData interface{}) error {
// Get query params & aplist from user data
data := userData.(*ApUserData)
if data == nil || data.apList == nil {
return errors.New("apList not found in userData")
}
Kevin Di Lallo
committed
// Retrieve AP info from DB
var apInfo AccessPointInfo
err := json.Unmarshal([]byte(jsonInfo), &apInfo)
if err != nil {
return err
}
Kevin Di Lallo
committed
// Ignore entries with no AP ID
if apInfo.AccessPointId == "" {
return nil
}
// Filter using query params
if data.queryInterestRealm != "" && apInfo.InterestRealm != data.queryInterestRealm {
return nil
Kevin Di Lallo
committed
// Add AP info to list
data.apList.AccessPoint = append(data.apList.AccessPoint, apInfo)
return nil
}
func userTrackingSubDelById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
Kevin Di Lallo
committed
err := rc.JSONDelEntry(baseKey+typeUserSubscription+":"+vars["subscriptionId"], ".")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
deregisterUser(vars["subscriptionId"])
w.WriteHeader(http.StatusNoContent)
}
func userTrackingSubGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
var response ResponseUserTrackingNotificationSubscriptionList
var userTrackingSubList UserTrackingNotificationSubscriptionList
Kevin Di Lallo
committed
userTrackingSubList.ResourceURL = hostUrl.String() + basePath + "subscriptions/userTracking"
response.NotificationSubscriptionList = &userTrackingSubList
Kevin Di Lallo
committed
keyName := baseKey + typeUserSubscription + "*"
err := rc.ForEachJSONEntry(keyName, populateUserTrackingList, &userTrackingSubList)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func userTrackingSubGetById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
var userTrackingSub UserTrackingSubscription
response.UserTrackingSubscription = &userTrackingSub
Kevin Di Lallo
committed
jsonUserTrackingSub, _ := rc.JSONGetEntry(baseKey+typeUserSubscription+":"+vars["subscriptionId"], ".")
if jsonUserTrackingSub == "" {
w.WriteHeader(http.StatusNotFound)
return
}
err := json.Unmarshal([]byte(jsonUserTrackingSub), &userTrackingSub)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}
func userTrackingSubPost(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
userTrackingSub := new(UserTrackingSubscription)
response.UserTrackingSubscription = userTrackingSub
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&userTrackingSub)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
newSubsId := nextUserSubscriptionIdAvailable
nextUserSubscriptionIdAvailable++
subsIdStr := strconv.Itoa(newSubsId)
registerUser(userTrackingSub.Address, userTrackingSub.UserEventCriteria, subsIdStr)
Kevin Di Lallo
committed
userTrackingSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/userTracking/" + subsIdStr
Kevin Di Lallo
committed
_ = rc.JSONSetEntry(baseKey+typeUserSubscription+":"+subsIdStr, ".", convertUserSubscriptionToJson(userTrackingSub))
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
fmt.Fprintf(w, string(jsonResponse))
}
func userTrackingSubPutById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
userTrackingSub := new(UserTrackingSubscription)
response.UserTrackingSubscription = userTrackingSub
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&userTrackingSub)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
}
subsIdStr := vars["subscriptionId"]
Kevin Di Lallo
committed
userTrackingSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/userTracking/" + subsIdStr
Kevin Di Lallo
committed
_ = rc.JSONSetEntry(baseKey+typeUserSubscription+":"+subsIdStr, ".", convertUserSubscriptionToJson(userTrackingSub))
deregisterUser(subsIdStr)
registerUser(userTrackingSub.Address, userTrackingSub.UserEventCriteria, subsIdStr)
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
Kevin Di Lallo
committed
func populateUserTrackingList(key string, jsonInfo string, userData interface{}) error {
userList := userData.(*UserTrackingNotificationSubscriptionList)
var userInfo UserTrackingSubscription
// Format response
err := json.Unmarshal([]byte(jsonInfo), &userInfo)
if err != nil {
return err
}
userList.UserTrackingSubscription = append(userList.UserTrackingSubscription, userInfo)
return nil
}
func zonalTrafficSubDelById(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
vars := mux.Vars(r)
Kevin Di Lallo
committed
err := rc.JSONDelEntry(baseKey+typeZonalSubscription+":"+vars["subscriptionId"], ".")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
deregisterZonal(vars["subscriptionId"])
w.WriteHeader(http.StatusNoContent)
}
func zonalTrafficSubGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
var response ResponseZonalTrafficNotificationSubscriptionList
var zonalTrafficSubList ZonalTrafficNotificationSubscriptionList
Kevin Di Lallo
committed
zonalTrafficSubList.ResourceURL = hostUrl.String() + basePath + "subscriptions/zonalTraffic"
response.NotificationSubscriptionList = &zonalTrafficSubList
Kevin Di Lallo
committed
keyName := baseKey + typeZonalSubscription + "*"
err := rc.ForEachJSONEntry(keyName, populateZonalTrafficList, &zonalTrafficSubList)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
jsonResponse, err := json.Marshal(response)