diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-07-19 14:15:48 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-07-19 14:15:48 -0400 |
commit | 7a489cb0011a34a68d3e77d0174076857cc37902 (patch) | |
tree | d21df8ea9b872ccc08cff117f203ad0d80b94a26 /lib/socket.go | |
parent | b3a66866b95d77f202f571efedd2f7ec309aacf5 (diff) | |
download | aerc-7a489cb0011a34a68d3e77d0174076857cc37902.tar.gz |
Add Unix socket for communicating with aerc
Diffstat (limited to 'lib/socket.go')
-rw-r--r-- | lib/socket.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/lib/socket.go b/lib/socket.go new file mode 100644 index 0000000..c256579 --- /dev/null +++ b/lib/socket.go @@ -0,0 +1,82 @@ +package lib + +import ( + "bufio" + "fmt" + "log" + "net" + "net/url" + "path" + "strings" + "sync/atomic" + "time" + + "github.com/kyoh86/xdg" +) + +type AercServer struct { + logger *log.Logger + listener net.Listener + OnMailto func(addr *url.URL) error +} + +func StartServer(logger *log.Logger) (*AercServer, error) { + sockpath := path.Join(xdg.RuntimeDir(), "aerc.sock") + l, err := net.Listen("unix", sockpath) + if err != nil { + return nil, err + } + as := &AercServer{ + logger: logger, + listener: l, + } + // TODO: stash clients and close them on exit... bleh racey + go func() { + for { + conn, err := l.Accept() + if err != nil { + // TODO: Something more useful, in some cases, on wednesdays, + // after 2 PM, I guess? + as.logger.Println("Closing Unix server: %v", err) + return + } + go as.handleClient(conn) + } + }() + return as, nil +} + +func (as *AercServer) Close() { + as.listener.Close() +} + +var lastId int64 = 0 // access via atomic + +func (as *AercServer) handleClient(conn net.Conn) { + clientId := atomic.AddInt64(&lastId, 1) + as.logger.Printf("Accepted Unix connection %d", clientId) + scanner := bufio.NewScanner(conn) + conn.SetDeadline(time.Now().Add(1 * time.Minute)) + for scanner.Scan() { + conn.SetDeadline(time.Now().Add(1 * time.Minute)) + msg := scanner.Text() + if !strings.ContainsRune(msg, ':') { + conn.Write([]byte("error: invalid command\n")) + } + as.logger.Printf("unix:%d: got message %s", clientId, msg) + prefix := msg[:strings.IndexRune(msg, ':')] + switch prefix { + case "mailto": + mailto, err := url.Parse(msg) + if err != nil { + conn.Write([]byte(fmt.Sprintf("error: %v\n", err))) + break + } + if as.OnMailto != nil { + err = as.OnMailto(mailto) + } + conn.Write([]byte(fmt.Sprintf("result: %v\n", err))) + } + } + as.logger.Printf("Closed Unix connection %d", clientId) +} |