Implement socket I/O
This commit is contained in:
parent
a960937095
commit
b2e610f9b1
@ -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
82
tools/cmd/at/socket_io.go
Normal 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)
|
||||||
|
}
|
||||||
@ -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" {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user