예제 #1
0
func GetPriv(ctx uintptr, privatedata interface{}) int {
	/*  Retrieve the private data stored by the milter
	    Retrieving the data will release the memory allocated for it
	    Don't try to retrieve it again unless you call SetPriv first
	*/

	// Call libmilter smfi_getpriv to get a pointer to our data
	CArray := (*byte)(C.smfi_getpriv(int2ctx(ctx)))

	// Make sure data has been set with a previous call to SetPriv
	if CArray == nil {
		return -1
	}

	// Read uint32 size bytes from the start of the pointer
	var length uint32
	lengthsize := unsafe.Sizeof(length)
	lengthbytes := make([]byte, lengthsize)

	lenStart := uintptr(unsafe.Pointer(CArray))
	seqStart := lenStart + uintptr(lengthsize)

	for i := uintptr(0); i < uintptr(lengthsize); i++ {
		CArray = (*byte)(unsafe.Pointer(lenStart + i))
		lengthbytes[i] = *CArray
	}

	// Binary decode the length bytes
	buf := bytes.NewBuffer(lengthbytes)
	err := binary.Read(buf, binary.BigEndian, &length)
	if err != nil {
		return -1
	}

	// Read byte sequence of data
	databytes := make([]byte, length)
	for i := uintptr(0); i < uintptr(length); i++ {
		CArray = (*byte)(unsafe.Pointer(seqStart + i))
		databytes[i] = *CArray
	}

	// Free the data malloc'ed by C
	C.free(unsafe.Pointer(lenStart))
	C.smfi_setpriv(int2ctx(ctx), nil)

	// Unserialize the data bytes back into a data structure
	err = GobDecode(databytes, privatedata)
	if err != nil {
		return -1
	}

	return 0
}
예제 #2
0
// See also: http://bit.ly/1HVWA9I
func SetPriv(ctx uintptr, privatedata interface{}) int {
	// privatedata seems to work for any data type
	// Structs must have exported fields

	// Serialize Go privatedata into a byte slice
	bytedata, _ := GobEncode(privatedata)

	// length and size
	// length is a uint32 (usually 4 bytes)
	// the length will be stored in front of the byte sequence
	length := uint32(len(bytedata))
	lengthsize := C.size_t(unsafe.Sizeof(length))
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, length)
	if err != nil {
		return -1
	}
	lengthbytes := buf.Bytes()

	// Allocate memory for the length and byte sequence
	CArray := (*C.uchar)(C.malloc(lengthsize + C.size_t(length)))

	var lenStart, seqStart uintptr
	lenStart = uintptr(unsafe.Pointer(CArray))
	seqStart = lenStart + uintptr(lengthsize)

	CArray = (*C.uchar)(unsafe.Pointer(lenStart))

	for i := uintptr(0); i < uintptr(lengthsize); i++ {
		CArray = (*C.uchar)(unsafe.Pointer(lenStart + i))
		*CArray = C.uchar(lengthbytes[i])
	}

	// Now copy the data bytes to the position after the length
	for i := uintptr(0); i < uintptr(length); i++ {
		CArray = (*C.uchar)(unsafe.Pointer(seqStart + i))
		*CArray = C.uchar(bytedata[i])
	}

	// Call libmilter smfi_setpriv
	type CtxPtr *C.struct_smfi_str
	return int(C.smfi_setpriv(int2ctx(ctx), unsafe.Pointer(lenStart)))
}