github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/Godeps/_workspace/src/google.golang.org/grpc/stream.go (about) 1 /* 2 * 3 * Copyright 2014, Google Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following disclaimer 14 * in the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Google Inc. nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34 package grpc 35 36 import ( 37 "errors" 38 "io" 39 "sync" 40 "time" 41 42 "golang.org/x/net/context" 43 "golang.org/x/net/trace" 44 "google.golang.org/grpc/codes" 45 "google.golang.org/grpc/metadata" 46 "google.golang.org/grpc/transport" 47 ) 48 49 type streamHandler func(srv interface{}, stream ServerStream) error 50 51 // StreamDesc represents a streaming RPC service's method specification. 52 type StreamDesc struct { 53 StreamName string 54 Handler streamHandler 55 56 // At least one of these is true. 57 ServerStreams bool 58 ClientStreams bool 59 } 60 61 // Stream defines the common interface a client or server stream has to satisfy. 62 type Stream interface { 63 // Context returns the context for this stream. 64 Context() context.Context 65 // SendMsg blocks until it sends m, the stream is done or the stream 66 // breaks. 67 // On error, it aborts the stream and returns an RPC status on client 68 // side. On server side, it simply returns the error to the caller. 69 // SendMsg is called by generated code. 70 SendMsg(m interface{}) error 71 // RecvMsg blocks until it receives a message or the stream is 72 // done. On client side, it returns io.EOF when the stream is done. On 73 // any other error, it aborts the streama nd returns an RPC status. On 74 // server side, it simply returns the error to the caller. 75 RecvMsg(m interface{}) error 76 } 77 78 // ClientStream defines the interface a client stream has to satify. 79 type ClientStream interface { 80 // Header returns the header metedata received from the server if there 81 // is any. It blocks if the metadata is not ready to read. 82 Header() (metadata.MD, error) 83 // Trailer returns the trailer metadata from the server. It must be called 84 // after stream.Recv() returns non-nil error (including io.EOF) for 85 // bi-directional streaming and server streaming or stream.CloseAndRecv() 86 // returns for client streaming in order to receive trailer metadata if 87 // present. Otherwise, it could returns an empty MD even though trailer 88 // is present. 89 Trailer() metadata.MD 90 // CloseSend closes the send direction of the stream. It closes the stream 91 // when non-nil error is met. 92 CloseSend() error 93 Stream 94 } 95 96 // NewClientStream creates a new Stream for the client side. This is called 97 // by generated code. 98 func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) { 99 var ( 100 t transport.ClientTransport 101 err error 102 ) 103 t, err = cc.dopts.picker.Pick(ctx) 104 if err != nil { 105 return nil, toRPCErr(err) 106 } 107 // TODO(zhaoq): CallOption is omitted. Add support when it is needed. 108 callHdr := &transport.CallHdr{ 109 Host: cc.authority, 110 Method: method, 111 } 112 cs := &clientStream{ 113 desc: desc, 114 codec: cc.dopts.codec, 115 tracing: EnableTracing, 116 } 117 if cs.tracing { 118 cs.trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method) 119 cs.trInfo.firstLine.client = true 120 if deadline, ok := ctx.Deadline(); ok { 121 cs.trInfo.firstLine.deadline = deadline.Sub(time.Now()) 122 } 123 cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false) 124 ctx = trace.NewContext(ctx, cs.trInfo.tr) 125 } 126 s, err := t.NewStream(ctx, callHdr) 127 if err != nil { 128 cs.finish(err) 129 return nil, toRPCErr(err) 130 } 131 cs.t = t 132 cs.s = s 133 cs.p = &parser{s: s} 134 // Listen on ctx.Done() to detect cancellation when there is no pending 135 // I/O operations on this stream. 136 go func() { 137 select { 138 case <-t.Error(): 139 // Incur transport error, simply exit. 140 case <-s.Context().Done(): 141 err := s.Context().Err() 142 cs.finish(err) 143 cs.closeTransportStream(transport.ContextErr(err)) 144 } 145 }() 146 return cs, nil 147 } 148 149 // clientStream implements a client side Stream. 150 type clientStream struct { 151 t transport.ClientTransport 152 s *transport.Stream 153 p *parser 154 desc *StreamDesc 155 codec Codec 156 157 tracing bool // set to EnableTracing when the clientStream is created. 158 159 mu sync.Mutex 160 closed bool 161 // trInfo.tr is set when the clientStream is created (if EnableTracing is true), 162 // and is set to nil when the clientStream's finish method is called. 163 trInfo traceInfo 164 } 165 166 func (cs *clientStream) Context() context.Context { 167 return cs.s.Context() 168 } 169 170 func (cs *clientStream) Header() (metadata.MD, error) { 171 m, err := cs.s.Header() 172 if err != nil { 173 if _, ok := err.(transport.ConnectionError); !ok { 174 cs.closeTransportStream(err) 175 } 176 } 177 return m, err 178 } 179 180 func (cs *clientStream) Trailer() metadata.MD { 181 return cs.s.Trailer() 182 } 183 184 func (cs *clientStream) SendMsg(m interface{}) (err error) { 185 if cs.tracing { 186 cs.mu.Lock() 187 if cs.trInfo.tr != nil { 188 cs.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) 189 } 190 cs.mu.Unlock() 191 } 192 defer func() { 193 if err == nil || err == io.EOF { 194 return 195 } 196 if _, ok := err.(transport.ConnectionError); !ok { 197 cs.closeTransportStream(err) 198 } 199 err = toRPCErr(err) 200 }() 201 out, err := encode(cs.codec, m, compressionNone) 202 if err != nil { 203 return transport.StreamErrorf(codes.Internal, "grpc: %v", err) 204 } 205 return cs.t.Write(cs.s, out, &transport.Options{Last: false}) 206 } 207 208 func (cs *clientStream) RecvMsg(m interface{}) (err error) { 209 err = recv(cs.p, cs.codec, m) 210 defer func() { 211 // err != nil indicates the termination of the stream. 212 if err != nil { 213 cs.finish(err) 214 } 215 }() 216 if err == nil { 217 if cs.tracing { 218 cs.mu.Lock() 219 if cs.trInfo.tr != nil { 220 cs.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) 221 } 222 cs.mu.Unlock() 223 } 224 if !cs.desc.ClientStreams || cs.desc.ServerStreams { 225 return 226 } 227 // Special handling for client streaming rpc. 228 err = recv(cs.p, cs.codec, m) 229 cs.closeTransportStream(err) 230 if err == nil { 231 return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>")) 232 } 233 if err == io.EOF { 234 if cs.s.StatusCode() == codes.OK { 235 return nil 236 } 237 return Errorf(cs.s.StatusCode(), cs.s.StatusDesc()) 238 } 239 return toRPCErr(err) 240 } 241 if _, ok := err.(transport.ConnectionError); !ok { 242 cs.closeTransportStream(err) 243 } 244 if err == io.EOF { 245 if cs.s.StatusCode() == codes.OK { 246 // Returns io.EOF to indicate the end of the stream. 247 return 248 } 249 return Errorf(cs.s.StatusCode(), cs.s.StatusDesc()) 250 } 251 return toRPCErr(err) 252 } 253 254 func (cs *clientStream) CloseSend() (err error) { 255 err = cs.t.Write(cs.s, nil, &transport.Options{Last: true}) 256 if err == nil || err == io.EOF { 257 return 258 } 259 if _, ok := err.(transport.ConnectionError); !ok { 260 cs.closeTransportStream(err) 261 } 262 err = toRPCErr(err) 263 return 264 } 265 266 func (cs *clientStream) closeTransportStream(err error) { 267 cs.mu.Lock() 268 if cs.closed { 269 cs.mu.Unlock() 270 return 271 } 272 cs.closed = true 273 cs.mu.Unlock() 274 cs.t.CloseStream(cs.s, err) 275 } 276 277 func (cs *clientStream) finish(err error) { 278 if !cs.tracing { 279 return 280 } 281 cs.mu.Lock() 282 defer cs.mu.Unlock() 283 if cs.trInfo.tr != nil { 284 if err == nil || err == io.EOF { 285 cs.trInfo.tr.LazyPrintf("RPC: [OK]") 286 } else { 287 cs.trInfo.tr.LazyPrintf("RPC: [%v]", err) 288 cs.trInfo.tr.SetError() 289 } 290 cs.trInfo.tr.Finish() 291 cs.trInfo.tr = nil 292 } 293 } 294 295 // ServerStream defines the interface a server stream has to satisfy. 296 type ServerStream interface { 297 // SendHeader sends the header metadata. It should not be called 298 // after SendProto. It fails if called multiple times or if 299 // called after SendProto. 300 SendHeader(metadata.MD) error 301 // SetTrailer sets the trailer metadata which will be sent with the 302 // RPC status. 303 SetTrailer(metadata.MD) 304 Stream 305 } 306 307 // serverStream implements a server side Stream. 308 type serverStream struct { 309 t transport.ServerTransport 310 s *transport.Stream 311 p *parser 312 codec Codec 313 statusCode codes.Code 314 statusDesc string 315 trInfo *traceInfo 316 317 mu sync.Mutex // protects trInfo.tr after the service handler runs. 318 } 319 320 func (ss *serverStream) Context() context.Context { 321 return ss.s.Context() 322 } 323 324 func (ss *serverStream) SendHeader(md metadata.MD) error { 325 return ss.t.WriteHeader(ss.s, md) 326 } 327 328 func (ss *serverStream) SetTrailer(md metadata.MD) { 329 if md.Len() == 0 { 330 return 331 } 332 ss.s.SetTrailer(md) 333 return 334 } 335 336 func (ss *serverStream) SendMsg(m interface{}) (err error) { 337 defer func() { 338 if ss.trInfo != nil { 339 ss.mu.Lock() 340 if ss.trInfo.tr != nil { 341 if err == nil { 342 ss.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true) 343 } else { 344 ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) 345 ss.trInfo.tr.SetError() 346 } 347 } 348 ss.mu.Unlock() 349 } 350 }() 351 out, err := encode(ss.codec, m, compressionNone) 352 if err != nil { 353 err = transport.StreamErrorf(codes.Internal, "grpc: %v", err) 354 return err 355 } 356 return ss.t.Write(ss.s, out, &transport.Options{Last: false}) 357 } 358 359 func (ss *serverStream) RecvMsg(m interface{}) (err error) { 360 defer func() { 361 if ss.trInfo != nil { 362 ss.mu.Lock() 363 if ss.trInfo.tr != nil { 364 if err == nil { 365 ss.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true) 366 } else if err != io.EOF { 367 ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) 368 ss.trInfo.tr.SetError() 369 } 370 } 371 ss.mu.Unlock() 372 } 373 }() 374 return recv(ss.p, ss.codec, m) 375 }