Clarify Memory Ownership Model of libCwtch and Callers
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
Provides a way of telling libCwtch to free memory returned from functions that provide CStrings as results.
This commit is contained in:
parent
23c15130c7
commit
f86e670241
|
@ -0,0 +1,27 @@
|
||||||
|
# Memory Model
|
||||||
|
|
||||||
|
This document provides an overview of the memory model of libCwtch. Callers should consult this document to ensure
|
||||||
|
that they are properly handling pointers passed to-and-from libCwtch.
|
||||||
|
|
||||||
|
## Pointer Parameters
|
||||||
|
|
||||||
|
All pointers **passed** into functions in this library, except `c_FreePointer`, are assumed to be owned by the caller.
|
||||||
|
|
||||||
|
libCwtch **will not** modifying the underlying memory, nor attempt to free or otherwise modify these pointers.
|
||||||
|
|
||||||
|
This is realized by copying the underlying memory using `C.GoStringN`. libCwtch guarantees that it will not depend
|
||||||
|
on the underlying memory of these pointers being available after returning from this function.
|
||||||
|
|
||||||
|
Callers are responsible for freeing these pointers after the call has been completed.
|
||||||
|
|
||||||
|
## Returned Pointers
|
||||||
|
|
||||||
|
All pointers **returned** by functions in libCwtch should be assumed to owned by libCwtch
|
||||||
|
|
||||||
|
Callers **must not** modifying the underlying memory of these pointers, nor attempt to free or otherwise modify these pointers
|
||||||
|
through any method other than the one provided below.
|
||||||
|
|
||||||
|
Calling functions **must** copy the contents of the memory into their own memory space and then call `c_FreePointer` providing
|
||||||
|
the returned pointer as a parameter.
|
||||||
|
|
||||||
|
libCwtch guarantees that it will not modify or free the underlying memory of these pointers prior to a call to `c_FreePointer`.
|
27
lib.go
27
lib.go
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
// //Needed to invoke C.free
|
||||||
|
// #include <stdlib.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"cwtch.im/cwtch/app"
|
"cwtch.im/cwtch/app"
|
||||||
|
@ -21,6 +24,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||||
|
@ -381,6 +385,7 @@ func SendProfileEvent(onion string, eventJson string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export c_GetAppBusEvent
|
//export c_GetAppBusEvent
|
||||||
|
// the pointer returned from this function **must** be freed using c_Free
|
||||||
func c_GetAppBusEvent() *C.char {
|
func c_GetAppBusEvent() *C.char {
|
||||||
return C.CString(GetAppBusEvent())
|
return C.CString(GetAppBusEvent())
|
||||||
}
|
}
|
||||||
|
@ -427,20 +432,6 @@ func LoadProfiles(pass string) {
|
||||||
application.LoadProfiles(pass)
|
application.LoadProfiles(pass)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export c_ContactEvents
|
|
||||||
func c_ContactEvents() *C.char {
|
|
||||||
return C.CString(ContactEvents())
|
|
||||||
}
|
|
||||||
|
|
||||||
func ContactEvents() string {
|
|
||||||
select {
|
|
||||||
case myevent := <-contactEventsQueue.OutChan():
|
|
||||||
return fmt.Sprintf("%v", myevent)
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//export c_AcceptContact
|
//export c_AcceptContact
|
||||||
func c_AcceptContact(profilePtr *C.char, profileLen C.int, handlePtr *C.char, handleLen C.int) {
|
func c_AcceptContact(profilePtr *C.char, profileLen C.int, handlePtr *C.char, handleLen C.int) {
|
||||||
AcceptContact(C.GoStringN(profilePtr, profileLen), C.GoStringN(handlePtr, handleLen))
|
AcceptContact(C.GoStringN(profilePtr, profileLen), C.GoStringN(handlePtr, handleLen))
|
||||||
|
@ -520,6 +511,7 @@ func UpdateMessageFlags(profileOnion, handle string, mIdx int, flags int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export c_GetMessage
|
//export c_GetMessage
|
||||||
|
// the pointer returned from this function **must** be Freed by c_Free
|
||||||
func c_GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char {
|
func c_GetMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, message_index C.int) *C.char {
|
||||||
profile := C.GoStringN(profile_ptr, profile_len)
|
profile := C.GoStringN(profile_ptr, profile_len)
|
||||||
handle := C.GoStringN(handle_ptr, handle_len)
|
handle := C.GoStringN(handle_ptr, handle_len)
|
||||||
|
@ -585,6 +577,7 @@ func GetMessage(profileOnion, handle string, message_index int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export c_GetMessagesByContentHash
|
//export c_GetMessagesByContentHash
|
||||||
|
// the pointer returned from this function **must** be freed by calling c_Free
|
||||||
func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, contenthash_ptr *C.char, contenthash_len C.int) *C.char {
|
func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, contenthash_ptr *C.char, contenthash_len C.int) *C.char {
|
||||||
profile := C.GoStringN(profile_ptr, profile_len)
|
profile := C.GoStringN(profile_ptr, profile_len)
|
||||||
handle := C.GoStringN(handle_ptr, handle_len)
|
handle := C.GoStringN(handle_ptr, handle_len)
|
||||||
|
@ -592,6 +585,12 @@ func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_p
|
||||||
return C.CString(GetMessagesByContentHash(profile, handle, contentHash))
|
return C.CString(GetMessagesByContentHash(profile, handle, contentHash))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export c_FreePointer
|
||||||
|
// Dangerous function. Should only be used as documented in `MEMORY.md`
|
||||||
|
func c_FreePointer(ptr *C.char) {
|
||||||
|
C.free(unsafe.Pointer(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
func GetMessagesByContentHash(profileOnion, handle string, contentHash string) string {
|
func GetMessagesByContentHash(profileOnion, handle string, contentHash string) string {
|
||||||
var indexedMessages []model.LocallyIndexedMessage
|
var indexedMessages []model.LocallyIndexedMessage
|
||||||
if application != nil {
|
if application != nil {
|
||||||
|
|
Reference in New Issue