2020-11-25 14:01:53 +03:00
|
|
|
package pipe
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2022-04-24 02:24:46 +03:00
|
|
|
"github.com/xtls/xray-core/common/buf"
|
2020-12-04 04:36:16 +03:00
|
|
|
"github.com/xtls/xray-core/common/signal"
|
|
|
|
"github.com/xtls/xray-core/common/signal/done"
|
|
|
|
"github.com/xtls/xray-core/features/policy"
|
2020-11-25 14:01:53 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// Option for creating new Pipes.
|
|
|
|
type Option func(*pipeOption)
|
|
|
|
|
|
|
|
// WithoutSizeLimit returns an Option for Pipe to have no size limit.
|
|
|
|
func WithoutSizeLimit() Option {
|
|
|
|
return func(opt *pipeOption) {
|
|
|
|
opt.limit = -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithSizeLimit returns an Option for Pipe to have the given size limit.
|
|
|
|
func WithSizeLimit(limit int32) Option {
|
|
|
|
return func(opt *pipeOption) {
|
|
|
|
opt.limit = limit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-24 02:24:46 +03:00
|
|
|
func OnTransmission(hook func(mb buf.MultiBuffer) buf.MultiBuffer) Option {
|
|
|
|
return func(option *pipeOption) {
|
|
|
|
option.onTransmission = hook
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-25 14:01:53 +03:00
|
|
|
// DiscardOverflow returns an Option for Pipe to discard writes if full.
|
|
|
|
func DiscardOverflow() Option {
|
|
|
|
return func(opt *pipeOption) {
|
|
|
|
opt.discardOverflow = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// OptionsFromContext returns a list of Options from context.
|
|
|
|
func OptionsFromContext(ctx context.Context) []Option {
|
|
|
|
var opt []Option
|
|
|
|
|
|
|
|
bp := policy.BufferPolicyFromContext(ctx)
|
|
|
|
if bp.PerConnection >= 0 {
|
|
|
|
opt = append(opt, WithSizeLimit(bp.PerConnection))
|
|
|
|
} else {
|
|
|
|
opt = append(opt, WithoutSizeLimit())
|
|
|
|
}
|
|
|
|
|
|
|
|
return opt
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates a new Reader and Writer that connects to each other.
|
|
|
|
func New(opts ...Option) (*Reader, *Writer) {
|
|
|
|
p := &pipe{
|
|
|
|
readSignal: signal.NewNotifier(),
|
|
|
|
writeSignal: signal.NewNotifier(),
|
|
|
|
done: done.New(),
|
|
|
|
option: pipeOption{
|
|
|
|
limit: -1,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
opt(&(p.option))
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Reader{
|
|
|
|
pipe: p,
|
|
|
|
}, &Writer{
|
|
|
|
pipe: p,
|
|
|
|
}
|
|
|
|
}
|