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