package fabricproto import ( "context" "errors" "io" ) type EventHandler func(SessionEvent) ([]Frame, error) type TransportLoop struct { Session *Session MaxPayload int OnEvent EventHandler } func (l TransportLoop) Run(ctx context.Context, r io.Reader, w io.Writer) error { if l.Session == nil { return ErrSessionNotConfigured } maxPayload := l.MaxPayload if maxPayload <= 0 { maxPayload = DefaultMaxPayload } for { select { case <-ctx.Done(): return ctx.Err() default: } frame, err := ReadFrame(r, maxPayload) if errors.Is(err, io.EOF) { return nil } if err != nil { return err } if err := l.Handle(ctx, frame, w); err != nil { return err } } } func (l TransportLoop) Handle(ctx context.Context, frame Frame, w io.Writer) error { responses, err := l.HandleFrame(ctx, frame) if err != nil { return err } for _, response := range responses { select { case <-ctx.Done(): return ctx.Err() default: } if err := WriteFrame(w, response); err != nil { return err } } return nil } func (l TransportLoop) HandleFrame(ctx context.Context, frame Frame) ([]Frame, error) { if l.Session == nil { return nil, ErrSessionNotConfigured } event, responses, err := l.Session.HandleFrame(frame) if err != nil { return nil, err } if l.OnEvent != nil && event.Type != SessionEventNone { extra, err := l.OnEvent(event) if err != nil { return nil, err } responses = append(responses, extra...) } select { case <-ctx.Done(): return nil, ctx.Err() default: } return responses, nil } var ErrSessionNotConfigured = errors.New("fabric transport loop session is not configured")