forked from koding/kite
/
handlers.go
123 lines (104 loc) · 3.19 KB
/
handlers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package kite
import (
"fmt"
"net/http"
"net/url"
"os/exec"
"runtime"
"time"
"code.google.com/p/go.crypto/ssh/terminal"
"github.com/gorilla/websocket"
"github.com/koding/kite/sockjsclient"
"github.com/koding/kite/systeminfo"
)
func (k *Kite) addDefaultHandlers() {
k.HandleFunc("kite.systemInfo", systemInfo)
k.HandleFunc("kite.heartbeat", k.handleHeartbeat)
k.HandleFunc("kite.ping", handlePing).DisableAuthentication()
k.HandleFunc("kite.tunnel", handleTunnel)
k.HandleFunc("kite.log", k.handleLog)
k.HandleFunc("kite.print", handlePrint)
k.HandleFunc("kite.prompt", handlePrompt)
k.HandleFunc("kite.getPass", handleGetPass)
if runtime.GOOS == "darwin" {
k.HandleFunc("kite.notify", handleNotifyDarwin)
}
}
// systemInfo returns info about the system (CPU, memory, disk...).
func systemInfo(r *Request) (interface{}, error) {
return systeminfo.New()
}
// handleHeartbeat pings the callback with the given interval seconds.
func (k *Kite) handleHeartbeat(r *Request) (interface{}, error) {
args := r.Args.MustSliceOfLength(2)
seconds := args[0].MustFloat64()
ping := args[1].MustFunction()
go func() {
for {
time.Sleep(time.Duration(seconds) * time.Second)
if err := ping.Call(); err != nil {
return
}
}
}()
return nil, nil
}
// handleLog prints a log message to stderr.
func (k *Kite) handleLog(r *Request) (interface{}, error) {
msg := r.Args.One().MustString()
k.Log.Info(fmt.Sprintf("%s: %s", r.Client.Name, msg))
return nil, nil
}
//handlePing returns a simple "pong" string
func handlePing(r *Request) (interface{}, error) {
return "pong", nil
}
// handlePrint prints a message to stdout.
func handlePrint(r *Request) (interface{}, error) {
return fmt.Print(r.Args.One().MustString())
}
// handlePrompt asks user a single line input.
func handlePrompt(r *Request) (interface{}, error) {
fmt.Print(r.Args.One().MustString())
var s string
_, err := fmt.Scanln(&s)
return s, err
}
// handleGetPass reads a line of input from a terminal without local echo.
func handleGetPass(r *Request) (interface{}, error) {
fmt.Print(r.Args.One().MustString())
data, err := terminal.ReadPassword(0) // stdin
fmt.Println()
if err != nil {
return nil, err
}
return string(data), nil
}
// handleNotifyDarwin displays a desktop notification on OS X.
func handleNotifyDarwin(r *Request) (interface{}, error) {
args := r.Args.MustSliceOfLength(3)
cmd := exec.Command("osascript", "-e", fmt.Sprintf("display notification \"%s\" with title \"%s\" subtitle \"%s\"",
args[1].MustString(), args[2].MustString(), args[0].MustString()))
return nil, cmd.Start()
}
// handleTunnel opens two websockets, one to proxy kite and one to itself,
// then it copies the message between them.
func handleTunnel(r *Request) (interface{}, error) {
var args struct {
URL string
}
r.Args.One().MustUnmarshal(&args)
parsed, err := url.Parse(args.URL)
if err != nil {
return nil, err
}
requestHeader := http.Header{}
requestHeader.Add("Origin", "http://"+parsed.Host)
remoteConn, _, err := websocket.DefaultDialer.Dial(parsed.String(), requestHeader)
if err != nil {
return nil, err
}
session := sockjsclient.NewWebsocketSession(remoteConn)
go r.LocalKite.sockjsHandler(session)
return nil, nil
}