sway/client.go

93 lines
1.7 KiB
Go

package sway
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"os"
"sync"
)
type Client struct {
sync.Mutex
socket string
conn net.Conn
}
func GetDefaultClient() (*Client, error) {
socket, ok := os.LookupEnv("SWAYSOCK")
if !ok {
return nil, errors.New("could not find sway socket. is $SWAYSOCK set properly?")
}
return GetClientBySocket(socket)
}
func GetClientBySocket(socket string) (*Client, error) {
conn, err := net.Dial("unix", socket)
if err != nil {
return nil, err
}
return &Client{
socket: socket,
conn: conn,
}, nil
}
func (c *Client) Close() error {
c.Lock()
defer c.Unlock()
return c.conn.Close()
}
func sendMessage[T any](client *Client, messageType uint32, payload string) (T, error) {
client.Lock()
defer client.Unlock()
if _, err := fmt.Fprint(client.conn, "i3-ipc"); err != nil {
return *new(T), err
}
if err := binary.Write(client.conn, binary.LittleEndian, uint32(len(payload))); err != nil {
return *new(T), err
}
if err := binary.Write(client.conn, binary.LittleEndian, messageType); err != nil {
return *new(T), err
}
if _, err := fmt.Fprint(client.conn, payload); err != nil {
return *new(T), err
}
if _, err := client.conn.Read(make([]byte, 6)); err != nil {
return *new(T), err
}
var length uint32
if err := binary.Read(client.conn, binary.LittleEndian, &length); err != nil {
return *new(T), err
}
var responseType uint32
if err := binary.Read(client.conn, binary.LittleEndian, &responseType); err != nil {
return *new(T), err
}
// io.Copy(os.Stdout, client.conn)
// return *new(T), nil
result := new(T)
if err := json.NewDecoder(io.LimitReader(client.conn, int64(length))).Decode(result); err != nil {
return *new(T), err
}
return *result, nil
}