-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial introduction of support for TCP
- Loading branch information
1 parent
a052d7f
commit 508298f
Showing
27 changed files
with
1,244 additions
and
809 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# SpeedTest Specifications | ||
This document records some of the interfaces defined in speedtest for reference only. | ||
|
||
## Native Socket Interfaces | ||
|
||
The protocol uses a plain text data stream and ends each message with '\n'. | ||
And '\n' and the operators are included in the total bytes. | ||
|
||
| Method | Protocol | Describe | | ||
|--------|----------|---------------------------------------------------| | ||
| Greet | TCP | Say Hello and get the server version information. | | ||
| PING | TCP | Echo with the server. | | ||
| Loss | TCP+UDP | Conduct UDP packet loss test. | | ||
| Down | TCP | Sending data to the server. | | ||
| Up | TCP | Receive data from the server. | | ||
|
||
### Great | ||
```shell | ||
Clinet: HI\n | ||
Server: HELLO [Major].[Minor] ([Major].[Minor].[Patch]) [YYYY]-[MM]-[DD].[LTSCCode].[GitHash]\n | ||
``` | ||
|
||
### PING | ||
```shell | ||
Clinet: PING [Local Timestamp]\n | ||
Server: PONG [Remote Timestamp]\n | ||
``` | ||
|
||
### Loss | ||
Please see https://github.com/showwin/speedtest-go/issues/169 | ||
|
||
### Down | ||
```shell | ||
Clinet: DOWNLOAD [Size]\n | ||
Server: DOWNLOAD [Random Data]\n | ||
``` | ||
|
||
### Up | ||
```shell | ||
Clinet: UPLOAD [Size]\n | ||
Clinet: [Random Data] | ||
Server: OK [Size] [Timestamp] | ||
``` | ||
|
||
## References | ||
[1] Reverse Engineering the Speedtest.net Protocol, Gökberk Yaltıraklı https://gist.github.com/sdstrowes/411fca9d900a846a704f68547941eb97 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package control | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
"sync" | ||
"time" | ||
) | ||
|
||
const DefaultReadChunkSize = 1024 // 1 KBytes with higher frequency rate feedback | ||
|
||
var ( | ||
ErrDuplicateCall = errors.New("multiple calls to the same chunk handler are not allowed") | ||
) | ||
|
||
type Chunk interface { | ||
UploadHandler(size int64) Chunk | ||
DownloadHandler(r io.Reader) error | ||
|
||
Rate() float64 | ||
Duration() time.Duration | ||
|
||
Type() Proto | ||
|
||
Len() int64 | ||
|
||
Read(b []byte) (n int, err error) | ||
} | ||
|
||
var BlackHole = sync.Pool{ | ||
New: func() any { | ||
b := make([]byte, 8192) | ||
return &b | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package control | ||
|
||
type Controller interface { | ||
// Get Reference counter volume | ||
Get() int64 | ||
// Add Reference counter increment | ||
Add(delta int64) | ||
// Repeat Pointing to duplicate memory space | ||
Repeat() []byte | ||
// Done Notification processing completed | ||
Done() <-chan struct{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package control | ||
|
||
import ( | ||
"math" | ||
"sync" | ||
) | ||
|
||
type Task func() error | ||
|
||
type TaskItem struct { | ||
fn func() error | ||
SlothIndex int64 | ||
Currents int64 | ||
} | ||
|
||
// LoadBalancer The implementation of Least-Connections Load Balancer with Failure Drop. | ||
type LoadBalancer struct { | ||
TaskQueue []*TaskItem | ||
sync.Mutex | ||
} | ||
|
||
func NewLoadBalancer() *LoadBalancer { | ||
return &LoadBalancer{} | ||
} | ||
|
||
func (lb *LoadBalancer) Len() int { | ||
return len(lb.TaskQueue) | ||
} | ||
|
||
// Add a new task to the [LoadBalancer] | ||
// @param priority The smaller the value, the higher the priority. | ||
func (lb *LoadBalancer) Add(task Task, priority int64) { | ||
if task == nil { | ||
panic("empty task is not allowed") | ||
} | ||
lb.TaskQueue = append(lb.TaskQueue, &TaskItem{fn: task, SlothIndex: priority, Currents: 0}) | ||
} | ||
|
||
func (lb *LoadBalancer) Dispatch() { | ||
var candidate *TaskItem | ||
lb.Lock() | ||
var minWeighted int64 = math.MaxInt64 | ||
for i := 0; i < lb.Len(); i++ { | ||
weighted := lb.TaskQueue[i].Currents * lb.TaskQueue[i].SlothIndex | ||
if weighted < minWeighted { | ||
minWeighted = weighted | ||
candidate = lb.TaskQueue[i] | ||
} | ||
} | ||
if candidate == nil || candidate.fn == nil { | ||
return | ||
} | ||
candidate.Currents++ | ||
lb.Unlock() | ||
err := candidate.fn() | ||
lb.Lock() | ||
defer lb.Unlock() | ||
if err == nil { | ||
candidate.Currents-- | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package control | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"sync" | ||
"sync/atomic" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestSLB(t *testing.T) { | ||
lb := NewLoadBalancer() | ||
var a int64 = 0 | ||
|
||
lb.Add(func() error { | ||
atomic.AddInt64(&a, 1) | ||
time.Sleep(time.Second * 2) | ||
return errors.New("error") | ||
}, 2) | ||
|
||
go func() { | ||
for { | ||
fmt.Printf("a:%d\n", a) | ||
time.Sleep(time.Second) | ||
} | ||
}() | ||
|
||
wg := sync.WaitGroup{} | ||
|
||
for i := 0; i < 8; i++ { | ||
wg.Add(1) | ||
go func() { | ||
for { | ||
lb.Dispatch() | ||
} | ||
}() | ||
} | ||
|
||
wg.Wait() | ||
} | ||
|
||
func TestLB(t *testing.T) { | ||
lb := NewLoadBalancer() | ||
var a int64 = 0 | ||
var b int64 = 0 | ||
var c int64 = 0 | ||
var d int64 = 0 | ||
|
||
lb.Add(func() error { | ||
atomic.AddInt64(&a, 1) | ||
time.Sleep(time.Second * 2) | ||
return nil | ||
}, 2) | ||
|
||
lb.Add(func() error { | ||
atomic.AddInt64(&b, 1) | ||
time.Sleep(time.Second * 2) | ||
return nil | ||
}, 1) | ||
|
||
lb.Add(func() error { | ||
atomic.AddInt64(&c, 1) | ||
time.Sleep(time.Second * 2) | ||
fmt.Println("error") | ||
return errors.New("error") | ||
}, 1) | ||
|
||
lb.Add(func() error { | ||
atomic.AddInt64(&d, 1) | ||
time.Sleep(time.Second * 2) | ||
return nil | ||
}, 5) | ||
|
||
wg := sync.WaitGroup{} | ||
|
||
go func() { | ||
for { | ||
fmt.Printf("a:%d, b:%d, c:%d, d:%d\n", a, b, c, d) | ||
time.Sleep(time.Second) | ||
} | ||
}() | ||
|
||
for i := 0; i < 8; i++ { | ||
wg.Add(1) | ||
go func() { | ||
for { | ||
lb.Dispatch() | ||
} | ||
}() | ||
} | ||
|
||
wg.Wait() | ||
} | ||
|
||
func BenchmarkDP(b *testing.B) { | ||
lb := NewLoadBalancer() | ||
lb.Add(func() error { | ||
return nil | ||
}, 1) | ||
lb.Add(func() error { | ||
return nil | ||
}, 1) | ||
lb.Add(func() error { | ||
return nil | ||
}, 1) | ||
lb.Add(func() error { | ||
return nil | ||
}, 1) | ||
lb.Add(func() error { | ||
return nil | ||
}, 1) | ||
|
||
for i := 0; i < b.N; i++ { | ||
lb.Dispatch() | ||
} | ||
} |
Oops, something went wrong.