This repository has been archived by the owner on Nov 10, 2023. It is now read-only.
forked from stanluk/wayland-client
-
Notifications
You must be signed in to change notification settings - Fork 1
/
request.go
112 lines (96 loc) · 2.12 KB
/
request.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package wl
import (
"errors"
"net"
"syscall"
)
type Request struct {
pid ProxyId
opcode uint32
data []byte
oob []byte
}
func (context *Context) sendRequest(proxy Proxy, opcode uint32, args ...interface{}) (err error) {
req := Request{
pid: proxy.Id(),
opcode: opcode,
}
for _, arg := range args {
req.Write(arg)
}
return writeRequest(context.conn, req)
}
func (r *Request) Write(arg interface{}) {
switch t := arg.(type) {
case Proxy:
r.PutProxy(t)
case uint32:
r.PutUint32(t)
case int32:
r.PutInt32(t)
case float32:
r.PutFloat32(t)
case string:
r.PutString(t)
case []int32:
r.PutArray(t)
case uintptr:
r.PutFd(t)
default:
panic("Invalid Wayland request parameter type.")
}
}
func (r *Request) PutUint32(u uint32) {
buf := bytePool.Take(4)
order.PutUint32(buf, u)
r.data = append(r.data, buf...)
}
func (r *Request) PutProxy(p Proxy) {
r.PutUint32(uint32(p.Id()))
}
func (r *Request) PutInt32(i int32) {
r.PutUint32(uint32(i))
}
func (r *Request) PutFloat32(f float32) {
fx := float64ToFixed(float64(f))
r.PutUint32(uint32(fx))
}
func (r *Request) PutString(s string) {
tail := 4 - (len(s) & 0x3)
r.PutUint32(uint32(len(s) + tail))
r.data = append(r.data, []byte(s)...)
// if padding required
if tail > 0 {
padding := make([]byte, tail)
r.data = append(r.data, padding...)
}
}
func (r *Request) PutArray(a []int32) {
r.PutUint32(uint32(len(a)))
for _, e := range a {
r.PutUint32(uint32(e))
}
}
func (r *Request) PutFd(fd uintptr) {
rights := syscall.UnixRights(int(fd))
r.oob = append(r.oob, rights...)
}
func writeRequest(conn *net.UnixConn, r Request) error {
var header []byte
// calculate message total size
size := uint32(len(r.data) + 8)
buf := make([]byte, 4)
order.PutUint32(buf, uint32(r.pid))
header = append(header, buf...)
order.PutUint32(buf, uint32(size<<16|r.opcode&0x0000ffff))
header = append(header, buf...)
d, c, err := conn.WriteMsgUnix(append(header, r.data...), r.oob, nil)
if err != nil {
return err
}
if c != len(r.oob) || d != (len(header)+len(r.data)) {
return errors.New("WriteMsgUnix failed")
}
bytePool.Give(r.data)
return nil
}