diff options
author | Moritz Poldrack <git@moritz.sh> | 2023-03-04 10:56:45 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-03-07 00:12:47 +0100 |
commit | 4838efdb1d5a746432a30ef0b86b090aab52fa7a (patch) | |
tree | 10c1c6954e47395ae9b310ce268a77cf9924a4d8 /lib/ipc/receive.go | |
parent | 3dbf33bb4c8988851eeed0292fcdc170eb0ee6c7 (diff) | |
download | aerc-4838efdb1d5a746432a30ef0b86b090aab52fa7a.tar.gz |
ipc: change protocol to JSON
In overhauling the IPC, it has become necessary to switch to a more
extendable message format, to ensure more complex commands can be sent.
Messages have the following basic structure and must not contain
linebreaks, as these are used to delimit separate messages from one
another.
{"arguments": ["mailto:moritz@poldrack.dev"]}
The responses have the following structure:
{"error": "epic fail"}
If the IPC request was successful, "error" will be empty.
{"error": ""}
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'lib/ipc/receive.go')
-rw-r--r-- | lib/ipc/receive.go | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/lib/ipc/receive.go b/lib/ipc/receive.go index c074b116..11a96e30 100644 --- a/lib/ipc/receive.go +++ b/lib/ipc/receive.go @@ -3,7 +3,6 @@ package ipc import ( "bufio" "errors" - "fmt" "net" "net/url" "os" @@ -26,7 +25,7 @@ type AercServer struct { func StartServer() (*AercServer, error) { sockpath := path.Join(xdg.RuntimeDir(), "aerc.sock") // remove the socket if it is not connected to a session - if err := ConnectAndExec(""); err != nil { + if err := ConnectAndExec(nil); err != nil { os.Remove(sockpath) } log.Debugf("Starting Unix server: %s", sockpath) @@ -69,14 +68,25 @@ func (as *AercServer) Serve() { log.Errorf("unix:%d failed to set deadline: %v", clientId, err) } for scanner.Scan() { + // allow up to 1 minute between commands err = conn.SetDeadline(time.Now().Add(1 * time.Minute)) if err != nil { log.Errorf("unix:%d failed to update deadline: %v", clientId, err) } - msg := scanner.Text() - log.Tracef("unix:%d got message %s", clientId, msg) + msg, err := DecodeRequest(scanner.Bytes()) + log.Tracef("unix:%d got message %s", clientId, scanner.Text()) + if err != nil { + log.Errorf("unix:%d failed to parse request: %v", clientId, err) + continue + } - _, err = conn.Write([]byte(as.handleMessage(msg))) + response := as.handleMessage(msg) + result, err := response.Encode() + if err != nil { + log.Errorf("unix:%d failed to encode result: %v", clientId, err) + continue + } + _, err = conn.Write(append(result, '\n')) if err != nil { log.Errorf("unix:%d failed to send response: %v", clientId, err) break @@ -86,31 +96,30 @@ func (as *AercServer) Serve() { } } -func (as *AercServer) handleMessage(msg string) string { - if !strings.ContainsRune(msg, ':') { - return "error: invalid command\n" +func (as *AercServer) handleMessage(req *Request) *Response { + if len(req.Arguments) == 0 { + return &Response{} // send noop success message, i.e. ping } - prefix := msg[:strings.IndexRune(msg, ':')] var err error - switch prefix { - case "mailto": - mailto, err := url.Parse(msg) + switch { + case strings.HasPrefix(req.Arguments[0], "mailto:"): + mailto, err := url.Parse(req.Arguments[0]) if err != nil { - return fmt.Sprintf("error: %v\n", err) + return &Response{Error: err.Error()} } - if as.OnMailto != nil { - err = as.OnMailto(mailto) - if err != nil { - return fmt.Sprintf("mailto failed: %v\n", err) + err = as.OnMailto(mailto) + if err != nil { + return &Response{ + Error: err.Error(), } } - case "mbox": - if as.OnMbox != nil { - err = as.OnMbox(msg) - if err != nil { - return fmt.Sprintf("mbox failed: %v\n", err) - } + case strings.HasPrefix(req.Arguments[0], "mbox:"): + err = as.OnMbox(req.Arguments[0]) + if err != nil { + return &Response{Error: err.Error()} } + default: + return &Response{Error: "command not understood"} } - return "result: success\n" + return &Response{} } |