@@ -92,6 +92,11 @@ type GetOutbound interface {
9292// It is used by XTLS to determine if switch to raw copy mode, It is used by Vision to calculate padding
9393type TrafficState struct {
9494 UserUUID []byte
95+ StartTime time.Time
96+ ByteSent int64
97+ ByteReceived int64
98+ NumberOfPacketSent int
99+ NumberOfPacketReceived int
95100 NumberOfPacketToFilter int
96101 EnableXtls bool
97102 IsTLS12orAbove bool
@@ -115,6 +120,11 @@ type TrafficState struct {
115120func NewTrafficState (userUUID []byte ) * TrafficState {
116121 return & TrafficState {
117122 UserUUID : userUUID ,
123+ StartTime : time.Time {},
124+ ByteSent : 0 ,
125+ ByteReceived : 0 ,
126+ NumberOfPacketSent : 0 ,
127+ NumberOfPacketReceived : 0 ,
118128 NumberOfPacketToFilter : 8 ,
119129 EnableXtls : false ,
120130 IsTLS12orAbove : false ,
@@ -151,6 +161,10 @@ func NewVisionReader(reader buf.Reader, state *TrafficState, context context.Con
151161func (w * VisionReader ) ReadMultiBuffer () (buf.MultiBuffer , error ) {
152162 buffer , err := w .Reader .ReadMultiBuffer ()
153163 if ! buffer .IsEmpty () {
164+ if w .trafficState .StartTime .IsZero () {
165+ w .trafficState .StartTime = time .Now ()
166+ }
167+ w .trafficState .ByteReceived += int64 (buffer .Len ())
154168 if w .trafficState .WithinPaddingBuffers || w .trafficState .NumberOfPacketToFilter > 0 {
155169 mb2 := make (buf.MultiBuffer , 0 , len (buffer ))
156170 for _ , b := range buffer {
@@ -171,6 +185,7 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
171185 newError ("XtlsRead unknown command " , w .trafficState .CurrentCommand , buffer .Len ()).WriteToLog (session .ExportIDToError (w .ctx ))
172186 }
173187 }
188+ w .trafficState .NumberOfPacketReceived += len (buffer )
174189 if w .trafficState .NumberOfPacketToFilter > 0 {
175190 XtlsFilterTls (buffer , w .trafficState , w .ctx )
176191 }
@@ -199,47 +214,52 @@ func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Con
199214}
200215
201216func (w * VisionWriter ) WriteMultiBuffer (mb buf.MultiBuffer ) error {
217+ w .trafficState .NumberOfPacketSent += len (mb )
202218 if w .trafficState .NumberOfPacketToFilter > 0 {
203219 XtlsFilterTls (mb , w .trafficState , w .ctx )
204220 }
205221 if w .trafficState .IsPadding {
206222 if len (mb ) == 1 && mb [0 ] == nil {
207223 mb [0 ] = XtlsPadding (nil , CommandPaddingContinue , & w .writeOnceUserUUID , true , w .ctx ) // we do a long padding to hide vless header
208- return w .Writer .WriteMultiBuffer (mb )
209- }
210- mb = ReshapeMultiBuffer (w .ctx , mb )
211- longPadding := w .trafficState .IsTLS
212- for i , b := range mb {
213- if w .trafficState .IsTLS && b .Len () >= 6 && bytes .Equal (TlsApplicationDataStart , b .BytesTo (3 )) {
214- if w .trafficState .EnableXtls {
215- w .trafficState .WriterSwitchToDirectCopy = true
224+ } else {
225+ mb = ReshapeMultiBuffer (w .ctx , mb )
226+ longPadding := w .trafficState .IsTLS
227+ for i , b := range mb {
228+ if w .trafficState .IsTLS && b .Len () >= 6 && bytes .Equal (TlsApplicationDataStart , b .BytesTo (3 )) {
229+ if w .trafficState .EnableXtls {
230+ w .trafficState .WriterSwitchToDirectCopy = true
231+ }
232+ var command byte = CommandPaddingContinue
233+ if i == len (mb ) - 1 {
234+ command = CommandPaddingEnd
235+ if w .trafficState .EnableXtls {
236+ command = CommandPaddingDirect
237+ }
238+ }
239+ mb [i ] = XtlsPadding (b , command , & w .writeOnceUserUUID , true , w .ctx )
240+ w .trafficState .IsPadding = false // padding going to end
241+ longPadding = false
242+ continue
243+ } else if ! w .trafficState .IsTLS12orAbove && w .trafficState .NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
244+ w .trafficState .IsPadding = false
245+ mb [i ] = XtlsPadding (b , CommandPaddingEnd , & w .writeOnceUserUUID , longPadding , w .ctx )
246+ break
216247 }
217248 var command byte = CommandPaddingContinue
218- if i == len (mb ) - 1 {
249+ if i == len (mb ) - 1 && ! w . trafficState . IsPadding {
219250 command = CommandPaddingEnd
220251 if w .trafficState .EnableXtls {
221252 command = CommandPaddingDirect
222253 }
223254 }
224- mb [i ] = XtlsPadding (b , command , & w .writeOnceUserUUID , true , w .ctx )
225- w .trafficState .IsPadding = false // padding going to end
226- longPadding = false
227- continue
228- } else if ! w .trafficState .IsTLS12orAbove && w .trafficState .NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
229- w .trafficState .IsPadding = false
230- mb [i ] = XtlsPadding (b , CommandPaddingEnd , & w .writeOnceUserUUID , longPadding , w .ctx )
231- break
255+ mb [i ] = XtlsPadding (b , command , & w .writeOnceUserUUID , longPadding , w .ctx )
232256 }
233- var command byte = CommandPaddingContinue
234- if i == len (mb ) - 1 && ! w .trafficState .IsPadding {
235- command = CommandPaddingEnd
236- if w .trafficState .EnableXtls {
237- command = CommandPaddingDirect
238- }
239- }
240- mb [i ] = XtlsPadding (b , command , & w .writeOnceUserUUID , longPadding , w .ctx )
241257 }
242258 }
259+ w .trafficState .ByteSent += int64 (mb .Len ())
260+ if w .trafficState .StartTime .IsZero () {
261+ w .trafficState .StartTime = time .Now ()
262+ }
243263 return w .Writer .WriteMultiBuffer (mb )
244264}
245265
0 commit comments