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"
sm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-sessions"
Simon Pastor
committed
"github.com/gorilla/mux"
)
const moduleName = "meep-loc-serv"
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
var sessionMgr *sm.SessionMgr
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
// hostUrl is the url of the node serving the resourceURL
// Retrieve public url address where service is reachable, if not present, use Host URL environment variable
hostUrl, err = url.Parse(strings.TrimSpace(os.Getenv("MEEP_PUBLIC_URL")))
if err != nil || hostUrl == nil || hostUrl.String() == "" {
hostUrl, err = url.Parse(strings.TrimSpace(os.Getenv("MEEP_HOST_URL")))
if err != nil {
hostUrl = new(url.URL)
}
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
// 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
// Connect to Session Manager
sessionMgr, err = sm.NewSessionMgr(moduleName, redisAddr, redisAddr)
if err != nil {
log.Error("Failed connection to Session Manager: ", err.Error())
return err
}
log.Info("Connected to Session Manager")
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
}
}
func checkNotificationRegisteredZoneStatus(zoneId string, apId string, nbUsersInAPStr string, nbUsersInZoneStr string) {
//check all that applies
for subsId, zoneStatus := range zoneStatusSubscriptionMap {
Kevin Di Lallo
committed
if zoneStatus == nil {
continue
}
Simon Pastor
committed
Kevin Di Lallo
committed
if zoneStatus.ZoneId == zoneId {
Simon Pastor
committed
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
}
Simon Pastor
committed
}
if zoneWarning || apWarning {
subsIdStr := strconv.Itoa(subsId)
jsonInfo, _ := rc.JSONGetEntry(baseKey+typeZoneStatusSubscription+":"+subsIdStr, ".")
if jsonInfo == "" {
return
}
subscription := convertJsonToZoneStatusSubscription(jsonInfo)
var zoneStatusNotif clientNotifOMA.ZoneStatusNotification
zoneStatusNotif.ZoneId = zoneId
if apWarning {
zoneStatusNotif.AccessPointId = apId
zoneStatusNotif.NumberOfUsersInAP = (int32)(nbUsersInAP)
}
if zoneWarning {
zoneStatusNotif.NumberOfUsersInZone = (int32)(nbUsersInZone)
}
zoneStatusNotif.Timestamp = time.Now()
sendStatusNotification(subscription.CallbackReference.NotifyURL, context.TODO(), subsIdStr, zoneStatusNotif)
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")
}
Simon Pastor
committed
}
}
}
}
}
func checkNotificationRegisteredUsers(oldZoneId string, newZoneId string, oldApId string, newApId string, userId string) {
//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] != "" && newZoneId != "" {
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 oldZoneId != "" {
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) {
//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