Use a `callReturn` type in `RoutineQueue`

This commit is contained in:
Pedro Pombeiro 2019-12-18 14:18:31 +01:00 committed by Pedro Pombeiro
parent 8d8880dc62
commit 90349b28c7
4 changed files with 106 additions and 98 deletions

View File

@ -75,14 +75,10 @@ func NewNodeBridge() Node {
} }
func (n *nimbusNodeWrapper) StartNimbus(privateKey *ecdsa.PrivateKey, listenAddr string, staging bool) error { func (n *nimbusNodeWrapper) StartNimbus(privateKey *ecdsa.PrivateKey, listenAddr string, staging bool) error {
retVal := n.routineQueue.Send(func(c chan<- interface{}) { return n.routineQueue.Send(func(c chan<- callReturn) {
c <- startNimbus(privateKey, listenAddr, staging) c <- callReturn{err: startNimbus(privateKey, listenAddr, staging)}
n.nodeStarted = true n.nodeStarted = true
}) }).err
if err, ok := retVal.(error); ok {
return err
}
return nil
} }
func (n *nimbusNodeWrapper) Stop() { func (n *nimbusNodeWrapper) Stop() {

View File

@ -40,63 +40,63 @@ func NewNimbusPublicWhisperAPIWrapper(filterMessagesMu *sync.Mutex, filterMessag
// AddPrivateKey imports the given private key. // AddPrivateKey imports the given private key.
func (w *nimbusPublicWhisperAPIWrapper) AddPrivateKey(ctx context.Context, privateKey types.HexBytes) (string, error) { func (w *nimbusPublicWhisperAPIWrapper) AddPrivateKey(ctx context.Context, privateKey types.HexBytes) (string, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
privKeyC := C.CBytes(privateKey) privKeyC := C.CBytes(privateKey)
defer C.free(unsafe.Pointer(privKeyC)) defer C.free(unsafe.Pointer(privKeyC))
idC := C.malloc(C.size_t(C.ID_LEN)) idC := C.malloc(C.size_t(C.ID_LEN))
defer C.free(idC) defer C.free(idC)
if C.nimbus_add_keypair((*C.uchar)(privKeyC), (*C.uchar)(idC)) { if C.nimbus_add_keypair((*C.uchar)(privKeyC), (*C.uchar)(idC)) {
c <- types.EncodeHex(C.GoBytes(idC, C.ID_LEN)) c <- callReturn{value: types.EncodeHex(C.GoBytes(idC, C.ID_LEN))}
} else { } else {
c <- errors.New("failed to add private key to Nimbus") c <- callReturn{err: errors.New("failed to add private key to Nimbus")}
} }
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID. // GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
func (w *nimbusPublicWhisperAPIWrapper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) { func (w *nimbusPublicWhisperAPIWrapper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
passwordC := C.CString(passwd) passwordC := C.CString(passwd)
defer C.free(unsafe.Pointer(passwordC)) defer C.free(unsafe.Pointer(passwordC))
idC := C.malloc(C.size_t(C.ID_LEN)) idC := C.malloc(C.size_t(C.ID_LEN))
defer C.free(idC) defer C.free(idC)
if C.nimbus_add_symkey_from_password(passwordC, (*C.uchar)(idC)) { if C.nimbus_add_symkey_from_password(passwordC, (*C.uchar)(idC)) {
c <- types.EncodeHex(C.GoBytes(idC, C.ID_LEN)) c <- callReturn{value: types.EncodeHex(C.GoBytes(idC, C.ID_LEN))}
} else { } else {
c <- errors.New("failed to add symkey to Nimbus") c <- callReturn{err: errors.New("failed to add symkey to Nimbus")}
} }
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
// DeleteKeyPair removes the key with the given key if it exists. // DeleteKeyPair removes the key with the given key if it exists.
func (w *nimbusPublicWhisperAPIWrapper) DeleteKeyPair(ctx context.Context, key string) (bool, error) { func (w *nimbusPublicWhisperAPIWrapper) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
keyC, err := decodeHexID(key) keyC, err := decodeHexID(key)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(keyC)) defer C.free(unsafe.Pointer(keyC))
c <- C.nimbus_delete_keypair(keyC) c <- callReturn{value: C.nimbus_delete_keypair(keyC)}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return false, err return false, retVal.err
} }
return retVal.(bool), nil return retVal.value.(bool), nil
} }
// NewMessageFilter creates a new filter that can be used to poll for // NewMessageFilter creates a new filter that can be used to poll for
@ -156,7 +156,7 @@ func (w *nimbusPublicWhisperAPIWrapper) GetFilterMessages(id string) ([]*types.M
// Post posts a message on the Whisper network. // Post posts a message on the Whisper network.
// returns the hash of the message in case of success. // returns the hash of the message in case of success.
func (w *nimbusPublicWhisperAPIWrapper) Post(ctx context.Context, req types.NewMessage) ([]byte, error) { func (w *nimbusPublicWhisperAPIWrapper) Post(ctx context.Context, req types.NewMessage) ([]byte, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
msg := C.post_message{ msg := C.post_message{
ttl: C.uint32_t(req.TTL), ttl: C.uint32_t(req.TTL),
powTime: C.double(req.PowTime), powTime: C.double(req.PowTime),
@ -165,7 +165,7 @@ func (w *nimbusPublicWhisperAPIWrapper) Post(ctx context.Context, req types.NewM
if req.SigID != "" { if req.SigID != "" {
sourceID, err := decodeHexID(req.SigID) sourceID, err := decodeHexID(req.SigID)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
msg.sourceID = sourceID msg.sourceID = sourceID
@ -174,7 +174,7 @@ func (w *nimbusPublicWhisperAPIWrapper) Post(ctx context.Context, req types.NewM
if req.SymKeyID != "" { if req.SymKeyID != "" {
symKeyID, err := decodeHexID(req.SymKeyID) symKeyID, err := decodeHexID(req.SymKeyID)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
msg.symKeyID = symKeyID msg.symKeyID = symKeyID
@ -194,19 +194,19 @@ func (w *nimbusPublicWhisperAPIWrapper) Post(ctx context.Context, req types.NewM
// TODO: return envelope hash once nimbus_post is improved to return it // TODO: return envelope hash once nimbus_post is improved to return it
if C.nimbus_post(&msg) { if C.nimbus_post(&msg) {
c <- make([]byte, 0) c <- callReturn{value: make([]byte, 0)}
return return
} }
c <- fmt.Errorf("failed to post message symkeyid=%s pubkey=%#x topic=%#x", req.SymKeyID, req.PublicKey, req.Topic[:]) c <- callReturn{err: fmt.Errorf("failed to post message symkeyid=%s pubkey=%#x topic=%#x", req.SymKeyID, req.PublicKey, req.Topic[:])}
// hashC := C.nimbus_post(&msg) // hashC := C.nimbus_post(&msg)
// if hashC == nil { // if hashC == nil {
// return nil, errors.New("Nimbus failed to post message") // return nil, errors.New("Nimbus failed to post message")
// } // }
// return hex.DecodeString(C.GoString(hashC)) // return hex.DecodeString(C.GoString(hashC))
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return nil, err return nil, retVal.err
} }
return retVal.([]byte), nil return retVal.value.([]byte), nil
} }

View File

@ -14,6 +14,11 @@ type RoutineQueue struct {
events chan event events chan event
} }
type callReturn struct {
value interface{}
err error
}
// NewRoutineQueue returns a new RoutineQueue object. // NewRoutineQueue returns a new RoutineQueue object.
func NewRoutineQueue() *RoutineQueue { func NewRoutineQueue() *RoutineQueue {
q := &RoutineQueue{ q := &RoutineQueue{
@ -26,8 +31,8 @@ func NewRoutineQueue() *RoutineQueue {
// event represents an event triggered by the user. // event represents an event triggered by the user.
type event struct { type event struct {
f func(chan<- interface{}) f func(chan<- callReturn)
done chan interface{} done chan callReturn
} }
func (q *RoutineQueue) HandleEvent() { func (q *RoutineQueue) HandleEvent() {
@ -47,8 +52,8 @@ func (q *RoutineQueue) HandleEvent() {
// goroutine in order to execute a Nimbus function. It is important to note that the // goroutine in order to execute a Nimbus function. It is important to note that the
// passed function won't be executed immediately, instead it will be added to // passed function won't be executed immediately, instead it will be added to
// the user events queue. // the user events queue.
func (q *RoutineQueue) Send(f func(chan<- interface{})) interface{} { func (q *RoutineQueue) Send(f func(chan<- callReturn)) callReturn {
ev := event{f: f, done: make(chan interface{}, 1)} ev := event{f: f, done: make(chan callReturn, 1)}
defer close(ev.done) defer close(ev.done)
if syscall.Gettid() == q.tid { if syscall.Gettid() == q.tid {
f(ev.done) f(ev.done)

View File

@ -52,9 +52,9 @@ func (w *nimbusWhisperWrapper) PublicWhisperAPI() types.PublicWhisperAPI {
// MinPow returns the PoW value required by this node. // MinPow returns the PoW value required by this node.
func (w *nimbusWhisperWrapper) MinPow() float64 { func (w *nimbusWhisperWrapper) MinPow() float64 {
return w.routineQueue.Send(func(c chan<- interface{}) { return w.routineQueue.Send(func(c chan<- callReturn) {
c <- float64(C.nimbus_get_min_pow()) c <- callReturn{value: float64(C.nimbus_get_min_pow())}
}).(float64) }).value.(float64)
} }
// BloomFilter returns the aggregated bloom filter for all the topics of interest. // BloomFilter returns the aggregated bloom filter for all the topics of interest.
@ -62,7 +62,7 @@ func (w *nimbusWhisperWrapper) MinPow() float64 {
// If a message does not match the bloom, it will tantamount to spam, and the peer will // If a message does not match the bloom, it will tantamount to spam, and the peer will
// be disconnected. // be disconnected.
func (w *nimbusWhisperWrapper) BloomFilter() []byte { func (w *nimbusWhisperWrapper) BloomFilter() []byte {
return w.routineQueue.Send(func(c chan<- interface{}) { return w.routineQueue.Send(func(c chan<- callReturn) {
// Allocate a buffer for Nimbus to return the bloom filter on // Allocate a buffer for Nimbus to return the bloom filter on
dataC := C.malloc(C.size_t(C.BLOOM_LEN)) dataC := C.malloc(C.size_t(C.BLOOM_LEN))
defer C.free(unsafe.Pointer(dataC)) defer C.free(unsafe.Pointer(dataC))
@ -72,8 +72,8 @@ func (w *nimbusWhisperWrapper) BloomFilter() []byte {
// Move the returned data into a Go array // Move the returned data into a Go array
data := make([]byte, C.BLOOM_LEN) data := make([]byte, C.BLOOM_LEN)
copy(data, C.GoBytes(dataC, C.BLOOM_LEN)) copy(data, C.GoBytes(dataC, C.BLOOM_LEN))
c <- data c <- callReturn{value: data}
}).([]byte) }).value.([]byte)
} }
// GetCurrentTime returns current time. // GetCurrentTime returns current time.
@ -98,10 +98,10 @@ func (w *nimbusWhisperWrapper) SelectedKeyPairID() string {
} }
func (w *nimbusWhisperWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { func (w *nimbusWhisperWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
idC, err := decodeHexID(id) idC, err := decodeHexID(id)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(idC)) defer C.free(unsafe.Pointer(idC))
@ -109,28 +109,28 @@ func (w *nimbusWhisperWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, erro
defer C.free(unsafe.Pointer(privKeyC)) defer C.free(unsafe.Pointer(privKeyC))
if !C.nimbus_get_private_key(idC, (*C.uchar)(privKeyC)) { if !C.nimbus_get_private_key(idC, (*C.uchar)(privKeyC)) {
c <- errors.New("failed to get private key from Nimbus") c <- callReturn{err: errors.New("failed to get private key from Nimbus")}
return return
} }
pk, err := crypto.ToECDSA(C.GoBytes(privKeyC, C.PRIVKEY_LEN)) pk, err := crypto.ToECDSA(C.GoBytes(privKeyC, C.PRIVKEY_LEN))
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
c <- pk c <- callReturn{value: pk}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return nil, err return nil, retVal.err
} }
return retVal.(*ecdsa.PrivateKey), nil return retVal.value.(*ecdsa.PrivateKey), nil
} }
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier. // AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
func (w *nimbusWhisperWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { func (w *nimbusWhisperWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
privKey := crypto.FromECDSA(key) privKey := crypto.FromECDSA(key)
privKeyC := C.CBytes(privKey) privKeyC := C.CBytes(privKey)
defer C.free(unsafe.Pointer(privKeyC)) defer C.free(unsafe.Pointer(privKeyC))
@ -138,56 +138,61 @@ func (w *nimbusWhisperWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error)
idC := C.malloc(C.size_t(C.ID_LEN)) idC := C.malloc(C.size_t(C.ID_LEN))
defer C.free(idC) defer C.free(idC)
if !C.nimbus_add_keypair((*C.uchar)(privKeyC), (*C.uchar)(idC)) { if !C.nimbus_add_keypair((*C.uchar)(privKeyC), (*C.uchar)(idC)) {
c <- errors.New("failed to add keypair to Nimbus") c <- callReturn{err: errors.New("failed to add keypair to Nimbus")}
return return
} }
c <- types.EncodeHex(C.GoBytes(idC, C.ID_LEN)) c <- callReturn{value: types.EncodeHex(C.GoBytes(idC, C.ID_LEN))}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
// DeleteKeyPair deletes the key with the specified ID if it exists. // DeleteKeyPair deletes the key with the specified ID if it exists.
func (w *nimbusWhisperWrapper) DeleteKeyPair(keyID string) bool { func (w *nimbusWhisperWrapper) DeleteKeyPair(keyID string) bool {
return w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
keyC, err := decodeHexID(keyID) keyC, err := decodeHexID(keyID)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(keyC)) defer C.free(unsafe.Pointer(keyC))
c <- C.nimbus_delete_keypair(keyC) c <- callReturn{value: C.nimbus_delete_keypair(keyC)}
}).(bool) })
if retVal.err != nil {
return false
}
return retVal.value.(bool)
} }
func (w *nimbusWhisperWrapper) AddSymKeyDirect(key []byte) (string, error) { func (w *nimbusWhisperWrapper) AddSymKeyDirect(key []byte) (string, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
keyC := C.CBytes(key) keyC := C.CBytes(key)
defer C.free(unsafe.Pointer(keyC)) defer C.free(unsafe.Pointer(keyC))
idC := C.malloc(C.size_t(C.ID_LEN)) idC := C.malloc(C.size_t(C.ID_LEN))
defer C.free(idC) defer C.free(idC)
if !C.nimbus_add_symkey((*C.uchar)(keyC), (*C.uchar)(idC)) { if !C.nimbus_add_symkey((*C.uchar)(keyC), (*C.uchar)(idC)) {
c <- errors.New("failed to add symkey to Nimbus") c <- callReturn{err: errors.New("failed to add symkey to Nimbus")}
return return
} }
c <- types.EncodeHex(C.GoBytes(idC, C.ID_LEN)) c <- callReturn{value: types.EncodeHex(C.GoBytes(idC, C.ID_LEN))}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
func (w *nimbusWhisperWrapper) AddSymKeyFromPassword(password string) (string, error) { func (w *nimbusWhisperWrapper) AddSymKeyFromPassword(password string) (string, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
passwordC := C.CString(password) passwordC := C.CString(password)
defer C.free(unsafe.Pointer(passwordC)) defer C.free(unsafe.Pointer(passwordC))
@ -195,36 +200,41 @@ func (w *nimbusWhisperWrapper) AddSymKeyFromPassword(password string) (string, e
defer C.free(idC) defer C.free(idC)
if C.nimbus_add_symkey_from_password(passwordC, (*C.uchar)(idC)) { if C.nimbus_add_symkey_from_password(passwordC, (*C.uchar)(idC)) {
id := C.GoBytes(idC, C.ID_LEN) id := C.GoBytes(idC, C.ID_LEN)
c <- types.EncodeHex(id) c <- callReturn{value: types.EncodeHex(id)}
} else { } else {
c <- errors.New("failed to add symkey to Nimbus") c <- callReturn{err: errors.New("failed to add symkey to Nimbus")}
} }
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
func (w *nimbusWhisperWrapper) DeleteSymKey(id string) bool { func (w *nimbusWhisperWrapper) DeleteSymKey(id string) bool {
return w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
idC, err := decodeHexID(id) idC, err := decodeHexID(id)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(idC)) defer C.free(unsafe.Pointer(idC))
c <- C.nimbus_delete_symkey(idC) c <- callReturn{value: C.nimbus_delete_symkey(idC)}
}).(bool) })
if retVal.err != nil {
return false
}
return retVal.value.(bool)
} }
func (w *nimbusWhisperWrapper) GetSymKey(id string) ([]byte, error) { func (w *nimbusWhisperWrapper) GetSymKey(id string) ([]byte, error) {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
idC, err := decodeHexID(id) idC, err := decodeHexID(id)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(idC)) defer C.free(unsafe.Pointer(idC))
@ -233,17 +243,17 @@ func (w *nimbusWhisperWrapper) GetSymKey(id string) ([]byte, error) {
dataC := C.malloc(C.size_t(C.SYMKEY_LEN)) dataC := C.malloc(C.size_t(C.SYMKEY_LEN))
defer C.free(unsafe.Pointer(dataC)) defer C.free(unsafe.Pointer(dataC))
if !C.nimbus_get_symkey(idC, (*C.uchar)(dataC)) { if !C.nimbus_get_symkey(idC, (*C.uchar)(dataC)) {
c <- errors.New("symkey not found") c <- callReturn{err: errors.New("symkey not found")}
return return
} }
c <- C.GoBytes(dataC, C.SYMKEY_LEN) c <- callReturn{value: C.GoBytes(dataC, C.SYMKEY_LEN)}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return nil, err return nil, retVal.err
} }
return retVal.([]byte), nil return retVal.value.([]byte), nil
} }
//export onMessageHandler //export onMessageHandler
@ -277,7 +287,7 @@ func (w *nimbusWhisperWrapper) Subscribe(opts *types.SubscriptionOptions) (strin
return "", err return "", err
} }
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
// Create a message store for this filter, so we can add new messages to it from the nimbus_subscribe_filter callback // Create a message store for this filter, so we can add new messages to it from the nimbus_subscribe_filter callback
messageList := list.New() messageList := list.New()
idC := C.malloc(C.size_t(C.ID_LEN)) idC := C.malloc(C.size_t(C.ID_LEN))
@ -286,7 +296,7 @@ func (w *nimbusWhisperWrapper) Subscribe(opts *types.SubscriptionOptions) (strin
GetNimbusFilterFrom(f), GetNimbusFilterFrom(f),
(C.received_msg_handler)(unsafe.Pointer(C.onMessageHandler_cgo)), gopointer.Save(messageList), (C.received_msg_handler)(unsafe.Pointer(C.onMessageHandler_cgo)), gopointer.Save(messageList),
(*C.uchar)(idC)) { (*C.uchar)(idC)) {
c <- errors.New("failed to subscribe to filter in Nimbus") c <- callReturn{err: errors.New("failed to subscribe to filter in Nimbus")}
return return
} }
filterID := C.GoString((*C.char)(idC)) filterID := C.GoString((*C.char)(idC))
@ -297,13 +307,13 @@ func (w *nimbusWhisperWrapper) Subscribe(opts *types.SubscriptionOptions) (strin
f.(*nimbusFilterWrapper).id = filterID f.(*nimbusFilterWrapper).id = filterID
c <- filterID c <- callReturn{value: filterID}
}) })
if err, ok := retVal.(error); ok { if retVal.err != nil {
return "", err return "", retVal.err
} }
return retVal.(string), nil return retVal.value.(string), nil
} }
func (w *nimbusWhisperWrapper) GetFilter(id string) types.Filter { func (w *nimbusWhisperWrapper) GetFilter(id string) types.Filter {
@ -316,16 +326,16 @@ func (w *nimbusWhisperWrapper) GetFilter(id string) types.Filter {
} }
func (w *nimbusWhisperWrapper) Unsubscribe(id string) error { func (w *nimbusWhisperWrapper) Unsubscribe(id string) error {
retVal := w.routineQueue.Send(func(c chan<- interface{}) { retVal := w.routineQueue.Send(func(c chan<- callReturn) {
idC, err := decodeHexID(id) idC, err := decodeHexID(id)
if err != nil { if err != nil {
c <- err c <- callReturn{err: err}
return return
} }
defer C.free(unsafe.Pointer(idC)) defer C.free(unsafe.Pointer(idC))
if ok := C.nimbus_unsubscribe_filter(idC); !ok { if ok := C.nimbus_unsubscribe_filter(idC); !ok {
c <- errors.New("filter not found") c <- callReturn{err: errors.New("filter not found")}
return return
} }
@ -341,12 +351,9 @@ func (w *nimbusWhisperWrapper) Unsubscribe(id string) error {
delete(w.filters, id) delete(w.filters, id)
} }
c <- nil c <- callReturn{err: nil}
}) })
if err, ok := retVal.(error); ok { return retVal.err
return err
}
return nil
} }
func decodeHexID(id string) (*C.uint8_t, error) { func decodeHexID(id string) (*C.uint8_t, error) {