add signals

This commit is contained in:
Andrea Franz 2021-09-29 11:32:34 +02:00
parent 22a20d3b45
commit c8d0142a16
5 changed files with 165 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/status-im/keycard-go/globalplatform"
"github.com/status-im/keycard-go/io"
"github.com/status-im/keycard-go/types"
"github.com/status-im/nim-keycard-go/go/keycard/signal"
)
type keycardContext struct {
@ -91,6 +92,7 @@ func (kc *keycardContext) run() {
return
}
signal.SendKeycardConnected("")
l("card found at index %d", index)
reader := kc.readers[index]

12
main.go
View File

@ -6,6 +6,9 @@ import (
"encoding/json"
"fmt"
"time"
"unsafe"
"github.com/status-im/nim-keycard-go/go/keycard/signal"
)
var kctx *keycardContext
@ -15,6 +18,10 @@ func main() {
}
func example() {
signal.SetDefaultNodeNotificationHandler(func(jsonEvent string) {
fmt.Printf("SIGNAL %+v\n", jsonEvent)
})
fmt.Printf("RUNNING EXAMPLE \n")
res := Start()
fmt.Printf("*** start %+v\n", C.GoString(res))
@ -399,3 +406,8 @@ func ChangePairingPassword(jsonParams *C.char) *C.char {
return retValue("ok", true)
}
//export SetSignalEventCallback
func SetSignalEventCallback(cb unsafe.Pointer) {
signal.SetSignalEventCallback(cb)
}

10
signal/events_keycard.go Normal file
View File

@ -0,0 +1,10 @@
package signal
const (
// EventSignRequestAdded is triggered when send transaction request is queued
EventKeycardConnected = "keycard.connected"
)
func SendKeycardConnected(event interface{}) {
send(EventKeycardConnected, event)
}

25
signal/signals.c Normal file
View File

@ -0,0 +1,25 @@
// ======================================================================================
// cgo compilation (for desktop platforms and local tests)
// ======================================================================================
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include "_cgo_export.h"
typedef void (*callback)(const char *jsonEvent);
callback gCallback = 0;
bool StatusServiceSignalEvent(const char *jsonEvent) {
if (gCallback) {
gCallback(jsonEvent);
} else {
NotifyNode((char *)jsonEvent); // re-send notification back to status node
}
return true;
}
void SetEventCallback(void *cb) {
gCallback = (callback)cb;
}

116
signal/signals.go Normal file
View File

@ -0,0 +1,116 @@
package signal
/*
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
extern bool StatusServiceSignalEvent(const char *jsonEvent);
extern void SetEventCallback(void *cb);
*/
import "C"
import (
"encoding/json"
"unsafe"
"sync"
"github.com/ethereum/go-ethereum/log"
)
// MobileSignalHandler is a simple callback function that gets called when any signal is received
type MobileSignalHandler func([]byte)
// storing the current signal handler here
var mobileSignalHandler MobileSignalHandler
// All general log messages in this package should be routed through this logger.
var logger = log.New("package", "status-go/signal")
// Envelope is a general signal sent upward from node to RN app
type Envelope struct {
Type string `json:"type"`
Event interface{} `json:"event"`
}
// NewEnvelope creates new envlope of given type and event payload.
func NewEnvelope(typ string, event interface{}) *Envelope {
return &Envelope{
Type: typ,
Event: event,
}
}
// send sends application signal (in JSON) upwards to application (via default notification handler)
func send(typ string, event interface{}) {
signal := NewEnvelope(typ, event)
data, err := json.Marshal(&signal)
if err != nil {
logger.Error("Marshalling signal envelope", "error", err)
return
}
// If a Go implementation of signal handler is set, let's use it.
if mobileSignalHandler != nil {
mobileSignalHandler(data)
} else {
// ...and fallback to C implementation otherwise.
str := C.CString(string(data))
C.StatusServiceSignalEvent(str)
C.free(unsafe.Pointer(str))
}
}
// NodeNotificationHandler defines a handler able to process incoming node events.
// Events are encoded as JSON strings.
type NodeNotificationHandler func(jsonEvent string)
var notificationHandler NodeNotificationHandler = TriggerDefaultNodeNotificationHandler
// notificationHandlerMutex guards notificationHandler for concurrent calls
var notificationHandlerMutex sync.RWMutex
// SetDefaultNodeNotificationHandler sets notification handler to invoke on Send
func SetDefaultNodeNotificationHandler(fn NodeNotificationHandler) {
notificationHandlerMutex.Lock()
notificationHandler = fn
notificationHandlerMutex.Unlock()
}
// ResetDefaultNodeNotificationHandler sets notification handler to default one
func ResetDefaultNodeNotificationHandler() {
notificationHandlerMutex.Lock()
notificationHandler = TriggerDefaultNodeNotificationHandler
notificationHandlerMutex.Unlock()
}
// TriggerDefaultNodeNotificationHandler triggers default notification handler (helpful in tests)
func TriggerDefaultNodeNotificationHandler(jsonEvent string) {
logger.Trace("Notification received", "event", jsonEvent)
}
//export NotifyNode
//nolint: golint
func NotifyNode(jsonEvent *C.char) {
notificationHandlerMutex.RLock()
defer notificationHandlerMutex.RUnlock()
notificationHandler(C.GoString(jsonEvent))
}
//export TriggerTestSignal
//nolint: golint
func TriggerTestSignal() {
str := C.CString(`{"answer": 42}`)
C.StatusServiceSignalEvent(str)
C.free(unsafe.Pointer(str))
}
// SetMobileSignalHandler sets new handler for geth events
// this function uses pure go implementation
func SetMobileSignalHandler(handler MobileSignalHandler) {
mobileSignalHandler = handler
}
// SetSignalEventCallback set callback
// this function uses C implementation (see `signals.c` file)
func SetSignalEventCallback(cb unsafe.Pointer) {
C.SetEventCallback(cb)
}