mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-02 23:08:07 +08:00
create daemon listener for listening for user commands
This commit is contained in:
parent
1fa7c07dc7
commit
05e457e197
107
daemon/daemon.go
Normal file
107
daemon/daemon.go
Normal file
@ -0,0 +1,107 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
|
||||
var ErrInvalidCommand = errors.New("invalid command")
|
||||
|
||||
type DaemonListener struct {
|
||||
list net.Listener
|
||||
CommChan chan *Command
|
||||
closed bool
|
||||
}
|
||||
|
||||
func NewDaemonListener(addr string) (*DaemonListener, error) {
|
||||
list, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DaemonListener{
|
||||
list: list,
|
||||
CommChan: make(chan *Command),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
command string
|
||||
args []string
|
||||
resp chan string
|
||||
}
|
||||
|
||||
func (dl *DaemonListener) Listen() {
|
||||
for {
|
||||
c, err := dl.list.Accept()
|
||||
if err != nil {
|
||||
if !dl.closed {
|
||||
u.PErr("DaemonListener Accept: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
go dl.handleConnection(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (dl *DaemonListener) handleConnection(c net.Conn) {
|
||||
dec := json.NewDecoder(c)
|
||||
enc := json.NewEncoder(c)
|
||||
var com string
|
||||
err := dec.Decode(&com)
|
||||
if err != nil {
|
||||
err := enc.Encode(err.Error())
|
||||
if err != nil {
|
||||
u.PErr("DaemonListener decode: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
u.DOut("Got command: %v\n", com)
|
||||
|
||||
cmd, err := parseCommand(com)
|
||||
if err != nil {
|
||||
err := enc.Encode(err.Error())
|
||||
if err != nil {
|
||||
u.PErr("DaemonListener parse: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case dl.CommChan <- cmd:
|
||||
default:
|
||||
u.PErr("Recieved command after closing...")
|
||||
return
|
||||
}
|
||||
|
||||
resp := <-cmd.resp
|
||||
err = enc.Encode(resp)
|
||||
if err != nil {
|
||||
u.PErr("handleConnection: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func parseCommand(cmdi string) (*Command, error) {
|
||||
params := strings.Split(cmdi, " ")
|
||||
if len(params) == 0 {
|
||||
return nil, ErrInvalidCommand
|
||||
}
|
||||
|
||||
//TODO: some sort of validation here
|
||||
|
||||
return &Command{
|
||||
command: params[0],
|
||||
args: params[1:],
|
||||
resp: make(chan string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (dl *DaemonListener) Close() error {
|
||||
dl.closed = true
|
||||
close(dl.CommChan)
|
||||
return dl.list.Close()
|
||||
}
|
||||
29
daemon/daemon_client.go
Normal file
29
daemon/daemon_client.go
Normal file
@ -0,0 +1,29 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
)
|
||||
|
||||
func SendCommand(command, server string) (string, error) {
|
||||
con, err := net.Dial("tcp", server)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(con)
|
||||
err = enc.Encode(command)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(con)
|
||||
|
||||
var resp string
|
||||
err = dec.Decode(&resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
70
daemon/daemon_test.go
Normal file
70
daemon/daemon_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommandCall(t *testing.T) {
|
||||
dl, err := NewDaemonListener("localhost:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go dl.Listen()
|
||||
defer dl.Close()
|
||||
|
||||
go func() {
|
||||
_, err := SendCommand("test command for fun", "localhost:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := <-dl.CommChan
|
||||
if cmd.command != "test" {
|
||||
t.Fatal("command parsing failed.")
|
||||
}
|
||||
|
||||
if cmd.args[0] != "command" ||
|
||||
cmd.args[1] != "for" ||
|
||||
cmd.args[2] != "fun" {
|
||||
t.Fatal("Args parsed incorrectly.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailures(t *testing.T) {
|
||||
dl, err := NewDaemonListener("localhost:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
go dl.Listen()
|
||||
defer dl.Close()
|
||||
|
||||
go func() {
|
||||
_, err := SendCommand("test", "localhost:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := <-dl.CommChan
|
||||
if cmd.command != "test" || len(cmd.args) > 0 {
|
||||
t.Fatal("Parsing Failed.")
|
||||
}
|
||||
|
||||
go func() {
|
||||
_, err := SendCommand("", "localhost:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
cmd = <-dl.CommChan
|
||||
if cmd.command != "" || len(cmd.args) > 0 {
|
||||
fmt.Println(cmd)
|
||||
t.Fatal("Parsing Failed.")
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user