// 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 }