Fixed events definition and callback processing.
[src/xds/xds-agent.git] / lib / agent / xdsserver.go
index b76908c..73a5bd9 100644 (file)
@@ -11,6 +11,7 @@ import (
        "time"
 
        "github.com/gin-gonic/gin"
+       "github.com/iotbzh/xds-agent/lib/apiv1"
        "github.com/iotbzh/xds-agent/lib/xdsconfig"
        common "github.com/iotbzh/xds-common/golib"
        uuid "github.com/satori/go.uuid"
@@ -111,11 +112,15 @@ type XdsEventFolderChange struct {
        Folder XdsFolderConfig `json:"folder"`
 }
 
+// Event emitter callback
+type EventCB func(privData interface{}, evtData interface{}) error
+
 // caller Used to chain event listeners
 type caller struct {
-       id        uuid.UUID
-       EventName string
-       Func      func(interface{})
+       id          uuid.UUID
+       EventName   string
+       Func        EventCB
+       PrivateData interface{}
 }
 
 const _IDTempoPrefix = "tempo-"
@@ -213,7 +218,7 @@ func (xs *XdsServer) GetFolders(folders *[]XdsFolderConfig) error {
 
 // FolderAdd Send POST request to add a folder
 func (xs *XdsServer) FolderAdd(fld *XdsFolderConfig, res interface{}) error {
-       response, err := xs._HTTPPost("/folder", fld)
+       response, err := xs._HTTPPost("/folders", fld)
        if err != nil {
                return err
        }
@@ -228,12 +233,12 @@ func (xs *XdsServer) FolderAdd(fld *XdsFolderConfig, res interface{}) error {
 
 // FolderDelete Send DELETE request to delete a folder
 func (xs *XdsServer) FolderDelete(id string) error {
-       return xs.client.HTTPDelete("/folder/" + id)
+       return xs.client.HTTPDelete("/folders/" + id)
 }
 
 // FolderSync Send POST request to force synchronization of a folder
 func (xs *XdsServer) FolderSync(id string) error {
-       return xs.client.HTTPPost("/folder/sync/"+id, "")
+       return xs.client.HTTPPost("/folders/sync/"+id, "")
 }
 
 // SetAPIRouterGroup .
@@ -250,7 +255,13 @@ func (xs *XdsServer) PassthroughGet(url string) {
 
        xs.apiRouter.GET(url, func(c *gin.Context) {
                var data interface{}
-               if err := xs._HTTPGet(url, &data); err != nil {
+               // Take care of param (eg. id in /projects/:id)
+               nURL := url
+               if strings.Contains(url, ":") {
+                       nURL = strings.TrimPrefix(c.Request.URL.Path, xs.APIURL)
+               }
+               // Send Get request
+               if err := xs._HTTPGet(nURL, &data); err != nil {
                        if strings.Contains(err.Error(), "connection refused") {
                                xs.Connected = false
                                xs._NotifyState()
@@ -278,7 +289,13 @@ func (xs *XdsServer) PassthroughPost(url string) {
                        return
                }
 
-               response, err := xs._HTTPPost(url, bodyReq[:n])
+               // Take care of param (eg. id in /projects/:id)
+               nURL := url
+               if strings.Contains(url, ":") {
+                       nURL = strings.TrimPrefix(c.Request.URL.Path, xs.APIURL)
+               }
+               // Send Post request
+               response, err := xs._HTTPPost(nURL, bodyReq[:n])
                if err != nil {
                        common.APIError(c, err.Error())
                        return
@@ -303,7 +320,7 @@ func (xs *XdsServer) EventRegister(evName string, id string) error {
 }
 
 // EventOn Register a callback on events reception
-func (xs *XdsServer) EventOn(evName string, f func(interface{})) (uuid.UUID, error) {
+func (xs *XdsServer) EventOn(evName string, privData interface{}, f EventCB) (uuid.UUID, error) {
        if xs.ioSock == nil {
                return uuid.Nil, fmt.Errorf("Io.Socket not initialized")
        }
@@ -320,14 +337,25 @@ func (xs *XdsServer) EventOn(evName string, f func(interface{})) (uuid.UUID, err
                if evName == "event:FolderStateChanged" {
                        err = xs.ioSock.On(evn, func(data XdsEventFolderChange) error {
                                xs.sockEventsLock.Lock()
-                               defer xs.sockEventsLock.Unlock()
-                               for _, c := range xs.sockEvents[evn] {
-                                       c.Func(data)
+                               sEvts := make([]*caller, len(xs.sockEvents[evn]))
+                               copy(sEvts, xs.sockEvents[evn])
+                               xs.sockEventsLock.Unlock()
+                               for _, c := range sEvts {
+                                       c.Func(c.PrivateData, data)
                                }
                                return nil
                        })
                } else {
-                       err = xs.ioSock.On(evn, f)
+                       err = xs.ioSock.On(evn, func(data interface{}) error {
+                               xs.sockEventsLock.Lock()
+                               sEvts := make([]*caller, len(xs.sockEvents[evn]))
+                               copy(sEvts, xs.sockEvents[evn])
+                               xs.sockEventsLock.Unlock()
+                               for _, c := range sEvts {
+                                       c.Func(c.PrivateData, data)
+                               }
+                               return nil
+                       })
                }
                if err != nil {
                        return uuid.Nil, err
@@ -335,9 +363,10 @@ func (xs *XdsServer) EventOn(evName string, f func(interface{})) (uuid.UUID, err
        }
 
        c := &caller{
-               id:        uuid.NewV1(),
-               EventName: evName,
-               Func:      f,
+               id:          uuid.NewV1(),
+               EventName:   evName,
+               Func:        f,
+               PrivateData: privData,
        }
 
        xs.sockEvents[evName] = append(xs.sockEvents[evName], c)
@@ -366,7 +395,7 @@ func (xs *XdsServer) EventOff(evName string, id uuid.UUID) error {
 }
 
 // ProjectToFolder Convert Project structure to Folder structure
-func (xs *XdsServer) ProjectToFolder(pPrj ProjectConfig) *XdsFolderConfig {
+func (xs *XdsServer) ProjectToFolder(pPrj apiv1.ProjectConfig) *XdsFolderConfig {
        stID := ""
        if pPrj.Type == XdsTypeCloudSync {
                stID, _ = xs.SThg.IDGet()
@@ -395,7 +424,7 @@ func (xs *XdsServer) ProjectToFolder(pPrj ProjectConfig) *XdsFolderConfig {
 }
 
 // FolderToProject Convert Folder structure to Project structure
-func (xs *XdsServer) FolderToProject(fPrj XdsFolderConfig) ProjectConfig {
+func (xs *XdsServer) FolderToProject(fPrj XdsFolderConfig) apiv1.ProjectConfig {
        inSync := fPrj.IsInSync
        sts := fPrj.Status
 
@@ -404,27 +433,27 @@ func (xs *XdsServer) FolderToProject(fPrj XdsFolderConfig) ProjectConfig {
 
                sts = fPrj.DataCloudSync.STSvrStatus
                switch fPrj.DataCloudSync.STLocStatus {
-               case StatusErrorConfig, StatusDisable, StatusPause:
+               case apiv1.StatusErrorConfig, apiv1.StatusDisable, apiv1.StatusPause:
                        sts = fPrj.DataCloudSync.STLocStatus
                        break
-               case StatusSyncing:
-                       if sts != StatusErrorConfig && sts != StatusDisable && sts != StatusPause {
-                               sts = StatusSyncing
+               case apiv1.StatusSyncing:
+                       if sts != apiv1.StatusErrorConfig && sts != apiv1.StatusDisable && sts != apiv1.StatusPause {
+                               sts = apiv1.StatusSyncing
                        }
                        break
-               case StatusEnable:
+               case apiv1.StatusEnable:
                        // keep STSvrStatus
                        break
                }
        }
 
-       pPrj := ProjectConfig{
+       pPrj := apiv1.ProjectConfig{
                ID:         fPrj.ID,
                ServerID:   xs.ID,
                Label:      fPrj.Label,
                ClientPath: fPrj.ClientPath,
                ServerPath: fPrj.DataPathMap.ServerPath,
-               Type:       ProjectType(fPrj.Type),
+               Type:       apiv1.ProjectType(fPrj.Type),
                Status:     sts,
                IsInSync:   inSync,
                DefaultSdk: fPrj.DefaultSdk,
@@ -591,7 +620,7 @@ func (xs *XdsServer) _SocketConnect() error {
 // Send event to notify changes
 func (xs *XdsServer) _NotifyState() {
 
-       evSts := ServerCfg{
+       evSts := apiv1.ServerCfg{
                ID:         xs.ID,
                URL:        xs.BaseURL,
                APIURL:     xs.APIURL,
@@ -599,7 +628,7 @@ func (xs *XdsServer) _NotifyState() {
                ConnRetry:  xs.ConnRetry,
                Connected:  xs.Connected,
        }
-       if err := xs.events.Emit(EVTServerConfig, evSts); err != nil {
+       if err := xs.events.Emit(apiv1.EVTServerConfig, evSts); err != nil {
                xs.Log.Warningf("Cannot notify XdsServer state change: %v", err)
        }
 }