Commit 05e457e1 authored by Jeromy's avatar Jeromy

create daemon listener for listening for user commands

parent 1fa7c07d
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()
}
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
}
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.")
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment