-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
219 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
"errors" | ||
"net" | ||
|
||
"golang.org/x/sys/unix" | ||
) | ||
|
||
type WaylandPacket struct { | ||
ObjectId uint32 | ||
Length uint16 | ||
Opcode uint16 | ||
Arguments []byte | ||
Fds []uintptr | ||
|
||
buffer *bytes.Buffer | ||
} | ||
|
||
type WaylandGlobal struct { | ||
Interface string | ||
GlobalId uint32 | ||
Version uint32 | ||
} | ||
|
||
type WaylandObject struct { | ||
ObjectId uint32 | ||
Interface string | ||
// TODO: Add interface, if we know it | ||
} | ||
|
||
func ReadPacket(conn *net.UnixConn) (*WaylandPacket, error) { | ||
var fds []uintptr | ||
var buf [8]byte | ||
control := make([]byte, 24) | ||
|
||
n, oobn, _, _, err := conn.ReadMsgUnix(buf[:], control) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if n != 8 { | ||
return nil, errors.New("Unable to read message header") | ||
} | ||
if oobn > 0 { | ||
if oobn > len(control) { | ||
return nil, errors.New("Control message buffer undersized") | ||
} | ||
|
||
ctrl, err := unix.ParseSocketControlMessage(control) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for _, msg := range ctrl { | ||
_fds, err := unix.ParseUnixRights(&msg) | ||
if err != nil { | ||
return nil, errors.New("Unable to parse unix rights") | ||
} | ||
if len(_fds) != 1 { | ||
return nil, errors.New("Unexpectedly got >1 file descriptor") | ||
} | ||
fds = append(fds, uintptr(_fds[0])) | ||
} | ||
} | ||
|
||
packet := &WaylandPacket{ | ||
ObjectId: binary.LittleEndian.Uint32(buf[0:4]), | ||
Opcode: binary.LittleEndian.Uint16(buf[4:6]), | ||
Length: binary.LittleEndian.Uint16(buf[6:8]), | ||
Fds: fds, | ||
} | ||
|
||
packet.Arguments = make([]byte, packet.Length - 8) | ||
|
||
n, err = conn.Read(packet.Arguments) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if int(packet.Length - 8) != len(packet.Arguments) { | ||
return nil, errors.New("Buffer is shorter than expected length") | ||
} | ||
|
||
packet.Reset() | ||
return packet, nil | ||
} | ||
|
||
func (packet WaylandPacket) WritePacket(conn *net.UnixConn) error { | ||
var header bytes.Buffer | ||
size := uint32(len(packet.Arguments) + 8) | ||
|
||
binary.Write(&header, binary.LittleEndian, uint32(packet.ObjectId)) | ||
binary.Write(&header, binary.LittleEndian, | ||
uint32(size<<16|uint32(packet.Opcode)&0x0000ffff)) | ||
|
||
var oob []byte | ||
for _, fd := range packet.Fds { | ||
rights := unix.UnixRights(int(fd)) | ||
oob = append(oob, rights...) | ||
} | ||
|
||
body := append(header.Bytes(), packet.Arguments...) | ||
d, c, err := conn.WriteMsgUnix(body, oob, nil) | ||
if err != nil { | ||
return err | ||
} | ||
if c != len(oob) || d != len(body) { | ||
return errors.New("WriteMsgUnix failed") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (packet *WaylandPacket) Reset() { | ||
packet.buffer = bytes.NewBuffer(packet.Arguments) | ||
} | ||
|
||
func szup(n uint32) uint32 { | ||
if n % 4 == 0 { | ||
return n | ||
} | ||
return n+(4-(n%4)) | ||
} | ||
|
||
func (packet *WaylandPacket) ReadUint32() (uint32, error) { | ||
var out uint32 | ||
err := binary.Read(packet.buffer, binary.LittleEndian, &out) | ||
return out, err | ||
} | ||
|
||
func (packet *WaylandPacket) ReadString() (string, error) { | ||
var l uint32 | ||
err := binary.Read(packet.buffer, binary.LittleEndian, &l) | ||
if err != nil { | ||
return "", err | ||
} | ||
var pl uint32 = szup(l) | ||
buf := make([]byte, pl) | ||
n, err := packet.buffer.Read(buf) | ||
if err != nil { | ||
return "", err | ||
} | ||
if n != int(pl) { | ||
return "", errors.New("ReadString underread") | ||
} | ||
return string(buf[:l]), nil | ||
} |
Oops, something went wrong.