PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/google.golang.org/grpc/transport/handler_server.go

https://gitlab.com/unofficial-mirrors/kubernetes
Go | 413 lines | 282 code | 49 blank | 82 comment | 63 complexity | f5f8ab92b12ff61f40485b158fe7bb05 MD5 | raw file
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. // This file is the implementation of a gRPC server using HTTP/2 which
  19. // uses the standard Go http2 Server implementation (via the
  20. // http.Handler interface), rather than speaking low-level HTTP/2
  21. // frames itself. It is the implementation of *grpc.Server.ServeHTTP.
  22. package transport
  23. import (
  24. "errors"
  25. "fmt"
  26. "io"
  27. "net"
  28. "net/http"
  29. "strings"
  30. "sync"
  31. "time"
  32. "github.com/golang/protobuf/proto"
  33. "golang.org/x/net/context"
  34. "golang.org/x/net/http2"
  35. "google.golang.org/grpc/codes"
  36. "google.golang.org/grpc/credentials"
  37. "google.golang.org/grpc/metadata"
  38. "google.golang.org/grpc/peer"
  39. "google.golang.org/grpc/status"
  40. )
  41. // NewServerHandlerTransport returns a ServerTransport handling gRPC
  42. // from inside an http.Handler. It requires that the http Server
  43. // supports HTTP/2.
  44. func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request) (ServerTransport, error) {
  45. if r.ProtoMajor != 2 {
  46. return nil, errors.New("gRPC requires HTTP/2")
  47. }
  48. if r.Method != "POST" {
  49. return nil, errors.New("invalid gRPC request method")
  50. }
  51. if !validContentType(r.Header.Get("Content-Type")) {
  52. return nil, errors.New("invalid gRPC request content-type")
  53. }
  54. if _, ok := w.(http.Flusher); !ok {
  55. return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
  56. }
  57. if _, ok := w.(http.CloseNotifier); !ok {
  58. return nil, errors.New("gRPC requires a ResponseWriter supporting http.CloseNotifier")
  59. }
  60. st := &serverHandlerTransport{
  61. rw: w,
  62. req: r,
  63. closedCh: make(chan struct{}),
  64. writes: make(chan func()),
  65. }
  66. if v := r.Header.Get("grpc-timeout"); v != "" {
  67. to, err := decodeTimeout(v)
  68. if err != nil {
  69. return nil, streamErrorf(codes.Internal, "malformed time-out: %v", err)
  70. }
  71. st.timeoutSet = true
  72. st.timeout = to
  73. }
  74. var metakv []string
  75. if r.Host != "" {
  76. metakv = append(metakv, ":authority", r.Host)
  77. }
  78. for k, vv := range r.Header {
  79. k = strings.ToLower(k)
  80. if isReservedHeader(k) && !isWhitelistedPseudoHeader(k) {
  81. continue
  82. }
  83. for _, v := range vv {
  84. v, err := decodeMetadataHeader(k, v)
  85. if err != nil {
  86. return nil, streamErrorf(codes.InvalidArgument, "malformed binary metadata: %v", err)
  87. }
  88. metakv = append(metakv, k, v)
  89. }
  90. }
  91. st.headerMD = metadata.Pairs(metakv...)
  92. return st, nil
  93. }
  94. // serverHandlerTransport is an implementation of ServerTransport
  95. // which replies to exactly one gRPC request (exactly one HTTP request),
  96. // using the net/http.Handler interface. This http.Handler is guaranteed
  97. // at this point to be speaking over HTTP/2, so it's able to speak valid
  98. // gRPC.
  99. type serverHandlerTransport struct {
  100. rw http.ResponseWriter
  101. req *http.Request
  102. timeoutSet bool
  103. timeout time.Duration
  104. didCommonHeaders bool
  105. headerMD metadata.MD
  106. closeOnce sync.Once
  107. closedCh chan struct{} // closed on Close
  108. // writes is a channel of code to run serialized in the
  109. // ServeHTTP (HandleStreams) goroutine. The channel is closed
  110. // when WriteStatus is called.
  111. writes chan func()
  112. // block concurrent WriteStatus calls
  113. // e.g. grpc/(*serverStream).SendMsg/RecvMsg
  114. writeStatusMu sync.Mutex
  115. }
  116. func (ht *serverHandlerTransport) Close() error {
  117. ht.closeOnce.Do(ht.closeCloseChanOnce)
  118. return nil
  119. }
  120. func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) }
  121. func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
  122. // strAddr is a net.Addr backed by either a TCP "ip:port" string, or
  123. // the empty string if unknown.
  124. type strAddr string
  125. func (a strAddr) Network() string {
  126. if a != "" {
  127. // Per the documentation on net/http.Request.RemoteAddr, if this is
  128. // set, it's set to the IP:port of the peer (hence, TCP):
  129. // https://golang.org/pkg/net/http/#Request
  130. //
  131. // If we want to support Unix sockets later, we can
  132. // add our own grpc-specific convention within the
  133. // grpc codebase to set RemoteAddr to a different
  134. // format, or probably better: we can attach it to the
  135. // context and use that from serverHandlerTransport.RemoteAddr.
  136. return "tcp"
  137. }
  138. return ""
  139. }
  140. func (a strAddr) String() string { return string(a) }
  141. // do runs fn in the ServeHTTP goroutine.
  142. func (ht *serverHandlerTransport) do(fn func()) error {
  143. // Avoid a panic writing to closed channel. Imperfect but maybe good enough.
  144. select {
  145. case <-ht.closedCh:
  146. return ErrConnClosing
  147. default:
  148. select {
  149. case ht.writes <- fn:
  150. return nil
  151. case <-ht.closedCh:
  152. return ErrConnClosing
  153. }
  154. }
  155. }
  156. func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error {
  157. ht.writeStatusMu.Lock()
  158. defer ht.writeStatusMu.Unlock()
  159. err := ht.do(func() {
  160. ht.writeCommonHeaders(s)
  161. // And flush, in case no header or body has been sent yet.
  162. // This forces a separation of headers and trailers if this is the
  163. // first call (for example, in end2end tests's TestNoService).
  164. ht.rw.(http.Flusher).Flush()
  165. h := ht.rw.Header()
  166. h.Set("Grpc-Status", fmt.Sprintf("%d", st.Code()))
  167. if m := st.Message(); m != "" {
  168. h.Set("Grpc-Message", encodeGrpcMessage(m))
  169. }
  170. if p := st.Proto(); p != nil && len(p.Details) > 0 {
  171. stBytes, err := proto.Marshal(p)
  172. if err != nil {
  173. // TODO: return error instead, when callers are able to handle it.
  174. panic(err)
  175. }
  176. h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
  177. }
  178. if md := s.Trailer(); len(md) > 0 {
  179. for k, vv := range md {
  180. // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
  181. if isReservedHeader(k) {
  182. continue
  183. }
  184. for _, v := range vv {
  185. // http2 ResponseWriter mechanism to send undeclared Trailers after
  186. // the headers have possibly been written.
  187. h.Add(http2.TrailerPrefix+k, encodeMetadataHeader(k, v))
  188. }
  189. }
  190. }
  191. })
  192. if err == nil { // transport has not been closed
  193. ht.Close()
  194. close(ht.writes)
  195. }
  196. return err
  197. }
  198. // writeCommonHeaders sets common headers on the first write
  199. // call (Write, WriteHeader, or WriteStatus).
  200. func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
  201. if ht.didCommonHeaders {
  202. return
  203. }
  204. ht.didCommonHeaders = true
  205. h := ht.rw.Header()
  206. h["Date"] = nil // suppress Date to make tests happy; TODO: restore
  207. h.Set("Content-Type", "application/grpc")
  208. // Predeclare trailers we'll set later in WriteStatus (after the body).
  209. // This is a SHOULD in the HTTP RFC, and the way you add (known)
  210. // Trailers per the net/http.ResponseWriter contract.
  211. // See https://golang.org/pkg/net/http/#ResponseWriter
  212. // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
  213. h.Add("Trailer", "Grpc-Status")
  214. h.Add("Trailer", "Grpc-Message")
  215. h.Add("Trailer", "Grpc-Status-Details-Bin")
  216. if s.sendCompress != "" {
  217. h.Set("Grpc-Encoding", s.sendCompress)
  218. }
  219. }
  220. func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
  221. return ht.do(func() {
  222. ht.writeCommonHeaders(s)
  223. ht.rw.Write(hdr)
  224. ht.rw.Write(data)
  225. if !opts.Delay {
  226. ht.rw.(http.Flusher).Flush()
  227. }
  228. })
  229. }
  230. func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
  231. return ht.do(func() {
  232. ht.writeCommonHeaders(s)
  233. h := ht.rw.Header()
  234. for k, vv := range md {
  235. // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
  236. if isReservedHeader(k) {
  237. continue
  238. }
  239. for _, v := range vv {
  240. v = encodeMetadataHeader(k, v)
  241. h.Add(k, v)
  242. }
  243. }
  244. ht.rw.WriteHeader(200)
  245. ht.rw.(http.Flusher).Flush()
  246. })
  247. }
  248. func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
  249. // With this transport type there will be exactly 1 stream: this HTTP request.
  250. var ctx context.Context
  251. var cancel context.CancelFunc
  252. if ht.timeoutSet {
  253. ctx, cancel = context.WithTimeout(context.Background(), ht.timeout)
  254. } else {
  255. ctx, cancel = context.WithCancel(context.Background())
  256. }
  257. // requestOver is closed when either the request's context is done
  258. // or the status has been written via WriteStatus.
  259. requestOver := make(chan struct{})
  260. // clientGone receives a single value if peer is gone, either
  261. // because the underlying connection is dead or because the
  262. // peer sends an http2 RST_STREAM.
  263. clientGone := ht.rw.(http.CloseNotifier).CloseNotify()
  264. go func() {
  265. select {
  266. case <-requestOver:
  267. return
  268. case <-ht.closedCh:
  269. case <-clientGone:
  270. }
  271. cancel()
  272. }()
  273. req := ht.req
  274. s := &Stream{
  275. id: 0, // irrelevant
  276. requestRead: func(int) {},
  277. cancel: cancel,
  278. buf: newRecvBuffer(),
  279. st: ht,
  280. method: req.URL.Path,
  281. recvCompress: req.Header.Get("grpc-encoding"),
  282. }
  283. pr := &peer.Peer{
  284. Addr: ht.RemoteAddr(),
  285. }
  286. if req.TLS != nil {
  287. pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
  288. }
  289. ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
  290. ctx = peer.NewContext(ctx, pr)
  291. s.ctx = newContextWithStream(ctx, s)
  292. s.trReader = &transportReader{
  293. reader: &recvBufferReader{ctx: s.ctx, recv: s.buf},
  294. windowHandler: func(int) {},
  295. }
  296. // readerDone is closed when the Body.Read-ing goroutine exits.
  297. readerDone := make(chan struct{})
  298. go func() {
  299. defer close(readerDone)
  300. // TODO: minimize garbage, optimize recvBuffer code/ownership
  301. const readSize = 8196
  302. for buf := make([]byte, readSize); ; {
  303. n, err := req.Body.Read(buf)
  304. if n > 0 {
  305. s.buf.put(recvMsg{data: buf[:n:n]})
  306. buf = buf[n:]
  307. }
  308. if err != nil {
  309. s.buf.put(recvMsg{err: mapRecvMsgError(err)})
  310. return
  311. }
  312. if len(buf) == 0 {
  313. buf = make([]byte, readSize)
  314. }
  315. }
  316. }()
  317. // startStream is provided by the *grpc.Server's serveStreams.
  318. // It starts a goroutine serving s and exits immediately.
  319. // The goroutine that is started is the one that then calls
  320. // into ht, calling WriteHeader, Write, WriteStatus, Close, etc.
  321. startStream(s)
  322. ht.runStream()
  323. close(requestOver)
  324. // Wait for reading goroutine to finish.
  325. req.Body.Close()
  326. <-readerDone
  327. }
  328. func (ht *serverHandlerTransport) runStream() {
  329. for {
  330. select {
  331. case fn, ok := <-ht.writes:
  332. if !ok {
  333. return
  334. }
  335. fn()
  336. case <-ht.closedCh:
  337. return
  338. }
  339. }
  340. }
  341. func (ht *serverHandlerTransport) Drain() {
  342. panic("Drain() is not implemented")
  343. }
  344. // mapRecvMsgError returns the non-nil err into the appropriate
  345. // error value as expected by callers of *grpc.parser.recvMsg.
  346. // In particular, in can only be:
  347. // * io.EOF
  348. // * io.ErrUnexpectedEOF
  349. // * of type transport.ConnectionError
  350. // * of type transport.StreamError
  351. func mapRecvMsgError(err error) error {
  352. if err == io.EOF || err == io.ErrUnexpectedEOF {
  353. return err
  354. }
  355. if se, ok := err.(http2.StreamError); ok {
  356. if code, ok := http2ErrConvTab[se.Code]; ok {
  357. return StreamError{
  358. Code: code,
  359. Desc: se.Error(),
  360. }
  361. }
  362. }
  363. return connectionErrorf(true, err, err.Error())
  364. }