summaryrefslogtreecommitdiffstats
path: root/vendor/google.golang.org/grpc/transport/transport.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/grpc/transport/transport.go')
-rw-r--r--vendor/google.golang.org/grpc/transport/transport.go37
1 files changed, 31 insertions, 6 deletions
diff --git a/vendor/google.golang.org/grpc/transport/transport.go b/vendor/google.golang.org/grpc/transport/transport.go
index 2f643a3d0..f51f87888 100644
--- a/vendor/google.golang.org/grpc/transport/transport.go
+++ b/vendor/google.golang.org/grpc/transport/transport.go
@@ -185,13 +185,20 @@ type Stream struct {
headerChan chan struct{} // closed to indicate the end of header metadata.
headerDone uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
- header metadata.MD // the received header metadata.
- trailer metadata.MD // the key-value map of trailer metadata.
- headerOk bool // becomes true from the first header is about to send
- state streamState
+ // hdrMu protects header and trailer metadata on the server-side.
+ hdrMu sync.Mutex
+ header metadata.MD // the received header metadata.
+ trailer metadata.MD // the key-value map of trailer metadata.
- status *status.Status // the status error received from the server
+ // On the server-side, headerSent is atomically set to 1 when the headers are sent out.
+ headerSent uint32
+
+ state streamState
+
+ // On client-side it is the status error received from the server.
+ // On server-side it is unused.
+ status *status.Status
bytesReceived uint32 // indicates whether any bytes have been received on this stream
unprocessed uint32 // set if the server sends a refused stream or GOAWAY including this stream
@@ -201,6 +208,17 @@ type Stream struct {
contentSubtype string
}
+// isHeaderSent is only valid on the server-side.
+func (s *Stream) isHeaderSent() bool {
+ return atomic.LoadUint32(&s.headerSent) == 1
+}
+
+// updateHeaderSent updates headerSent and returns true
+// if it was alreay set. It is valid only on server-side.
+func (s *Stream) updateHeaderSent() bool {
+ return atomic.SwapUint32(&s.headerSent, 1) == 1
+}
+
func (s *Stream) swapState(st streamState) streamState {
return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
}
@@ -313,10 +331,12 @@ func (s *Stream) SetHeader(md metadata.MD) error {
if md.Len() == 0 {
return nil
}
- if s.headerOk || atomic.LoadUint32((*uint32)(&s.state)) == uint32(streamDone) {
+ if s.isHeaderSent() || s.getState() == streamDone {
return ErrIllegalHeaderWrite
}
+ s.hdrMu.Lock()
s.header = metadata.Join(s.header, md)
+ s.hdrMu.Unlock()
return nil
}
@@ -335,7 +355,12 @@ func (s *Stream) SetTrailer(md metadata.MD) error {
if md.Len() == 0 {
return nil
}
+ if s.getState() == streamDone {
+ return ErrIllegalHeaderWrite
+ }
+ s.hdrMu.Lock()
s.trailer = metadata.Join(s.trailer, md)
+ s.hdrMu.Unlock()
return nil
}