mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	
		
			
	
	
		
			62 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			62 lines
		
	
	
		
			1.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package ratelimit
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"context"
							 | 
						||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
							 | 
						||
| 
								 | 
							
									"sync/atomic"
							 | 
						||
| 
								 | 
							
									"time"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Bandwidth lossy bandwidth limiter
							 | 
						||
| 
								 | 
							
								type Bandwidth struct {
							 | 
						||
| 
								 | 
							
									totalBytes int64
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									currentTimestamp int64
							 | 
						||
| 
								 | 
							
									currentBytes     int64
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// NewBandwidth create new bandwidth limiter
							 | 
						||
| 
								 | 
							
								func NewBandwidth(totalBytes int64) *Bandwidth {
							 | 
						||
| 
								 | 
							
									return &Bandwidth{totalBytes: totalBytes}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Ack acquire next chance to send data
							 | 
						||
| 
								 | 
							
								func (this *Bandwidth) Ack(ctx context.Context, newBytes int) {
							 | 
						||
| 
								 | 
							
									if newBytes <= 0 {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if this.totalBytes <= 0 {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var timestamp = fasttime.Now().Unix()
							 | 
						||
| 
								 | 
							
									if this.currentTimestamp != 0 && this.currentTimestamp != timestamp {
							 | 
						||
| 
								 | 
							
										this.currentTimestamp = timestamp
							 | 
						||
| 
								 | 
							
										this.currentBytes = int64(newBytes)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// 第一次发送直接放行,不需要判断
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if this.currentTimestamp == 0 {
							 | 
						||
| 
								 | 
							
										this.currentTimestamp = timestamp
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if atomic.AddInt64(&this.currentBytes, int64(newBytes)) <= this.totalBytes {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var timeout = time.NewTimer(1 * time.Second)
							 | 
						||
| 
								 | 
							
									if ctx != nil {
							 | 
						||
| 
								 | 
							
										select {
							 | 
						||
| 
								 | 
							
										case <-timeout.C:
							 | 
						||
| 
								 | 
							
										case <-ctx.Done():
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										select {
							 | 
						||
| 
								 | 
							
										case <-timeout.C:
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |