diff --git a/io.go b/io.go index 371bd8f..39b11ef 100644 --- a/io.go +++ b/io.go @@ -3,9 +3,11 @@ package rpcfetch import ( "encoding/binary" "encoding/json" + "errors" "net" "os" "strconv" + "syscall" ) type Client struct { @@ -33,6 +35,17 @@ func Raw[T any](d *Client, opcode uint32, payload any) (uint32, T, error) { // Raw writes a raw payload to Discord and returns the response opcode and payload func (d *Client) Raw(opcode uint32, payload any) (uint32, []byte, error) { + opcodeResp, payloadResp, err := d.raw(opcode, payload) + if errors.Is(err, syscall.EPIPE) { + // clean up as much as possible + _ = d.Close() + // advise retry + err = ErrAgain + } + return opcodeResp, payloadResp, err +} + +func (d *Client) raw(opcode uint32, payload any) (uint32, []byte, error) { if err := binary.Write(d.conn, binary.LittleEndian, opcode); err != nil { return 0, nil, err } diff --git a/io_unix.go b/io_unix.go index e646c76..32d3284 100644 --- a/io_unix.go +++ b/io_unix.go @@ -1,16 +1,25 @@ package rpcfetch import ( + "errors" + "io/fs" "net" "time" ) +var ( + ErrAgain = errors.New("operation not performed") +) + func (d *Client) dial() error { if d.dialed { panic("attempted to dial on open client") } if conn, err := net.DialTimeout("unix", sockPath()+"/discord-ipc-0", 5*time.Second); err != nil { + if errors.Is(err, fs.ErrNotExist) { + return ErrAgain + } return err } else { d.conn = conn