// requestID returns the request id for stream. func (h *portForwardStreamHandler) requestID(stream httpstream.Stream) string { requestID := stream.Headers().Get(api.PortForwardRequestIDHeader) if len(requestID) == 0 { glog.V(5).Infof("(conn=%p) stream received without %s header", h.conn, api.PortForwardRequestIDHeader) // If we get here, it's because the connection came from an older client // that isn't generating the request id header // (https://github.com/kubernetes/kubernetes/blob/843134885e7e0b360eb5441e85b1410a8b1a7a0c/pkg/client/unversioned/portforward/portforward.go#L258-L287) // // This is a best-effort attempt at supporting older clients. // // When there aren't concurrent new forwarded connections, each connection // will have a pair of streams (data, error), and the stream IDs will be // consecutive odd numbers, e.g. 1 and 3 for the first connection. Convert // the stream ID into a pseudo-request id by taking the stream type and // using id = stream.Identifier() when the stream type is error, // and id = stream.Identifier() - 2 when it's data. // // NOTE: this only works when there are not concurrent new streams from // multiple forwarded connections; it's a best-effort attempt at supporting // old clients that don't generate request ids. If there are concurrent // new connections, it's possible that 1 connection gets streams whose IDs // are not consecutive (e.g. 5 and 9 instead of 5 and 7). streamType := stream.Headers().Get(api.StreamType) switch streamType { case api.StreamTypeError: requestID = strconv.Itoa(int(stream.Identifier())) case api.StreamTypeData: requestID = strconv.Itoa(int(stream.Identifier()) - 2) } glog.V(5).Infof("(conn=%p) automatically assigning request ID=%q from stream type=%s, stream ID=%d", h.conn, requestID, streamType, stream.Identifier()) } return requestID }
// add adds the stream to the portForwardStreamPair. If the pair already // contains a stream for the new stream's type, an error is returned. add // returns true if both the data and error streams for this pair have been // received. func (p *portForwardStreamPair) add(stream httpstream.Stream) (bool, error) { p.lock.Lock() defer p.lock.Unlock() switch stream.Headers().Get(api.StreamType) { case api.StreamTypeError: if p.errorStream != nil { return false, errors.New("error stream already assigned") } p.errorStream = stream case api.StreamTypeData: if p.dataStream != nil { return false, errors.New("data stream already assigned") } p.dataStream = stream } complete := p.errorStream != nil && p.dataStream != nil if complete { close(p.complete) } return complete, nil }