You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/bsr/meta_recording.go

171 lines
3.8 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package bsr
import (
"bufio"
"context"
"fmt"
"io"
"strings"
)
// SessionRecordingMeta contains metadata about a session in a BSR.
// Most fields are written to the meta file as k:v pairs
// Slice fields are written to the meta file as id_k:v
// Nested slice fields are written as parentId_parentKey_id_k:v
type SessionRecordingMeta struct {
Id string
Protocol Protocol
connections map[string]bool
}
func (s *SessionRecordingMeta) writeMeta(ctx context.Context, c *container) error {
_, err := c.WriteMeta(ctx, "id", s.Id)
if err != nil {
return err
}
_, err = c.WriteMeta(ctx, "protocol", string(s.Protocol))
if err != nil {
return err
}
return nil
}
// decodeSessionRecordingMeta will populate a SessionRecordingMeta for an opened BSR Session
func decodeSessionRecordingMeta(ctx context.Context, r io.Reader) (*SessionRecordingMeta, error) {
const op = "bsr.decodeSessionRecordingMeta"
switch {
case r == nil:
return nil, fmt.Errorf("%s: missing session meta file: %w", op, ErrInvalidParameter)
}
connections := make(map[string]bool)
s := &SessionRecordingMeta{}
scanner := bufio.NewScanner(r)
for scanner.Scan() {
l := scanner.Text()
if len(l) == 0 {
continue
}
k, v, ok := strings.Cut(l, ":")
if !ok {
return nil, fmt.Errorf("%s: session meta file contains invalid entry; expecting k: v pair:%s", op, l)
}
v = strings.TrimSpace(v)
switch {
case k == "id":
s.Id = v
case k == "protocol":
s.Protocol = Protocol(v)
// connections
case k == "connection":
connections[v] = true
}
}
s.connections = connections
return s, nil
}
// ConnectionRecordingMeta contains metadata about a connection in a BSR.
type ConnectionRecordingMeta struct {
Id string
channels map[string]bool
}
func (c ConnectionRecordingMeta) isValid() bool {
switch {
case c.Id == "":
return false
default:
return true
}
}
// decodeConnectionRecordingMeta will populate the ConnectionRecordingMeta for a BSR Connection
func decodeConnectionRecordingMeta(ctx context.Context, r io.Reader) (*ConnectionRecordingMeta, error) {
const op = "bsr.decodeConnectionRecordingMeta"
switch {
case r == nil:
return nil, fmt.Errorf("%s: missing connection meta file: %w", op, ErrInvalidParameter)
}
c := &ConnectionRecordingMeta{}
channels := make(map[string]bool)
scanner := bufio.NewScanner(r)
for scanner.Scan() {
l := scanner.Text()
if len(l) == 0 {
continue
}
k, v, ok := strings.Cut(l, ":")
if !ok {
return nil, fmt.Errorf("%s: connection meta file contains invalid entry; expecting k: v pair:%s", op, l)
}
v = strings.TrimSpace(v)
switch {
case k == "id":
c.Id = v
case k == "channel":
channels[v] = true
}
}
c.channels = channels
return c, nil
}
// ChannelRecordingMeta contains metadata about a channel in a BSR.
type ChannelRecordingMeta struct {
Id string
Type string
}
func (c ChannelRecordingMeta) isValid() bool {
switch {
case c.Id == "":
return false
case c.Type == "":
return false
default:
return true
}
}
// decodeChannelRecordingMeta will populate the ChannelRecordingMeta for a BSR Channel
func decodeChannelRecordingMeta(ctx context.Context, r io.Reader) (*ChannelRecordingMeta, error) {
const op = "bsr.decodeChannelRecordingMeta"
switch {
case r == nil:
return nil, fmt.Errorf("%s: missing channel meta file: %w", op, ErrInvalidParameter)
}
c := &ChannelRecordingMeta{}
scanner := bufio.NewScanner(r)
for scanner.Scan() {
l := scanner.Text()
if len(l) == 0 {
continue
}
k, v, ok := strings.Cut(l, ":")
if !ok {
return nil, fmt.Errorf("%s: channel meta file contains invalid entry; expecting k: v pair:%s", op, l)
}
v = strings.TrimSpace(v)
switch {
case k == "id":
c.Id = v
case k == "channelType":
c.Type = v
}
}
return c, nil
}