summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/gorilla/websocket/examples
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gorilla/websocket/examples')
-rw-r--r--vendor/github.com/gorilla/websocket/examples/autobahn/server.go8
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/README.md86
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/client.go134
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/conn.go105
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/home.html54
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/hub.go56
-rw-r--r--vendor/github.com/gorilla/websocket/examples/chat/main.go12
-rw-r--r--vendor/github.com/gorilla/websocket/examples/command/main.go12
8 files changed, 300 insertions, 167 deletions
diff --git a/vendor/github.com/gorilla/websocket/examples/autobahn/server.go b/vendor/github.com/gorilla/websocket/examples/autobahn/server.go
index d96ac84db..e98563be9 100644
--- a/vendor/github.com/gorilla/websocket/examples/autobahn/server.go
+++ b/vendor/github.com/gorilla/websocket/examples/autobahn/server.go
@@ -8,17 +8,19 @@ package main
import (
"errors"
"flag"
- "github.com/gorilla/websocket"
"io"
"log"
"net/http"
"time"
"unicode/utf8"
+
+ "github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
- ReadBufferSize: 4096,
- WriteBufferSize: 4096,
+ ReadBufferSize: 4096,
+ WriteBufferSize: 4096,
+ EnableCompression: true,
CheckOrigin: func(r *http.Request) bool {
return true
},
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/README.md b/vendor/github.com/gorilla/websocket/examples/chat/README.md
index 5df3cf1a3..47c82f908 100644
--- a/vendor/github.com/gorilla/websocket/examples/chat/README.md
+++ b/vendor/github.com/gorilla/websocket/examples/chat/README.md
@@ -1,8 +1,8 @@
# Chat Example
This application shows how to use use the
-[websocket](https://github.com/gorilla/websocket) package and
-[jQuery](http://jquery.com) to implement a simple web chat application.
+[websocket](https://github.com/gorilla/websocket) package to implement a simple
+web chat application.
## Running the example
@@ -18,3 +18,85 @@ using the following commands.
$ go run *.go
To use the chat example, open http://localhost:8080/ in your browser.
+
+## Server
+
+The server application defines two types, `Client` and `Hub`. The server
+creates an instance of the `Client` type for each websocket connection. A
+`Client` acts as an intermediary between the websocket connection and a single
+instance of the `Hub` type. The `Hub` maintains a set of registered clients and
+broadcasts messages to the clients.
+
+The application runs one goroutine for the `Hub` and two goroutines for each
+`Client`. The goroutines communicate with each other using channels. The `Hub`
+has channels for registering clients, unregistering clients and broadcasting
+messages. A `Client` has a buffered channel of outbound messages. One of the
+client's goroutines reads messages from this channel and writes the messages to
+the websocket. The other client goroutine reads messages from the websocket and
+sends them to the hub.
+
+### Hub
+
+The code for the `Hub` type is in
+[hub.go](https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go).
+The application's `main` function starts the hub's `run` method as a goroutine.
+Clients send requests to the hub using the `register`, `unregister` and
+`broadcast` channels.
+
+The hub registers clients by adding the client pointer as a key in the
+`clients` map. The map value is always true.
+
+The unregister code is a little more complicated. In addition to deleting the
+client pointer from the `clients` map, the hub closes the clients's `send`
+channel to signal the client that no more messages will be sent to the client.
+
+The hub handles messages by looping over the registered clients and sending the
+message to the client's `send` channel. If the client's `send` buffer is full,
+then the hub assumes that the client is dead or stuck. In this case, the hub
+unregisters the client and closes the websocket.
+
+### Client
+
+The code for the `Client` type is in [client.go](https://github.com/gorilla/websocket/blob/master/examples/chat/client.go).
+
+The `serveWs` function is registered by the application's `main` function as
+an HTTP handler. The handler upgrades the HTTP connection to the WebSocket
+protocol, creates a client, registers the client with the hub and schedules the
+client to be unregistered using a defer statement.
+
+Next, the HTTP handler starts the client's `writePump` method as a goroutine.
+This method transfers messages from the client's send channel to the websocket
+connection. The writer method exits when the channel is closed by the hub or
+there's an error writing to the websocket connection.
+
+Finally, the HTTP handler calls the client's `readPump` method. This method
+transfers inbound messages from the websocket to the hub.
+
+WebSocket connections [support one concurrent reader and one concurrent
+writer](https://godoc.org/github.com/gorilla/websocket#hdr-Concurrency). The
+application ensures that these concurrency requirements are met by executing
+all reads from the `readPump` goroutine and all writes from the `writePump`
+goroutine.
+
+To improve efficiency under high load, the `writePump` function coalesces
+pending chat messages in the `send` channel to a single WebSocket message. This
+reduces the number of system calls and the amount of data sent over the
+network.
+
+## Frontend
+
+The frontend code is in [home.html](https://github.com/gorilla/websocket/blob/master/examples/chat/home.html).
+
+On document load, the script checks for websocket functionality in the browser.
+If websocket functionality is available, then the script opens a connection to
+the server and registers a callback to handle messages from the server. The
+callback appends the message to the chat log using the appendLog function.
+
+To allow the user to manually scroll through the chat log without interruption
+from new messages, the `appendLog` function checks the scroll position before
+adding new content. If the chat log is scrolled to the bottom, then the
+function scrolls new content into view after adding the content. Otherwise, the
+scroll position is not changed.
+
+The form handler writes the user input to the websocket and clears the input
+field.
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/client.go b/vendor/github.com/gorilla/websocket/examples/chat/client.go
new file mode 100644
index 000000000..26468477c
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/examples/chat/client.go
@@ -0,0 +1,134 @@
+// 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 (
+ "bytes"
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/gorilla/websocket"
+)
+
+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 (
+ newline = []byte{'\n'}
+ space = []byte{' '}
+)
+
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+}
+
+// Client is a middleman between the websocket connection and the hub.
+type Client struct {
+ hub *Hub
+
+ // The websocket connection.
+ conn *websocket.Conn
+
+ // Buffered channel of outbound messages.
+ send chan []byte
+}
+
+// readPump pumps messages from the websocket connection to the hub.
+//
+// The application runs readPump in a per-connection goroutine. The application
+// ensures that there is at most one reader on a connection by executing all
+// reads from this goroutine.
+func (c *Client) readPump() {
+ defer func() {
+ c.hub.unregister <- c
+ c.conn.Close()
+ }()
+ c.conn.SetReadLimit(maxMessageSize)
+ c.conn.SetReadDeadline(time.Now().Add(pongWait))
+ c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
+ for {
+ _, message, err := c.conn.ReadMessage()
+ if err != nil {
+ if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
+ log.Printf("error: %v", err)
+ }
+ break
+ }
+ message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
+ c.hub.broadcast <- message
+ }
+}
+
+// writePump pumps messages from the hub to the websocket connection.
+//
+// A goroutine running writePump is started for each connection. The
+// application ensures that there is at most one writer to a connection by
+// executing all writes from this goroutine.
+func (c *Client) writePump() {
+ ticker := time.NewTicker(pingPeriod)
+ defer func() {
+ ticker.Stop()
+ c.conn.Close()
+ }()
+ for {
+ select {
+ case message, ok := <-c.send:
+ c.conn.SetWriteDeadline(time.Now().Add(writeWait))
+ if !ok {
+ // The hub closed the channel.
+ c.conn.WriteMessage(websocket.CloseMessage, []byte{})
+ return
+ }
+
+ w, err := c.conn.NextWriter(websocket.TextMessage)
+ if err != nil {
+ return
+ }
+ w.Write(message)
+
+ // Add queued chat messages to the current websocket message.
+ n := len(c.send)
+ for i := 0; i < n; i++ {
+ w.Write(newline)
+ w.Write(<-c.send)
+ }
+
+ if err := w.Close(); err != nil {
+ return
+ }
+ case <-ticker.C:
+ c.conn.SetWriteDeadline(time.Now().Add(writeWait))
+ if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
+ return
+ }
+ }
+ }
+}
+
+// serveWs handles websocket requests from the peer.
+func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
+ conn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
+ client.hub.register <- client
+ go client.writePump()
+ client.readPump()
+}
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/conn.go b/vendor/github.com/gorilla/websocket/examples/chat/conn.go
deleted file mode 100644
index 40fd38c2c..000000000
--- a/vendor/github.com/gorilla/websocket/examples/chat/conn.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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/home.html b/vendor/github.com/gorilla/websocket/examples/chat/home.html
index 29599225c..7262918ec 100644
--- a/vendor/github.com/gorilla/websocket/examples/chat/home.html
+++ b/vendor/github.com/gorilla/websocket/examples/chat/home.html
@@ -2,47 +2,53 @@
<html lang="en">
<head>
<title>Chat Example</title>
-<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript">
- $(function() {
-
+window.onload = function () {
var conn;
- var msg = $("#msg");
- var log = $("#log");
+ var msg = document.getElementById("msg");
+ var log = document.getElementById("log");
- function appendLog(msg) {
- var d = log[0]
- var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
- msg.appendTo(log)
+ function appendLog(item) {
+ var doScroll = log.scrollTop === log.scrollHeight - log.clientHeight;
+ log.appendChild(item);
if (doScroll) {
- d.scrollTop = d.scrollHeight - d.clientHeight;
+ log.scrollTop = log.scrollHeight - log.clientHeight;
}
}
- $("#form").submit(function() {
+ document.getElementById("form").onsubmit = function () {
if (!conn) {
return false;
}
- if (!msg.val()) {
+ if (!msg.value) {
return false;
}
- conn.send(msg.val());
- msg.val("");
- return false
- });
+ conn.send(msg.value);
+ msg.value = "";
+ return false;
+ };
if (window["WebSocket"]) {
conn = new WebSocket("ws://{{$}}/ws");
- conn.onclose = function(evt) {
- appendLog($("<div><b>Connection closed.</b></div>"))
- }
- conn.onmessage = function(evt) {
- appendLog($("<div/>").text(evt.data))
- }
+ conn.onclose = function (evt) {
+ var item = document.createElement("div");
+ item.innerHTML = "<b>Connection closed.</b>";
+ appendLog(item);
+ };
+ conn.onmessage = function (evt) {
+ var messages = evt.data.split('\n');
+ for (var i = 0; i < messages.length; i++) {
+ var item = document.createElement("div");
+ item.innerText = messages[i];
+ appendLog(item);
+ }
+ };
} else {
- appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
+ var item = document.createElement("div");
+ item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
+ appendLog(item);
}
- });
+};
</script>
<style type="text/css">
html {
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/hub.go b/vendor/github.com/gorilla/websocket/examples/chat/hub.go
index 449ba753d..7f07ea079 100644
--- a/vendor/github.com/gorilla/websocket/examples/chat/hub.go
+++ b/vendor/github.com/gorilla/websocket/examples/chat/hub.go
@@ -4,46 +4,48 @@
package main
-// hub maintains the set of active connections and broadcasts messages to the
-// connections.
-type hub struct {
- // Registered connections.
- connections map[*connection]bool
+// hub maintains the set of active clients and broadcasts messages to the
+// clients.
+type Hub struct {
+ // Registered clients.
+ clients map[*Client]bool
- // Inbound messages from the connections.
+ // Inbound messages from the clients.
broadcast chan []byte
- // Register requests from the connections.
- register chan *connection
+ // Register requests from the clients.
+ register chan *Client
- // Unregister requests from connections.
- unregister chan *connection
+ // Unregister requests from clients.
+ unregister chan *Client
}
-var h = hub{
- broadcast: make(chan []byte),
- register: make(chan *connection),
- unregister: make(chan *connection),
- connections: make(map[*connection]bool),
+func newHub() *Hub {
+ return &Hub{
+ broadcast: make(chan []byte),
+ register: make(chan *Client),
+ unregister: make(chan *Client),
+ clients: make(map[*Client]bool),
+ }
}
-func (h *hub) run() {
+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 client := <-h.register:
+ h.clients[client] = true
+ case client := <-h.unregister:
+ if _, ok := h.clients[client]; ok {
+ delete(h.clients, client)
+ close(client.send)
}
- case m := <-h.broadcast:
- for c := range h.connections {
+ case message := <-h.broadcast:
+ for client := range h.clients {
select {
- case c.send <- m:
+ case client.send <- message:
default:
- close(c.send)
- delete(h.connections, c)
+ close(client.send)
+ delete(h.clients, client)
}
}
}
diff --git a/vendor/github.com/gorilla/websocket/examples/chat/main.go b/vendor/github.com/gorilla/websocket/examples/chat/main.go
index 3c4448d72..a865ffec5 100644
--- a/vendor/github.com/gorilla/websocket/examples/chat/main.go
+++ b/vendor/github.com/gorilla/websocket/examples/chat/main.go
@@ -12,9 +12,10 @@ import (
)
var addr = flag.String("addr", ":8080", "http service address")
-var homeTempl = template.Must(template.ParseFiles("home.html"))
+var homeTemplate = template.Must(template.ParseFiles("home.html"))
func serveHome(w http.ResponseWriter, r *http.Request) {
+ log.Println(r.URL)
if r.URL.Path != "/" {
http.Error(w, "Not found", 404)
return
@@ -24,14 +25,17 @@ func serveHome(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
- homeTempl.Execute(w, r.Host)
+ homeTemplate.Execute(w, r.Host)
}
func main() {
flag.Parse()
- go h.run()
+ hub := newHub()
+ go hub.run()
http.HandleFunc("/", serveHome)
- http.HandleFunc("/ws", serveWs)
+ http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
+ serveWs(hub, w, r)
+ })
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
index f3f022edb..438fb8328 100644
--- a/vendor/github.com/gorilla/websocket/examples/command/main.go
+++ b/vendor/github.com/gorilla/websocket/examples/command/main.go
@@ -36,6 +36,9 @@ const (
// 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) {
@@ -57,19 +60,24 @@ func pumpStdin(ws *websocket.Conn, w io.Writer) {
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 {
+ 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{}) {