@cryptotaxi247 / kubo / commits / 05e457e19

create daemon listener for listening for user commands

Jeromy committed Sep 8, 2014 at 18:21 UTC 05e457e197539bb24947fc95fa0e99db61d69102
3 files changed +206
daemon/daemon.go new
+107
@@ -0,0 +1,107 @@
1 +package daemon
2 +
3 +import (
4 + "encoding/json"
5 + "errors"
6 + "net"
7 + "strings"
8 +
9 + u "github.com/jbenet/go-ipfs/util"
10 +)
11 +
12 +var ErrInvalidCommand = errors.New("invalid command")
13 +
14 +type DaemonListener struct {
15 + list net.Listener
16 + CommChan chan *Command
17 + closed bool
18 +}
19 +
20 +func NewDaemonListener(addr string) (*DaemonListener, error) {
21 + list, err := net.Listen("tcp", addr)
22 + if err != nil {
23 + return nil, err
24 + }
25 +
26 + return &DaemonListener{
27 + list: list,
28 + CommChan: make(chan *Command),
29 + }, nil
30 +}
31 +
32 +type Command struct {
33 + command string
34 + args []string
35 + resp chan string
36 +}
37 +
38 +func (dl *DaemonListener) Listen() {
39 + for {
40 + c, err := dl.list.Accept()
41 + if err != nil {
42 + if !dl.closed {
43 + u.PErr("DaemonListener Accept: %v\n", err)
44 + }
45 + return
46 + }
47 + go dl.handleConnection(c)
48 + }
49 +}
50 +
51 +func (dl *DaemonListener) handleConnection(c net.Conn) {
52 + dec := json.NewDecoder(c)
53 + enc := json.NewEncoder(c)
54 + var com string
55 + err := dec.Decode(&com)
56 + if err != nil {
57 + err := enc.Encode(err.Error())
58 + if err != nil {
59 + u.PErr("DaemonListener decode: %v\n", err)
60 + }
61 + return
62 + }
63 + u.DOut("Got command: %v\n", com)
64 +
65 + cmd, err := parseCommand(com)
66 + if err != nil {
67 + err := enc.Encode(err.Error())
68 + if err != nil {
69 + u.PErr("DaemonListener parse: %v\n", err)
70 + }
71 + return
72 + }
73 +
74 + select {
75 + case dl.CommChan <- cmd:
76 + default:
77 + u.PErr("Recieved command after closing...")
78 + return
79 + }
80 +
81 + resp := <-cmd.resp
82 + err = enc.Encode(resp)
83 + if err != nil {
84 + u.PErr("handleConnection: %v\n", err)
85 + }
86 +}
87 +
88 +func parseCommand(cmdi string) (*Command, error) {
89 + params := strings.Split(cmdi, " ")
90 + if len(params) == 0 {
91 + return nil, ErrInvalidCommand
92 + }
93 +
94 + //TODO: some sort of validation here
95 +
96 + return &Command{
97 + command: params[0],
98 + args: params[1:],
99 + resp: make(chan string),
100 + }, nil
101 +}
102 +
103 +func (dl *DaemonListener) Close() error {
104 + dl.closed = true
105 + close(dl.CommChan)
106 + return dl.list.Close()
107 +}
daemon/daemon_client.go new
+29
@@ -0,0 +1,29 @@
1 +package daemon
2 +
3 +import (
4 + "encoding/json"
5 + "net"
6 +)
7 +
8 +func SendCommand(command, server string) (string, error) {
9 + con, err := net.Dial("tcp", server)
10 + if err != nil {
11 + return "", err
12 + }
13 +
14 + enc := json.NewEncoder(con)
15 + err = enc.Encode(command)
16 + if err != nil {
17 + return "", err
18 + }
19 +
20 + dec := json.NewDecoder(con)
21 +
22 + var resp string
23 + err = dec.Decode(&resp)
24 + if err != nil {
25 + return "", err
26 + }
27 +
28 + return resp, nil
29 +}
daemon/daemon_test.go new
+70
@@ -0,0 +1,70 @@
1 +package daemon
2 +
3 +import (
4 + "fmt"
5 + "testing"
6 +)
7 +
8 +func TestCommandCall(t *testing.T) {
9 + dl, err := NewDaemonListener("localhost:12345")
10 + if err != nil {
11 + t.Fatal(err)
12 + }
13 +
14 + go dl.Listen()
15 + defer dl.Close()
16 +
17 + go func() {
18 + _, err := SendCommand("test command for fun", "localhost:12345")
19 + if err != nil {
20 + t.Fatal(err)
21 + }
22 + }()
23 +
24 + cmd := <-dl.CommChan
25 + if cmd.command != "test" {
26 + t.Fatal("command parsing failed.")
27 + }
28 +
29 + if cmd.args[0] != "command" ||
30 + cmd.args[1] != "for" ||
31 + cmd.args[2] != "fun" {
32 + t.Fatal("Args parsed incorrectly.")
33 + }
34 +}
35 +
36 +func TestFailures(t *testing.T) {
37 + dl, err := NewDaemonListener("localhost:12345")
38 + if err != nil {
39 + t.Fatal(err)
40 + }
41 +
42 + go dl.Listen()
43 + defer dl.Close()
44 +
45 + go func() {
46 + _, err := SendCommand("test", "localhost:12345")
47 + if err != nil {
48 + t.Fatal(err)
49 + }
50 + }()
51 +
52 + cmd := <-dl.CommChan
53 + if cmd.command != "test" || len(cmd.args) > 0 {
54 + t.Fatal("Parsing Failed.")
55 + }
56 +
57 + go func() {
58 + _, err := SendCommand("", "localhost:12345")
59 + if err != nil {
60 + t.Fatal(err)
61 + }
62 + }()
63 +
64 + cmd = <-dl.CommChan
65 + if cmd.command != "" || len(cmd.args) > 0 {
66 + fmt.Println(cmd)
67 + t.Fatal("Parsing Failed.")
68 + }
69 +
70 +}