package libsignal /* #include */ import "C" import ( "runtime/cgo" "unsafe" ) // storeFromUserData recovers the Store bound to a StoreContext from the // cgo.Handle round-tripped through the vtable's void *user_data (see // store.go's NewStoreContext, which is the only place that creates such a // handle). func storeFromUserData(userData unsafe.Pointer) (Store, bool) { if userData == nil { return nil, false } s, ok := cgo.Handle(uintptr(userData)).Value().(Store) return s, ok } // ---- identity key store ---- //export go_get_identity_key_pair func go_get_identity_key_pair(publicData, privateData **C.signal_buffer, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } pub, priv, err := store.GetIdentityKeyPair() if err != nil { return C.int(ErrUnknown) } *publicData = bytesToBuffer(pub) *privateData = bytesToBuffer(priv) return C.SG_SUCCESS } //export go_get_local_registration_id func go_get_local_registration_id(userData unsafe.Pointer, registrationID *C.uint32_t) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } id, err := store.GetLocalRegistrationID() if err != nil { return C.int(ErrUnknown) } *registrationID = C.uint32_t(id) return C.SG_SUCCESS } //export go_save_identity func go_save_identity(address *C.signal_protocol_address, keyData *C.uint8_t, keyLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.SaveIdentity(addressFromC(address), cBytesToGo(keyData, keyLen)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_is_trusted_identity func go_is_trusted_identity(address *C.signal_protocol_address, keyData *C.uint8_t, keyLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } trusted, err := store.IsTrustedIdentity(addressFromC(address), cBytesToGo(keyData, keyLen)) if err != nil { return C.int(ErrUnknown) } if trusted { return 1 } return 0 } //export go_identity_destroy func go_identity_destroy(userData unsafe.Pointer) {} // ---- pre key store ---- //export go_load_pre_key func go_load_pre_key(record **C.signal_buffer, preKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } data, found, err := store.LoadPreKey(uint32(preKeyID)) if err != nil { return C.int(ErrUnknown) } if !found { return C.int(ErrInvalidKeyID) } *record = bytesToBuffer(data) return C.SG_SUCCESS } //export go_store_pre_key func go_store_pre_key(preKeyID C.uint32_t, record *C.uint8_t, recordLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.StorePreKey(uint32(preKeyID), cBytesToGo(record, recordLen)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_contains_pre_key func go_contains_pre_key(preKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return 0 } if store.ContainsPreKey(uint32(preKeyID)) { return 1 } return 0 } //export go_remove_pre_key func go_remove_pre_key(preKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.RemovePreKey(uint32(preKeyID)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_pre_key_destroy func go_pre_key_destroy(userData unsafe.Pointer) {} // ---- signed pre key store ---- //export go_load_signed_pre_key func go_load_signed_pre_key(record **C.signal_buffer, signedPreKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } data, found, err := store.LoadSignedPreKey(uint32(signedPreKeyID)) if err != nil { return C.int(ErrUnknown) } if !found { return C.int(ErrInvalidKeyID) } *record = bytesToBuffer(data) return C.SG_SUCCESS } //export go_store_signed_pre_key func go_store_signed_pre_key(signedPreKeyID C.uint32_t, record *C.uint8_t, recordLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.StoreSignedPreKey(uint32(signedPreKeyID), cBytesToGo(record, recordLen)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_contains_signed_pre_key func go_contains_signed_pre_key(signedPreKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return 0 } if store.ContainsSignedPreKey(uint32(signedPreKeyID)) { return 1 } return 0 } //export go_remove_signed_pre_key func go_remove_signed_pre_key(signedPreKeyID C.uint32_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.RemoveSignedPreKey(uint32(signedPreKeyID)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_signed_pre_key_destroy func go_signed_pre_key_destroy(userData unsafe.Pointer) {} // ---- session store ---- //export go_load_session func go_load_session(record, userRecord **C.signal_buffer, address *C.signal_protocol_address, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } data, found, err := store.LoadSession(addressFromC(address)) if err != nil { return C.int(ErrUnknown) } if !found { return 0 } *record = bytesToBuffer(data) return 1 } //export go_get_sub_device_sessions func go_get_sub_device_sessions(sessions **C.signal_int_list, name *C.char, nameLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } deviceIDs, err := store.GetSubDeviceSessions(C.GoStringN(name, C.int(nameLen))) if err != nil { return C.int(ErrUnknown) } list := C.signal_int_list_alloc() if list == nil { return C.int(ErrNoMemory) } for _, id := range deviceIDs { C.signal_int_list_push_back(list, C.int(id)) } *sessions = list return C.int(len(deviceIDs)) } //export go_store_session func go_store_session(address *C.signal_protocol_address, record *C.uint8_t, recordLen C.size_t, userRecord *C.uint8_t, userRecordLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.StoreSession(addressFromC(address), cBytesToGo(record, recordLen)); err != nil { return C.int(ErrUnknown) } return C.SG_SUCCESS } //export go_contains_session func go_contains_session(address *C.signal_protocol_address, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return 0 } if store.ContainsSession(addressFromC(address)) { return 1 } return 0 } //export go_delete_session func go_delete_session(address *C.signal_protocol_address, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } if err := store.DeleteSession(addressFromC(address)); err != nil { return C.int(ErrUnknown) } return 1 } //export go_delete_all_sessions func go_delete_all_sessions(name *C.char, nameLen C.size_t, userData unsafe.Pointer) C.int { store, ok := storeFromUserData(userData) if !ok { return C.int(ErrUnknown) } count, err := store.DeleteAllSessions(C.GoStringN(name, C.int(nameLen))) if err != nil { return C.int(ErrUnknown) } return C.int(count) } //export go_session_destroy func go_session_destroy(userData unsafe.Pointer) {}