summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/gorilla/websocket/examples
diff options
context:
space:
mode:
authorWim <wim@42.be>2016-04-10 23:39:38 +0200
committerWim <wim@42.be>2016-04-10 23:39:38 +0200
commitde4c7804101a47a01d0c9b88ea34d2b153e2b6b9 (patch)
treefa379bc2e706951a913e0c7009d9906e42363655 /vendor/github.com/gorilla/websocket/examples
parent6b18257185b1830bd2eff83fae30bdd2055f78b0 (diff)
downloadmatterbridge-msglm-de4c7804101a47a01d0c9b88ea34d2b153e2b6b9.tar.gz
matterbridge-msglm-de4c7804101a47a01d0c9b88ea34d2b153e2b6b9.tar.bz2
matterbridge-msglm-de4c7804101a47a01d0c9b88ea34d2b153e2b6b9.zip
Vendor libs
Diffstat (limited to 'vendor/github.com/gorilla/websocket/examples')
-rw-r--r--vendor/github.com/gorilla/websocket/examples/autobahn/server.go246
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/conn.go105
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/hub.go51
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/main.go39
-rw-r--r--vendor/github.com/gorilla/websocket/examples/command/main.go188
-rw-r--r--vendor/github.com/gorilla/websocket/examples/echo/client.go81
-rw-r--r--vendor/github.com/gorilla/websocket/examples/echo/server.go132
-rw-r--r--vendor/github.com/gorilla/websocket/examples/filewatch/main.go193
8 files changed, 1035 insertions, 0 deletions
diff --git a/vendor/github.com/gorilla/websocket/examples/autobahn/server.go b/vendor/github.com/gorilla/websocket/examples/autobahn/server.go
new file mode 100644
index 00000000..d96ac84d
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/autobahn/server.go
@@ -0,0 +1,246 @@
+// Copyright 2013 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.
+
+// Command server is a test server for the Autobahn WebSockets Test Suite.
+package main
+
+import (
+ "errors"
+ "flag"
+ "github.com/gorilla/websocket"
+ "io"
+ "log"
+ "net/http"
+ "time"
+ "unicode/utf8"
+)
+
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 4096,
+ WriteBufferSize: 4096,
+ CheckOrigin: func(r *http.Request) bool {
+ return true
+ },
+}
+
+// echoCopy echoes messages from the client using io.Copy.
+func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
+ conn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Println("Upgrade:", err)
+ return
+ }
+ defer conn.Close()
+ for {
+ mt, r, err := conn.NextReader()
+ if err != nil {
+ if err != io.EOF {
+ log.Println("NextReader:", err)
+ }
+ return
+ }
+ if mt == websocket.TextMessage {
+ r = &validator{r: r}
+ }
+ w, err := conn.NextWriter(mt)
+ if err != nil {
+ log.Println("NextWriter:", err)
+ return
+ }
+ if mt == websocket.TextMessage {
+ r = &validator{r: r}
+ }
+ if writerOnly {
+ _, err = io.Copy(struct{ io.Writer }{w}, r)
+ } else {
+ _, err = io.Copy(w, r)
+ }
+ if err != nil {
+ if err == errInvalidUTF8 {
+ conn.WriteControl(websocket.CloseMessage,
+ websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
+ time.Time{})
+ }
+ log.Println("Copy:", err)
+ return
+ }
+ err = w.Close()
+ if err != nil {
+ log.Println("Close:", err)
+ return
+ }
+ }
+}
+
+func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
+ echoCopy(w, r, true)
+}
+
+func echoCopyFull(w http.ResponseWriter, r *http.Request) {
+ echoCopy(w, r, false)
+}
+
+// echoReadAll echoes messages from the client by reading the entire message
+// with ioutil.ReadAll.
+func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
+ conn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Println("Upgrade:", err)
+ return
+ }
+ defer conn.Close()
+ for {
+ mt, b, err := conn.ReadMessage()
+ if err != nil {
+ if err != io.EOF {
+ log.Println("NextReader:", err)
+ }
+ return
+ }
+ if mt == websocket.TextMessage {
+ if !utf8.Valid(b) {
+ conn.WriteControl(websocket.CloseMessage,
+ websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
+ time.Time{})
+ log.Println("ReadAll: invalid utf8")
+ }
+ }
+ if writeMessage {
+ err = conn.WriteMessage(mt, b)
+ if err != nil {
+ log.Println("WriteMessage:", err)
+ }
+ } else {
+ w, err := conn.NextWriter(mt)
+ if err != nil {
+ log.Println("NextWriter:", err)
+ return
+ }
+ if _, err := w.Write(b); err != nil {
+ log.Println("Writer:", err)
+ return
+ }
+ if err := w.Close(); err != nil {
+ log.Println("Close:", err)
+ return
+ }
+ }
+ }
+}
+
+func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
+ echoReadAll(w, r, false)
+}
+
+func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
+ echoReadAll(w, r, true)
+}
+
+func serveHome(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.Error(w, "Not found.", 404)
+ return
+ }
+ if r.Method != "GET" {
+ http.Error(w, "Method not allowed", 405)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ io.WriteString(w, "<html><body>Echo Server</body></html>")
+}
+
+var addr = flag.String("addr", ":9000", "http service address")
+
+func main() {
+ flag.Parse()
+ http.HandleFunc("/", serveHome)
+ http.HandleFunc("/c", echoCopyWriterOnly)
+ http.HandleFunc("/f", echoCopyFull)
+ http.HandleFunc("/r", echoReadAllWriter)
+ http.HandleFunc("/m", echoReadAllWriteMessage)
+ err := http.ListenAndServe(*addr, nil)
+ if err != nil {
+ log.Fatal("ListenAndServe: ", err)
+ }
+}
+
+type validator struct {
+ state int
+ x rune
+ r io.Reader
+}
+
+var errInvalidUTF8 = errors.New("invalid utf8")
+
+func (r *validator) Read(p []byte) (int, error) {
+ n, err := r.r.Read(p)
+ state := r.state
+ x := r.x
+ for _, b := range p[:n] {
+ state, x = decode(state, x, b)
+ if state == utf8Reject {
+ break
+ }
+ }
+ r.state = state
+ r.x = x
+ if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
+ return n, errInvalidUTF8
+ }
+ return n, err
+}
+
+// UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+//
+// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+var utf8d = [...]byte{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
+ 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
+ 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
+ 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
+ 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+ 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+ 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+ 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
+}
+
+const (
+ utf8Accept = 0
+ utf8Reject = 1
+)
+
+func decode(state int, x rune, b byte) (int, rune) {
+ t := utf8d[b]
+ if state != utf8Accept {
+ x = rune(b&0x3f) | (x << 6)
+ } else {
+ x = rune((0xff >> t) & b)
+ }
+ state = int(utf8d[256+state*16+int(t)])
+ return state, x
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/conn.go b/vendor/github.com/gorilla/websocket/examples/chat/conn.go
new file mode 100644
index 00000000..40fd38c2
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/chat/conn.go
@@ -0,0 +1,105 @@
+// Copyright 2013 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 (
+ "github.com/gorilla/websocket"
+ "log"
+ "net/http"
+ "time"
+)
+
+const (
+ // Time allowed to write a message to the peer.
+ writeWait = 10 * time.Second
+
+ // 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
+
+ // Maximum message size allowed from peer.
+ maxMessageSize = 512
+)
+
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+}
+
+// connection is an middleman between the websocket connection and the hub.
+type connection struct {
+ // The websocket connection.
+ ws *websocket.Conn
+
+ // Buffered channel of outbound messages.
+ send chan []byte
+}
+
+// readPump pumps messages from the websocket connection to the hub.
+func (c *connection) readPump() {
+ defer func() {
+ h.unregister <- c
+ c.ws.Close()
+ }()
+ c.ws.SetReadLimit(maxMessageSize)
+ c.ws.SetReadDeadline(time.Now().Add(pongWait))
+ c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
+ for {
+ _, message, err := c.ws.ReadMessage()
+ if err != nil {
+ if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
+ log.Printf("error: %v", err)
+ }
+ break
+ }
+ h.broadcast <- message
+ }
+}
+
+// write writes a message with the given message type and payload.
+func (c *connection) write(mt int, payload []byte) error {
+ c.ws.SetWriteDeadline(time.Now().Add(writeWait))
+ return c.ws.WriteMessage(mt, payload)
+}
+
+// writePump pumps messages from the hub to the websocket connection.
+func (c *connection) writePump() {
+ ticker := time.NewTicker(pingPeriod)
+ defer func() {
+ ticker.Stop()
+ c.ws.Close()
+ }()
+ for {
+ select {
+ case message, ok := <-c.send:
+ if !ok {
+ c.write(websocket.CloseMessage, []byte{})
+ return
+ }
+ if err := c.write(websocket.TextMessage, message); err != nil {
+ return
+ }
+ case <-ticker.C:
+ if err := c.write(websocket.PingMessage, []byte{}); err != nil {
+ return
+ }
+ }
+ }
+}
+
+// serveWs handles websocket requests from the peer.
+func serveWs(w http.ResponseWriter, r *http.Request) {
+ ws, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ c := &connection{send: make(chan []byte, 256), ws: ws}
+ h.register <- c
+ go c.writePump()
+ c.readPump()
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/hub.go b/vendor/github.com/gorilla/websocket/examples/chat/hub.go
new file mode 100644
index 00000000..449ba753
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/chat/hub.go
@@ -0,0 +1,51 @@
+// Copyright 2013 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
+
+// hub maintains the set of active connections and broadcasts messages to the
+// connections.
+type hub struct {
+ // Registered connections.
+ connections map[*connection]bool
+
+ // Inbound messages from the connections.
+ broadcast chan []byte
+
+ // Register requests from the connections.
+ register chan *connection
+
+ // Unregister requests from connections.
+ unregister chan *connection
+}
+
+var h = hub{
+ broadcast: make(chan []byte),
+ register: make(chan *connection),
+ unregister: make(chan *connection),
+ connections: make(map[*connection]bool),
+}
+
+func (h *hub) run() {
+ for {
+ select {
+ case c := <-h.register:
+ h.connections[c] = true
+ case c := <-h.unregister:
+ if _, ok := h.connections[c]; ok {
+ delete(h.connections, c)
+ close(c.send)
+ }
+ case m := <-h.broadcast:
+ for c := range h.connections {
+ select {
+ case c.send <- m:
+ default:
+ close(c.send)
+ delete(h.connections, c)
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/main.go b/vendor/github.com/gorilla/websocket/examples/chat/main.go
new file mode 100644
index 00000000..3c4448d7
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/chat/main.go
@@ -0,0 +1,39 @@
+// Copyright 2013 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 (
+ "flag"
+ "log"
+ "net/http"
+ "text/template"
+)
+
+var addr = flag.String("addr", ":8080", "http service address")
+var homeTempl = template.Must(template.ParseFiles("home.html"))
+
+func serveHome(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.Error(w, "Not found", 404)
+ return
+ }
+ if r.Method != "GET" {
+ http.Error(w, "Method not allowed", 405)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ homeTempl.Execute(w, r.Host)
+}
+
+func main() {
+ flag.Parse()
+ go h.run()
+ http.HandleFunc("/", serveHome)
+ http.HandleFunc("/ws", serveWs)
+ err := http.ListenAndServe(*addr, nil)
+ if err != nil {
+ log.Fatal("ListenAndServe: ", err)
+ }
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/command/main.go b/vendor/github.com/gorilla/websocket/examples/command/main.go
new file mode 100644
index 00000000..f3f022ed
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/command/main.go
@@ -0,0 +1,188 @@
+// 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"
+ "text/template"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+var (
+ addr = flag.String("addr", "127.0.0.1:8080", "http service address")
+ cmdPath string
+ homeTempl = template.Must(template.ParseFiles("home.html"))
+)
+
+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
+)
+
+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() {
+ ws.Close()
+ close(done)
+ }()
+ s := bufio.NewScanner(r)
+ for s.Scan() {
+ ws.SetWriteDeadline(time.Now().Add(writeWait))
+ if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
+ break
+ }
+ }
+ if s.Err() != nil {
+ log.Println("scan:", s.Err())
+ }
+}
+
+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", 404)
+ return
+ }
+ if r.Method != "GET" {
+ http.Error(w, "Method not allowed", 405)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ homeTempl.Execute(w, r.Host)
+}
+
+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))
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/echo/client.go b/vendor/github.com/gorilla/websocket/examples/echo/client.go
new file mode 100644
index 00000000..6578094e
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/echo/client.go
@@ -0,0 +1,81 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+ "flag"
+ "log"
+ "net/url"
+ "os"
+ "os/signal"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+var addr = flag.String("addr", "localhost:8080", "http service address")
+
+func main() {
+ flag.Parse()
+ log.SetFlags(0)
+
+ interrupt := make(chan os.Signal, 1)
+ signal.Notify(interrupt, os.Interrupt)
+
+ u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
+ log.Printf("connecting to %s", u.String())
+
+ c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
+ if err != nil {
+ log.Fatal("dial:", err)
+ }
+ defer c.Close()
+
+ done := make(chan struct{})
+
+ go func() {
+ defer c.Close()
+ defer close(done)
+ for {
+ _, message, err := c.ReadMessage()
+ if err != nil {
+ log.Println("read:", err)
+ return
+ }
+ log.Printf("recv: %s", message)
+ }
+ }()
+
+ ticker := time.NewTicker(time.Second)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case t := <-ticker.C:
+ err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
+ if err != nil {
+ log.Println("write:", err)
+ return
+ }
+ case <-interrupt:
+ log.Println("interrupt")
+ // To cleanly close a connection, a client should send a close
+ // frame and wait for the server to close the connection.
+ err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+ if err != nil {
+ log.Println("write close:", err)
+ return
+ }
+ select {
+ case <-done:
+ case <-time.After(time.Second):
+ }
+ c.Close()
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/echo/server.go b/vendor/github.com/gorilla/websocket/examples/echo/server.go
new file mode 100644
index 00000000..a685b097
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/echo/server.go
@@ -0,0 +1,132 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+ "flag"
+ "html/template"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/websocket"
+)
+
+var addr = flag.String("addr", "localhost:8080", "http service address")
+
+var upgrader = websocket.Upgrader{} // use default options
+
+func echo(w http.ResponseWriter, r *http.Request) {
+ c, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Print("upgrade:", err)
+ return
+ }
+ defer c.Close()
+ for {
+ mt, message, err := c.ReadMessage()
+ if err != nil {
+ log.Println("read:", err)
+ break
+ }
+ log.Printf("recv: %s", message)
+ err = c.WriteMessage(mt, message)
+ if err != nil {
+ log.Println("write:", err)
+ break
+ }
+ }
+}
+
+func home(w http.ResponseWriter, r *http.Request) {
+ homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
+}
+
+func main() {
+ flag.Parse()
+ log.SetFlags(0)
+ http.HandleFunc("/echo", echo)
+ http.HandleFunc("/", home)
+ log.Fatal(http.ListenAndServe(*addr, nil))
+}
+
+var homeTemplate = template.Must(template.New("").Parse(`
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<script>
+window.addEventListener("load", function(evt) {
+
+ var output = document.getElementById("output");
+ var input = document.getElementById("input");
+ var ws;
+
+ var print = function(message) {
+ var d = document.createElement("div");
+ d.innerHTML = message;
+ output.appendChild(d);
+ };
+
+ document.getElementById("open").onclick = function(evt) {
+ if (ws) {
+ return false;
+ }
+ ws = new WebSocket("{{.}}");
+ ws.onopen = function(evt) {
+ print("OPEN");
+ }
+ ws.onclose = function(evt) {
+ print("CLOSE");
+ ws = null;
+ }
+ ws.onmessage = function(evt) {
+ print("RESPONSE: " + evt.data);
+ }
+ ws.onerror = function(evt) {
+ print("ERROR: " + evt.data);
+ }
+ return false;
+ };
+
+ document.getElementById("send").onclick = function(evt) {
+ if (!ws) {
+ return false;
+ }
+ print("SEND: " + input.value);
+ ws.send(input.value);
+ return false;
+ };
+
+ document.getElementById("close").onclick = function(evt) {
+ if (!ws) {
+ return false;
+ }
+ ws.close();
+ return false;
+ };
+
+});
+</script>
+</head>
+<body>
+<table>
+<tr><td valign="top" width="50%">
+<p>Click "Open" to create a connection to the server,
+"Send" to send a message to the server and "Close" to close the connection.
+You can change the message and send multiple times.
+<p>
+<form>
+<button id="open">Open</button>
+<button id="close">Close</button>
+<p><input id="input" type="text" value="Hello world!">
+<button id="send">Send</button>
+</form>
+</td><td valign="top" width="50%">
+<div id="output"></div>
+</td></tr></table>
+</body>
+</html>
+`))
diff --git a/vendor/github.com/gorilla/websocket/examples/filewatch/main.go b/vendor/github.com/gorilla/websocket/examples/filewatch/main.go
new file mode 100644
index 00000000..a2c7b85f
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/filewatch/main.go
@@ -0,0 +1,193 @@
+// Copyright 2013 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 (
+ "flag"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "strconv"
+ "text/template"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+const (
+ // Time allowed to write the file to the client.
+ writeWait = 10 * time.Second
+
+ // Time allowed to read the next pong message from the client.
+ pongWait = 60 * time.Second
+
+ // Send pings to client with this period. Must be less than pongWait.
+ pingPeriod = (pongWait * 9) / 10
+
+ // Poll file for changes with this period.
+ filePeriod = 10 * time.Second
+)
+
+var (
+ addr = flag.String("addr", ":8080", "http service address")
+ homeTempl = template.Must(template.New("").Parse(homeHTML))
+ filename string
+ upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+ }
+)
+
+func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) {
+ fi, err := os.Stat(filename)
+ if err != nil {
+ return nil, lastMod, err
+ }
+ if !fi.ModTime().After(lastMod) {
+ return nil, lastMod, nil
+ }
+ p, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, fi.ModTime(), err
+ }
+ return p, fi.ModTime(), nil
+}
+
+func reader(ws *websocket.Conn) {
+ defer ws.Close()
+ ws.SetReadLimit(512)
+ ws.SetReadDeadline(time.Now().Add(pongWait))
+ ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
+ for {
+ _, _, err := ws.ReadMessage()
+ if err != nil {
+ break
+ }
+ }
+}
+
+func writer(ws *websocket.Conn, lastMod time.Time) {
+ lastError := ""
+ pingTicker := time.NewTicker(pingPeriod)
+ fileTicker := time.NewTicker(filePeriod)
+ defer func() {
+ pingTicker.Stop()
+ fileTicker.Stop()
+ ws.Close()
+ }()
+ for {
+ select {
+ case <-fileTicker.C:
+ var p []byte
+ var err error
+
+ p, lastMod, err = readFileIfModified(lastMod)
+
+ if err != nil {
+ if s := err.Error(); s != lastError {
+ lastError = s
+ p = []byte(lastError)
+ }
+ } else {
+ lastError = ""
+ }
+
+ if p != nil {
+ ws.SetWriteDeadline(time.Now().Add(writeWait))
+ if err := ws.WriteMessage(websocket.TextMessage, p); err != nil {
+ return
+ }
+ }
+ case <-pingTicker.C:
+ ws.SetWriteDeadline(time.Now().Add(writeWait))
+ if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
+ return
+ }
+ }
+ }
+}
+
+func serveWs(w http.ResponseWriter, r *http.Request) {
+ ws, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ if _, ok := err.(websocket.HandshakeError); !ok {
+ log.Println(err)
+ }
+ return
+ }
+
+ var lastMod time.Time
+ if n, err := strconv.ParseInt(r.FormValue("lastMod"), 16, 64); err != nil {
+ lastMod = time.Unix(0, n)
+ }
+
+ go writer(ws, lastMod)
+ reader(ws)
+}
+
+func serveHome(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.Error(w, "Not found", 404)
+ return
+ }
+ if r.Method != "GET" {
+ http.Error(w, "Method not allowed", 405)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ p, lastMod, err := readFileIfModified(time.Time{})
+ if err != nil {
+ p = []byte(err.Error())
+ lastMod = time.Unix(0, 0)
+ }
+ var v = struct {
+ Host string
+ Data string
+ LastMod string
+ }{
+ r.Host,
+ string(p),
+ strconv.FormatInt(lastMod.UnixNano(), 16),
+ }
+ homeTempl.Execute(w, &v)
+}
+
+func main() {
+ flag.Parse()
+ if flag.NArg() != 1 {
+ log.Fatal("filename not specified")
+ }
+ filename = flag.Args()[0]
+ http.HandleFunc("/", serveHome)
+ http.HandleFunc("/ws", serveWs)
+ if err := http.ListenAndServe(*addr, nil); err != nil {
+ log.Fatal(err)
+ }
+}
+
+const homeHTML = `<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>WebSocket Example</title>
+ </head>
+ <body>
+ <pre id="fileData">{{.Data}}</pre>
+ <script type="text/javascript">
+ (function() {
+ var data = document.getElementById("fileData");
+ var conn = new WebSocket("ws://{{.Host}}/ws?lastMod={{.LastMod}}");
+ conn.onclose = function(evt) {
+ data.textContent = 'Connection closed';
+ }
+ conn.onmessage = function(evt) {
+ console.log('file updated');
+ data.textContent = evt.data;
+ }
+ })();
+ </script>
+ </body>
+</html>
+`