google.golang.org/grpc@v1.72.2/internal/transport/http2_server.go (about) 1 /* 2 * 3 * Copyright 2014 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 19 package transport 20 21 import ( 22 "bytes" 23 "context" 24 "errors" 25 "fmt" 26 "io" 27 "math" 28 rand "math/rand/v2" 29 "net" 30 "net/http" 31 "strconv" 32 "sync" 33 "sync/atomic" 34 "time" 35 36 "golang.org/x/net/http2" 37 "golang.org/x/net/http2/hpack" 38 "google.golang.org/grpc/internal" 39 "google.golang.org/grpc/internal/grpclog" 40 "google.golang.org/grpc/internal/grpcutil" 41 "google.golang.org/grpc/internal/pretty" 42 "google.golang.org/grpc/internal/syscall" 43 "google.golang.org/grpc/mem" 44 "google.golang.org/protobuf/proto" 45 46 "google.golang.org/grpc/codes" 47 "google.golang.org/grpc/credentials" 48 "google.golang.org/grpc/internal/channelz" 49 "google.golang.org/grpc/internal/grpcsync" 50 "google.golang.org/grpc/keepalive" 51 "google.golang.org/grpc/metadata" 52 "google.golang.org/grpc/peer" 53 "google.golang.org/grpc/stats" 54 "google.golang.org/grpc/status" 55 "google.golang.org/grpc/tap" 56 ) 57 58 var ( 59 // ErrIllegalHeaderWrite indicates that setting header is illegal because of 60 // the stream's state. 61 ErrIllegalHeaderWrite = status.Error(codes.Internal, "transport: SendHeader called multiple times") 62 // ErrHeaderListSizeLimitViolation indicates that the header list size is larger 63 // than the limit set by peer. 64 ErrHeaderListSizeLimitViolation = status.Error(codes.Internal, "transport: trying to send header list size larger than the limit set by peer") 65 ) 66 67 // serverConnectionCounter counts the number of connections a server has seen 68 // (equal to the number of http2Servers created). Must be accessed atomically. 69 var serverConnectionCounter uint64 70 71 // http2Server implements the ServerTransport interface with HTTP2. 72 type http2Server struct { 73 lastRead int64 // Keep this field 64-bit aligned. Accessed atomically. 74 done chan struct{} 75 conn net.Conn 76 loopy *loopyWriter 77 readerDone chan struct{} // sync point to enable testing. 78 loopyWriterDone chan struct{} 79 peer peer.Peer 80 inTapHandle tap.ServerInHandle 81 framer *framer 82 // The max number of concurrent streams. 83 maxStreams uint32 84 // controlBuf delivers all the control related tasks (e.g., window 85 // updates, reset streams, and various settings) to the controller. 86 controlBuf *controlBuffer 87 fc *trInFlow 88 stats []stats.Handler 89 // Keepalive and max-age parameters for the server. 90 kp keepalive.ServerParameters 91 // Keepalive enforcement policy. 92 kep keepalive.EnforcementPolicy 93 // The time instance last ping was received. 94 lastPingAt time.Time 95 // Number of times the client has violated keepalive ping policy so far. 96 pingStrikes uint8 97 // Flag to signify that number of ping strikes should be reset to 0. 98 // This is set whenever data or header frames are sent. 99 // 1 means yes. 100 resetPingStrikes uint32 // Accessed atomically. 101 initialWindowSize int32 102 bdpEst *bdpEstimator 103 maxSendHeaderListSize *uint32 104 105 mu sync.Mutex // guard the following 106 107 // drainEvent is initialized when Drain() is called the first time. After 108 // which the server writes out the first GoAway(with ID 2^31-1) frame. Then 109 // an independent goroutine will be launched to later send the second 110 // GoAway. During this time we don't want to write another first GoAway(with 111 // ID 2^31 -1) frame. Thus call to Drain() will be a no-op if drainEvent is 112 // already initialized since draining is already underway. 113 drainEvent *grpcsync.Event 114 state transportState 115 activeStreams map[uint32]*ServerStream 116 // idle is the time instant when the connection went idle. 117 // This is either the beginning of the connection or when the number of 118 // RPCs go down to 0. 119 // When the connection is busy, this value is set to 0. 120 idle time.Time 121 122 // Fields below are for channelz metric collection. 123 channelz *channelz.Socket 124 bufferPool mem.BufferPool 125 126 connectionID uint64 127 128 // maxStreamMu guards the maximum stream ID 129 // This lock may not be taken if mu is already held. 130 maxStreamMu sync.Mutex 131 maxStreamID uint32 // max stream ID ever seen 132 133 logger *grpclog.PrefixLogger 134 } 135 136 // NewServerTransport creates a http2 transport with conn and configuration 137 // options from config. 138 // 139 // It returns a non-nil transport and a nil error on success. On failure, it 140 // returns a nil transport and a non-nil error. For a special case where the 141 // underlying conn gets closed before the client preface could be read, it 142 // returns a nil transport and a nil error. 143 func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { 144 var authInfo credentials.AuthInfo 145 rawConn := conn 146 if config.Credentials != nil { 147 var err error 148 conn, authInfo, err = config.Credentials.ServerHandshake(rawConn) 149 if err != nil { 150 // ErrConnDispatched means that the connection was dispatched away 151 // from gRPC; those connections should be left open. io.EOF means 152 // the connection was closed before handshaking completed, which can 153 // happen naturally from probers. Return these errors directly. 154 if err == credentials.ErrConnDispatched || err == io.EOF { 155 return nil, err 156 } 157 return nil, connectionErrorf(false, err, "ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) 158 } 159 } 160 writeBufSize := config.WriteBufferSize 161 readBufSize := config.ReadBufferSize 162 maxHeaderListSize := defaultServerMaxHeaderListSize 163 if config.MaxHeaderListSize != nil { 164 maxHeaderListSize = *config.MaxHeaderListSize 165 } 166 framer := newFramer(conn, writeBufSize, readBufSize, config.SharedWriteBuffer, maxHeaderListSize) 167 // Send initial settings as connection preface to client. 168 isettings := []http2.Setting{{ 169 ID: http2.SettingMaxFrameSize, 170 Val: http2MaxFrameLen, 171 }} 172 if config.MaxStreams != math.MaxUint32 { 173 isettings = append(isettings, http2.Setting{ 174 ID: http2.SettingMaxConcurrentStreams, 175 Val: config.MaxStreams, 176 }) 177 } 178 dynamicWindow := true 179 iwz := int32(initialWindowSize) 180 if config.InitialWindowSize >= defaultWindowSize { 181 iwz = config.InitialWindowSize 182 dynamicWindow = false 183 } 184 icwz := int32(initialWindowSize) 185 if config.InitialConnWindowSize >= defaultWindowSize { 186 icwz = config.InitialConnWindowSize 187 dynamicWindow = false 188 } 189 if iwz != defaultWindowSize { 190 isettings = append(isettings, http2.Setting{ 191 ID: http2.SettingInitialWindowSize, 192 Val: uint32(iwz)}) 193 } 194 if config.MaxHeaderListSize != nil { 195 isettings = append(isettings, http2.Setting{ 196 ID: http2.SettingMaxHeaderListSize, 197 Val: *config.MaxHeaderListSize, 198 }) 199 } 200 if config.HeaderTableSize != nil { 201 isettings = append(isettings, http2.Setting{ 202 ID: http2.SettingHeaderTableSize, 203 Val: *config.HeaderTableSize, 204 }) 205 } 206 if err := framer.fr.WriteSettings(isettings...); err != nil { 207 return nil, connectionErrorf(false, err, "transport: %v", err) 208 } 209 // Adjust the connection flow control window if needed. 210 if delta := uint32(icwz - defaultWindowSize); delta > 0 { 211 if err := framer.fr.WriteWindowUpdate(0, delta); err != nil { 212 return nil, connectionErrorf(false, err, "transport: %v", err) 213 } 214 } 215 kp := config.KeepaliveParams 216 if kp.MaxConnectionIdle == 0 { 217 kp.MaxConnectionIdle = defaultMaxConnectionIdle 218 } 219 if kp.MaxConnectionAge == 0 { 220 kp.MaxConnectionAge = defaultMaxConnectionAge 221 } 222 // Add a jitter to MaxConnectionAge. 223 kp.MaxConnectionAge += getJitter(kp.MaxConnectionAge) 224 if kp.MaxConnectionAgeGrace == 0 { 225 kp.MaxConnectionAgeGrace = defaultMaxConnectionAgeGrace 226 } 227 if kp.Time == 0 { 228 kp.Time = defaultServerKeepaliveTime 229 } 230 if kp.Timeout == 0 { 231 kp.Timeout = defaultServerKeepaliveTimeout 232 } 233 if kp.Time != infinity { 234 if err = syscall.SetTCPUserTimeout(rawConn, kp.Timeout); err != nil { 235 return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err) 236 } 237 } 238 kep := config.KeepalivePolicy 239 if kep.MinTime == 0 { 240 kep.MinTime = defaultKeepalivePolicyMinTime 241 } 242 243 done := make(chan struct{}) 244 peer := peer.Peer{ 245 Addr: conn.RemoteAddr(), 246 LocalAddr: conn.LocalAddr(), 247 AuthInfo: authInfo, 248 } 249 t := &http2Server{ 250 done: done, 251 conn: conn, 252 peer: peer, 253 framer: framer, 254 readerDone: make(chan struct{}), 255 loopyWriterDone: make(chan struct{}), 256 maxStreams: config.MaxStreams, 257 inTapHandle: config.InTapHandle, 258 fc: &trInFlow{limit: uint32(icwz)}, 259 state: reachable, 260 activeStreams: make(map[uint32]*ServerStream), 261 stats: config.StatsHandlers, 262 kp: kp, 263 idle: time.Now(), 264 kep: kep, 265 initialWindowSize: iwz, 266 bufferPool: config.BufferPool, 267 } 268 var czSecurity credentials.ChannelzSecurityValue 269 if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok { 270 czSecurity = au.GetSecurityValue() 271 } 272 t.channelz = channelz.RegisterSocket( 273 &channelz.Socket{ 274 SocketType: channelz.SocketTypeNormal, 275 Parent: config.ChannelzParent, 276 SocketMetrics: channelz.SocketMetrics{}, 277 EphemeralMetrics: t.socketMetrics, 278 LocalAddr: t.peer.LocalAddr, 279 RemoteAddr: t.peer.Addr, 280 SocketOptions: channelz.GetSocketOption(t.conn), 281 Security: czSecurity, 282 }, 283 ) 284 t.logger = prefixLoggerForServerTransport(t) 285 286 t.controlBuf = newControlBuffer(t.done) 287 if dynamicWindow { 288 t.bdpEst = &bdpEstimator{ 289 bdp: initialWindowSize, 290 updateFlowControl: t.updateFlowControl, 291 } 292 } 293 294 t.connectionID = atomic.AddUint64(&serverConnectionCounter, 1) 295 t.framer.writer.Flush() 296 297 defer func() { 298 if err != nil { 299 t.Close(err) 300 } 301 }() 302 303 // Check the validity of client preface. 304 preface := make([]byte, len(clientPreface)) 305 if _, err := io.ReadFull(t.conn, preface); err != nil { 306 // In deployments where a gRPC server runs behind a cloud load balancer 307 // which performs regular TCP level health checks, the connection is 308 // closed immediately by the latter. Returning io.EOF here allows the 309 // grpc server implementation to recognize this scenario and suppress 310 // logging to reduce spam. 311 if err == io.EOF { 312 return nil, io.EOF 313 } 314 return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) 315 } 316 if !bytes.Equal(preface, clientPreface) { 317 return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams received bogus greeting from client: %q", preface) 318 } 319 320 frame, err := t.framer.fr.ReadFrame() 321 if err == io.EOF || err == io.ErrUnexpectedEOF { 322 return nil, err 323 } 324 if err != nil { 325 return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to read initial settings frame: %v", err) 326 } 327 atomic.StoreInt64(&t.lastRead, time.Now().UnixNano()) 328 sf, ok := frame.(*http2.SettingsFrame) 329 if !ok { 330 return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams saw invalid preface type %T from client", frame) 331 } 332 t.handleSettings(sf) 333 334 go func() { 335 t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger, t.outgoingGoAwayHandler, t.bufferPool) 336 err := t.loopy.run() 337 close(t.loopyWriterDone) 338 if !isIOError(err) { 339 // Close the connection if a non-I/O error occurs (for I/O errors 340 // the reader will also encounter the error and close). Wait 1 341 // second before closing the connection, or when the reader is done 342 // (i.e. the client already closed the connection or a connection 343 // error occurred). This avoids the potential problem where there 344 // is unread data on the receive side of the connection, which, if 345 // closed, would lead to a TCP RST instead of FIN, and the client 346 // encountering errors. For more info: 347 // https://github.com/grpc/grpc-go/issues/5358 348 timer := time.NewTimer(time.Second) 349 defer timer.Stop() 350 select { 351 case <-t.readerDone: 352 case <-timer.C: 353 } 354 t.conn.Close() 355 } 356 }() 357 go t.keepalive() 358 return t, nil 359 } 360 361 // operateHeaders takes action on the decoded headers. Returns an error if fatal 362 // error encountered and transport needs to close, otherwise returns nil. 363 func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*ServerStream)) error { 364 // Acquire max stream ID lock for entire duration 365 t.maxStreamMu.Lock() 366 defer t.maxStreamMu.Unlock() 367 368 streamID := frame.Header().StreamID 369 370 // frame.Truncated is set to true when framer detects that the current header 371 // list size hits MaxHeaderListSize limit. 372 if frame.Truncated { 373 t.controlBuf.put(&cleanupStream{ 374 streamID: streamID, 375 rst: true, 376 rstCode: http2.ErrCodeFrameSize, 377 onWrite: func() {}, 378 }) 379 return nil 380 } 381 382 if streamID%2 != 1 || streamID <= t.maxStreamID { 383 // illegal gRPC stream id. 384 return fmt.Errorf("received an illegal stream id: %v. headers frame: %+v", streamID, frame) 385 } 386 t.maxStreamID = streamID 387 388 buf := newRecvBuffer() 389 s := &ServerStream{ 390 Stream: &Stream{ 391 id: streamID, 392 buf: buf, 393 fc: &inFlow{limit: uint32(t.initialWindowSize)}, 394 }, 395 st: t, 396 headerWireLength: int(frame.Header().Length), 397 } 398 var ( 399 // if false, content-type was missing or invalid 400 isGRPC = false 401 contentType = "" 402 mdata = make(metadata.MD, len(frame.Fields)) 403 httpMethod string 404 // these are set if an error is encountered while parsing the headers 405 protocolError bool 406 headerError *status.Status 407 408 timeoutSet bool 409 timeout time.Duration 410 ) 411 412 for _, hf := range frame.Fields { 413 switch hf.Name { 414 case "content-type": 415 contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value) 416 if !validContentType { 417 contentType = hf.Value 418 break 419 } 420 mdata[hf.Name] = append(mdata[hf.Name], hf.Value) 421 s.contentSubtype = contentSubtype 422 isGRPC = true 423 424 case "grpc-accept-encoding": 425 mdata[hf.Name] = append(mdata[hf.Name], hf.Value) 426 if hf.Value == "" { 427 continue 428 } 429 compressors := hf.Value 430 if s.clientAdvertisedCompressors != "" { 431 compressors = s.clientAdvertisedCompressors + "," + compressors 432 } 433 s.clientAdvertisedCompressors = compressors 434 case "grpc-encoding": 435 s.recvCompress = hf.Value 436 case ":method": 437 httpMethod = hf.Value 438 case ":path": 439 s.method = hf.Value 440 case "grpc-timeout": 441 timeoutSet = true 442 var err error 443 if timeout, err = decodeTimeout(hf.Value); err != nil { 444 headerError = status.Newf(codes.Internal, "malformed grpc-timeout: %v", err) 445 } 446 // "Transports must consider requests containing the Connection header 447 // as malformed." - A41 448 case "connection": 449 if t.logger.V(logLevel) { 450 t.logger.Infof("Received a HEADERS frame with a :connection header which makes the request malformed, as per the HTTP/2 spec") 451 } 452 protocolError = true 453 default: 454 if isReservedHeader(hf.Name) && !isWhitelistedHeader(hf.Name) { 455 break 456 } 457 v, err := decodeMetadataHeader(hf.Name, hf.Value) 458 if err != nil { 459 headerError = status.Newf(codes.Internal, "malformed binary metadata %q in header %q: %v", hf.Value, hf.Name, err) 460 t.logger.Warningf("Failed to decode metadata header (%q, %q): %v", hf.Name, hf.Value, err) 461 break 462 } 463 mdata[hf.Name] = append(mdata[hf.Name], v) 464 } 465 } 466 467 // "If multiple Host headers or multiple :authority headers are present, the 468 // request must be rejected with an HTTP status code 400 as required by Host 469 // validation in RFC 7230 ยง5.4, gRPC status code INTERNAL, or RST_STREAM 470 // with HTTP/2 error code PROTOCOL_ERROR." - A41. Since this is a HTTP/2 471 // error, this takes precedence over a client not speaking gRPC. 472 if len(mdata[":authority"]) > 1 || len(mdata["host"]) > 1 { 473 errMsg := fmt.Sprintf("num values of :authority: %v, num values of host: %v, both must only have 1 value as per HTTP/2 spec", len(mdata[":authority"]), len(mdata["host"])) 474 if t.logger.V(logLevel) { 475 t.logger.Infof("Aborting the stream early: %v", errMsg) 476 } 477 t.controlBuf.put(&earlyAbortStream{ 478 httpStatus: http.StatusBadRequest, 479 streamID: streamID, 480 contentSubtype: s.contentSubtype, 481 status: status.New(codes.Internal, errMsg), 482 rst: !frame.StreamEnded(), 483 }) 484 return nil 485 } 486 487 if protocolError { 488 t.controlBuf.put(&cleanupStream{ 489 streamID: streamID, 490 rst: true, 491 rstCode: http2.ErrCodeProtocol, 492 onWrite: func() {}, 493 }) 494 return nil 495 } 496 if !isGRPC { 497 t.controlBuf.put(&earlyAbortStream{ 498 httpStatus: http.StatusUnsupportedMediaType, 499 streamID: streamID, 500 contentSubtype: s.contentSubtype, 501 status: status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType), 502 rst: !frame.StreamEnded(), 503 }) 504 return nil 505 } 506 if headerError != nil { 507 t.controlBuf.put(&earlyAbortStream{ 508 httpStatus: http.StatusBadRequest, 509 streamID: streamID, 510 contentSubtype: s.contentSubtype, 511 status: headerError, 512 rst: !frame.StreamEnded(), 513 }) 514 return nil 515 } 516 517 // "If :authority is missing, Host must be renamed to :authority." - A41 518 if len(mdata[":authority"]) == 0 { 519 // No-op if host isn't present, no eventual :authority header is a valid 520 // RPC. 521 if host, ok := mdata["host"]; ok { 522 mdata[":authority"] = host 523 delete(mdata, "host") 524 } 525 } else { 526 // "If :authority is present, Host must be discarded" - A41 527 delete(mdata, "host") 528 } 529 530 if frame.StreamEnded() { 531 // s is just created by the caller. No lock needed. 532 s.state = streamReadDone 533 } 534 if timeoutSet { 535 s.ctx, s.cancel = context.WithTimeout(ctx, timeout) 536 } else { 537 s.ctx, s.cancel = context.WithCancel(ctx) 538 } 539 540 // Attach the received metadata to the context. 541 if len(mdata) > 0 { 542 s.ctx = metadata.NewIncomingContext(s.ctx, mdata) 543 } 544 t.mu.Lock() 545 if t.state != reachable { 546 t.mu.Unlock() 547 s.cancel() 548 return nil 549 } 550 if uint32(len(t.activeStreams)) >= t.maxStreams { 551 t.mu.Unlock() 552 t.controlBuf.put(&cleanupStream{ 553 streamID: streamID, 554 rst: true, 555 rstCode: http2.ErrCodeRefusedStream, 556 onWrite: func() {}, 557 }) 558 s.cancel() 559 return nil 560 } 561 if httpMethod != http.MethodPost { 562 t.mu.Unlock() 563 errMsg := fmt.Sprintf("Received a HEADERS frame with :method %q which should be POST", httpMethod) 564 if t.logger.V(logLevel) { 565 t.logger.Infof("Aborting the stream early: %v", errMsg) 566 } 567 t.controlBuf.put(&earlyAbortStream{ 568 httpStatus: http.StatusMethodNotAllowed, 569 streamID: streamID, 570 contentSubtype: s.contentSubtype, 571 status: status.New(codes.Internal, errMsg), 572 rst: !frame.StreamEnded(), 573 }) 574 s.cancel() 575 return nil 576 } 577 if t.inTapHandle != nil { 578 var err error 579 if s.ctx, err = t.inTapHandle(s.ctx, &tap.Info{FullMethodName: s.method, Header: mdata}); err != nil { 580 t.mu.Unlock() 581 if t.logger.V(logLevel) { 582 t.logger.Infof("Aborting the stream early due to InTapHandle failure: %v", err) 583 } 584 stat, ok := status.FromError(err) 585 if !ok { 586 stat = status.New(codes.PermissionDenied, err.Error()) 587 } 588 t.controlBuf.put(&earlyAbortStream{ 589 httpStatus: http.StatusOK, 590 streamID: s.id, 591 contentSubtype: s.contentSubtype, 592 status: stat, 593 rst: !frame.StreamEnded(), 594 }) 595 return nil 596 } 597 } 598 t.activeStreams[streamID] = s 599 if len(t.activeStreams) == 1 { 600 t.idle = time.Time{} 601 } 602 // Start a timer to close the stream on reaching the deadline. 603 if timeoutSet { 604 // We need to wait for s.cancel to be updated before calling 605 // t.closeStream to avoid data races. 606 cancelUpdated := make(chan struct{}) 607 timer := internal.TimeAfterFunc(timeout, func() { 608 <-cancelUpdated 609 t.closeStream(s, true, http2.ErrCodeCancel, false) 610 }) 611 oldCancel := s.cancel 612 s.cancel = func() { 613 oldCancel() 614 timer.Stop() 615 } 616 close(cancelUpdated) 617 } 618 t.mu.Unlock() 619 if channelz.IsOn() { 620 t.channelz.SocketMetrics.StreamsStarted.Add(1) 621 t.channelz.SocketMetrics.LastRemoteStreamCreatedTimestamp.Store(time.Now().UnixNano()) 622 } 623 s.requestRead = func(n int) { 624 t.adjustWindow(s, uint32(n)) 625 } 626 s.ctxDone = s.ctx.Done() 627 s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone) 628 s.trReader = &transportReader{ 629 reader: &recvBufferReader{ 630 ctx: s.ctx, 631 ctxDone: s.ctxDone, 632 recv: s.buf, 633 }, 634 windowHandler: func(n int) { 635 t.updateWindow(s, uint32(n)) 636 }, 637 } 638 // Register the stream with loopy. 639 t.controlBuf.put(®isterStream{ 640 streamID: s.id, 641 wq: s.wq, 642 }) 643 handle(s) 644 return nil 645 } 646 647 // HandleStreams receives incoming streams using the given handler. This is 648 // typically run in a separate goroutine. 649 // traceCtx attaches trace to ctx and returns the new context. 650 func (t *http2Server) HandleStreams(ctx context.Context, handle func(*ServerStream)) { 651 defer func() { 652 close(t.readerDone) 653 <-t.loopyWriterDone 654 }() 655 for { 656 t.controlBuf.throttle() 657 frame, err := t.framer.fr.ReadFrame() 658 atomic.StoreInt64(&t.lastRead, time.Now().UnixNano()) 659 if err != nil { 660 if se, ok := err.(http2.StreamError); ok { 661 if t.logger.V(logLevel) { 662 t.logger.Warningf("Encountered http2.StreamError: %v", se) 663 } 664 t.mu.Lock() 665 s := t.activeStreams[se.StreamID] 666 t.mu.Unlock() 667 if s != nil { 668 t.closeStream(s, true, se.Code, false) 669 } else { 670 t.controlBuf.put(&cleanupStream{ 671 streamID: se.StreamID, 672 rst: true, 673 rstCode: se.Code, 674 onWrite: func() {}, 675 }) 676 } 677 continue 678 } 679 t.Close(err) 680 return 681 } 682 switch frame := frame.(type) { 683 case *http2.MetaHeadersFrame: 684 if err := t.operateHeaders(ctx, frame, handle); err != nil { 685 // Any error processing client headers, e.g. invalid stream ID, 686 // is considered a protocol violation. 687 t.controlBuf.put(&goAway{ 688 code: http2.ErrCodeProtocol, 689 debugData: []byte(err.Error()), 690 closeConn: err, 691 }) 692 continue 693 } 694 case *http2.DataFrame: 695 t.handleData(frame) 696 case *http2.RSTStreamFrame: 697 t.handleRSTStream(frame) 698 case *http2.SettingsFrame: 699 t.handleSettings(frame) 700 case *http2.PingFrame: 701 t.handlePing(frame) 702 case *http2.WindowUpdateFrame: 703 t.handleWindowUpdate(frame) 704 case *http2.GoAwayFrame: 705 // TODO: Handle GoAway from the client appropriately. 706 default: 707 if t.logger.V(logLevel) { 708 t.logger.Infof("Received unsupported frame type %T", frame) 709 } 710 } 711 } 712 } 713 714 func (t *http2Server) getStream(f http2.Frame) (*ServerStream, bool) { 715 t.mu.Lock() 716 defer t.mu.Unlock() 717 if t.activeStreams == nil { 718 // The transport is closing. 719 return nil, false 720 } 721 s, ok := t.activeStreams[f.Header().StreamID] 722 if !ok { 723 // The stream is already done. 724 return nil, false 725 } 726 return s, true 727 } 728 729 // adjustWindow sends out extra window update over the initial window size 730 // of stream if the application is requesting data larger in size than 731 // the window. 732 func (t *http2Server) adjustWindow(s *ServerStream, n uint32) { 733 if w := s.fc.maybeAdjust(n); w > 0 { 734 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w}) 735 } 736 737 } 738 739 // updateWindow adjusts the inbound quota for the stream and the transport. 740 // Window updates will deliver to the controller for sending when 741 // the cumulative quota exceeds the corresponding threshold. 742 func (t *http2Server) updateWindow(s *ServerStream, n uint32) { 743 if w := s.fc.onRead(n); w > 0 { 744 t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, 745 increment: w, 746 }) 747 } 748 } 749 750 // updateFlowControl updates the incoming flow control windows 751 // for the transport and the stream based on the current bdp 752 // estimation. 753 func (t *http2Server) updateFlowControl(n uint32) { 754 t.mu.Lock() 755 for _, s := range t.activeStreams { 756 s.fc.newLimit(n) 757 } 758 t.initialWindowSize = int32(n) 759 t.mu.Unlock() 760 t.controlBuf.put(&outgoingWindowUpdate{ 761 streamID: 0, 762 increment: t.fc.newLimit(n), 763 }) 764 t.controlBuf.put(&outgoingSettings{ 765 ss: []http2.Setting{ 766 { 767 ID: http2.SettingInitialWindowSize, 768 Val: n, 769 }, 770 }, 771 }) 772 773 } 774 775 func (t *http2Server) handleData(f *http2.DataFrame) { 776 size := f.Header().Length 777 var sendBDPPing bool 778 if t.bdpEst != nil { 779 sendBDPPing = t.bdpEst.add(size) 780 } 781 // Decouple connection's flow control from application's read. 782 // An update on connection's flow control should not depend on 783 // whether user application has read the data or not. Such a 784 // restriction is already imposed on the stream's flow control, 785 // and therefore the sender will be blocked anyways. 786 // Decoupling the connection flow control will prevent other 787 // active(fast) streams from starving in presence of slow or 788 // inactive streams. 789 if w := t.fc.onData(size); w > 0 { 790 t.controlBuf.put(&outgoingWindowUpdate{ 791 streamID: 0, 792 increment: w, 793 }) 794 } 795 if sendBDPPing { 796 // Avoid excessive ping detection (e.g. in an L7 proxy) 797 // by sending a window update prior to the BDP ping. 798 if w := t.fc.reset(); w > 0 { 799 t.controlBuf.put(&outgoingWindowUpdate{ 800 streamID: 0, 801 increment: w, 802 }) 803 } 804 t.controlBuf.put(bdpPing) 805 } 806 // Select the right stream to dispatch. 807 s, ok := t.getStream(f) 808 if !ok { 809 return 810 } 811 if s.getState() == streamReadDone { 812 t.closeStream(s, true, http2.ErrCodeStreamClosed, false) 813 return 814 } 815 if size > 0 { 816 if err := s.fc.onData(size); err != nil { 817 t.closeStream(s, true, http2.ErrCodeFlowControl, false) 818 return 819 } 820 if f.Header().Flags.Has(http2.FlagDataPadded) { 821 if w := s.fc.onRead(size - uint32(len(f.Data()))); w > 0 { 822 t.controlBuf.put(&outgoingWindowUpdate{s.id, w}) 823 } 824 } 825 // TODO(bradfitz, zhaoq): A copy is required here because there is no 826 // guarantee f.Data() is consumed before the arrival of next frame. 827 // Can this copy be eliminated? 828 if len(f.Data()) > 0 { 829 pool := t.bufferPool 830 if pool == nil { 831 // Note that this is only supposed to be nil in tests. Otherwise, stream is 832 // always initialized with a BufferPool. 833 pool = mem.DefaultBufferPool() 834 } 835 s.write(recvMsg{buffer: mem.Copy(f.Data(), pool)}) 836 } 837 } 838 if f.StreamEnded() { 839 // Received the end of stream from the client. 840 s.compareAndSwapState(streamActive, streamReadDone) 841 s.write(recvMsg{err: io.EOF}) 842 } 843 } 844 845 func (t *http2Server) handleRSTStream(f *http2.RSTStreamFrame) { 846 // If the stream is not deleted from the transport's active streams map, then do a regular close stream. 847 if s, ok := t.getStream(f); ok { 848 t.closeStream(s, false, 0, false) 849 return 850 } 851 // If the stream is already deleted from the active streams map, then put a cleanupStream item into controlbuf to delete the stream from loopy writer's established streams map. 852 t.controlBuf.put(&cleanupStream{ 853 streamID: f.Header().StreamID, 854 rst: false, 855 rstCode: 0, 856 onWrite: func() {}, 857 }) 858 } 859 860 func (t *http2Server) handleSettings(f *http2.SettingsFrame) { 861 if f.IsAck() { 862 return 863 } 864 var ss []http2.Setting 865 var updateFuncs []func() 866 f.ForeachSetting(func(s http2.Setting) error { 867 switch s.ID { 868 case http2.SettingMaxHeaderListSize: 869 updateFuncs = append(updateFuncs, func() { 870 t.maxSendHeaderListSize = new(uint32) 871 *t.maxSendHeaderListSize = s.Val 872 }) 873 default: 874 ss = append(ss, s) 875 } 876 return nil 877 }) 878 t.controlBuf.executeAndPut(func() bool { 879 for _, f := range updateFuncs { 880 f() 881 } 882 return true 883 }, &incomingSettings{ 884 ss: ss, 885 }) 886 } 887 888 const ( 889 maxPingStrikes = 2 890 defaultPingTimeout = 2 * time.Hour 891 ) 892 893 func (t *http2Server) handlePing(f *http2.PingFrame) { 894 if f.IsAck() { 895 if f.Data == goAwayPing.data && t.drainEvent != nil { 896 t.drainEvent.Fire() 897 return 898 } 899 // Maybe it's a BDP ping. 900 if t.bdpEst != nil { 901 t.bdpEst.calculate(f.Data) 902 } 903 return 904 } 905 pingAck := &ping{ack: true} 906 copy(pingAck.data[:], f.Data[:]) 907 t.controlBuf.put(pingAck) 908 909 now := time.Now() 910 defer func() { 911 t.lastPingAt = now 912 }() 913 // A reset ping strikes means that we don't need to check for policy 914 // violation for this ping and the pingStrikes counter should be set 915 // to 0. 916 if atomic.CompareAndSwapUint32(&t.resetPingStrikes, 1, 0) { 917 t.pingStrikes = 0 918 return 919 } 920 t.mu.Lock() 921 ns := len(t.activeStreams) 922 t.mu.Unlock() 923 if ns < 1 && !t.kep.PermitWithoutStream { 924 // Keepalive shouldn't be active thus, this new ping should 925 // have come after at least defaultPingTimeout. 926 if t.lastPingAt.Add(defaultPingTimeout).After(now) { 927 t.pingStrikes++ 928 } 929 } else { 930 // Check if keepalive policy is respected. 931 if t.lastPingAt.Add(t.kep.MinTime).After(now) { 932 t.pingStrikes++ 933 } 934 } 935 936 if t.pingStrikes > maxPingStrikes { 937 // Send goaway and close the connection. 938 t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: errors.New("got too many pings from the client")}) 939 } 940 } 941 942 func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) { 943 t.controlBuf.put(&incomingWindowUpdate{ 944 streamID: f.Header().StreamID, 945 increment: f.Increment, 946 }) 947 } 948 949 func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) []hpack.HeaderField { 950 for k, vv := range md { 951 if isReservedHeader(k) { 952 // Clients don't tolerate reading restricted headers after some non restricted ones were sent. 953 continue 954 } 955 for _, v := range vv { 956 headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)}) 957 } 958 } 959 return headerFields 960 } 961 962 func (t *http2Server) checkForHeaderListSize(it any) bool { 963 if t.maxSendHeaderListSize == nil { 964 return true 965 } 966 hdrFrame := it.(*headerFrame) 967 var sz int64 968 for _, f := range hdrFrame.hf { 969 if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) { 970 if t.logger.V(logLevel) { 971 t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize) 972 } 973 return false 974 } 975 } 976 return true 977 } 978 979 func (t *http2Server) streamContextErr(s *ServerStream) error { 980 select { 981 case <-t.done: 982 return ErrConnClosing 983 default: 984 } 985 return ContextErr(s.ctx.Err()) 986 } 987 988 // WriteHeader sends the header metadata md back to the client. 989 func (t *http2Server) writeHeader(s *ServerStream, md metadata.MD) error { 990 s.hdrMu.Lock() 991 defer s.hdrMu.Unlock() 992 if s.getState() == streamDone { 993 return t.streamContextErr(s) 994 } 995 996 if s.updateHeaderSent() { 997 return ErrIllegalHeaderWrite 998 } 999 1000 if md.Len() > 0 { 1001 if s.header.Len() > 0 { 1002 s.header = metadata.Join(s.header, md) 1003 } else { 1004 s.header = md 1005 } 1006 } 1007 if err := t.writeHeaderLocked(s); err != nil { 1008 switch e := err.(type) { 1009 case ConnectionError: 1010 return status.Error(codes.Unavailable, e.Desc) 1011 default: 1012 return status.Convert(err).Err() 1013 } 1014 } 1015 return nil 1016 } 1017 1018 func (t *http2Server) setResetPingStrikes() { 1019 atomic.StoreUint32(&t.resetPingStrikes, 1) 1020 } 1021 1022 func (t *http2Server) writeHeaderLocked(s *ServerStream) error { 1023 // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields 1024 // first and create a slice of that exact size. 1025 headerFields := make([]hpack.HeaderField, 0, 2) // at least :status, content-type will be there if none else. 1026 headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"}) 1027 headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: grpcutil.ContentType(s.contentSubtype)}) 1028 if s.sendCompress != "" { 1029 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) 1030 } 1031 headerFields = appendHeaderFieldsFromMD(headerFields, s.header) 1032 hf := &headerFrame{ 1033 streamID: s.id, 1034 hf: headerFields, 1035 endStream: false, 1036 onWrite: t.setResetPingStrikes, 1037 } 1038 success, err := t.controlBuf.executeAndPut(func() bool { return t.checkForHeaderListSize(hf) }, hf) 1039 if !success { 1040 if err != nil { 1041 return err 1042 } 1043 t.closeStream(s, true, http2.ErrCodeInternal, false) 1044 return ErrHeaderListSizeLimitViolation 1045 } 1046 for _, sh := range t.stats { 1047 // Note: Headers are compressed with hpack after this call returns. 1048 // No WireLength field is set here. 1049 outHeader := &stats.OutHeader{ 1050 Header: s.header.Copy(), 1051 Compression: s.sendCompress, 1052 } 1053 sh.HandleRPC(s.Context(), outHeader) 1054 } 1055 return nil 1056 } 1057 1058 // WriteStatus sends stream status to the client and terminates the stream. 1059 // There is no further I/O operations being able to perform on this stream. 1060 // TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early 1061 // OK is adopted. 1062 func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error { 1063 s.hdrMu.Lock() 1064 defer s.hdrMu.Unlock() 1065 1066 if s.getState() == streamDone { 1067 return nil 1068 } 1069 1070 // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields 1071 // first and create a slice of that exact size. 1072 headerFields := make([]hpack.HeaderField, 0, 2) // grpc-status and grpc-message will be there if none else. 1073 if !s.updateHeaderSent() { // No headers have been sent. 1074 if len(s.header) > 0 { // Send a separate header frame. 1075 if err := t.writeHeaderLocked(s); err != nil { 1076 return err 1077 } 1078 } else { // Send a trailer only response. 1079 headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"}) 1080 headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: grpcutil.ContentType(s.contentSubtype)}) 1081 } 1082 } 1083 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status", Value: strconv.Itoa(int(st.Code()))}) 1084 headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())}) 1085 1086 if p := st.Proto(); p != nil && len(p.Details) > 0 { 1087 // Do not use the user's grpc-status-details-bin (if present) if we are 1088 // even attempting to set our own. 1089 delete(s.trailer, grpcStatusDetailsBinHeader) 1090 stBytes, err := proto.Marshal(p) 1091 if err != nil { 1092 // TODO: return error instead, when callers are able to handle it. 1093 t.logger.Errorf("Failed to marshal rpc status: %s, error: %v", pretty.ToJSON(p), err) 1094 } else { 1095 headerFields = append(headerFields, hpack.HeaderField{Name: grpcStatusDetailsBinHeader, Value: encodeBinHeader(stBytes)}) 1096 } 1097 } 1098 1099 // Attach the trailer metadata. 1100 headerFields = appendHeaderFieldsFromMD(headerFields, s.trailer) 1101 trailingHeader := &headerFrame{ 1102 streamID: s.id, 1103 hf: headerFields, 1104 endStream: true, 1105 onWrite: t.setResetPingStrikes, 1106 } 1107 1108 success, err := t.controlBuf.executeAndPut(func() bool { 1109 return t.checkForHeaderListSize(trailingHeader) 1110 }, nil) 1111 if !success { 1112 if err != nil { 1113 return err 1114 } 1115 t.closeStream(s, true, http2.ErrCodeInternal, false) 1116 return ErrHeaderListSizeLimitViolation 1117 } 1118 // Send a RST_STREAM after the trailers if the client has not already half-closed. 1119 rst := s.getState() == streamActive 1120 t.finishStream(s, rst, http2.ErrCodeNo, trailingHeader, true) 1121 for _, sh := range t.stats { 1122 // Note: The trailer fields are compressed with hpack after this call returns. 1123 // No WireLength field is set here. 1124 sh.HandleRPC(s.Context(), &stats.OutTrailer{ 1125 Trailer: s.trailer.Copy(), 1126 }) 1127 } 1128 return nil 1129 } 1130 1131 // Write converts the data into HTTP2 data frame and sends it out. Non-nil error 1132 // is returns if it fails (e.g., framing error, transport error). 1133 func (t *http2Server) write(s *ServerStream, hdr []byte, data mem.BufferSlice, _ *WriteOptions) error { 1134 reader := data.Reader() 1135 1136 if !s.isHeaderSent() { // Headers haven't been written yet. 1137 if err := t.writeHeader(s, nil); err != nil { 1138 _ = reader.Close() 1139 return err 1140 } 1141 } else { 1142 // Writing headers checks for this condition. 1143 if s.getState() == streamDone { 1144 _ = reader.Close() 1145 return t.streamContextErr(s) 1146 } 1147 } 1148 1149 df := &dataFrame{ 1150 streamID: s.id, 1151 h: hdr, 1152 reader: reader, 1153 onEachWrite: t.setResetPingStrikes, 1154 } 1155 if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil { 1156 _ = reader.Close() 1157 return t.streamContextErr(s) 1158 } 1159 if err := t.controlBuf.put(df); err != nil { 1160 _ = reader.Close() 1161 return err 1162 } 1163 t.incrMsgSent() 1164 return nil 1165 } 1166 1167 // keepalive running in a separate goroutine does the following: 1168 // 1. Gracefully closes an idle connection after a duration of keepalive.MaxConnectionIdle. 1169 // 2. Gracefully closes any connection after a duration of keepalive.MaxConnectionAge. 1170 // 3. Forcibly closes a connection after an additive period of keepalive.MaxConnectionAgeGrace over keepalive.MaxConnectionAge. 1171 // 4. Makes sure a connection is alive by sending pings with a frequency of keepalive.Time and closes a non-responsive connection 1172 // after an additional duration of keepalive.Timeout. 1173 func (t *http2Server) keepalive() { 1174 p := &ping{} 1175 // True iff a ping has been sent, and no data has been received since then. 1176 outstandingPing := false 1177 // Amount of time remaining before which we should receive an ACK for the 1178 // last sent ping. 1179 kpTimeoutLeft := time.Duration(0) 1180 // Records the last value of t.lastRead before we go block on the timer. 1181 // This is required to check for read activity since then. 1182 prevNano := time.Now().UnixNano() 1183 // Initialize the different timers to their default values. 1184 idleTimer := time.NewTimer(t.kp.MaxConnectionIdle) 1185 ageTimer := time.NewTimer(t.kp.MaxConnectionAge) 1186 kpTimer := time.NewTimer(t.kp.Time) 1187 defer func() { 1188 // We need to drain the underlying channel in these timers after a call 1189 // to Stop(), only if we are interested in resetting them. Clearly we 1190 // are not interested in resetting them here. 1191 idleTimer.Stop() 1192 ageTimer.Stop() 1193 kpTimer.Stop() 1194 }() 1195 1196 for { 1197 select { 1198 case <-idleTimer.C: 1199 t.mu.Lock() 1200 idle := t.idle 1201 if idle.IsZero() { // The connection is non-idle. 1202 t.mu.Unlock() 1203 idleTimer.Reset(t.kp.MaxConnectionIdle) 1204 continue 1205 } 1206 val := t.kp.MaxConnectionIdle - time.Since(idle) 1207 t.mu.Unlock() 1208 if val <= 0 { 1209 // The connection has been idle for a duration of keepalive.MaxConnectionIdle or more. 1210 // Gracefully close the connection. 1211 t.Drain("max_idle") 1212 return 1213 } 1214 idleTimer.Reset(val) 1215 case <-ageTimer.C: 1216 t.Drain("max_age") 1217 ageTimer.Reset(t.kp.MaxConnectionAgeGrace) 1218 select { 1219 case <-ageTimer.C: 1220 // Close the connection after grace period. 1221 if t.logger.V(logLevel) { 1222 t.logger.Infof("Closing server transport due to maximum connection age") 1223 } 1224 t.controlBuf.put(closeConnection{}) 1225 case <-t.done: 1226 } 1227 return 1228 case <-kpTimer.C: 1229 lastRead := atomic.LoadInt64(&t.lastRead) 1230 if lastRead > prevNano { 1231 // There has been read activity since the last time we were 1232 // here. Setup the timer to fire at kp.Time seconds from 1233 // lastRead time and continue. 1234 outstandingPing = false 1235 kpTimer.Reset(time.Duration(lastRead) + t.kp.Time - time.Duration(time.Now().UnixNano())) 1236 prevNano = lastRead 1237 continue 1238 } 1239 if outstandingPing && kpTimeoutLeft <= 0 { 1240 t.Close(fmt.Errorf("keepalive ping not acked within timeout %s", t.kp.Timeout)) 1241 return 1242 } 1243 if !outstandingPing { 1244 if channelz.IsOn() { 1245 t.channelz.SocketMetrics.KeepAlivesSent.Add(1) 1246 } 1247 t.controlBuf.put(p) 1248 kpTimeoutLeft = t.kp.Timeout 1249 outstandingPing = true 1250 } 1251 // The amount of time to sleep here is the minimum of kp.Time and 1252 // timeoutLeft. This will ensure that we wait only for kp.Time 1253 // before sending out the next ping (for cases where the ping is 1254 // acked). 1255 sleepDuration := min(t.kp.Time, kpTimeoutLeft) 1256 kpTimeoutLeft -= sleepDuration 1257 kpTimer.Reset(sleepDuration) 1258 case <-t.done: 1259 return 1260 } 1261 } 1262 } 1263 1264 // Close starts shutting down the http2Server transport. 1265 // TODO(zhaoq): Now the destruction is not blocked on any pending streams. This 1266 // could cause some resource issue. Revisit this later. 1267 func (t *http2Server) Close(err error) { 1268 t.mu.Lock() 1269 if t.state == closing { 1270 t.mu.Unlock() 1271 return 1272 } 1273 if t.logger.V(logLevel) { 1274 t.logger.Infof("Closing: %v", err) 1275 } 1276 t.state = closing 1277 streams := t.activeStreams 1278 t.activeStreams = nil 1279 t.mu.Unlock() 1280 t.controlBuf.finish() 1281 close(t.done) 1282 if err := t.conn.Close(); err != nil && t.logger.V(logLevel) { 1283 t.logger.Infof("Error closing underlying net.Conn during Close: %v", err) 1284 } 1285 channelz.RemoveEntry(t.channelz.ID) 1286 // Cancel all active streams. 1287 for _, s := range streams { 1288 s.cancel() 1289 } 1290 } 1291 1292 // deleteStream deletes the stream s from transport's active streams. 1293 func (t *http2Server) deleteStream(s *ServerStream, eosReceived bool) { 1294 t.mu.Lock() 1295 if _, ok := t.activeStreams[s.id]; ok { 1296 delete(t.activeStreams, s.id) 1297 if len(t.activeStreams) == 0 { 1298 t.idle = time.Now() 1299 } 1300 } 1301 t.mu.Unlock() 1302 1303 if channelz.IsOn() { 1304 if eosReceived { 1305 t.channelz.SocketMetrics.StreamsSucceeded.Add(1) 1306 } else { 1307 t.channelz.SocketMetrics.StreamsFailed.Add(1) 1308 } 1309 } 1310 } 1311 1312 // finishStream closes the stream and puts the trailing headerFrame into controlbuf. 1313 func (t *http2Server) finishStream(s *ServerStream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) { 1314 // In case stream sending and receiving are invoked in separate 1315 // goroutines (e.g., bi-directional streaming), cancel needs to be 1316 // called to interrupt the potential blocking on other goroutines. 1317 s.cancel() 1318 1319 oldState := s.swapState(streamDone) 1320 if oldState == streamDone { 1321 // If the stream was already done, return. 1322 return 1323 } 1324 1325 hdr.cleanup = &cleanupStream{ 1326 streamID: s.id, 1327 rst: rst, 1328 rstCode: rstCode, 1329 onWrite: func() { 1330 t.deleteStream(s, eosReceived) 1331 }, 1332 } 1333 t.controlBuf.put(hdr) 1334 } 1335 1336 // closeStream clears the footprint of a stream when the stream is not needed any more. 1337 func (t *http2Server) closeStream(s *ServerStream, rst bool, rstCode http2.ErrCode, eosReceived bool) { 1338 // In case stream sending and receiving are invoked in separate 1339 // goroutines (e.g., bi-directional streaming), cancel needs to be 1340 // called to interrupt the potential blocking on other goroutines. 1341 s.cancel() 1342 1343 oldState := s.swapState(streamDone) 1344 if oldState == streamDone { 1345 return 1346 } 1347 t.deleteStream(s, eosReceived) 1348 1349 t.controlBuf.put(&cleanupStream{ 1350 streamID: s.id, 1351 rst: rst, 1352 rstCode: rstCode, 1353 onWrite: func() {}, 1354 }) 1355 } 1356 1357 func (t *http2Server) Drain(debugData string) { 1358 t.mu.Lock() 1359 defer t.mu.Unlock() 1360 if t.drainEvent != nil { 1361 return 1362 } 1363 t.drainEvent = grpcsync.NewEvent() 1364 t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte(debugData), headsUp: true}) 1365 } 1366 1367 var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}} 1368 1369 // Handles outgoing GoAway and returns true if loopy needs to put itself 1370 // in draining mode. 1371 func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { 1372 t.maxStreamMu.Lock() 1373 t.mu.Lock() 1374 if t.state == closing { // TODO(mmukhi): This seems unnecessary. 1375 t.mu.Unlock() 1376 t.maxStreamMu.Unlock() 1377 // The transport is closing. 1378 return false, ErrConnClosing 1379 } 1380 if !g.headsUp { 1381 // Stop accepting more streams now. 1382 t.state = draining 1383 sid := t.maxStreamID 1384 retErr := g.closeConn 1385 if len(t.activeStreams) == 0 { 1386 retErr = errors.New("second GOAWAY written and no active streams left to process") 1387 } 1388 t.mu.Unlock() 1389 t.maxStreamMu.Unlock() 1390 if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil { 1391 return false, err 1392 } 1393 t.framer.writer.Flush() 1394 if retErr != nil { 1395 return false, retErr 1396 } 1397 return true, nil 1398 } 1399 t.mu.Unlock() 1400 t.maxStreamMu.Unlock() 1401 // For a graceful close, send out a GoAway with stream ID of MaxUInt32, 1402 // Follow that with a ping and wait for the ack to come back or a timer 1403 // to expire. During this time accept new streams since they might have 1404 // originated before the GoAway reaches the client. 1405 // After getting the ack or timer expiration send out another GoAway this 1406 // time with an ID of the max stream server intends to process. 1407 if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, g.debugData); err != nil { 1408 return false, err 1409 } 1410 if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil { 1411 return false, err 1412 } 1413 go func() { 1414 timer := time.NewTimer(5 * time.Second) 1415 defer timer.Stop() 1416 select { 1417 case <-t.drainEvent.Done(): 1418 case <-timer.C: 1419 case <-t.done: 1420 return 1421 } 1422 t.controlBuf.put(&goAway{code: g.code, debugData: g.debugData}) 1423 }() 1424 return false, nil 1425 } 1426 1427 func (t *http2Server) socketMetrics() *channelz.EphemeralSocketMetrics { 1428 return &channelz.EphemeralSocketMetrics{ 1429 LocalFlowControlWindow: int64(t.fc.getSize()), 1430 RemoteFlowControlWindow: t.getOutFlowWindow(), 1431 } 1432 } 1433 1434 func (t *http2Server) incrMsgSent() { 1435 if channelz.IsOn() { 1436 t.channelz.SocketMetrics.MessagesSent.Add(1) 1437 t.channelz.SocketMetrics.LastMessageSentTimestamp.Add(1) 1438 } 1439 } 1440 1441 func (t *http2Server) incrMsgRecv() { 1442 if channelz.IsOn() { 1443 t.channelz.SocketMetrics.MessagesReceived.Add(1) 1444 t.channelz.SocketMetrics.LastMessageReceivedTimestamp.Add(1) 1445 } 1446 } 1447 1448 func (t *http2Server) getOutFlowWindow() int64 { 1449 resp := make(chan uint32, 1) 1450 timer := time.NewTimer(time.Second) 1451 defer timer.Stop() 1452 t.controlBuf.put(&outFlowControlSizeRequest{resp}) 1453 select { 1454 case sz := <-resp: 1455 return int64(sz) 1456 case <-t.done: 1457 return -1 1458 case <-timer.C: 1459 return -2 1460 } 1461 } 1462 1463 // Peer returns the peer of the transport. 1464 func (t *http2Server) Peer() *peer.Peer { 1465 return &peer.Peer{ 1466 Addr: t.peer.Addr, 1467 LocalAddr: t.peer.LocalAddr, 1468 AuthInfo: t.peer.AuthInfo, // Can be nil 1469 } 1470 } 1471 1472 func getJitter(v time.Duration) time.Duration { 1473 if v == infinity { 1474 return 0 1475 } 1476 // Generate a jitter between +/- 10% of the value. 1477 r := int64(v / 10) 1478 j := rand.Int64N(2*r) - r 1479 return time.Duration(j) 1480 } 1481 1482 type connectionKey struct{} 1483 1484 // GetConnection gets the connection from the context. 1485 func GetConnection(ctx context.Context) net.Conn { 1486 conn, _ := ctx.Value(connectionKey{}).(net.Conn) 1487 return conn 1488 } 1489 1490 // SetConnection adds the connection to the context to be able to get 1491 // information about the destination ip and port for an incoming RPC. This also 1492 // allows any unary or streaming interceptors to see the connection. 1493 func SetConnection(ctx context.Context, conn net.Conn) context.Context { 1494 return context.WithValue(ctx, connectionKey{}, conn) 1495 }