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  }