func (g *grpcServer) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, codec grpc.Codec, opts *transport.Options) error { p, err := encode(codec, msg, nil, nil) if err != nil { log.Fatalf("grpc: Server failed to encode response %v", err) } return t.Write(stream, p, opts) }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc) (err error) { ss := &serverStream{ t: t, s: stream, p: &parser{s: stream}, codec: s.opts.codec, tracing: EnableTracing, } if ss.tracing { ss.traceInfo.tr = trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) ss.traceInfo.firstLine.client = false ss.traceInfo.tr.LazyLog(&ss.traceInfo.firstLine, false) defer func() { ss.mu.Lock() if err != nil && err != io.EOF { ss.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) ss.traceInfo.tr.SetError() } ss.traceInfo.tr.Finish() ss.traceInfo.tr = nil ss.mu.Unlock() }() } if appErr := sd.Handler(srv.server, ss); appErr != nil { if err, ok := appErr.(rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options) error { var ( cbuf *bytes.Buffer outPayload *stats.OutPayload ) if cp != nil { cbuf = new(bytes.Buffer) } if stats.On() { outPayload = &stats.OutPayload{} } p, err := encode(s.opts.codec, msg, cp, cbuf, outPayload) if err != nil { // This typically indicates a fatal issue (e.g., memory // corruption or hardware faults) the application program // cannot handle. // // TODO(zhaoq): There exist other options also such as only closing the // faulty stream locally and remotely (Other streams can keep going). Find // the optimal option. grpclog.Fatalf("grpc: Server failed to encode response %v", err) } err = t.Write(stream, p, opts) if err == nil && outPayload != nil { outPayload.SentTime = time.Now() stats.HandleRPC(stream.Context(), outPayload) } return err }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { var cp Compressor if s.opts.cg != nil { cp = s.opts.cg() stream.SetSendCompress(cp.Type()) } ss := &serverStream{ t: t, s: stream, p: &parser{s: stream}, codec: s.opts.codec, cp: cp, dg: s.opts.dg, trInfo: trInfo, } if cp != nil { ss.cbuf = new(bytes.Buffer) } if trInfo != nil { trInfo.tr.LazyLog(&trInfo.firstLine, false) defer func() { ss.mu.Lock() if err != nil && err != io.EOF { ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) ss.trInfo.tr.SetError() } ss.trInfo.tr.Finish() ss.trInfo.tr = nil ss.mu.Unlock() }() } if appErr := sd.Handler(srv.server, ss); appErr != nil { if err, ok := appErr.(rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else if err, ok := appErr.(transport.StreamError); ok { ss.statusCode = err.Code ss.statusDesc = err.Desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } if trInfo != nil { ss.mu.Lock() if ss.statusCode != codes.OK { ss.trInfo.tr.LazyLog(stringer(ss.statusDesc), true) ss.trInfo.tr.SetError() } else { ss.trInfo.tr.LazyLog(stringer("OK"), false) } ss.mu.Unlock() } return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (g *grpcServer) processStream(t transport.ServerTransport, stream *transport.Stream, service *service, mtype *methodType, codec grpc.Codec, ct string, ctx context.Context) (err error) { opts := g.opts r := &rpcRequest{ service: opts.Name, contentType: ct, method: stream.Method(), stream: true, } ss := &rpcStream{ request: r, t: t, s: stream, p: &parser{r: stream}, codec: codec, maxMsgSize: defaultMaxMsgSize, } function := mtype.method.Func var returnValues []reflect.Value // Invoke the method, providing a new value for the reply. fn := func(ctx context.Context, req server.Request, stream interface{}) error { returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(stream)}) if err := returnValues[0].Interface(); err != nil { return err.(error) } return nil } for i := len(opts.HdlrWrappers); i > 0; i-- { fn = opts.HdlrWrappers[i-1](fn) } appErr := fn(ctx, r, ss) if appErr != nil { if err, ok := appErr.(*rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else if err, ok := appErr.(transport.StreamError); ok { ss.statusCode = err.Code ss.statusDesc = err.Desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (s *Server) serveStreams(st transport.ServerTransport) { defer s.removeConn(st) defer st.Close() var wg sync.WaitGroup st.HandleStreams(func(stream *transport.Stream) { wg.Add(1) go func() { defer wg.Done() s.handleStream(st, stream, s.traceInfo(st, stream)) }() }) wg.Wait() }
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, pf payloadFormat, opts *transport.Options) error { p, err := encode(s.opts.codec, msg, pf) if err != nil { // This typically indicates a fatal issue (e.g., memory // corruption or hardware faults) the application program // cannot handle. // // TODO(zhaoq): There exist other options also such as only closing the // faulty stream locally and remotely (Other streams can keep going). Find // the optimal option. log.Fatalf("grpc: Server failed to encode response %v", err) } return t.Write(stream, p, opts) }
// ProxyStream performs a forward of a gRPC frontend stream to a backend. func ProxyStream(director StreamDirector, logger grpclog.Logger, frontTrans transport.ServerTransport, frontStream *transport.Stream) { backendTrans, backendStream, err := backendTransportStream(director, frontStream.Context()) if err != nil { frontTrans.WriteStatus(frontStream, grpc.Code(err), grpc.ErrorDesc(err)) logger.Printf("proxy: Proxy.handleStream %v failed to allocate backend: %v", frontStream.Method(), err) return } defer backendTrans.CloseStream(backendStream, nil) // data coming from client call to backend ingressPathChan := forwardDataFrames(frontStream, backendStream, backendTrans) // custom header handling *must* be after some data is processed by the backend, otherwise there's a deadlock headerMd, err := backendStream.Header() if err == nil && len(headerMd) > 0 { frontTrans.WriteHeader(frontStream, headerMd) } // data coming from backend back to client call egressPathChan := forwardDataFrames(backendStream, frontStream, frontTrans) // wait for both data streams to complete. egressErr := <-egressPathChan ingressErr := <-ingressPathChan if egressErr != io.EOF || ingressErr != io.EOF { logger.Printf("proxy: Proxy.handleStream %v failure during transfer ingres: %v egress: %v", frontStream.Method(), ingressErr, egressErr) frontTrans.WriteStatus(frontStream, codes.Unavailable, fmt.Sprintf("problem in transfer ingress: %v egress: %v", ingressErr, egressErr)) return } // handle trailing metadata trailingMd := backendStream.Trailer() if len(trailingMd) > 0 { frontStream.SetTrailer(trailingMd) } frontTrans.WriteStatus(frontStream, backendStream.StatusCode(), backendStream.StatusDesc()) }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc) { ss := &serverStream{ t: t, s: stream, p: &parser{s: stream}, } if err := sd.Handler(srv.server, ss); err != nil { ss.statusCode = convertCode(err) ss.statusDesc = err.Error() } if err := t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc); err != nil { log.Printf("grpc: Server.processStreamingRPC failed to write status: %v", err) } }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc) (err error) { ss := &serverStream{ t: t, s: stream, p: &parser{s: stream}, codec: s.opts.codec, tracing: EnableTracing, } if ss.tracing { ss.traceInfo.tr = stream.Trace() ss.traceInfo.firstLine.client = false ss.traceInfo.firstLine.remoteAddr = t.RemoteAddr() if dl, ok := stream.Context().Deadline(); ok { ss.traceInfo.firstLine.deadline = dl.Sub(time.Now()) } ss.traceInfo.tr.LazyLog(&ss.traceInfo.firstLine, false) defer func() { ss.mu.Lock() if err != nil && err != io.EOF { ss.traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) ss.traceInfo.tr.SetError() } ss.traceInfo.tr.Finish() ss.traceInfo.tr = nil ss.mu.Unlock() }() } if appErr := sd.Handler(srv.server, ss); appErr != nil { if err, ok := appErr.(rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } if ss.tracing { ss.mu.Lock() if ss.statusCode != codes.OK { ss.traceInfo.tr.LazyLog(stringer(ss.statusDesc), true) ss.traceInfo.tr.SetError() } else { ss.traceInfo.tr.LazyLog(stringer("OK"), false) } ss.mu.Unlock() } return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (s *Proxy) handleStream(frontTrans transport.ServerTransport, frontStream *transport.Stream) { sm := frontStream.Method() if sm != "" && sm[0] == '/' { sm = sm[1:] } pos := strings.LastIndex(sm, "/") if pos == -1 { if err := frontTrans.WriteStatus(frontStream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", frontStream.Method())); err != nil { s.logger.Printf("proxy: Proxy.handleStream failed to write status: %v", err) } return } ProxyStream(s.director, s.logger, frontTrans, frontStream) }
// traceInfo returns a traceInfo and associates it with stream, if tracing is enabled. // If tracing is not enabled, it returns nil. func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Stream) (trInfo *traceInfo) { if !EnableTracing { return nil } trInfo = &traceInfo{ tr: trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()), } trInfo.firstLine.client = false trInfo.firstLine.remoteAddr = st.RemoteAddr() stream.TraceContext(trInfo.tr) if dl, ok := stream.Context().Deadline(); ok { trInfo.firstLine.deadline = dl.Sub(time.Now()) } return trInfo }
// traceInfo returns a traceInfo and associates it with stream, if tracing is enabled. // If tracing is not enabled, it returns nil. func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Stream) (trInfo *traceInfo) { tr, ok := trace.FromContext(stream.Context()) if !ok { return nil } trInfo = &traceInfo{ tr: tr, } trInfo.firstLine.client = false trInfo.firstLine.remoteAddr = st.RemoteAddr() if dl, ok := stream.Context().Deadline(); ok { trInfo.firstLine.deadline = dl.Sub(time.Now()) } return trInfo }
func (s *Server) serveStreams(st transport.ServerTransport) { defer s.removeConn(st) defer st.Close() var wg sync.WaitGroup // 可以认为: 在Transport上维持一个长连接,然后接下来就处理一个个Request/Stream st.HandleStreams(func(stream *transport.Stream) { wg.Add(1) go func() { defer wg.Done() // stream是不是一个个被分割的请求 // 将st的Stream交给s进行处理 s.handleStream(st, stream, s.traceInfo(st, stream)) }() }) wg.Wait() }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc) { ss := &serverStream{ t: t, s: stream, p: &parser{s: stream}, codec: s.opts.codec, } if appErr := sd.Handler(srv.server, ss); appErr != nil { if err, ok := appErr.(rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (s *Server) serveStreams(st transport.ServerTransport) { defer s.removeConn(st) defer st.Close() var wg sync.WaitGroup st.HandleStreams(func(stream *transport.Stream) { wg.Add(1) go func() { defer wg.Done() s.handleStream(st, stream, s.traceInfo(st, stream)) }() }, func(ctx context.Context, method string) context.Context { if !EnableTracing { return ctx } tr := trace.New("grpc.Recv."+methodFamily(method), method) return trace.NewContext(ctx, tr) }) wg.Wait() }
func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream) { sm := stream.Method() if sm != "" && sm[0] == '/' { sm = sm[1:] } pos := strings.LastIndex(sm, "/") if pos == -1 { if err := t.WriteStatus(stream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", stream.Method())); err != nil { log.Printf("grpc: Server.handleStream failed to write status: %v", err) } return } service := sm[:pos] method := sm[pos+1:] srv, ok := s.m[service] if !ok { if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil { log.Printf("grpc: Server.handleStream failed to write status: %v", err) } return } // Unary RPC or Streaming RPC? if md, ok := srv.md[method]; ok { s.processUnaryRPC(t, stream, srv, md) return } if sd, ok := srv.sd[method]; ok { s.processStreamingRPC(t, stream, srv, sd) return } if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown method %v", method)); err != nil { log.Printf("grpc: Server.handleStream failed to write status: %v", err) } }
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc) { p := &parser{s: stream} for { pf, req, err := p.recvMsg() if err == io.EOF { // The entire stream is done (for unary RPC only). return } if err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return } switch pf { case compressionNone: reply, appErr := md.Handler(srv.server, stream.Context(), req) if appErr != nil { if err := t.WriteStatus(stream, convertCode(appErr), appErr.Error()); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) } return } opts := &transport.Options{ Last: true, Delay: false, } statusCode := codes.OK statusDesc := "" if err := s.sendProto(t, stream, reply, compressionNone, opts); err != nil { if _, ok := err.(transport.ConnectionError); ok { return } if e, ok := err.(transport.StreamError); ok { statusCode = e.Code statusDesc = e.Desc } else { statusCode = codes.Unknown statusDesc = err.Error() } } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) } default: panic(fmt.Sprintf("payload format to be supported: %d", pf)) } } }
func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { sm := stream.Method() if sm != "" && sm[0] == '/' { sm = sm[1:] } pos := strings.LastIndex(sm, "/") if pos == -1 { if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{sm}}, true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", stream.Method())); err != nil { if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) } if trInfo != nil { trInfo.tr.Finish() } return } service := sm[:pos] method := sm[pos+1:] srv, ok := s.m[service] if !ok { if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil { if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) } if trInfo != nil { trInfo.tr.Finish() } return } // Unary RPC or Streaming RPC? if md, ok := srv.md[method]; ok { s.processUnaryRPC(t, stream, srv, md, trInfo) return } if sd, ok := srv.sd[method]; ok { s.processStreamingRPC(t, stream, srv, sd, trInfo) return } if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"Unknown method %v", []interface{}{method}}, true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown method %v", method)); err != nil { if trInfo != nil { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } grpclog.Printf("grpc: Server.handleStream failed to write status: %v", err) } if trInfo != nil { trInfo.tr.Finish() } }
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc) (err error) { var traceInfo traceInfo if EnableTracing { traceInfo.tr = trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) defer traceInfo.tr.Finish() traceInfo.firstLine.client = false traceInfo.tr.LazyLog(&traceInfo.firstLine, false) defer func() { if err != nil && err != io.EOF { traceInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) traceInfo.tr.SetError() } }() } p := &parser{s: stream} for { pf, req, err := p.recvMsg() if err == io.EOF { // The entire stream is done (for unary RPC only). return err } if err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return err } if traceInfo.tr != nil { traceInfo.tr.LazyLog(&payload{sent: false, msg: req}, true) } switch pf { case compressionNone: statusCode := codes.OK statusDesc := "" reply, appErr := md.Handler(srv.server, stream.Context(), s.opts.codec, req) if appErr != nil { if err, ok := appErr.(rpcError); ok { statusCode = err.code statusDesc = err.desc } else { statusCode = convertCode(appErr) statusDesc = appErr.Error() } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) return err } return nil } opts := &transport.Options{ Last: true, Delay: false, } if err := s.sendResponse(t, stream, reply, compressionNone, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: statusCode = err.Code statusDesc = err.Desc default: statusCode = codes.Unknown statusDesc = err.Error() } return err } if traceInfo.tr != nil { traceInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) } return t.WriteStatus(stream, statusCode, statusDesc) default: panic(fmt.Sprintf("payload format to be supported: %d", pf)) } } }
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { if trInfo != nil { defer trInfo.tr.Finish() trInfo.firstLine.client = false trInfo.tr.LazyLog(&trInfo.firstLine, false) defer func() { if err != nil && err != io.EOF { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } }() } p := &parser{r: stream} for { pf, req, err := p.recvMsg() if err == io.EOF { // The entire stream is done (for unary RPC only). return err } if err == io.ErrUnexpectedEOF { err = transport.StreamError{Code: codes.Internal, Desc: "io.ErrUnexpectedEOF"} } if err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return err } if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { switch err := err.(type) { case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } } return err } statusCode := codes.OK statusDesc := "" df := func(v interface{}) error { if pf == compressionMade { var err error req, err = s.opts.dc.Do(bytes.NewReader(req)) if err != nil { if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } return err } } if err := s.opts.codec.Unmarshal(req, v); err != nil { return err } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) } return nil } reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) if appErr != nil { if err, ok := appErr.(rpcError); ok { statusCode = err.code statusDesc = err.desc } else { statusCode = convertCode(appErr) statusDesc = appErr.Error() } if trInfo != nil && statusCode != codes.OK { trInfo.tr.LazyLog(stringer(statusDesc), true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) return err } return nil } if trInfo != nil { trInfo.tr.LazyLog(stringer("OK"), false) } opts := &transport.Options{ Last: true, Delay: false, } if s.opts.cp != nil { stream.SetSendCompress(s.opts.cp.Type()) } if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: statusCode = err.Code statusDesc = err.Desc default: statusCode = codes.Unknown statusDesc = err.Error() } return err } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) } return t.WriteStatus(stream, statusCode, statusDesc) } }
func (g *grpcServer) serveStream(t transport.ServerTransport, stream *transport.Stream) { serviceMethod := strings.Split(stream.Method(), ".") if len(serviceMethod) != 2 { if err := t.WriteStatus(stream, codes.InvalidArgument, fmt.Sprintf("malformed method name: %q", stream.Method())); err != nil { log.Printf("grpc: Server.serveStream failed to write status: %v", err) } return } g.rpc.mu.Lock() service := g.rpc.serviceMap[serviceMethod[0]] g.rpc.mu.Unlock() if service == nil { if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil { log.Printf("grpc: Server.serveStream failed to write status: %v", err) } return } mtype := service.method[serviceMethod[1]] if mtype == nil { if err := t.WriteStatus(stream, codes.Unimplemented, fmt.Sprintf("unknown service %v", service)); err != nil { log.Printf("grpc: Server.serveStream failed to write status: %v", err) } } // get grpc metadata gmd, ok := metadata.FromContext(stream.Context()) if !ok { gmd = metadata.MD{} } // copy the metadata to go-micro.metadata md := meta.Metadata{} for k, v := range gmd { md[k] = strings.Join(v, ", ") } // get content type ct := defaultContentType if ctype, ok := md["x-content-type"]; ok { ct = ctype } // get codec codec, err := g.newGRPCCodec(ct) if err != nil { if errr := t.WriteStatus(stream, codes.Internal, err.Error()); errr != nil { log.Printf("grpc: Server.serveStream failed to write status: %v", errr) } return } // timeout for server deadline to := md["timeout"] delete(md, "x-content-type") delete(md, "timeout") // create new context ctx := meta.NewContext(stream.Context(), md) // set the timeout if we have it if len(to) > 0 { if n, err := strconv.ParseUint(to, 10, 64); err == nil { ctx, _ = context.WithTimeout(ctx, time.Duration(n)) } } // process unary if !mtype.stream { g.processRequest(t, stream, service, mtype, codec, ct, ctx) return } // process strea g.processStream(t, stream, service, mtype, codec, ct, ctx) }
func (g *grpcServer) processRequest(t transport.ServerTransport, stream *transport.Stream, service *service, mtype *methodType, codec grpc.Codec, ct string, ctx context.Context) (err error) { p := &parser{r: stream} for { pf, req, err := p.recvMsg(defaultMaxMsgSize) if err == io.EOF { // The entire stream is done (for unary RPC only). return err } if err == io.ErrUnexpectedEOF { err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) } if err != nil { switch err := err.(type) { case *rpcError: if err := t.WriteStatus(stream, err.code, err.desc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } case transport.ConnectionError: // Nothing to do here. case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return err } if err := checkRecvPayload(pf, stream.RecvCompress(), nil); err != nil { switch err := err.(type) { case *rpcError: if err := t.WriteStatus(stream, err.code, err.desc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } } return err } // status code/desc statusCode := codes.OK statusDesc := "" // exceeds max message size, bail early if len(req) > defaultMaxMsgSize { statusCode = codes.Internal statusDesc = fmt.Sprintf("grpc: server received a message of %d bytes exceeding %d limit", len(req), defaultMaxMsgSize) return t.WriteStatus(stream, statusCode, statusDesc) } var argv, replyv reflect.Value // Decode the argument value. argIsValue := false // if true, need to indirect before calling. if mtype.ArgType.Kind() == reflect.Ptr { argv = reflect.New(mtype.ArgType.Elem()) } else { argv = reflect.New(mtype.ArgType) argIsValue = true } // Unmarshal request if err := codec.Unmarshal(req, argv.Interface()); err != nil { return err } if argIsValue { argv = argv.Elem() } // reply value replyv = reflect.New(mtype.ReplyType.Elem()) function := mtype.method.Func var returnValues []reflect.Value // create a client.Request r := &rpcRequest{ service: g.opts.Name, contentType: ct, method: stream.Method(), request: argv.Interface(), } // define the handler func fn := func(ctx context.Context, req server.Request, rsp interface{}) error { returnValues = function.Call([]reflect.Value{service.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req.Request()), reflect.ValueOf(rsp)}) // The return value for the method is an error. if err := returnValues[0].Interface(); err != nil { return err.(error) } return nil } // wrap the handler func for i := len(g.opts.HdlrWrappers); i > 0; i-- { fn = g.opts.HdlrWrappers[i-1](fn) } // execute the handler if appErr := fn(ctx, r, replyv.Interface()); appErr != nil { if err, ok := appErr.(*rpcError); ok { statusCode = err.code statusDesc = err.desc } else { statusCode = convertCode(appErr) statusDesc = appErr.Error() } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { log.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) return err } return nil } opts := &transport.Options{ Last: true, Delay: false, } if err := g.sendResponse(t, stream, replyv.Interface(), codec, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: statusCode = err.Code statusDesc = err.Desc default: statusCode = codes.Unknown statusDesc = err.Error() } return err } return t.WriteStatus(stream, statusCode, statusDesc) } }
// // service存在, MethodDesc也存在 // func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { if trInfo != nil { defer trInfo.tr.Finish() trInfo.firstLine.client = false trInfo.tr.LazyLog(&trInfo.firstLine, false) defer func() { if err != nil && err != io.EOF { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } }() } p := &parser{r: stream} for { // PayloadFormat, Request Data, Err pf, req, err := p.recvMsg() if err == io.EOF { // The entire stream is done (for unary RPC only). return err } if err == io.ErrUnexpectedEOF { err = transport.StreamError{Code: codes.Internal, Desc: "io.ErrUnexpectedEOF"} } if err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. // 连接断开了,则直接返回 case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return err } if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { switch err := err.(type) { case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } } return err } // 处理正常的Method Invocation statusCode := codes.OK statusDesc := "" // Decode Input df := func(v interface{}) error { if pf == compressionMade { // 如果数据有压缩,则通过opts中配置的Compressor/Decompressor进行处理 var err error req, err = s.opts.dc.Do(bytes.NewReader(req)) if err != nil { if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } return err } } // 将req中的数据反序列化到: v 中,例如: // in := new(HelloRequest) // if err := dec(in); err != nil { // return nil, err // } if err := s.opts.codec.Unmarshal(req, v); err != nil { return err } // 打印trace info if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) } return nil } // 参考: func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { //var _Greeter_serviceDesc = grpc.ServiceDesc{ // ServiceName: "helloworld.Greeter", // HandlerType: (*GreeterServer)(nil), // Methods: []grpc.MethodDesc{ // { // // 方法的描述 // MethodName: "SayHello", // Handler: _Greeter_SayHello_Handler, // }, // }, // // // Streams如何处理呢? // Streams: []grpc.StreamDesc{}, //} // Handler是直接可调用的函数 // 其中: df 接受输入参数的类型,进行数据的反序列化 // reply, appErr := md.Handler(srv.server, stream.Context(), df) // 如果处理应用返回来的Error if appErr != nil { if err, ok := appErr.(rpcError); ok { statusCode = err.code statusDesc = err.desc } else { statusCode = convertCode(appErr) statusDesc = appErr.Error() } if trInfo != nil && statusCode != codes.OK { trInfo.tr.LazyLog(stringer(statusDesc), true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) return err } return nil } // 处理完毕之后,正常返回数据 if trInfo != nil { trInfo.tr.LazyLog(stringer("OK"), false) } opts := &transport.Options{ Last: true, Delay: false, } if s.opts.cp != nil { stream.SetSendCompress(s.opts.cp.Type()) } // 返回数据 if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: statusCode = err.Code statusDesc = err.Desc default: statusCode = codes.Unknown statusDesc = err.Error() } return err } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) } return t.WriteStatus(stream, statusCode, statusDesc) } }
func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { if s.opts.cp != nil { stream.SetSendCompress(s.opts.cp.Type()) } ss := &serverStream{ t: t, s: stream, p: &parser{r: stream}, codec: s.opts.codec, cp: s.opts.cp, dc: s.opts.dc, maxMsgSize: s.opts.maxMsgSize, trInfo: trInfo, } if ss.cp != nil { ss.cbuf = new(bytes.Buffer) } if trInfo != nil { trInfo.tr.LazyLog(&trInfo.firstLine, false) defer func() { ss.mu.Lock() if err != nil && err != io.EOF { ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) ss.trInfo.tr.SetError() } ss.trInfo.tr.Finish() ss.trInfo.tr = nil ss.mu.Unlock() }() } var appErr error if s.opts.streamInt == nil { appErr = sd.Handler(srv.server, ss) } else { info := &StreamServerInfo{ FullMethod: stream.Method(), IsClientStream: sd.ClientStreams, IsServerStream: sd.ServerStreams, } appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler) } if appErr != nil { if err, ok := appErr.(*rpcError); ok { ss.statusCode = err.code ss.statusDesc = err.desc } else if err, ok := appErr.(transport.StreamError); ok { ss.statusCode = err.Code ss.statusDesc = err.Desc } else { ss.statusCode = convertCode(appErr) ss.statusDesc = appErr.Error() } } if trInfo != nil { ss.mu.Lock() if ss.statusCode != codes.OK { ss.trInfo.tr.LazyLog(stringer(ss.statusDesc), true) ss.trInfo.tr.SetError() } else { ss.trInfo.tr.LazyLog(stringer("OK"), false) } ss.mu.Unlock() } return t.WriteStatus(ss.s, ss.statusCode, ss.statusDesc) }
func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { if trInfo != nil { defer trInfo.tr.Finish() trInfo.firstLine.client = false trInfo.tr.LazyLog(&trInfo.firstLine, false) defer func() { if err != nil && err != io.EOF { trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true) trInfo.tr.SetError() } }() } if s.opts.cp != nil { // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686. stream.SetSendCompress(s.opts.cp.Type()) } p := &parser{r: stream} for { pf, req, err := p.recvMsg(s.opts.maxMsgSize) if err == io.EOF { // The entire stream is done (for unary RPC only). return err } if err == io.ErrUnexpectedEOF { err = Errorf(codes.Internal, io.ErrUnexpectedEOF.Error()) } if err != nil { switch err := err.(type) { case *rpcError: if err := t.WriteStatus(stream, err.code, err.desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } case transport.ConnectionError: // Nothing to do here. case transport.StreamError: if err := t.WriteStatus(stream, err.Code, err.Desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: panic(fmt.Sprintf("grpc: Unexpected error (%T) from recvMsg: %v", err, err)) } return err } if err := checkRecvPayload(pf, stream.RecvCompress(), s.opts.dc); err != nil { switch err := err.(type) { case *rpcError: if err := t.WriteStatus(stream, err.code, err.desc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } default: if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } } return err } statusCode := codes.OK statusDesc := "" df := func(v interface{}) error { if pf == compressionMade { var err error req, err = s.opts.dc.Do(bytes.NewReader(req)) if err != nil { if err := t.WriteStatus(stream, codes.Internal, err.Error()); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status %v", err) } return err } } if len(req) > s.opts.maxMsgSize { // TODO: Revisit the error code. Currently keep it consistent with // java implementation. statusCode = codes.Internal statusDesc = fmt.Sprintf("grpc: server received a message of %d bytes exceeding %d limit", len(req), s.opts.maxMsgSize) } if err := s.opts.codec.Unmarshal(req, v); err != nil { return err } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) } return nil } reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt) if appErr != nil { if err, ok := appErr.(*rpcError); ok { statusCode = err.code statusDesc = err.desc } else { statusCode = convertCode(appErr) statusDesc = appErr.Error() } if trInfo != nil && statusCode != codes.OK { trInfo.tr.LazyLog(stringer(statusDesc), true) trInfo.tr.SetError() } if err := t.WriteStatus(stream, statusCode, statusDesc); err != nil { grpclog.Printf("grpc: Server.processUnaryRPC failed to write status: %v", err) return err } return nil } if trInfo != nil { trInfo.tr.LazyLog(stringer("OK"), false) } opts := &transport.Options{ Last: true, Delay: false, } if err := s.sendResponse(t, stream, reply, s.opts.cp, opts); err != nil { switch err := err.(type) { case transport.ConnectionError: // Nothing to do here. case transport.StreamError: statusCode = err.Code statusDesc = err.Desc default: statusCode = codes.Unknown statusDesc = err.Error() } return err } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true) } return t.WriteStatus(stream, statusCode, statusDesc) } }