diff --git a/proxy/proxy.go b/proxy/proxy.go index 7bce570d..df10d1f9 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -215,7 +215,7 @@ type VisionWriter struct { addons *Addons trafficState *TrafficState ctx context.Context - writeOnceUserUUID []byte + writeOnceUserUUID *[]byte scheduler *Scheduler } @@ -227,8 +227,8 @@ func NewVisionWriter(writer buf.Writer, addon *Addons, state *TrafficState, cont addons: addon, trafficState: state, ctx: context, - writeOnceUserUUID: w, - scheduler: NewScheduler(writer, addon, state, context), + writeOnceUserUUID: &w, + scheduler: NewScheduler(writer, addon, state, &w, context), } } @@ -239,7 +239,7 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } if w.trafficState.IsPadding && ShouldStartSeed(w.addons, w.trafficState){ if len(mb) == 1 && mb[0] == nil { - mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.addons, w.ctx) // we do a long padding to hide vless header + mb[0] = XtlsPadding(nil, CommandPaddingContinue, w.writeOnceUserUUID, true, w.addons, w.ctx) // we do a long padding to hide vless header } else { mb = ReshapeMultiBuffer(w.ctx, mb) longPadding := w.trafficState.IsTLS @@ -258,12 +258,12 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { w.trafficState.IsPadding = false } } - mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, true, w.addons, w.ctx) + mb[i] = XtlsPadding(b, command, w.writeOnceUserUUID, true, w.addons, w.ctx) longPadding = false continue } else if !w.trafficState.IsTLS12orAbove && ShouldStopSeed(w.addons, w.trafficState) { w.trafficState.IsPadding = false - mb[i] = XtlsPadding(b, CommandPaddingEnd, &w.writeOnceUserUUID, longPadding, w.addons, w.ctx) + mb[i] = XtlsPadding(b, CommandPaddingEnd, w.writeOnceUserUUID, longPadding, w.addons, w.ctx) break } var command byte = CommandPaddingContinue @@ -273,7 +273,7 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { command = CommandPaddingDirect } } - mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, longPadding, w.addons, w.ctx) + mb[i] = XtlsPadding(b, command, w.writeOnceUserUUID, longPadding, w.addons, w.ctx) } } } diff --git a/proxy/scheduler.go b/proxy/scheduler.go index dec1f4be..24c59888 100644 --- a/proxy/scheduler.go +++ b/proxy/scheduler.go @@ -12,25 +12,29 @@ import ( ) type Scheduler struct { - Buffer chan buf.MultiBuffer - Trigger chan int - Error chan error - bufferReadLock *sync.Mutex - writer buf.Writer - addons *Addons - trafficState *TrafficState - ctx context.Context + Buffer chan buf.MultiBuffer + Trigger chan int + Error chan error + closed chan int + bufferReadLock *sync.Mutex + writer buf.Writer + addons *Addons + trafficState *TrafficState + writeOnceUserUUID *[]byte + ctx context.Context } -func NewScheduler(w buf.Writer, addon *Addons, state *TrafficState, context context.Context) *Scheduler { +func NewScheduler(w buf.Writer, addon *Addons, state *TrafficState, userUUID *[]byte, context context.Context) *Scheduler { var s = Scheduler{ Buffer: make(chan buf.MultiBuffer, 100), Trigger: make(chan int), Error: make(chan error, 100), + closed: make(chan int), bufferReadLock: new(sync.Mutex), writer: w, addons: addon, trafficState: state, + writeOnceUserUUID: userUUID, ctx: context, } go s.mainLoop() @@ -42,6 +46,9 @@ func NewScheduler(w buf.Writer, addon *Addons, state *TrafficState, context cont func(s *Scheduler) mainLoop() { for trigger := range s.Trigger { + if len(s.closed) > 0 { + return + } go func() { // each trigger has independent delay, trigger does not block var d = 0 * time.Millisecond if s.addons.Delay != nil { @@ -58,12 +65,31 @@ func(s *Scheduler) mainLoop() { if sending > 0 { errors.LogDebug(s.ctx, "Scheduler Trigger for ", sending, " buffer(s) with ", d, " ", trigger) for i := 0; i 0 { + } else if trigger > 0 && s.trafficState.IsPadding && ShouldStartSeed(s.addons, s.trafficState) && !ShouldStopSeed(s.addons, s.trafficState) { errors.LogDebug(s.ctx, "Scheduler Trigger for fake buffer with ", d, " ", trigger) + s.trafficState.NumberOfPacketSent += 1 mb := make(buf.MultiBuffer, 1) - s.Error <- s.writer.WriteMultiBuffer(mb) + mb[0] = XtlsPadding(nil, CommandPaddingContinue, s.writeOnceUserUUID, true, s.addons, s.ctx) + s.trafficState.ByteSent += int64(mb.Len()) + if s.trafficState.StartTime.IsZero() { + s.trafficState.StartTime = time.Now() + } + err := s.writer.WriteMultiBuffer(mb) + if err != nil { + s.Error <- err + s.closed <- 1 + return + } + if buffered, ok := s.writer.(*buf.BufferedWriter); ok { + buffered.SetBuffered(false) + } } s.bufferReadLock.Unlock() }() @@ -72,7 +98,10 @@ func(s *Scheduler) mainLoop() { func(s *Scheduler) exampleIndependentScheduler() { for { - time.Sleep(500 * time.Millisecond) + if len(s.closed) > 0 { + return + } s.Trigger <- 1 // send fake buffer if no pending + time.Sleep(500 * time.Millisecond) } } diff --git a/proxy/vless/encoding/addons.go b/proxy/vless/encoding/addons.go index 403ffe29..feee6e87 100644 --- a/proxy/vless/encoding/addons.go +++ b/proxy/vless/encoding/addons.go @@ -189,11 +189,11 @@ func PopulateSeed(seed string, addons *proxy.Addons) { LongMin: 900, LongMax: 1400, } - addons.Delay = &proxy.DelayConfig{ - IsRandom: true, - MinMillis: 100, - MaxMillis: 500, - } + // addons.Delay = &proxy.DelayConfig{ + // IsRandom: true, + // MinMillis: 100, + // MaxMillis: 500, + // } addons.Scheduler = &proxy.SchedulerConfig{ TimeoutMillis: 600, }