Initial commit
This commit is contained in:
63
vendor/go.i3wm.org/i3/byteorder.go
generated
vendored
Normal file
63
vendor/go.i3wm.org/i3/byteorder.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package i3
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// detectByteOrder sends messages to i3 to determine the byte order it uses.
|
||||
// For details on this technique, see:
|
||||
// https://build.i3wm.org/docs/ipc.html#_appendix_a_detecting_byte_order_in_memory_safe_languages
|
||||
func detectByteOrder(conn io.ReadWriter) (binary.ByteOrder, error) {
|
||||
const (
|
||||
// targetLen is 0x00 01 01 00 in both, big and little endian
|
||||
targetLen = 65536 + 256
|
||||
|
||||
// SUBSCRIBE was introduced in 3.e (2010-03-30)
|
||||
prefixSubscribe = "[]"
|
||||
|
||||
// RUN_COMMAND was always present
|
||||
prefixCmd = "nop byte-order detection. padding: "
|
||||
)
|
||||
|
||||
// 2. Send a big endian encoded message of type SUBSCRIBE:
|
||||
payload := []byte(prefixSubscribe + strings.Repeat(" ", targetLen-len(prefixSubscribe)))
|
||||
if err := binary.Write(conn, binary.BigEndian, &header{magic, uint32(len(payload)), messageTypeSubscribe}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := conn.Write(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. Send a byte order independent RUN_COMMAND message:
|
||||
payload = []byte(prefixCmd + strings.Repeat("a", targetLen-len(prefixCmd)))
|
||||
if err := binary.Write(conn, binary.BigEndian, &header{magic, uint32(len(payload)), messageTypeRunCommand}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := conn.Write(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 4. Receive a message header, decode the message type as big endian:
|
||||
var header [14]byte
|
||||
if _, err := io.ReadFull(conn, header[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if messageType(binary.BigEndian.Uint32(header[10:14])) == messageReplyTypeCommand {
|
||||
order := binary.LittleEndian // our big endian message was not answered
|
||||
// Read remaining payload
|
||||
_, err := io.ReadFull(conn, make([]byte, order.Uint32(header[6:10])))
|
||||
return order, err
|
||||
}
|
||||
order := binary.BigEndian // our big endian message was answered
|
||||
// Read remaining payload
|
||||
if _, err := io.ReadFull(conn, make([]byte, order.Uint32(header[6:10]))); err != nil {
|
||||
return order, err
|
||||
}
|
||||
|
||||
// Slurp the pending RUN_COMMAND reply.
|
||||
sock := &socket{conn: conn, order: order}
|
||||
_, err := sock.recvMsg()
|
||||
return binary.BigEndian, err
|
||||
}
|
||||
Reference in New Issue
Block a user