mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 12:17:06 +00:00
293 lines
7.5 KiB
Go
293 lines
7.5 KiB
Go
package libsignal
|
|
|
|
/*
|
|
#include <signal_protocol.h>
|
|
*/
|
|
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) {}
|