library: io: make connection private and implement Close method

Since some of the state of the connection is tracked by the Client struct and the Raw method is sufficient for any low-level interaction with the Discord RPC, users of the API should not and does not have any reason to interact with the underlying connection.

Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
Ophestra Umiker 2024-06-19 23:32:51 +09:00
parent a8dc09e90c
commit a985e2b9df
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
2 changed files with 20 additions and 8 deletions

26
io.go
View File

@ -16,7 +16,7 @@ type Client struct {
dialed bool dialed bool
active bool active bool
net.Conn conn net.Conn
} }
// Raw wraps around the Raw method to provide generic json parsing // Raw wraps around the Raw method to provide generic json parsing
@ -33,18 +33,18 @@ 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 // 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) { func (d *Client) Raw(opcode uint32, payload any) (uint32, []byte, error) {
if err := binary.Write(d.Conn, binary.LittleEndian, opcode); err != nil { if err := binary.Write(d.conn, binary.LittleEndian, opcode); err != nil {
return 0, nil, err return 0, nil, err
} }
if p, err := json.Marshal(payload); err != nil { if p, err := json.Marshal(payload); err != nil {
return 0, nil, err return 0, nil, err
} else { } else {
if err = binary.Write(d.Conn, binary.LittleEndian, uint32(len(p))); err != nil { if err = binary.Write(d.conn, binary.LittleEndian, uint32(len(p))); err != nil {
return 0, nil, err return 0, nil, err
} }
if _, err = d.Conn.Write(p); err != nil { if _, err = d.conn.Write(p); err != nil {
return 0, nil, err return 0, nil, err
} }
} }
@ -54,19 +54,31 @@ func (d *Client) Raw(opcode uint32, payload any) (uint32, []byte, error) {
lengthResp uint32 lengthResp uint32
) )
if err := binary.Read(d.Conn, binary.LittleEndian, &opcodeResp); err != nil { if err := binary.Read(d.conn, binary.LittleEndian, &opcodeResp); err != nil {
return 0, nil, err return 0, nil, err
} }
if err := binary.Read(d.Conn, binary.LittleEndian, &lengthResp); err != nil { if err := binary.Read(d.conn, binary.LittleEndian, &lengthResp); err != nil {
return 0, nil, err return 0, nil, err
} }
payloadResp := make([]byte, lengthResp) payloadResp := make([]byte, lengthResp)
_, err := d.Read(payloadResp) _, err := d.conn.Read(payloadResp)
return opcodeResp, payloadResp, err return opcodeResp, payloadResp, err
} }
// Close the client, this is required before exit
func (d *Client) Close() error {
if !d.dialed {
// silently succeed because client activation is implicit
return nil
}
d.active = false
d.dialed = false
return d.conn.Close()
}
// New sets up and returns the reference to a new Client // New sets up and returns the reference to a new Client
func New(id string) *Client { func New(id string) *Client {
d := &Client{ d := &Client{

View File

@ -13,7 +13,7 @@ func (d *Client) dial() error {
if conn, err := net.DialTimeout("unix", sockPath()+"/discord-ipc-0", 5*time.Second); err != nil { if conn, err := net.DialTimeout("unix", sockPath()+"/discord-ipc-0", 5*time.Second); err != nil {
return err return err
} else { } else {
d.Conn = conn d.conn = conn
d.dialed = true d.dialed = true
} }
return nil return nil