OSDN Git Service

fix commands
[bytom/shuttle.git] / vendor / github.com / bytom / vendor / github.com / gorilla / websocket / examples / command / main.go
diff --git a/vendor/github.com/bytom/vendor/github.com/gorilla/websocket/examples/command/main.go b/vendor/github.com/bytom/vendor/github.com/gorilla/websocket/examples/command/main.go
new file mode 100644 (file)
index 0000000..304f1a5
--- /dev/null
@@ -0,0 +1,193 @@
+// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bufio"
+       "flag"
+       "io"
+       "log"
+       "net/http"
+       "os"
+       "os/exec"
+       "time"
+
+       "github.com/gorilla/websocket"
+)
+
+var (
+       addr    = flag.String("addr", "127.0.0.1:8080", "http service address")
+       cmdPath string
+)
+
+const (
+       // Time allowed to write a message to the peer.
+       writeWait = 10 * time.Second
+
+       // Maximum message size allowed from peer.
+       maxMessageSize = 8192
+
+       // Time allowed to read the next pong message from the peer.
+       pongWait = 60 * time.Second
+
+       // Send pings to peer with this period. Must be less than pongWait.
+       pingPeriod = (pongWait * 9) / 10
+
+       // Time to wait before force close on connection.
+       closeGracePeriod = 10 * time.Second
+)
+
+func pumpStdin(ws *websocket.Conn, w io.Writer) {
+       defer ws.Close()
+       ws.SetReadLimit(maxMessageSize)
+       ws.SetReadDeadline(time.Now().Add(pongWait))
+       ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
+       for {
+               _, message, err := ws.ReadMessage()
+               if err != nil {
+                       break
+               }
+               message = append(message, '\n')
+               if _, err := w.Write(message); err != nil {
+                       break
+               }
+       }
+}
+
+func pumpStdout(ws *websocket.Conn, r io.Reader, done chan struct{}) {
+       defer func() {
+       }()
+       s := bufio.NewScanner(r)
+       for s.Scan() {
+               ws.SetWriteDeadline(time.Now().Add(writeWait))
+               if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
+                       ws.Close()
+                       break
+               }
+       }
+       if s.Err() != nil {
+               log.Println("scan:", s.Err())
+       }
+       close(done)
+
+       ws.SetWriteDeadline(time.Now().Add(writeWait))
+       ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+       time.Sleep(closeGracePeriod)
+       ws.Close()
+}
+
+func ping(ws *websocket.Conn, done chan struct{}) {
+       ticker := time.NewTicker(pingPeriod)
+       defer ticker.Stop()
+       for {
+               select {
+               case <-ticker.C:
+                       if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
+                               log.Println("ping:", err)
+                       }
+               case <-done:
+                       return
+               }
+       }
+}
+
+func internalError(ws *websocket.Conn, msg string, err error) {
+       log.Println(msg, err)
+       ws.WriteMessage(websocket.TextMessage, []byte("Internal server error."))
+}
+
+var upgrader = websocket.Upgrader{}
+
+func serveWs(w http.ResponseWriter, r *http.Request) {
+       ws, err := upgrader.Upgrade(w, r, nil)
+       if err != nil {
+               log.Println("upgrade:", err)
+               return
+       }
+
+       defer ws.Close()
+
+       outr, outw, err := os.Pipe()
+       if err != nil {
+               internalError(ws, "stdout:", err)
+               return
+       }
+       defer outr.Close()
+       defer outw.Close()
+
+       inr, inw, err := os.Pipe()
+       if err != nil {
+               internalError(ws, "stdin:", err)
+               return
+       }
+       defer inr.Close()
+       defer inw.Close()
+
+       proc, err := os.StartProcess(cmdPath, flag.Args(), &os.ProcAttr{
+               Files: []*os.File{inr, outw, outw},
+       })
+       if err != nil {
+               internalError(ws, "start:", err)
+               return
+       }
+
+       inr.Close()
+       outw.Close()
+
+       stdoutDone := make(chan struct{})
+       go pumpStdout(ws, outr, stdoutDone)
+       go ping(ws, stdoutDone)
+
+       pumpStdin(ws, inw)
+
+       // Some commands will exit when stdin is closed.
+       inw.Close()
+
+       // Other commands need a bonk on the head.
+       if err := proc.Signal(os.Interrupt); err != nil {
+               log.Println("inter:", err)
+       }
+
+       select {
+       case <-stdoutDone:
+       case <-time.After(time.Second):
+               // A bigger bonk on the head.
+               if err := proc.Signal(os.Kill); err != nil {
+                       log.Println("term:", err)
+               }
+               <-stdoutDone
+       }
+
+       if _, err := proc.Wait(); err != nil {
+               log.Println("wait:", err)
+       }
+}
+
+func serveHome(w http.ResponseWriter, r *http.Request) {
+       if r.URL.Path != "/" {
+               http.Error(w, "Not found", http.StatusNotFound)
+               return
+       }
+       if r.Method != "GET" {
+               http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+               return
+       }
+       http.ServeFile(w, r, "home.html")
+}
+
+func main() {
+       flag.Parse()
+       if len(flag.Args()) < 1 {
+               log.Fatal("must specify at least one argument")
+       }
+       var err error
+       cmdPath, err = exec.LookPath(flag.Args()[0])
+       if err != nil {
+               log.Fatal(err)
+       }
+       http.HandleFunc("/", serveHome)
+       http.HandleFunc("/ws", serveWs)
+       log.Fatal(http.ListenAndServe(*addr, nil))
+}