github.com/status-im/status-go@v1.1.0/signal/signals.go (about) 1 package signal 2 3 /* 4 #include <stddef.h> 5 #include <stdbool.h> 6 #include <stdlib.h> 7 extern bool StatusServiceSignalEvent(const char *jsonEvent); 8 extern void SetEventCallback(void *cb); 9 */ 10 import "C" 11 import ( 12 "encoding/json" 13 "unsafe" 14 15 "sync" 16 17 "github.com/ethereum/go-ethereum/log" 18 ) 19 20 // MobileSignalHandler is a simple callback function that gets called when any signal is received 21 type MobileSignalHandler func([]byte) 22 23 // storing the current signal handler here 24 var mobileSignalHandler MobileSignalHandler 25 26 // All general log messages in this package should be routed through this logger. 27 var logger = log.New("package", "status-go/signal") 28 29 // Envelope is a general signal sent upward from node to RN app 30 type Envelope struct { 31 Type string `json:"type"` 32 Event interface{} `json:"event"` 33 } 34 35 // NewEnvelope creates new envlope of given type and event payload. 36 func NewEnvelope(typ string, event interface{}) *Envelope { 37 return &Envelope{ 38 Type: typ, 39 Event: event, 40 } 41 } 42 43 // send sends application signal (in JSON) upwards to application (via default notification handler) 44 func send(typ string, event interface{}) { 45 signal := NewEnvelope(typ, event) 46 data, err := json.Marshal(&signal) 47 if err != nil { 48 logger.Error("Marshalling signal envelope", "error", err) 49 return 50 } 51 // If a Go implementation of signal handler is set, let's use it. 52 if mobileSignalHandler != nil { 53 mobileSignalHandler(data) 54 } else { 55 // ...and fallback to C implementation otherwise. 56 str := C.CString(string(data)) 57 C.StatusServiceSignalEvent(str) 58 C.free(unsafe.Pointer(str)) 59 } 60 } 61 62 // NodeNotificationHandler defines a handler able to process incoming node events. 63 // Events are encoded as JSON strings. 64 type NodeNotificationHandler func(jsonEvent string) 65 66 var notificationHandler NodeNotificationHandler = TriggerDefaultNodeNotificationHandler 67 68 // notificationHandlerMutex guards notificationHandler for concurrent calls 69 var notificationHandlerMutex sync.RWMutex 70 71 // SetDefaultNodeNotificationHandler sets notification handler to invoke on Send 72 func SetDefaultNodeNotificationHandler(fn NodeNotificationHandler) { 73 notificationHandlerMutex.Lock() 74 notificationHandler = fn 75 notificationHandlerMutex.Unlock() 76 } 77 78 // ResetDefaultNodeNotificationHandler sets notification handler to default one 79 func ResetDefaultNodeNotificationHandler() { 80 notificationHandlerMutex.Lock() 81 notificationHandler = TriggerDefaultNodeNotificationHandler 82 notificationHandlerMutex.Unlock() 83 } 84 85 // TriggerDefaultNodeNotificationHandler triggers default notification handler (helpful in tests) 86 func TriggerDefaultNodeNotificationHandler(jsonEvent string) { 87 logger.Trace("Notification received", "event", jsonEvent) 88 } 89 90 // nolint: golint 91 // 92 //export NotifyNode 93 func NotifyNode(jsonEvent *C.char) { 94 notificationHandlerMutex.RLock() 95 defer notificationHandlerMutex.RUnlock() 96 notificationHandler(C.GoString(jsonEvent)) 97 } 98 99 // nolint: golint 100 // 101 //export TriggerTestSignal 102 func TriggerTestSignal() { 103 str := C.CString(`{"answer": 42}`) 104 C.StatusServiceSignalEvent(str) 105 C.free(unsafe.Pointer(str)) 106 } 107 108 // SetMobileSignalHandler sets new handler for geth events 109 // this function uses pure go implementation 110 func SetMobileSignalHandler(handler MobileSignalHandler) { 111 mobileSignalHandler = handler 112 } 113 114 func ResetMobileSignalHandler() { 115 mobileSignalHandler = nil 116 } 117 118 // SetSignalEventCallback set callback 119 // this function uses C implementation (see `signals.c` file) 120 func SetSignalEventCallback(cb unsafe.Pointer) { 121 C.SetEventCallback(cb) 122 }