go-bbs/openconn/openconn.go

52 lines
1.7 KiB
Go

// openconn provides a basic context.Context object to be used with gaio.Watcher
// the context carries two channels, InChan and OutChan, which are used by menuHandler
// and doorHandler to read input from the remote connection
// TODO: decide whether or not we'll actuallly need OutChan - possibly for maintaining
// output writes in order and/or ensuring output is delivered exactly once
package openconn
import (
"context"
"github.com/xtaci/gaio"
)
// The key type is unexported to prevent collisions with context keys defined in
// other packages.
type key int
const inChanKey key = 0
const outChanKey key = 1
// NewContext returns a new Context carrying two new channels.
func NewContext(ctx context.Context) context.Context {
inChan := make(chan gaio.OpResult)
outChan := make(chan gaio.OpResult)
ctx = context.WithValue(ctx, inChanKey, inChan)
ctx = context.WithValue(ctx, outChanKey, outChan)
return ctx
}
// FromContext extracts the two channels from ctx, if present.
func FromContext(ctx context.Context) (chan gaio.OpResult, chan gaio.OpResult, bool) {
// ctx.Value returns nil if ctx has no value for the key;
// the type assertion returns ok=false for nil.
inChan, iok := ctx.Value(inChanKey).(chan gaio.OpResult)
outChan, ook := ctx.Value(outChanKey).(chan gaio.OpResult)
if iok && ook {
return inChan, outChan, iok && ook
}
return nil, nil, iok && ook
}
// FromOpResult extracts the two channels from a gaio.OpResult, if present.
func FromOpResult(res gaio.OpResult) (chan gaio.OpResult, chan gaio.OpResult, bool) {
ctx, ok := res.Context.(context.Context)
if ok {
inChan, iok := ctx.Value(inChanKey).(chan gaio.OpResult)
outChan, ook := ctx.Value(outChanKey).(chan gaio.OpResult)
return inChan, outChan, iok && ook
}
return nil, nil, ok
}