74 lines
1.4 KiB
Go
74 lines
1.4 KiB
Go
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 {
|
|
if l.Session == nil {
|
|
return ErrSessionNotConfigured
|
|
}
|
|
event, responses, err := l.Session.HandleFrame(frame)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if l.OnEvent != nil && event.Type != SessionEventNone {
|
|
extra, err := l.OnEvent(event)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
responses = append(responses, extra...)
|
|
}
|
|
for _, response := range responses {
|
|
select {
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
default:
|
|
}
|
|
if err := WriteFrame(w, response); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var ErrSessionNotConfigured = errors.New("fabric transport loop session is not configured")
|