stream.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  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. package grpc
  19. import (
  20. "errors"
  21. "io"
  22. "sync"
  23. "time"
  24. "golang.org/x/net/context"
  25. "golang.org/x/net/trace"
  26. "google.golang.org/grpc/balancer"
  27. "google.golang.org/grpc/codes"
  28. "google.golang.org/grpc/encoding"
  29. "google.golang.org/grpc/metadata"
  30. "google.golang.org/grpc/stats"
  31. "google.golang.org/grpc/status"
  32. "google.golang.org/grpc/transport"
  33. )
  34. // StreamHandler defines the handler called by gRPC server to complete the
  35. // execution of a streaming RPC. If a StreamHandler returns an error, it
  36. // should be produced by the status package, or else gRPC will use
  37. // codes.Unknown as the status code and err.Error() as the status message
  38. // of the RPC.
  39. type StreamHandler func(srv interface{}, stream ServerStream) error
  40. // StreamDesc represents a streaming RPC service's method specification.
  41. type StreamDesc struct {
  42. StreamName string
  43. Handler StreamHandler
  44. // At least one of these is true.
  45. ServerStreams bool
  46. ClientStreams bool
  47. }
  48. // Stream defines the common interface a client or server stream has to satisfy.
  49. //
  50. // All errors returned from Stream are compatible with the status package.
  51. type Stream interface {
  52. // Context returns the context for this stream.
  53. Context() context.Context
  54. // SendMsg blocks until it sends m, the stream is done or the stream
  55. // breaks.
  56. // On error, it aborts the stream and returns an RPC status on client
  57. // side. On server side, it simply returns the error to the caller.
  58. // SendMsg is called by generated code. Also Users can call SendMsg
  59. // directly when it is really needed in their use cases.
  60. // It's safe to have a goroutine calling SendMsg and another goroutine calling
  61. // recvMsg on the same stream at the same time.
  62. // But it is not safe to call SendMsg on the same stream in different goroutines.
  63. SendMsg(m interface{}) error
  64. // RecvMsg blocks until it receives a message or the stream is
  65. // done. On client side, it returns io.EOF when the stream is done. On
  66. // any other error, it aborts the stream and returns an RPC status. On
  67. // server side, it simply returns the error to the caller.
  68. // It's safe to have a goroutine calling SendMsg and another goroutine calling
  69. // recvMsg on the same stream at the same time.
  70. // But it is not safe to call RecvMsg on the same stream in different goroutines.
  71. RecvMsg(m interface{}) error
  72. }
  73. // ClientStream defines the interface a client stream has to satisfy.
  74. type ClientStream interface {
  75. // Header returns the header metadata received from the server if there
  76. // is any. It blocks if the metadata is not ready to read.
  77. Header() (metadata.MD, error)
  78. // Trailer returns the trailer metadata from the server, if there is any.
  79. // It must only be called after stream.CloseAndRecv has returned, or
  80. // stream.Recv has returned a non-nil error (including io.EOF).
  81. Trailer() metadata.MD
  82. // CloseSend closes the send direction of the stream. It closes the stream
  83. // when non-nil error is met.
  84. CloseSend() error
  85. // Stream.SendMsg() may return a non-nil error when something wrong happens sending
  86. // the request. The returned error indicates the status of this sending, not the final
  87. // status of the RPC.
  88. //
  89. // Always call Stream.RecvMsg() to drain the stream and get the final
  90. // status, otherwise there could be leaked resources.
  91. Stream
  92. }
  93. // NewStream creates a new Stream for the client side. This is typically
  94. // called by generated code.
  95. func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
  96. // allow interceptor to see all applicable call options, which means those
  97. // configured as defaults from dial option as well as per-call options
  98. opts = combine(cc.dopts.callOptions, opts)
  99. if cc.dopts.streamInt != nil {
  100. return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...)
  101. }
  102. return newClientStream(ctx, desc, cc, method, opts...)
  103. }
  104. // NewClientStream creates a new Stream for the client side. This is typically
  105. // called by generated code.
  106. //
  107. // DEPRECATED: Use ClientConn.NewStream instead.
  108. func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
  109. return cc.NewStream(ctx, desc, method, opts...)
  110. }
  111. func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) {
  112. c := defaultCallInfo()
  113. mc := cc.GetMethodConfig(method)
  114. if mc.WaitForReady != nil {
  115. c.failFast = !*mc.WaitForReady
  116. }
  117. // Possible context leak:
  118. // The cancel function for the child context we create will only be called
  119. // when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
  120. // an error is generated by SendMsg.
  121. // https://github.com/grpc/grpc-go/issues/1818.
  122. var cancel context.CancelFunc
  123. if mc.Timeout != nil && *mc.Timeout >= 0 {
  124. ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)
  125. } else {
  126. ctx, cancel = context.WithCancel(ctx)
  127. }
  128. defer func() {
  129. if err != nil {
  130. cancel()
  131. }
  132. }()
  133. for _, o := range opts {
  134. if err := o.before(c); err != nil {
  135. return nil, toRPCErr(err)
  136. }
  137. }
  138. c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize)
  139. c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
  140. if err := setCallInfoCodec(c); err != nil {
  141. return nil, err
  142. }
  143. callHdr := &transport.CallHdr{
  144. Host: cc.authority,
  145. Method: method,
  146. // If it's not client streaming, we should already have the request to be sent,
  147. // so we don't flush the header.
  148. // If it's client streaming, the user may never send a request or send it any
  149. // time soon, so we ask the transport to flush the header.
  150. Flush: desc.ClientStreams,
  151. ContentSubtype: c.contentSubtype,
  152. }
  153. // Set our outgoing compression according to the UseCompressor CallOption, if
  154. // set. In that case, also find the compressor from the encoding package.
  155. // Otherwise, use the compressor configured by the WithCompressor DialOption,
  156. // if set.
  157. var cp Compressor
  158. var comp encoding.Compressor
  159. if ct := c.compressorType; ct != "" {
  160. callHdr.SendCompress = ct
  161. if ct != encoding.Identity {
  162. comp = encoding.GetCompressor(ct)
  163. if comp == nil {
  164. return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
  165. }
  166. }
  167. } else if cc.dopts.cp != nil {
  168. callHdr.SendCompress = cc.dopts.cp.Type()
  169. cp = cc.dopts.cp
  170. }
  171. if c.creds != nil {
  172. callHdr.Creds = c.creds
  173. }
  174. var trInfo traceInfo
  175. if EnableTracing {
  176. trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
  177. trInfo.firstLine.client = true
  178. if deadline, ok := ctx.Deadline(); ok {
  179. trInfo.firstLine.deadline = deadline.Sub(time.Now())
  180. }
  181. trInfo.tr.LazyLog(&trInfo.firstLine, false)
  182. ctx = trace.NewContext(ctx, trInfo.tr)
  183. defer func() {
  184. if err != nil {
  185. // Need to call tr.finish() if error is returned.
  186. // Because tr will not be returned to caller.
  187. trInfo.tr.LazyPrintf("RPC: [%v]", err)
  188. trInfo.tr.SetError()
  189. trInfo.tr.Finish()
  190. }
  191. }()
  192. }
  193. ctx = newContextWithRPCInfo(ctx, c.failFast)
  194. sh := cc.dopts.copts.StatsHandler
  195. var beginTime time.Time
  196. if sh != nil {
  197. ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast})
  198. beginTime = time.Now()
  199. begin := &stats.Begin{
  200. Client: true,
  201. BeginTime: beginTime,
  202. FailFast: c.failFast,
  203. }
  204. sh.HandleRPC(ctx, begin)
  205. defer func() {
  206. if err != nil {
  207. // Only handle end stats if err != nil.
  208. end := &stats.End{
  209. Client: true,
  210. Error: err,
  211. BeginTime: beginTime,
  212. EndTime: time.Now(),
  213. }
  214. sh.HandleRPC(ctx, end)
  215. }
  216. }()
  217. }
  218. var (
  219. t transport.ClientTransport
  220. s *transport.Stream
  221. done func(balancer.DoneInfo)
  222. )
  223. for {
  224. // Check to make sure the context has expired. This will prevent us from
  225. // looping forever if an error occurs for wait-for-ready RPCs where no data
  226. // is sent on the wire.
  227. select {
  228. case <-ctx.Done():
  229. return nil, toRPCErr(ctx.Err())
  230. default:
  231. }
  232. t, done, err = cc.getTransport(ctx, c.failFast)
  233. if err != nil {
  234. return nil, err
  235. }
  236. s, err = t.NewStream(ctx, callHdr)
  237. if err != nil {
  238. if done != nil {
  239. done(balancer.DoneInfo{Err: err})
  240. done = nil
  241. }
  242. // In the event of any error from NewStream, we never attempted to write
  243. // anything to the wire, so we can retry indefinitely for non-fail-fast
  244. // RPCs.
  245. if !c.failFast {
  246. continue
  247. }
  248. return nil, toRPCErr(err)
  249. }
  250. break
  251. }
  252. cs := &clientStream{
  253. opts: opts,
  254. c: c,
  255. desc: desc,
  256. codec: c.codec,
  257. cp: cp,
  258. comp: comp,
  259. cancel: cancel,
  260. attempt: &csAttempt{
  261. t: t,
  262. s: s,
  263. p: &parser{r: s},
  264. done: done,
  265. dc: cc.dopts.dc,
  266. ctx: ctx,
  267. trInfo: trInfo,
  268. statsHandler: sh,
  269. beginTime: beginTime,
  270. },
  271. }
  272. cs.c.stream = cs
  273. cs.attempt.cs = cs
  274. if desc != unaryStreamDesc {
  275. // Listen on cc and stream contexts to cleanup when the user closes the
  276. // ClientConn or cancels the stream context. In all other cases, an error
  277. // should already be injected into the recv buffer by the transport, which
  278. // the client will eventually receive, and then we will cancel the stream's
  279. // context in clientStream.finish.
  280. go func() {
  281. select {
  282. case <-cc.ctx.Done():
  283. cs.finish(ErrClientConnClosing)
  284. case <-ctx.Done():
  285. cs.finish(toRPCErr(ctx.Err()))
  286. }
  287. }()
  288. }
  289. return cs, nil
  290. }
  291. // clientStream implements a client side Stream.
  292. type clientStream struct {
  293. opts []CallOption
  294. c *callInfo
  295. desc *StreamDesc
  296. codec baseCodec
  297. cp Compressor
  298. comp encoding.Compressor
  299. cancel context.CancelFunc // cancels all attempts
  300. sentLast bool // sent an end stream
  301. mu sync.Mutex // guards finished
  302. finished bool // TODO: replace with atomic cmpxchg or sync.Once?
  303. attempt *csAttempt // the active client stream attempt
  304. // TODO(hedging): hedging will have multiple attempts simultaneously.
  305. }
  306. // csAttempt implements a single transport stream attempt within a
  307. // clientStream.
  308. type csAttempt struct {
  309. cs *clientStream
  310. t transport.ClientTransport
  311. s *transport.Stream
  312. p *parser
  313. done func(balancer.DoneInfo)
  314. dc Decompressor
  315. decomp encoding.Compressor
  316. decompSet bool
  317. ctx context.Context // the application's context, wrapped by stats/tracing
  318. mu sync.Mutex // guards trInfo.tr
  319. // trInfo.tr is set when created (if EnableTracing is true),
  320. // and cleared when the finish method is called.
  321. trInfo traceInfo
  322. statsHandler stats.Handler
  323. beginTime time.Time
  324. }
  325. func (cs *clientStream) Context() context.Context {
  326. // TODO(retry): commit the current attempt (the context has peer-aware data).
  327. return cs.attempt.context()
  328. }
  329. func (cs *clientStream) Header() (metadata.MD, error) {
  330. m, err := cs.attempt.header()
  331. if err != nil {
  332. // TODO(retry): maybe retry on error or commit attempt on success.
  333. err = toRPCErr(err)
  334. cs.finish(err)
  335. }
  336. return m, err
  337. }
  338. func (cs *clientStream) Trailer() metadata.MD {
  339. // TODO(retry): on error, maybe retry (trailers-only).
  340. return cs.attempt.trailer()
  341. }
  342. func (cs *clientStream) SendMsg(m interface{}) (err error) {
  343. // TODO(retry): buffer message for replaying if not committed.
  344. return cs.attempt.sendMsg(m)
  345. }
  346. func (cs *clientStream) RecvMsg(m interface{}) (err error) {
  347. // TODO(retry): maybe retry on error or commit attempt on success.
  348. return cs.attempt.recvMsg(m)
  349. }
  350. func (cs *clientStream) CloseSend() error {
  351. cs.attempt.closeSend()
  352. return nil
  353. }
  354. func (cs *clientStream) finish(err error) {
  355. if err == io.EOF {
  356. // Ending a stream with EOF indicates a success.
  357. err = nil
  358. }
  359. cs.mu.Lock()
  360. if cs.finished {
  361. cs.mu.Unlock()
  362. return
  363. }
  364. cs.finished = true
  365. cs.mu.Unlock()
  366. // TODO(retry): commit current attempt if necessary.
  367. cs.attempt.finish(err)
  368. for _, o := range cs.opts {
  369. o.after(cs.c)
  370. }
  371. cs.cancel()
  372. }
  373. func (a *csAttempt) context() context.Context {
  374. return a.s.Context()
  375. }
  376. func (a *csAttempt) header() (metadata.MD, error) {
  377. return a.s.Header()
  378. }
  379. func (a *csAttempt) trailer() metadata.MD {
  380. return a.s.Trailer()
  381. }
  382. func (a *csAttempt) sendMsg(m interface{}) (err error) {
  383. // TODO Investigate how to signal the stats handling party.
  384. // generate error stats if err != nil && err != io.EOF?
  385. cs := a.cs
  386. defer func() {
  387. // For non-client-streaming RPCs, we return nil instead of EOF on success
  388. // because the generated code requires it. finish is not called; RecvMsg()
  389. // will call it with the stream's status independently.
  390. if err == io.EOF && !cs.desc.ClientStreams {
  391. err = nil
  392. }
  393. if err != nil && err != io.EOF {
  394. // Call finish on the client stream for errors generated by this SendMsg
  395. // call, as these indicate problems created by this client. (Transport
  396. // errors are converted to an io.EOF error below; the real error will be
  397. // returned from RecvMsg eventually in that case, or be retried.)
  398. cs.finish(err)
  399. }
  400. }()
  401. // TODO: Check cs.sentLast and error if we already ended the stream.
  402. if EnableTracing {
  403. a.mu.Lock()
  404. if a.trInfo.tr != nil {
  405. a.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
  406. }
  407. a.mu.Unlock()
  408. }
  409. var outPayload *stats.OutPayload
  410. if a.statsHandler != nil {
  411. outPayload = &stats.OutPayload{
  412. Client: true,
  413. }
  414. }
  415. hdr, data, err := encode(cs.codec, m, cs.cp, outPayload, cs.comp)
  416. if err != nil {
  417. return err
  418. }
  419. if len(data) > *cs.c.maxSendMessageSize {
  420. return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), *cs.c.maxSendMessageSize)
  421. }
  422. if !cs.desc.ClientStreams {
  423. cs.sentLast = true
  424. }
  425. err = a.t.Write(a.s, hdr, data, &transport.Options{Last: !cs.desc.ClientStreams})
  426. if err == nil {
  427. if outPayload != nil {
  428. outPayload.SentTime = time.Now()
  429. a.statsHandler.HandleRPC(a.ctx, outPayload)
  430. }
  431. return nil
  432. }
  433. return io.EOF
  434. }
  435. func (a *csAttempt) recvMsg(m interface{}) (err error) {
  436. cs := a.cs
  437. defer func() {
  438. if err != nil || !cs.desc.ServerStreams {
  439. // err != nil or non-server-streaming indicates end of stream.
  440. cs.finish(err)
  441. }
  442. }()
  443. var inPayload *stats.InPayload
  444. if a.statsHandler != nil {
  445. inPayload = &stats.InPayload{
  446. Client: true,
  447. }
  448. }
  449. if !a.decompSet {
  450. // Block until we receive headers containing received message encoding.
  451. if ct := a.s.RecvCompress(); ct != "" && ct != encoding.Identity {
  452. if a.dc == nil || a.dc.Type() != ct {
  453. // No configured decompressor, or it does not match the incoming
  454. // message encoding; attempt to find a registered compressor that does.
  455. a.dc = nil
  456. a.decomp = encoding.GetCompressor(ct)
  457. }
  458. } else {
  459. // No compression is used; disable our decompressor.
  460. a.dc = nil
  461. }
  462. // Only initialize this state once per stream.
  463. a.decompSet = true
  464. }
  465. err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.c.maxReceiveMessageSize, inPayload, a.decomp)
  466. if err != nil {
  467. if err == io.EOF {
  468. if statusErr := a.s.Status().Err(); statusErr != nil {
  469. return statusErr
  470. }
  471. return io.EOF // indicates successful end of stream.
  472. }
  473. return toRPCErr(err)
  474. }
  475. if EnableTracing {
  476. a.mu.Lock()
  477. if a.trInfo.tr != nil {
  478. a.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
  479. }
  480. a.mu.Unlock()
  481. }
  482. if inPayload != nil {
  483. a.statsHandler.HandleRPC(a.ctx, inPayload)
  484. }
  485. if cs.desc.ServerStreams {
  486. // Subsequent messages should be received by subsequent RecvMsg calls.
  487. return nil
  488. }
  489. // Special handling for non-server-stream rpcs.
  490. // This recv expects EOF or errors, so we don't collect inPayload.
  491. err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.c.maxReceiveMessageSize, nil, a.decomp)
  492. if err == nil {
  493. return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
  494. }
  495. if err == io.EOF {
  496. return a.s.Status().Err() // non-server streaming Recv returns nil on success
  497. }
  498. return toRPCErr(err)
  499. }
  500. func (a *csAttempt) closeSend() {
  501. cs := a.cs
  502. if cs.sentLast {
  503. return
  504. }
  505. cs.sentLast = true
  506. cs.attempt.t.Write(cs.attempt.s, nil, nil, &transport.Options{Last: true})
  507. // We ignore errors from Write. Any error it would return would also be
  508. // returned by a subsequent RecvMsg call, and the user is supposed to always
  509. // finish the stream by calling RecvMsg until it returns err != nil.
  510. }
  511. func (a *csAttempt) finish(err error) {
  512. a.mu.Lock()
  513. a.t.CloseStream(a.s, err)
  514. if a.done != nil {
  515. a.done(balancer.DoneInfo{
  516. Err: err,
  517. BytesSent: true,
  518. BytesReceived: a.s.BytesReceived(),
  519. })
  520. }
  521. if a.statsHandler != nil {
  522. end := &stats.End{
  523. Client: true,
  524. BeginTime: a.beginTime,
  525. EndTime: time.Now(),
  526. Error: err,
  527. }
  528. a.statsHandler.HandleRPC(a.ctx, end)
  529. }
  530. if a.trInfo.tr != nil {
  531. if err == nil {
  532. a.trInfo.tr.LazyPrintf("RPC: [OK]")
  533. } else {
  534. a.trInfo.tr.LazyPrintf("RPC: [%v]", err)
  535. a.trInfo.tr.SetError()
  536. }
  537. a.trInfo.tr.Finish()
  538. a.trInfo.tr = nil
  539. }
  540. a.mu.Unlock()
  541. }
  542. // ServerStream defines the interface a server stream has to satisfy.
  543. type ServerStream interface {
  544. // SetHeader sets the header metadata. It may be called multiple times.
  545. // When call multiple times, all the provided metadata will be merged.
  546. // All the metadata will be sent out when one of the following happens:
  547. // - ServerStream.SendHeader() is called;
  548. // - The first response is sent out;
  549. // - An RPC status is sent out (error or success).
  550. SetHeader(metadata.MD) error
  551. // SendHeader sends the header metadata.
  552. // The provided md and headers set by SetHeader() will be sent.
  553. // It fails if called multiple times.
  554. SendHeader(metadata.MD) error
  555. // SetTrailer sets the trailer metadata which will be sent with the RPC status.
  556. // When called more than once, all the provided metadata will be merged.
  557. SetTrailer(metadata.MD)
  558. Stream
  559. }
  560. // serverStream implements a server side Stream.
  561. type serverStream struct {
  562. ctx context.Context
  563. t transport.ServerTransport
  564. s *transport.Stream
  565. p *parser
  566. codec baseCodec
  567. cp Compressor
  568. dc Decompressor
  569. comp encoding.Compressor
  570. decomp encoding.Compressor
  571. maxReceiveMessageSize int
  572. maxSendMessageSize int
  573. trInfo *traceInfo
  574. statsHandler stats.Handler
  575. mu sync.Mutex // protects trInfo.tr after the service handler runs.
  576. }
  577. func (ss *serverStream) Context() context.Context {
  578. return ss.ctx
  579. }
  580. func (ss *serverStream) SetHeader(md metadata.MD) error {
  581. if md.Len() == 0 {
  582. return nil
  583. }
  584. return ss.s.SetHeader(md)
  585. }
  586. func (ss *serverStream) SendHeader(md metadata.MD) error {
  587. return ss.t.WriteHeader(ss.s, md)
  588. }
  589. func (ss *serverStream) SetTrailer(md metadata.MD) {
  590. if md.Len() == 0 {
  591. return
  592. }
  593. ss.s.SetTrailer(md)
  594. return
  595. }
  596. func (ss *serverStream) SendMsg(m interface{}) (err error) {
  597. defer func() {
  598. if ss.trInfo != nil {
  599. ss.mu.Lock()
  600. if ss.trInfo.tr != nil {
  601. if err == nil {
  602. ss.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
  603. } else {
  604. ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
  605. ss.trInfo.tr.SetError()
  606. }
  607. }
  608. ss.mu.Unlock()
  609. }
  610. if err != nil && err != io.EOF {
  611. st, _ := status.FromError(toRPCErr(err))
  612. ss.t.WriteStatus(ss.s, st)
  613. }
  614. }()
  615. var outPayload *stats.OutPayload
  616. if ss.statsHandler != nil {
  617. outPayload = &stats.OutPayload{}
  618. }
  619. hdr, data, err := encode(ss.codec, m, ss.cp, outPayload, ss.comp)
  620. if err != nil {
  621. return err
  622. }
  623. if len(data) > ss.maxSendMessageSize {
  624. return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(data), ss.maxSendMessageSize)
  625. }
  626. if err := ss.t.Write(ss.s, hdr, data, &transport.Options{Last: false}); err != nil {
  627. return toRPCErr(err)
  628. }
  629. if outPayload != nil {
  630. outPayload.SentTime = time.Now()
  631. ss.statsHandler.HandleRPC(ss.s.Context(), outPayload)
  632. }
  633. return nil
  634. }
  635. func (ss *serverStream) RecvMsg(m interface{}) (err error) {
  636. defer func() {
  637. if ss.trInfo != nil {
  638. ss.mu.Lock()
  639. if ss.trInfo.tr != nil {
  640. if err == nil {
  641. ss.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
  642. } else if err != io.EOF {
  643. ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
  644. ss.trInfo.tr.SetError()
  645. }
  646. }
  647. ss.mu.Unlock()
  648. }
  649. if err != nil && err != io.EOF {
  650. st, _ := status.FromError(toRPCErr(err))
  651. ss.t.WriteStatus(ss.s, st)
  652. }
  653. }()
  654. var inPayload *stats.InPayload
  655. if ss.statsHandler != nil {
  656. inPayload = &stats.InPayload{}
  657. }
  658. if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, inPayload, ss.decomp); err != nil {
  659. if err == io.EOF {
  660. return err
  661. }
  662. if err == io.ErrUnexpectedEOF {
  663. err = status.Errorf(codes.Internal, io.ErrUnexpectedEOF.Error())
  664. }
  665. return toRPCErr(err)
  666. }
  667. if inPayload != nil {
  668. ss.statsHandler.HandleRPC(ss.s.Context(), inPayload)
  669. }
  670. return nil
  671. }
  672. // MethodFromServerStream returns the method string for the input stream.
  673. // The returned string is in the format of "/service/method".
  674. func MethodFromServerStream(stream ServerStream) (string, bool) {
  675. s := serverTransportStreamFromContext(stream.Context())
  676. if s == nil {
  677. return "", false
  678. }
  679. return s.Method(), true
  680. }