Add fabric binary transport loop
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
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")
|
||||
Reference in New Issue
Block a user