helper.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. package wsutil
  2. import (
  3. "bytes"
  4. "io"
  5. "io/ioutil"
  6. "github.com/gobwas/ws"
  7. )
  8. // Message represents a message from peer, that could be presented in one or
  9. // more frames. That is, it contains payload of all message fragments and
  10. // operation code of initial frame for this message.
  11. type Message struct {
  12. OpCode ws.OpCode
  13. Payload []byte
  14. }
  15. // ReadMessage is a helper function that reads next message from r. It appends
  16. // received message(s) to the third argument and returns the result of it and
  17. // an error if some failure happened. That is, it probably could receive more
  18. // than one message when peer sending fragmented message in multiple frames and
  19. // want to send some control frame between fragments. Then returned slice will
  20. // contain those control frames at first, and then result of gluing fragments.
  21. //
  22. // TODO(gobwas): add DefaultReader with buffer size options.
  23. func ReadMessage(r io.Reader, s ws.State, m []Message) ([]Message, error) {
  24. rd := Reader{
  25. Source: r,
  26. State: s,
  27. CheckUTF8: true,
  28. OnIntermediate: func(hdr ws.Header, src io.Reader) error {
  29. bts, err := ioutil.ReadAll(src)
  30. if err != nil {
  31. return err
  32. }
  33. m = append(m, Message{hdr.OpCode, bts})
  34. return nil
  35. },
  36. }
  37. h, err := rd.NextFrame()
  38. if err != nil {
  39. return m, err
  40. }
  41. var p []byte
  42. if h.Fin {
  43. // No more frames will be read. Use fixed sized buffer to read payload.
  44. p = make([]byte, h.Length)
  45. // It is not possible to receive io.EOF here because Reader does not
  46. // return EOF if frame payload was successfully fetched.
  47. // Thus we consistent here with io.Reader behavior.
  48. _, err = io.ReadFull(&rd, p)
  49. } else {
  50. // Frame is fragmented, thus use ioutil.ReadAll behavior.
  51. var buf bytes.Buffer
  52. _, err = buf.ReadFrom(&rd)
  53. p = buf.Bytes()
  54. }
  55. if err != nil {
  56. return m, err
  57. }
  58. return append(m, Message{h.OpCode, p}), nil
  59. }
  60. // ReadClientMessage reads next message from r, considering that caller
  61. // represents server side.
  62. // It is a shortcut for ReadMessage(r, ws.StateServerSide, m)
  63. func ReadClientMessage(r io.Reader, m []Message) ([]Message, error) {
  64. return ReadMessage(r, ws.StateServerSide, m)
  65. }
  66. // ReadServerMessage reads next message from r, considering that caller
  67. // represents client side.
  68. // It is a shortcut for ReadMessage(r, ws.StateClientSide, m)
  69. func ReadServerMessage(r io.Reader, m []Message) ([]Message, error) {
  70. return ReadMessage(r, ws.StateClientSide, m)
  71. }
  72. // ReadData is a helper function that reads next data (non-control) message
  73. // from rw.
  74. // It takes care on handling all control frames. It will write response on
  75. // control frames to the write part of rw. It blocks until some data frame
  76. // will be received.
  77. //
  78. // Note this may handle and write control frames into the writer part of a
  79. // given io.ReadWriter.
  80. func ReadData(rw io.ReadWriter, s ws.State) ([]byte, ws.OpCode, error) {
  81. return readData(rw, s, ws.OpText|ws.OpBinary)
  82. }
  83. // ReadClientData reads next data message from rw, considering that caller
  84. // represents server side. It is a shortcut for ReadData(rw, ws.StateServerSide).
  85. //
  86. // Note this may handle and write control frames into the writer part of a
  87. // given io.ReadWriter.
  88. func ReadClientData(rw io.ReadWriter) ([]byte, ws.OpCode, error) {
  89. return ReadData(rw, ws.StateServerSide)
  90. }
  91. // ReadClientText reads next text message from rw, considering that caller
  92. // represents server side. It is a shortcut for ReadData(rw, ws.StateServerSide).
  93. // It discards received binary messages.
  94. //
  95. // Note this may handle and write control frames into the writer part of a
  96. // given io.ReadWriter.
  97. func ReadClientText(rw io.ReadWriter) ([]byte, error) {
  98. p, _, err := readData(rw, ws.StateServerSide, ws.OpText)
  99. return p, err
  100. }
  101. // ReadClientBinary reads next binary message from rw, considering that caller
  102. // represents server side. It is a shortcut for ReadData(rw, ws.StateServerSide).
  103. // It discards received text messages.
  104. //
  105. // Note this may handle and write control frames into the writer part of a given
  106. // io.ReadWriter.
  107. func ReadClientBinary(rw io.ReadWriter) ([]byte, error) {
  108. p, _, err := readData(rw, ws.StateServerSide, ws.OpBinary)
  109. return p, err
  110. }
  111. // ReadServerData reads next data message from rw, considering that caller
  112. // represents client side. It is a shortcut for ReadData(rw, ws.StateClientSide).
  113. //
  114. // Note this may handle and write control frames into the writer part of a
  115. // given io.ReadWriter.
  116. func ReadServerData(rw io.ReadWriter) ([]byte, ws.OpCode, error) {
  117. return ReadData(rw, ws.StateClientSide)
  118. }
  119. // ReadServerText reads next text message from rw, considering that caller
  120. // represents client side. It is a shortcut for ReadData(rw, ws.StateClientSide).
  121. // It discards received binary messages.
  122. //
  123. // Note this may handle and write control frames into the writer part of a given
  124. // io.ReadWriter.
  125. func ReadServerText(rw io.ReadWriter) ([]byte, error) {
  126. p, _, err := readData(rw, ws.StateClientSide, ws.OpText)
  127. return p, err
  128. }
  129. // ReadServerBinary reads next binary message from rw, considering that caller
  130. // represents client side. It is a shortcut for ReadData(rw, ws.StateClientSide).
  131. // It discards received text messages.
  132. //
  133. // Note this may handle and write control frames into the writer part of a
  134. // given io.ReadWriter.
  135. func ReadServerBinary(rw io.ReadWriter) ([]byte, error) {
  136. p, _, err := readData(rw, ws.StateClientSide, ws.OpBinary)
  137. return p, err
  138. }
  139. // WriteMessage is a helper function that writes message to the w. It
  140. // constructs single frame with given operation code and payload.
  141. // It uses given state to prepare side-dependent things, like cipher
  142. // payload bytes from client to server. It will not mutate p bytes if
  143. // cipher must be made.
  144. //
  145. // If you want to write message in fragmented frames, use Writer instead.
  146. func WriteMessage(w io.Writer, s ws.State, op ws.OpCode, p []byte) error {
  147. return writeFrame(w, s, op, true, p)
  148. }
  149. // WriteServerMessage writes message to w, considering that caller
  150. // represents server side.
  151. func WriteServerMessage(w io.Writer, op ws.OpCode, p []byte) error {
  152. return WriteMessage(w, ws.StateServerSide, op, p)
  153. }
  154. // WriteServerText is the same as WriteServerMessage with
  155. // ws.OpText.
  156. func WriteServerText(w io.Writer, p []byte) error {
  157. return WriteServerMessage(w, ws.OpText, p)
  158. }
  159. // WriteServerBinary is the same as WriteServerMessage with
  160. // ws.OpBinary.
  161. func WriteServerBinary(w io.Writer, p []byte) error {
  162. return WriteServerMessage(w, ws.OpBinary, p)
  163. }
  164. // WriteClientMessage writes message to w, considering that caller
  165. // represents client side.
  166. func WriteClientMessage(w io.Writer, op ws.OpCode, p []byte) error {
  167. return WriteMessage(w, ws.StateClientSide, op, p)
  168. }
  169. // WriteClientText is the same as WriteClientMessage with
  170. // ws.OpText.
  171. func WriteClientText(w io.Writer, p []byte) error {
  172. return WriteClientMessage(w, ws.OpText, p)
  173. }
  174. // WriteClientBinary is the same as WriteClientMessage with
  175. // ws.OpBinary.
  176. func WriteClientBinary(w io.Writer, p []byte) error {
  177. return WriteClientMessage(w, ws.OpBinary, p)
  178. }
  179. // HandleClientControlMessage handles control frame from conn and writes
  180. // response when needed.
  181. //
  182. // It considers that caller represents server side.
  183. func HandleClientControlMessage(conn io.Writer, msg Message) error {
  184. return HandleControlMessage(conn, ws.StateServerSide, msg)
  185. }
  186. // HandleServerControlMessage handles control frame from conn and writes
  187. // response when needed.
  188. //
  189. // It considers that caller represents client side.
  190. func HandleServerControlMessage(conn io.Writer, msg Message) error {
  191. return HandleControlMessage(conn, ws.StateClientSide, msg)
  192. }
  193. // HandleControlMessage handles message which was read by ReadMessage()
  194. // functions.
  195. //
  196. // That is, it is expected, that payload is already unmasked and frame header
  197. // were checked by ws.CheckHeader() call.
  198. func HandleControlMessage(conn io.Writer, state ws.State, msg Message) error {
  199. return (ControlHandler{
  200. DisableSrcCiphering: true,
  201. Src: bytes.NewReader(msg.Payload),
  202. Dst: conn,
  203. State: state,
  204. }).Handle(ws.Header{
  205. Length: int64(len(msg.Payload)),
  206. OpCode: msg.OpCode,
  207. Fin: true,
  208. Masked: state.ServerSide(),
  209. })
  210. }
  211. // ControlFrameHandler returns FrameHandlerFunc for handling control frames.
  212. // For more info see ControlHandler docs.
  213. func ControlFrameHandler(w io.Writer, state ws.State) FrameHandlerFunc {
  214. return func(h ws.Header, r io.Reader) error {
  215. return (ControlHandler{
  216. DisableSrcCiphering: true,
  217. Src: r,
  218. Dst: w,
  219. State: state,
  220. }).Handle(h)
  221. }
  222. }
  223. func readData(rw io.ReadWriter, s ws.State, want ws.OpCode) ([]byte, ws.OpCode, error) {
  224. controlHandler := ControlFrameHandler(rw, s)
  225. rd := Reader{
  226. Source: rw,
  227. State: s,
  228. CheckUTF8: true,
  229. SkipHeaderCheck: false,
  230. OnIntermediate: controlHandler,
  231. }
  232. for {
  233. hdr, err := rd.NextFrame()
  234. if err != nil {
  235. return nil, 0, err
  236. }
  237. if hdr.OpCode.IsControl() {
  238. if err := controlHandler(hdr, &rd); err != nil {
  239. return nil, 0, err
  240. }
  241. continue
  242. }
  243. if hdr.OpCode&want == 0 {
  244. if err := rd.Discard(); err != nil {
  245. return nil, 0, err
  246. }
  247. continue
  248. }
  249. bts, err := ioutil.ReadAll(&rd)
  250. return bts, hdr.OpCode, err
  251. }
  252. }