Skip to content

Commit ff02172

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
feat: add server-side binder protocol constants, TransactionReceiver interface, and local binder parcel support
1 parent 0be049e commit ff02172

3 files changed

Lines changed: 57 additions & 3 deletions

File tree

binder/transaction_receiver.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package binder
2+
3+
import (
4+
"context"
5+
6+
"github.com/xaionaro-go/binder/parcel"
7+
)
8+
9+
// TransactionReceiver processes incoming binder transactions.
10+
// Implemented by generated Stub types that dispatch transaction
11+
// codes to typed Go interface methods.
12+
type TransactionReceiver interface {
13+
OnTransaction(
14+
ctx context.Context,
15+
code TransactionCode,
16+
data *parcel.Parcel,
17+
) (*parcel.Parcel, error)
18+
}

kernelbinder/protocol.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@ import "unsafe"
77
// Binder command (BC) codes -- written to the driver.
88
// Codes that carry a struct payload encode sizeof(payload) in the ioctl-style
99
// number, so they must be computed from the actual Go struct sizes.
10-
//
11-
// Only currently-used codes are defined here. The full protocol is documented
12-
// in the design doc and additional codes can be added as features are implemented.
1310
var (
1411
bcTransaction = uint32(iow('c', 0, unsafe.Sizeof(binderTransactionData{})))
12+
bcReply = uint32(iow('c', 1, unsafe.Sizeof(binderTransactionData{})))
1513
bcFreeBuffer = uint32(iow('c', 3, unsafe.Sizeof(uintptr(0)))) // binder_uintptr_t
1614
bcIncRefs = uint32(iow('c', 4, unsafe.Sizeof(uint32(0))))
1715
bcAcquire = uint32(iow('c', 5, unsafe.Sizeof(uint32(0))))
1816
bcRelease = uint32(iow('c', 6, unsafe.Sizeof(uint32(0))))
1917
bcDecRefs = uint32(iow('c', 7, unsafe.Sizeof(uint32(0))))
18+
bcIncRefsDone = uint32(iow('c', 8, binderPtrCookieSize))
19+
bcAcquireDone = uint32(iow('c', 9, binderPtrCookieSize))
20+
bcRegisterLooper = uint32(ioc(0, 'c', 11, 0))
21+
bcEnterLooper = uint32(ioc(0, 'c', 12, 0))
22+
bcExitLooper = uint32(ioc(0, 'c', 13, 0))
2023
bcRequestDeathNotif = uint32(iow('c', 14, binderHandleCookieSize))
2124
bcClearDeathNotif = uint32(iow('c', 15, binderHandleCookieSize))
2225
)
2326

27+
// binderPtrCookieSize is the size of the kernel's binder_ptr_cookie struct:
28+
// binder_uintptr_t ptr + binder_uintptr_t cookie (2 x pointer-sized).
29+
const binderPtrCookieSize = 2 * unsafe.Sizeof(uintptr(0)) // = 16 on 64-bit
30+
2431
// binderHandleCookieSize is the packed size of the kernel's binder_handle_cookie
2532
// struct: __u32 handle + binder_uintptr_t cookie. The kernel struct uses
2633
// __attribute__((packed)), so there is NO alignment padding between fields.
@@ -29,9 +36,14 @@ const binderHandleCookieSize = unsafe.Sizeof(uint32(0)) + unsafe.Sizeof(uintptr(
2936
// Binder return (BR) codes -- read from the driver.
3037
var (
3138
brError = uint32(ior('r', 0, unsafe.Sizeof(int32(0))))
39+
brTransaction = uint32(ior('r', 2, unsafe.Sizeof(binderTransactionData{})))
3240
brReply = uint32(ior('r', 3, unsafe.Sizeof(binderTransactionData{})))
3341
brDeadReply = uint32(ioc(0, 'r', 5, 0))
3442
brTransactionComplete = uint32(ioc(0, 'r', 6, 0))
43+
brIncRefs = uint32(ior('r', 7, binderPtrCookieSize))
44+
brAcquire = uint32(ior('r', 8, binderPtrCookieSize))
45+
brRelease = uint32(ior('r', 9, binderPtrCookieSize))
46+
brDecrefs = uint32(ior('r', 10, binderPtrCookieSize))
3547
brNoop = uint32(ioc(0, 'r', 12, 0))
3648
brSpawnLooper = uint32(ioc(0, 'r', 13, 0))
3749
brFailedReply = uint32(ioc(0, 'r', 17, 0))

parcel/binder_object.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,30 @@ const (
2222
flatBinderObjectSize = 24
2323
)
2424

25+
// WriteLocalBinder writes a local binder object to the parcel.
26+
// The cookie identifies the object for incoming BR_TRANSACTION dispatch.
27+
// The kernel converts this to a handle in the remote process.
28+
func (p *Parcel) WriteLocalBinder(
29+
cookie uintptr,
30+
) {
31+
offset := uint64(p.Len())
32+
p.objects = append(p.objects, offset)
33+
34+
buf := p.grow(flatBinderObjectSize)
35+
36+
// type (uint32, offset 0)
37+
binary.LittleEndian.PutUint32(buf[0:], binderTypeBinder)
38+
39+
// flags (uint32, offset 4)
40+
binary.LittleEndian.PutUint32(buf[4:], binderFlagsAcceptFDs)
41+
42+
// binder (binder_uintptr_t, offset 8)
43+
binary.LittleEndian.PutUint64(buf[8:], uint64(cookie))
44+
45+
// cookie (binder_uintptr_t, offset 16)
46+
binary.LittleEndian.PutUint64(buf[16:], uint64(cookie))
47+
}
48+
2549
// WriteStrongBinder writes a flat_binder_object with the given handle.
2650
// Records the offset in the parcel's objects array.
2751
func (p *Parcel) WriteStrongBinder(

0 commit comments

Comments
 (0)