Implement socket I/O

This commit is contained in:
Kovid Goyal 2022-08-26 20:09:03 +05:30
parent a960937095
commit b2e610f9b1
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 87 additions and 2 deletions

View File

@ -223,7 +223,10 @@ func send_rc_command(io_data *rc_io_data) (err error) {
return return
} }
} else { } else {
return fmt.Errorf("TODO: Implement socket IO") response, err = get_response(do_socket_io, io_data)
if err != nil {
return
}
} }
if err != nil || response == nil { if err != nil || response == nil {
return err return err

82
tools/cmd/at/socket_io.go Normal file
View File

@ -0,0 +1,82 @@
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package at
import (
"bytes"
"errors"
"io"
"net"
"time"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
func write_all_to_conn(conn *net.Conn, data []byte) error {
for len(data) > 0 {
n, err := (*conn).Write(data)
if err != nil && errors.Is(err, io.ErrShortWrite) {
err = nil
}
if err != nil {
return err
}
data = data[n:]
}
return nil
}
func read_response_from_conn(conn *net.Conn, timeout time.Duration) (serialized_response []byte, err error) {
p := wcswidth.EscapeCodeParser{}
keep_going := true
p.HandleDCS = func(data []byte) error {
if bytes.HasPrefix(data, []byte("@kitty-cmd")) {
serialized_response = data[len("@kitty-cmd"):]
keep_going = false
}
return nil
}
buf := make([]byte, utils.DEFAULT_IO_BUFFER_SIZE)
for keep_going {
var n int
(*conn).SetDeadline(time.Now().Add(timeout))
n, err = (*conn).Read(buf)
if err != nil {
keep_going = false
break
}
p.Parse(buf[:n])
}
return
}
func simple_socket_io(conn *net.Conn, io_data *rc_io_data) (serialized_response []byte, err error) {
for {
var chunk []byte
chunk, err = io_data.next_chunk(false)
if err != nil {
return
}
if len(chunk) == 0 {
break
}
err = write_all_to_conn(conn, chunk)
if err != nil {
return
}
}
if io_data.rc.NoResponse {
return
}
return read_response_from_conn(conn, io_data.timeout)
}
func do_socket_io(io_data *rc_io_data) (serialized_response []byte, err error) {
conn, err := net.Dial(global_options.to_network, global_options.to_address)
if err != nil {
return
}
defer conn.Close()
return simple_socket_io(&conn, io_data)
}

View File

@ -20,7 +20,7 @@ func Cut(s string, sep string) (string, string, bool) {
func ParseSocketAddress(spec string) (network string, addr string, err error) { func ParseSocketAddress(spec string) (network string, addr string, err error) {
network, addr, found := Cut(spec, ":") network, addr, found := Cut(spec, ":")
if !found { if !found {
err = fmt.Errorf("Invalid socket address: %s", spec) err = fmt.Errorf("Invalid socket address: %s must be prefix by a protocol such as unix:", spec)
return return
} }
if network == "unix" { if network == "unix" {