support for shm prefixes
[govpp.git] / adapter / vppapiclient / vppapiclient_adapter.go
index dfdd973..5a05a58 100644 (file)
@@ -49,9 +49,9 @@ govpp_msg_callback (unsigned char *data, int size)
 }
 
 static int
-govpp_connect()
+govpp_connect (char *shm)
 {
-    return vac_connect("govpp", NULL, govpp_msg_callback, 32);
+    return vac_connect("govpp", shm, govpp_msg_callback, 32);
 }
 
 static int
@@ -77,7 +77,6 @@ govpp_get_msg_index(char *name_and_crc)
 import "C"
 
 import (
-       "errors"
        "fmt"
        "os"
        "reflect"
@@ -91,27 +90,36 @@ const (
        // watchedFolder is a folder where vpp's shared memory is supposed to be created.
        // File system events are monitored in this folder.
        watchedFolder = "/dev/shm/"
-       // watchedFile is a name of the file in the watchedFolder. Once the file is present
+       // watchedFile is a default name of the file in the watchedFolder. Once the file is present,
        // the vpp is ready to accept a new connection.
-       watchedFile = watchedFolder + "vpe-api"
+       watchedFile = "vpe-api"
 )
 
 // vppAPIClientAdapter is the opaque context of the adapter.
 type vppAPIClientAdapter struct {
-       callback func(context uint32, msgId uint16, data []byte)
+       shmPrefix string
+       callback  func(context uint32, msgId uint16, data []byte)
 }
 
 var vppClient *vppAPIClientAdapter // global vpp API client adapter context
 
 // NewVppAdapter returns a new vpp API client adapter.
-func NewVppAdapter() adapter.VppAdapter {
-       return &vppAPIClientAdapter{}
+func NewVppAdapter(shmPrefix string) adapter.VppAdapter {
+       return &vppAPIClientAdapter{
+               shmPrefix: shmPrefix,
+       }
 }
 
 // Connect connects the process to VPP.
 func (a *vppAPIClientAdapter) Connect() error {
        vppClient = a
-       rc := C.govpp_connect()
+       var rc _Ctype_int
+       if a.shmPrefix == "" {
+               rc = C.govpp_connect(nil)
+       } else {
+               shm := C.CString(a.shmPrefix)
+               rc = C.govpp_connect(shm)
+       }
        if rc != 0 {
                return fmt.Errorf("unable to connect to VPP (error=%d)", rc)
        }
@@ -125,12 +133,12 @@ func (a *vppAPIClientAdapter) Disconnect() {
 
 // GetMsgID returns a runtime message ID for the given message name and CRC.
 func (a *vppAPIClientAdapter) GetMsgID(msgName string, msgCrc string) (uint16, error) {
-       nameAndCrc := C.CString(fmt.Sprintf("%s_%s", msgName, msgCrc))
+       nameAndCrc := C.CString(msgName + "_" + msgCrc)
        defer C.free(unsafe.Pointer(nameAndCrc))
 
        msgID := uint16(C.govpp_get_msg_index(nameAndCrc))
        if msgID == ^uint16(0) {
-               return msgID, errors.New("unkonwn message")
+               return msgID, fmt.Errorf("unknown message: %v (crc: %v)", msgName, msgCrc)
        }
 
        return msgID, nil
@@ -150,33 +158,37 @@ func (a *vppAPIClientAdapter) SetMsgCallback(cb func(context uint32, msgID uint1
        a.callback = cb
 }
 
-// WaitReady returns func which blocks until shared memory
-// for sending bin api calls is present on the file system.
-func (a *vppAPIClientAdapter) WaitReady() func() error {
-       return func() error {
-               watcher, err := fsnotify.NewWatcher()
-               if err != nil {
-                       return err
-               }
-               defer watcher.Close()
-
-               err = watcher.Add(watchedFolder)
-               if err != nil {
-                       return err
-               }
+// WaitReady blocks until shared memory for sending
+// binary api calls is present on the file system.
+func (a *vppAPIClientAdapter) WaitReady() error {
+       watcher, err := fsnotify.NewWatcher()
+       if err != nil {
+               return err
+       }
+       defer watcher.Close()
 
-               if fileExists(watchedFile) {
-                       return nil
-               }
+       err = watcher.Add(watchedFolder)
+       if err != nil {
+               return err
+       }
+       // Path to the shared memory segment with prefix, if set
+       var path string
+       if a.shmPrefix == "" {
+               path = watchedFolder + watchedFile
+       } else {
+               path = watchedFolder + a.shmPrefix + "-" + watchedFile
+       }
+       if fileExists(path) {
+               return nil
+       }
 
-               for {
-                       ev := <-watcher.Events
-                       if ev.Name == watchedFile && (ev.Op&fsnotify.Create) == fsnotify.Create {
-                               break
-                       }
+       for {
+               ev := <-watcher.Events
+               if ev.Name == path && (ev.Op&fsnotify.Create) == fsnotify.Create {
+                       break
                }
-               return nil
        }
+       return nil
 }
 
 func fileExists(name string) bool {
@@ -195,4 +207,4 @@ func go_msg_callback(msgID C.uint16_t, context C.uint32_t, data unsafe.Pointer,
        byteArr := *(*[]byte)(unsafe.Pointer(slice))
 
        vppClient.callback(uint32(context), uint16(msgID), byteArr)
-}
+}
\ No newline at end of file