http urls monitor.

rpc.go 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  2. // Use of this source code is governed by a MIT license found in the LICENSE file.
  3. package codec
  4. import (
  5. "bufio"
  6. "errors"
  7. "io"
  8. "net/rpc"
  9. "sync"
  10. )
  11. // Rpc provides a rpc Server or Client Codec for rpc communication.
  12. type Rpc interface {
  13. ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec
  14. ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec
  15. }
  16. // RPCOptions holds options specific to rpc functionality
  17. type RPCOptions struct {
  18. // RPCNoBuffer configures whether we attempt to buffer reads and writes during RPC calls.
  19. //
  20. // Set RPCNoBuffer=true to turn buffering off.
  21. // Buffering can still be done if buffered connections are passed in, or
  22. // buffering is configured on the handle.
  23. RPCNoBuffer bool
  24. }
  25. // rpcCodec defines the struct members and common methods.
  26. type rpcCodec struct {
  27. c io.Closer
  28. r io.Reader
  29. w io.Writer
  30. f ioFlusher
  31. dec *Decoder
  32. enc *Encoder
  33. // bw *bufio.Writer
  34. // br *bufio.Reader
  35. mu sync.Mutex
  36. h Handle
  37. cls bool
  38. clsmu sync.RWMutex
  39. clsErr error
  40. }
  41. func newRPCCodec(conn io.ReadWriteCloser, h Handle) rpcCodec {
  42. // return newRPCCodec2(bufio.NewReader(conn), bufio.NewWriter(conn), conn, h)
  43. return newRPCCodec2(conn, conn, conn, h)
  44. }
  45. func newRPCCodec2(r io.Reader, w io.Writer, c io.Closer, h Handle) rpcCodec {
  46. // defensive: ensure that jsonH has TermWhitespace turned on.
  47. if jsonH, ok := h.(*JsonHandle); ok && !jsonH.TermWhitespace {
  48. panic(errors.New("rpc requires a JsonHandle with TermWhitespace set to true"))
  49. }
  50. // always ensure that we use a flusher, and always flush what was written to the connection.
  51. // we lose nothing by using a buffered writer internally.
  52. f, ok := w.(ioFlusher)
  53. bh := h.getBasicHandle()
  54. if !bh.RPCNoBuffer {
  55. if bh.WriterBufferSize <= 0 {
  56. if !ok {
  57. bw := bufio.NewWriter(w)
  58. f, w = bw, bw
  59. }
  60. }
  61. if bh.ReaderBufferSize <= 0 {
  62. if _, ok = w.(ioPeeker); !ok {
  63. if _, ok = w.(ioBuffered); !ok {
  64. br := bufio.NewReader(r)
  65. r = br
  66. }
  67. }
  68. }
  69. }
  70. return rpcCodec{
  71. c: c,
  72. w: w,
  73. r: r,
  74. f: f,
  75. h: h,
  76. enc: NewEncoder(w, h),
  77. dec: NewDecoder(r, h),
  78. }
  79. }
  80. func (c *rpcCodec) write(obj1, obj2 interface{}, writeObj2 bool) (err error) {
  81. if c.isClosed() {
  82. return c.clsErr
  83. }
  84. err = c.enc.Encode(obj1)
  85. if err == nil {
  86. if writeObj2 {
  87. err = c.enc.Encode(obj2)
  88. }
  89. // if err == nil && c.f != nil {
  90. // err = c.f.Flush()
  91. // }
  92. }
  93. if c.f != nil {
  94. if err == nil {
  95. err = c.f.Flush()
  96. } else {
  97. _ = c.f.Flush() // swallow flush error, so we maintain prior error on write
  98. }
  99. }
  100. return
  101. }
  102. func (c *rpcCodec) swallow(err *error) {
  103. defer panicToErr(c.dec, err)
  104. c.dec.swallow()
  105. }
  106. func (c *rpcCodec) read(obj interface{}) (err error) {
  107. if c.isClosed() {
  108. return c.clsErr
  109. }
  110. //If nil is passed in, we should read and discard
  111. if obj == nil {
  112. // var obj2 interface{}
  113. // return c.dec.Decode(&obj2)
  114. c.swallow(&err)
  115. return
  116. }
  117. return c.dec.Decode(obj)
  118. }
  119. func (c *rpcCodec) isClosed() (b bool) {
  120. if c.c != nil {
  121. c.clsmu.RLock()
  122. b = c.cls
  123. c.clsmu.RUnlock()
  124. }
  125. return
  126. }
  127. func (c *rpcCodec) Close() error {
  128. if c.c == nil || c.isClosed() {
  129. return c.clsErr
  130. }
  131. c.clsmu.Lock()
  132. c.cls = true
  133. c.clsErr = c.c.Close()
  134. c.clsmu.Unlock()
  135. return c.clsErr
  136. }
  137. func (c *rpcCodec) ReadResponseBody(body interface{}) error {
  138. return c.read(body)
  139. }
  140. // -------------------------------------
  141. type goRpcCodec struct {
  142. rpcCodec
  143. }
  144. func (c *goRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error {
  145. // Must protect for concurrent access as per API
  146. c.mu.Lock()
  147. defer c.mu.Unlock()
  148. return c.write(r, body, true)
  149. }
  150. func (c *goRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error {
  151. c.mu.Lock()
  152. defer c.mu.Unlock()
  153. return c.write(r, body, true)
  154. }
  155. func (c *goRpcCodec) ReadResponseHeader(r *rpc.Response) error {
  156. return c.read(r)
  157. }
  158. func (c *goRpcCodec) ReadRequestHeader(r *rpc.Request) error {
  159. return c.read(r)
  160. }
  161. func (c *goRpcCodec) ReadRequestBody(body interface{}) error {
  162. return c.read(body)
  163. }
  164. // -------------------------------------
  165. // goRpc is the implementation of Rpc that uses the communication protocol
  166. // as defined in net/rpc package.
  167. type goRpc struct{}
  168. // GoRpc implements Rpc using the communication protocol defined in net/rpc package.
  169. //
  170. // Note: network connection (from net.Dial, of type io.ReadWriteCloser) is not buffered.
  171. //
  172. // For performance, you should configure WriterBufferSize and ReaderBufferSize on the handle.
  173. // This ensures we use an adequate buffer during reading and writing.
  174. // If not configured, we will internally initialize and use a buffer during reads and writes.
  175. // This can be turned off via the RPCNoBuffer option on the Handle.
  176. // var handle codec.JsonHandle
  177. // handle.RPCNoBuffer = true // turns off attempt by rpc module to initialize a buffer
  178. //
  179. // Example 1: one way of configuring buffering explicitly:
  180. // var handle codec.JsonHandle // codec handle
  181. // handle.ReaderBufferSize = 1024
  182. // handle.WriterBufferSize = 1024
  183. // var conn io.ReadWriteCloser // connection got from a socket
  184. // var serverCodec = GoRpc.ServerCodec(conn, handle)
  185. // var clientCodec = GoRpc.ClientCodec(conn, handle)
  186. //
  187. // Example 2: you can also explicitly create a buffered connection yourself,
  188. // and not worry about configuring the buffer sizes in the Handle.
  189. // var handle codec.Handle // codec handle
  190. // var conn io.ReadWriteCloser // connection got from a socket
  191. // var bufconn = struct { // bufconn here is a buffered io.ReadWriteCloser
  192. // io.Closer
  193. // *bufio.Reader
  194. // *bufio.Writer
  195. // }{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
  196. // var serverCodec = GoRpc.ServerCodec(bufconn, handle)
  197. // var clientCodec = GoRpc.ClientCodec(bufconn, handle)
  198. //
  199. var GoRpc goRpc
  200. func (x goRpc) ServerCodec(conn io.ReadWriteCloser, h Handle) rpc.ServerCodec {
  201. return &goRpcCodec{newRPCCodec(conn, h)}
  202. }
  203. func (x goRpc) ClientCodec(conn io.ReadWriteCloser, h Handle) rpc.ClientCodec {
  204. return &goRpcCodec{newRPCCodec(conn, h)}
  205. }