server.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Command server is a test server for the Autobahn WebSockets Test Suite.
  5. package main
  6. import (
  7. "errors"
  8. "flag"
  9. "github.com/gorilla/websocket"
  10. "io"
  11. "log"
  12. "net/http"
  13. "time"
  14. "unicode/utf8"
  15. )
  16. var upgrader = websocket.Upgrader{
  17. ReadBufferSize: 4096,
  18. WriteBufferSize: 4096,
  19. CheckOrigin: func(r *http.Request) bool {
  20. return true
  21. },
  22. }
  23. // echoCopy echoes messages from the client using io.Copy.
  24. func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
  25. conn, err := upgrader.Upgrade(w, r, nil)
  26. if err != nil {
  27. log.Println("Upgrade:", err)
  28. return
  29. }
  30. defer conn.Close()
  31. for {
  32. mt, r, err := conn.NextReader()
  33. if err != nil {
  34. if err != io.EOF {
  35. log.Println("NextReader:", err)
  36. }
  37. return
  38. }
  39. if mt == websocket.TextMessage {
  40. r = &validator{r: r}
  41. }
  42. w, err := conn.NextWriter(mt)
  43. if err != nil {
  44. log.Println("NextWriter:", err)
  45. return
  46. }
  47. if mt == websocket.TextMessage {
  48. r = &validator{r: r}
  49. }
  50. if writerOnly {
  51. _, err = io.Copy(struct{ io.Writer }{w}, r)
  52. } else {
  53. _, err = io.Copy(w, r)
  54. }
  55. if err != nil {
  56. if err == errInvalidUTF8 {
  57. conn.WriteControl(websocket.CloseMessage,
  58. websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
  59. time.Time{})
  60. }
  61. log.Println("Copy:", err)
  62. return
  63. }
  64. err = w.Close()
  65. if err != nil {
  66. log.Println("Close:", err)
  67. return
  68. }
  69. }
  70. }
  71. func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
  72. echoCopy(w, r, true)
  73. }
  74. func echoCopyFull(w http.ResponseWriter, r *http.Request) {
  75. echoCopy(w, r, false)
  76. }
  77. // echoReadAll echoes messages from the client by reading the entire message
  78. // with ioutil.ReadAll.
  79. func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
  80. conn, err := upgrader.Upgrade(w, r, nil)
  81. if err != nil {
  82. log.Println("Upgrade:", err)
  83. return
  84. }
  85. defer conn.Close()
  86. for {
  87. mt, b, err := conn.ReadMessage()
  88. if err != nil {
  89. if err != io.EOF {
  90. log.Println("NextReader:", err)
  91. }
  92. return
  93. }
  94. if mt == websocket.TextMessage {
  95. if !utf8.Valid(b) {
  96. conn.WriteControl(websocket.CloseMessage,
  97. websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
  98. time.Time{})
  99. log.Println("ReadAll: invalid utf8")
  100. }
  101. }
  102. if writeMessage {
  103. err = conn.WriteMessage(mt, b)
  104. if err != nil {
  105. log.Println("WriteMessage:", err)
  106. }
  107. } else {
  108. w, err := conn.NextWriter(mt)
  109. if err != nil {
  110. log.Println("NextWriter:", err)
  111. return
  112. }
  113. if _, err := w.Write(b); err != nil {
  114. log.Println("Writer:", err)
  115. return
  116. }
  117. if err := w.Close(); err != nil {
  118. log.Println("Close:", err)
  119. return
  120. }
  121. }
  122. }
  123. }
  124. func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
  125. echoReadAll(w, r, false)
  126. }
  127. func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
  128. echoReadAll(w, r, true)
  129. }
  130. func serveHome(w http.ResponseWriter, r *http.Request) {
  131. if r.URL.Path != "/" {
  132. http.Error(w, "Not found.", 404)
  133. return
  134. }
  135. if r.Method != "GET" {
  136. http.Error(w, "Method not allowed", 405)
  137. return
  138. }
  139. w.Header().Set("Content-Type", "text/html; charset=utf-8")
  140. io.WriteString(w, "<html><body>Echo Server</body></html")
  141. }
  142. var addr = flag.String("addr", ":9000", "http service address")
  143. func main() {
  144. flag.Parse()
  145. http.HandleFunc("/", serveHome)
  146. http.HandleFunc("/c", echoCopyWriterOnly)
  147. http.HandleFunc("/f", echoCopyFull)
  148. http.HandleFunc("/r", echoReadAllWriter)
  149. http.HandleFunc("/m", echoReadAllWriteMessage)
  150. err := http.ListenAndServe(*addr, nil)
  151. if err != nil {
  152. log.Fatal("ListenAndServe: ", err)
  153. }
  154. }
  155. type validator struct {
  156. state int
  157. x rune
  158. r io.Reader
  159. }
  160. var errInvalidUTF8 = errors.New("invalid utf8")
  161. func (r *validator) Read(p []byte) (int, error) {
  162. n, err := r.r.Read(p)
  163. state := r.state
  164. x := r.x
  165. for _, b := range p[:n] {
  166. state, x = decode(state, x, b)
  167. if state == utf8Reject {
  168. break
  169. }
  170. }
  171. r.state = state
  172. r.x = x
  173. if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
  174. return n, errInvalidUTF8
  175. }
  176. return n, err
  177. }
  178. // UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
  179. //
  180. // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  181. //
  182. // Permission is hereby granted, free of charge, to any person obtaining a copy
  183. // of this software and associated documentation files (the "Software"), to
  184. // deal in the Software without restriction, including without limitation the
  185. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  186. // sell copies of the Software, and to permit persons to whom the Software is
  187. // furnished to do so, subject to the following conditions:
  188. //
  189. // The above copyright notice and this permission notice shall be included in
  190. // all copies or substantial portions of the Software.
  191. //
  192. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  193. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  194. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  195. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  196. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  197. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  198. // IN THE SOFTWARE.
  199. var utf8d = [...]byte{
  200. 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
  201. 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
  202. 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
  203. 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
  204. 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
  205. 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
  206. 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
  207. 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
  208. 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
  209. 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
  210. 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
  211. 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
  212. 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
  213. 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
  214. }
  215. const (
  216. utf8Accept = 0
  217. utf8Reject = 1
  218. )
  219. func decode(state int, x rune, b byte) (int, rune) {
  220. t := utf8d[b]
  221. if state != utf8Accept {
  222. x = rune(b&0x3f) | (x << 6)
  223. } else {
  224. x = rune((0xff >> t) & b)
  225. }
  226. state = int(utf8d[256+state*16+int(t)])
  227. return state, x
  228. }