hijack.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
  2. // See LICENSE.txt for license information.
  3. package plugin
  4. import (
  5. "bufio"
  6. "errors"
  7. "net"
  8. "net/http"
  9. "net/rpc"
  10. "time"
  11. )
  12. const (
  13. hijackedConnReadBufSize = 4096
  14. )
  15. var (
  16. ErrNotHijacked = errors.New("response is not hijacked")
  17. ErrAlreadyHijacked = errors.New("response was already hijacked")
  18. ErrCannotHijack = errors.New("response cannot be hijacked")
  19. )
  20. func (w *httpResponseWriterRPCServer) HjConnRWRead(b []byte, reply *[]byte) error {
  21. if w.hjr == nil {
  22. return ErrNotHijacked
  23. }
  24. data := make([]byte, len(b))
  25. n, err := w.hjr.bufrw.Read(data)
  26. if err != nil {
  27. return err
  28. }
  29. *reply = data[:n]
  30. return nil
  31. }
  32. func (w *httpResponseWriterRPCServer) HjConnRWWrite(b []byte, reply *int) error {
  33. if w.hjr == nil {
  34. return ErrNotHijacked
  35. }
  36. n, err := w.hjr.bufrw.Write(b)
  37. if err != nil {
  38. return err
  39. }
  40. *reply = n
  41. return nil
  42. }
  43. func (w *httpResponseWriterRPCServer) HjConnRead(size int, reply *[]byte) error {
  44. if w.hjr == nil {
  45. return ErrNotHijacked
  46. }
  47. if len(w.hjr.readBuf) < size {
  48. w.hjr.readBuf = make([]byte, size)
  49. }
  50. n, err := w.hjr.conn.Read(w.hjr.readBuf[:size])
  51. if err != nil {
  52. return err
  53. }
  54. *reply = w.hjr.readBuf[:n]
  55. return nil
  56. }
  57. func (w *httpResponseWriterRPCServer) HjConnWrite(b []byte, reply *int) error {
  58. if w.hjr == nil {
  59. return ErrNotHijacked
  60. }
  61. n, err := w.hjr.conn.Write(b)
  62. if err != nil {
  63. return err
  64. }
  65. *reply = n
  66. return nil
  67. }
  68. func (w *httpResponseWriterRPCServer) HjConnClose(args struct{}, reply *struct{}) error {
  69. if w.hjr == nil {
  70. return ErrNotHijacked
  71. }
  72. return w.hjr.conn.Close()
  73. }
  74. func (w *httpResponseWriterRPCServer) HjConnSetDeadline(t time.Time, reply *struct{}) error {
  75. if w.hjr == nil {
  76. return ErrNotHijacked
  77. }
  78. return w.hjr.conn.SetDeadline(t)
  79. }
  80. func (w *httpResponseWriterRPCServer) HjConnSetReadDeadline(t time.Time, reply *struct{}) error {
  81. if w.hjr == nil {
  82. return ErrNotHijacked
  83. }
  84. return w.hjr.conn.SetReadDeadline(t)
  85. }
  86. func (w *httpResponseWriterRPCServer) HjConnSetWriteDeadline(t time.Time, reply *struct{}) error {
  87. if w.hjr == nil {
  88. return ErrNotHijacked
  89. }
  90. return w.hjr.conn.SetWriteDeadline(t)
  91. }
  92. func (w *httpResponseWriterRPCServer) HijackResponse(args struct{}, reply *struct{}) error {
  93. if w.hjr != nil {
  94. return ErrAlreadyHijacked
  95. }
  96. hj, ok := w.w.(http.Hijacker)
  97. if !ok {
  98. return ErrCannotHijack
  99. }
  100. conn, bufrw, err := hj.Hijack()
  101. if err != nil {
  102. return err
  103. }
  104. w.hjr = &hijackedResponse{
  105. conn: conn,
  106. bufrw: bufrw,
  107. readBuf: make([]byte, hijackedConnReadBufSize),
  108. }
  109. return nil
  110. }
  111. type hijackedConn struct {
  112. client *rpc.Client
  113. }
  114. type hijackedConnRW struct {
  115. client *rpc.Client
  116. }
  117. func (w *hijackedConnRW) Read(b []byte) (int, error) {
  118. var data []byte
  119. if err := w.client.Call("Plugin.HjConnRWRead", b, &data); err != nil {
  120. return 0, err
  121. }
  122. copy(b, data)
  123. return len(data), nil
  124. }
  125. func (w *hijackedConnRW) Write(b []byte) (int, error) {
  126. var n int
  127. if err := w.client.Call("Plugin.HjConnRWWrite", b, &n); err != nil {
  128. return 0, err
  129. }
  130. return n, nil
  131. }
  132. func (w *hijackedConn) Read(b []byte) (int, error) {
  133. var data []byte
  134. if err := w.client.Call("Plugin.HjConnRead", len(b), &data); err != nil {
  135. return 0, err
  136. }
  137. copy(b, data)
  138. return len(data), nil
  139. }
  140. func (w *hijackedConn) Write(b []byte) (int, error) {
  141. var n int
  142. if err := w.client.Call("Plugin.HjConnWrite", b, &n); err != nil {
  143. return 0, err
  144. }
  145. return n, nil
  146. }
  147. func (w *hijackedConn) Close() error {
  148. return w.client.Call("Plugin.HjConnClose", struct{}{}, nil)
  149. }
  150. func (w *hijackedConn) LocalAddr() net.Addr {
  151. return nil
  152. }
  153. func (w *hijackedConn) RemoteAddr() net.Addr {
  154. return nil
  155. }
  156. func (w *hijackedConn) SetDeadline(t time.Time) error {
  157. return w.client.Call("Plugin.HjConnSetDeadline", t, nil)
  158. }
  159. func (w *hijackedConn) SetReadDeadline(t time.Time) error {
  160. return w.client.Call("Plugin.HjConnSetReadDeadline", t, nil)
  161. }
  162. func (w *hijackedConn) SetWriteDeadline(t time.Time) error {
  163. return w.client.Call("Plugin.HjConnSetWriteDeadline", t, nil)
  164. }
  165. func (w *httpResponseWriterRPCClient) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  166. c := &hijackedConn{
  167. client: w.client,
  168. }
  169. rw := &hijackedConnRW{
  170. client: w.client,
  171. }
  172. if err := w.client.Call("Plugin.HijackResponse", struct{}{}, nil); err != nil {
  173. return nil, nil, err
  174. }
  175. return c, bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)), nil
  176. }