This commit is contained in:
qwqdanchun 2022-12-09 02:19:42 +08:00
parent 2a3b3597ea
commit 19a1007c9b
135 changed files with 10783 additions and 545 deletions

View File

@ -1,34 +0,0 @@
name: Docker Image CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: esrrhs/spp:latest

View File

@ -1,32 +1,56 @@
name: Go
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
name: Go-AutoBuild
on:
push:
branches: [ master ]
branches: [ "master" ]
pull_request:
branches: [ master ]
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: 1.19
- name: Get dependencies
run: |
GO111MODULE=off go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Build
run: GO111MODULE=off go build -v ./...
- name: Test
run: GO111MODULE=off go test -v ./...
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" main.go
- name: Delete-tag-and-release
uses: dev-drprasad/delete-tag-and-release@v0.2.0
with:
delete_release: true # default: false
tag_name: AutoBuild # tag name to delete
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
id: create_release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: AutoBuild
release_name: AutoBuild
body: ${{ steps.changelog.outputs.changelog }}
draft: false
prerelease: false
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./main.exe
asset_name: main.exe
asset_content_type: application/exe

15
.gitignore vendored
View File

@ -1,15 +0,0 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

View File

@ -1,9 +0,0 @@
FROM golang AS build-env
RUN GO111MODULE=off go get -u github.com/esrrhs/spp
RUN GO111MODULE=off go get -u github.com/esrrhs/spp/...
RUN GO111MODULE=off go install github.com/esrrhs/spp
FROM debian
COPY --from=build-env /go/bin/spp .
WORKDIR ./

View File

@ -1,124 +0,0 @@
# spp
[<img src="https://img.shields.io/github/license/esrrhs/spp">](https://github.com/esrrhs/spp)
[<img src="https://img.shields.io/github/languages/top/esrrhs/spp">](https://github.com/esrrhs/spp)
[![Go Report Card](https://goreportcard.com/badge/github.com/esrrhs/spp)](https://goreportcard.com/report/github.com/esrrhs/spp)
[<img src="https://img.shields.io/github/v/release/esrrhs/spp">](https://github.com/esrrhs/spp/releases)
[<img src="https://img.shields.io/github/downloads/esrrhs/spp/total">](https://github.com/esrrhs/spp/releases)
[<img src="https://img.shields.io/docker/pulls/esrrhs/spp">](https://hub.docker.com/repository/docker/esrrhs/spp)
[<img src="https://img.shields.io/github/workflow/status/esrrhs/spp/Go">](https://github.com/esrrhs/spp/actions)
SPP is a simple and powerful proxy
![image](show.png)
# Features
* Supported protocol: TCP, UDP, RUDP (Reliable UDP), RICMP (Reliable ICMP), RHTTP (Reliable HTTP), KCP, Quic
* Support type: forward proxy, reverse agent, SOCKS5 forward agent, SOCKS5 reverse agent
* Agreement and type can be freely combined
* External agent agreement and internal forwarding protocols can freely combine
* Support Shadowsocks plug-in, [spp-shadowsocks-plugin](https://github.com/esrrhs/spp-shadowsocks-plugin)[spp-shadowsocks-plugin-android](https://github.com/esrrhs/spp-shadowsocks-plugin-android)
# Instructions
### Server
* Start Server, assume that the server IP is www.server.com, listening port 8888
```
# ./spp -type server -proto tcp -listen :8888
```
* You can also listen simultaneously with other types of ports and protocols.
```
# ./spp -type server -proto tcp -listen :8888 -proto rudp -listen :9999 -proto ricmp -listen 0.0.0.0
```
* Can also use Docker
```
# docker run --name my-server -d --restart=always --network host esrrhs/spp ./spp -proto tcp -listen :8888
```
### Client
* Start TCP forward proxy, map the 8080 port of www.server.com to the local 8080 so that access to local 8080 is equivalent to accessing www.server.com 8080
```
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp
```
* Start the TCP reverse agent, map the local 8080 to the 8080 port of www.server.com, which visit www.server.com 8080 is equivalent to accessing the local 8080
```
# ./spp -name "test" -type reverse_proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp
```
* Start TCP Positive Socks5 Agent, open the SOCKS5 protocol in the local 8080 port, access the network in Server through Server
```
# ./spp -name "test" -type socks5_client -server www.server.com:8888 -fromaddr :8080 -proxyproto tcp
```
* Start TCP Reverse Socks5 Agent, open the Socks5 protocol at www.server.com's 8080 port, access the network in the client through the Client
```
# ./spp -name "test" -type reverse_socks5_client -server www.server.com:8888 -fromaddr :8080 -proxyproto tcp
```
* Other proxy protocols, only need to modify the proxyProto parameters of the client, for example
```
Proxy UDP
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto udp
Proxy rudp
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8081 -toaddr :8081 -proxyproto rudp
Proxy ricmp
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8082 -toaddr :8082 -proxyproto ricmp
At the same time, the above three
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto udp -fromaddr :8081 -toaddr :8081 -proxyproto rudp -fromaddr :8082 -toaddr :8082 -proxyproto ricmp
```
* Internal communication between Client and Server, can also be modified to other protocols, automatic conversion between external protocols and internal protocols. E.g
```
Proxy TCP, internal RUDP protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp -proto rudp
Proxy TCP, internal RICMP protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com -fromaddr :8080 -toaddr :8080 -proxyproto tcp -proto ricmp
Agent UDP, internal TCP protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto udp -proto tcp
Agent UDP, internal KCP protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto udp -proto kcp
Proxy TCP, internal Quic protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp -proto quic
Proxy TCP, internal RHTTP protocol forwarding
# ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp -proto rhttp
```
* Can also use Docker
```
# docker run --name my-client -d --restart=always --network host esrrhs/spp ./spp -name "test" -type proxy_client -server www.server.com:8888 -fromaddr :8080 -toaddr :8080 -proxyproto tcp
```
# Performance Testing
* Test the maximum bandwidth speed in the case where the IPERF script using the Benchmark / local_tcp directory is tested in the CPU. The proxy protocol is TCP, and the results of various transit protocols are used as follows:
| Agent | Speed | Speed (Ency) | Speed (Encryption Compression)
|--------------|----------|----------|----------|
| Direct connection | 3535 MBytes/sec | | |
| tcp forwarding | 663 MBytes/sec | 225 MBytes/sec | 23.4 MBytes/sec |
| rudp forwarding | 5.15 MBytes/sec | 5.81 MBytes/sec | 5.05 MBytes/sec|
| ricmp forwarding | 3.34 MBytes/sec | 3.25 MBytes/sec|3.46 MBytes/sec |
| rhttp forwarding | 10.7 MBytes/sec | 10.8 MBytes/sec| 8.73 MBytes/sec|
| kcp forwarding | 18.2 MBytes/sec | 18.6 MBytes/sec| 14.7 MBytes/sec|
| quic forwarding | 35.5 MBytes/sec | 32.8 MBytes/sec|15.1 MBytes/sec |
* Using the IPERF script of the Benchmark / Remote_TCP directory, in the multi-machine test, the server is located in Tencent Cloud, the client is located locally, and the maximum bandwidth speed is tested. The proxy protocol is TCP, and the results of various transit protocols are used as follows:
| Agent | Speed | Speed (Ency) | Speed (Encryption Compression)
|--------------|----------|----------|----------|
| Direct connection | 2.74 MBytes/sec | | |
| tcp forwarding | 3.81 MBytes/sec |3.90 MBytes/sec | 4.02 MBytes/sec|
| rudp forwarding | 3.33 MBytes/sec | 3.41 MBytes/sec| 3.58 MBytes/sec|
| ricmp forwarding | 3.21 MBytes/sec | 2.95 MBytes/sec| 3.17 MBytes/sec|
| rhttp forwarding | 3.48 MBytes/sec |3.49 MBytes/sec |3.39 MBytes/sec |
| kcp forwarding | 3.58 MBytes/sec |3.58 MBytes/sec | 3.75 MBytes/sec |
| quic forwarding | 3.85 MBytes/sec | 3.83 MBytes/sec | 3.92 MBytes/sec |
* Note: The test data is Centos.ISO, which has been compressed, so the effect of compression forwarding is not obvious.
* If you want to directly test each protocol bandwidth of the network, use multi-protocol bandwidth test tools [connperf](https://github.com/esrrhs/connperf)

View File

@ -1 +0,0 @@
theme: jekyll-theme-cayman

View File

@ -1,3 +0,0 @@
#! /bin/bash
../iperf -c 127.0.0.1 -p 8844 -f M -F ../data.bin -t 60

View File

@ -1,3 +0,0 @@
#! /bin/bash
../iperf -c 127.0.0.1 -p 8855 -f M -F ../data.bin -t 60

View File

@ -1,3 +0,0 @@
#! /bin/bash
../iperf -s -p 8844 -f M

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server 127.0.0.1 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server 127.0.0.1 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server 127.0.0.1 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp -compress 0 -encrypt=""

View File

@ -1,22 +0,0 @@
#! /bin/bash
if test -f "data.bin"; then
echo "data.bin exist"
else
rm CentOS-8.2.2004-x86_64-minimal.iso -rf
wget http://mirrors.cqu.edu.cn/CentOS/8.2.2004/isos/x86_64/CentOS-8.2.2004-x86_64-minimal.iso
mv CentOS-8.2.2004-x86_64-minimal.iso data.bin
fi
if test -f "smalldata.bin"; then
echo "smalldata.bin exist"
else
rm CentOS-8.2.2004-x86_64-boot.iso -rf
wget http://mirrors.cqu.edu.cn/CentOS/8.2.2004/isos/x86_64/CentOS-8.2.2004-x86_64-boot.iso
mv CentOS-8.2.2004-x86_64-boot.iso smalldata.bin
fi
rm ./iperf
sudo wget -O ./iperf https://iperf.fr/download/ubuntu/iperf_2.0.9
chmod a+x ./iperf

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../iperf -c $SER -p 8844 -f M -F ../smalldata.bin -t 60

View File

@ -1,3 +0,0 @@
#! /bin/bash
../iperf -c 127.0.0.1 -p 8855 -f M -F ../smalldata.bin -t 60

View File

@ -1,3 +0,0 @@
#! /bin/bash
../iperf -s -p 8844 -f M

View File

@ -1 +0,0 @@
www.esrrhs.gq

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp -compress 0

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp -compress 0 -encrypt=""

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic -compress 0 -encrypt=""

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp -compress 0 -encrypt=""

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto ricmp -compress 0 -encrypt=""

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp -compress 0 -encrypt=""

View File

@ -1,4 +0,0 @@
#! /bin/bash
SER=`cat server`
../../spp -name "test" -type proxy_client -server $SER:8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp -compress 0

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto kcp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto quic -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rhttp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto rudp -compress 0 -encrypt=""

View File

@ -1,3 +0,0 @@
#! /bin/bash
../../spp -type server -listen :8888 -proto tcp -compress 0 -encrypt=""

43
common/alg.go Normal file
View File

@ -0,0 +1,43 @@
package common
import (
"bytes"
"compress/zlib"
"crypto/rc4"
"github.com/google/uuid"
"io"
)
func CompressData(src []byte) []byte {
var b bytes.Buffer
w := zlib.NewWriter(&b)
w.Write(src)
w.Close()
return b.Bytes()
}
func DeCompressData(src []byte) ([]byte, error) {
b := bytes.NewReader(src)
r, err := zlib.NewReader(b)
if err != nil {
return nil, err
}
var out bytes.Buffer
io.Copy(&out, r)
r.Close()
return out.Bytes(), nil
}
func Rc4(key string, src []byte) ([]byte, error) {
c, err := rc4.NewCipher([]byte(key))
if err != nil {
return nil, err
}
dst := make([]byte, len(src))
c.XORKeyStream(dst, src)
return dst, nil
}
func Guid() string {
return uuid.New().String()
}

61
common/channel.go Normal file
View File

@ -0,0 +1,61 @@
package common
import "time"
type Channel struct {
ch chan interface{}
closed bool
}
func NewChannel(len int) *Channel {
return &Channel{ch: make(chan interface{}, len)}
}
func (c *Channel) Close() {
defer func() {
if recover() != nil {
c.closed = true
}
}()
if !c.closed {
c.closed = true
close(c.ch)
}
}
func (c *Channel) Write(v interface{}) {
defer func() {
if recover() != nil {
c.closed = true
}
}()
if !c.closed {
c.ch <- v
}
}
func (c *Channel) WriteTimeout(v interface{}, timeoutms int) bool {
defer func() {
if recover() != nil {
c.closed = true
}
}()
if !c.closed {
select {
case c.ch <- v:
return true
case <-time.After(time.Duration(timeoutms) * time.Millisecond):
return false
}
}
return true
}
func (c *Channel) Ch() <-chan interface{} {
return c.ch
}

48
common/color.go Normal file
View File

@ -0,0 +1,48 @@
package common
import (
"image/color"
"math"
)
/*
Black #000000 (0,0,0)
White #FFFFFF (255,255,255)
Red #FF0000 (255,0,0)
Lime #00FF00 (0,255,0)
Blue #0000FF (0,0,255)
Yellow #FFFF00 (255,255,0)
Cyan #00FFFF (0,255,255)
Magenta #FF00FF (255,0,255)
Silver #C0C0C0 (192,192,192)
Gray #808080 (128,128,128)
Maroon #800000 (128,0,0)
Olive #808000 (128,128,0)
Green #008000 (0,128,0)
Purple #800080 (128,0,128)
Teal #008080 (0,128,128)
Navy #000080 (0,0,128)
*/
var Black = color.RGBA{0, 0, 0, 0}
var White = color.RGBA{255, 255, 255, 0}
var Red = color.RGBA{255, 0, 0, 0}
var Lime = color.RGBA{0, 255, 0, 0}
var Blue = color.RGBA{0, 0, 255, 0}
var Yellow = color.RGBA{255, 255, 0, 0}
var Cyan = color.RGBA{0, 255, 255, 0}
var Magenta = color.RGBA{255, 0, 255, 0}
var Silver = color.RGBA{192, 192, 192, 0}
var Gray = color.RGBA{128, 128, 128, 0}
var Maroon = color.RGBA{128, 0, 0, 0}
var Olive = color.RGBA{128, 128, 0, 0}
var Green = color.RGBA{0, 128, 0, 0}
var Purple = color.RGBA{128, 0, 128, 0}
var Teal = color.RGBA{0, 128, 128, 0}
var Navy = color.RGBA{0, 0, 128, 0}
func ColorDistance(c1 color.RGBA, c2 color.RGBA) float64 {
return math.Sqrt((float64(c1.R)-float64(c2.R))*(float64(c1.R)-float64(c2.R)) +
(float64(c1.G)-float64(c2.G))*(float64(c1.G)-float64(c2.G)) +
(float64(c1.B)-float64(c2.B))*(float64(c1.B)-float64(c2.B)))
}

33
common/error.go Normal file
View File

@ -0,0 +1,33 @@
package common
import (
"errors"
"fmt"
"runtime"
"spp/loggo"
)
func CrashLog() {
if r := recover(); r != nil {
var err error
switch x := r.(type) {
case string:
err = errors.New(x)
case error:
err = x
default:
err = errors.New("Unknown panic")
}
if err != nil {
loggo.Error("crash %s \n%s", err, DumpStacks())
}
panic(err)
}
}
func DumpStacks() string {
buf := make([]byte, 16384)
buf = buf[:runtime.Stack(buf, true)]
return fmt.Sprintf("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}

201
common/file.go Normal file
View File

@ -0,0 +1,201 @@
package common
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
func LoadJson(filename string, conf interface{}) error {
err := loadJson(filename, conf)
if err != nil {
err := loadJson(filename+".back", conf)
if err != nil {
return err
}
}
return nil
}
func loadJson(filename string, conf interface{}) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
decoder := json.NewDecoder(file)
err = decoder.Decode(conf)
if err != nil {
return err
}
return nil
}
func SaveJson(filename string, conf interface{}) error {
err1 := saveJson(filename, conf)
err2 := saveJson(filename+".back", conf)
if err1 != nil {
return err1
}
if err2 != nil {
return err2
}
return nil
}
func saveJson(filename string, conf interface{}) error {
str, err := json.MarshalIndent(conf, "", " ")
if err != nil {
return err
}
jsonFile, err := os.OpenFile(filename,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
jsonFile.Write(str)
jsonFile.Close()
return nil
}
func Copy(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
}
func FileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
func FileMd5(filename string) (string, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
md5 := GetMd5String(string(data))
return md5, nil
}
func FileReplace(filename string, from string, to string) error {
data, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
str := string(data)
str = strings.Replace(str, from, to, -1)
out, err := os.Create(filename)
if err != nil {
return err
}
defer out.Close()
out.WriteString(str)
return nil
}
func FileFind(filename string, dst string) int {
data, err := ioutil.ReadFile(filename)
if err != nil {
return 0
}
str := string(data)
n := 0
for _, str := range strings.Split(str, "\n") {
if strings.Contains(str, dst) {
n++
}
}
return n
}
func FileLineCount(filename string) int {
data, err := ioutil.ReadFile(filename)
if err != nil {
return 0
}
lineSep := []byte{'\n'}
return bytes.Count(data, lineSep) + 1
}
func IsSymlink(filename string) bool {
fi, err := os.Lstat(filename)
if err != nil {
return false
}
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
return true
} else {
return false
}
}
// symwalkFunc calls the provided WalkFn for regular files.
// However, when it encounters a symbolic link, it resolves the link fully using the
// filepath.EvalSymlinks function and recursively calls symwalk.Walk on the resolved path.
// This ensures that unlink filepath.Walk, traversal does not stop at symbolic links.
//
// Note that symwalk.Walk does not terminate if there are any non-terminating loops in
// the file structure.
func walk(filename string, linkDirname string, walkFn filepath.WalkFunc) error {
symWalkFunc := func(path string, info os.FileInfo, err error) error {
if fname, err := filepath.Rel(filename, path); err == nil {
path = filepath.Join(linkDirname, fname)
} else {
return err
}
if err == nil && info.Mode()&os.ModeSymlink == os.ModeSymlink {
finalPath, err := filepath.EvalSymlinks(path)
if err != nil {
return err
}
info, err := os.Lstat(finalPath)
if err != nil {
return walkFn(path, info, err)
}
if info.IsDir() {
return walk(finalPath, path, walkFn)
}
}
return walkFn(path, info, err)
}
return filepath.Walk(filename, symWalkFunc)
}
// Walk extends filepath.Walk to also follow symlinks
func Walk(path string, walkFn filepath.WalkFunc) error {
return walk(path, path, walkFn)
}

35
common/hash.go Normal file
View File

@ -0,0 +1,35 @@
package common
import (
"crypto/md5"
"encoding/hex"
"github.com/OneOfOne/xxhash"
"hash/crc32"
"strconv"
)
func GetMd5String(s string) string {
h := md5.New()
h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil))
}
func GetXXHashString(s string) string {
h := xxhash.New64()
h.WriteString(s)
return strconv.FormatUint(h.Sum64(), 10)
}
func GetCrc32String(s string) string {
hash := crc32.New(crc32.IEEETable)
hash.Write([]byte(s))
hashInBytes := hash.Sum(nil)[:]
return hex.EncodeToString(hashInBytes)
}
func GetCrc32(data []byte) string {
hash := crc32.New(crc32.IEEETable)
hash.Write(data)
hashInBytes := hash.Sum(nil)[:]
return hex.EncodeToString(hashInBytes)
}

223
common/math.go Normal file
View File

@ -0,0 +1,223 @@
package common
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"hash/fnv"
"io"
"math"
"math/big"
mrand "math/rand"
"time"
)
func init() {
mrand.Seed(time.Now().UnixNano())
}
func HasInt(data []int, dst int) bool {
for _, i := range data {
if i == dst {
return true
}
}
return false
}
func HasString(data []string, dst string) bool {
for _, i := range data {
if i == dst {
return true
}
}
return false
}
func MinOfInt(vars ...int) int {
min := vars[0]
for _, i := range vars {
if min > i {
min = i
}
}
return min
}
func MaxOfInt(vars ...int) int {
max := vars[0]
for _, i := range vars {
if max < i {
max = i
}
}
return max
}
func MinOfInt64(vars ...int64) int64 {
min := vars[0]
for _, i := range vars {
if min > i {
min = i
}
}
return min
}
func MaxOfInt64(vars ...int64) int64 {
max := vars[0]
for _, i := range vars {
if max < i {
max = i
}
}
return max
}
func AbsInt(v int) int {
if v > 0 {
return v
}
return -v
}
func AbsInt32(v int32) int32 {
if v > 0 {
return v
}
return -v
}
func AbsInt64(v int64) int64 {
if v > 0 {
return v
}
return -v
}
func HashString(s string) uint32 {
h := fnv.New32a()
h.Write([]byte(s))
return h.Sum32()
}
func UniqueId() string {
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return GetMd5String(base64.URLEncoding.EncodeToString(b))
}
func RandInt31n(n int) int32 {
ret := mrand.Int31n((int32)(n))
return int32(ret)
}
func RandInt() int32 {
ret := mrand.Int()
return int32(ret)
}
func Shuffle(n int, swap func(i, j int)) {
mrand.Shuffle(n, swap)
}
func MAKEINT64(high int32, low int32) int64 {
return (int64)(((int64)(low)) | ((int64)((int32)(high)))<<32)
}
func HIINT32(I int64) int32 {
return (int32)(((int64)(I) >> 32) & 0xFFFFFFFF)
}
func LOINT32(l int64) int32 {
return (int32)(l)
}
func MAKEINT32(high int16, low int16) int32 {
return (int32)(((int32)(low)) | ((int32)((int16)(high)))<<16)
}
func HIINT16(I int32) int16 {
return (int16)(((int32)(I) >> 16) & 0xFFFF)
}
func LOINT16(l int32) int16 {
return (int16)(l)
}
func IsInt(r float64) bool {
return (r - math.Floor(r)) == 0
}
func ArrayContainInt(a []int, f int) bool {
for _, i := range a {
if f == i {
return true
}
}
return false
}
func ArrayContainString(a []string, f string) bool {
for _, i := range a {
if f == i {
return true
}
}
return false
}
func SafeDivide(a int64, b int64) int64 {
if b == 0 {
return 0
}
return a / b
}
func NearlyEqual(a int, b int) bool {
max := a
if b > a {
max = b
}
aa := float64(a) / float64(max)
bb := float64(b) / float64(max)
return math.Abs(aa-bb) < 0.1
}
// Setup a bare-bones TLS config for the server
func GenerateTLSConfig(name string) (*tls.Config, error) {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
return nil, err
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
return nil, err
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
return nil, err
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{name},
}, nil
}

17
common/net.go Normal file
View File

@ -0,0 +1,17 @@
package common
import (
"net"
)
func GetOutboundIP() (net.IP, error) {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return nil, err
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP, nil
}

79
common/proto.go Normal file
View File

@ -0,0 +1,79 @@
package common
import (
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/dynamicpb"
"io/ioutil"
)
func LoadProtobuf(filename string) (error, []protoreflect.FileDescriptor) {
b, err := ioutil.ReadFile(filename)
if err != nil {
return err, nil
}
fds := &descriptorpb.FileDescriptorSet{}
err = proto.Unmarshal(b, fds)
if err != nil {
return err, nil
}
ff, err := protodesc.NewFiles(fds)
if err != nil {
return err, nil
}
var ret []protoreflect.FileDescriptor
ff.RangeFiles(func(descriptor protoreflect.FileDescriptor) bool {
ret = append(ret, descriptor)
return true
})
return nil, ret
}
func LoadProtobufMethods(filename string) (error, []protoreflect.MethodDescriptor) {
err, descriptors := LoadProtobuf(filename)
if err != nil {
return err, nil
}
var ret []protoreflect.MethodDescriptor
for _, descriptor := range descriptors {
for i := 0; i < descriptor.Services().Len(); i++ {
sd := descriptor.Services().Get(i)
for j := 0; j < sd.Methods().Len(); j++ {
m := sd.Methods().Get(j)
ret = append(ret, m)
}
}
}
return nil, ret
}
func MessageToFullJson(mi protoreflect.MessageDescriptor) (error, string) {
message := dynamicpb.NewMessage(mi)
fullFill(message, mi)
b, err := protojson.MarshalOptions{Multiline: true, Indent: " ", EmitUnpopulated: true}.Marshal(message)
if err != nil {
return err, ""
}
return nil, string(b)
}
func fullFill(message *dynamicpb.Message, mi protoreflect.MessageDescriptor) {
for i := 0; i < mi.Fields().Len(); i++ {
fd := mi.Fields().Get(i)
if !fd.IsMap() && !fd.IsList() && fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind {
submi := fd.Message()
submessage := dynamicpb.NewMessage(submi)
fullFill(submessage, submi)
message.Set(fd, protoreflect.ValueOfMessage(submessage))
}
}
}

250
common/string.go Normal file
View File

@ -0,0 +1,250 @@
package common
import (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"math"
"reflect"
"strconv"
"strings"
)
const gcharset = "abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func IntArrayToString(a []int, delim string) string {
var ret string
for _, s := range a {
ret += strconv.Itoa(s) + delim
}
return ret
}
func Int32ArrayToString(a []int32, delim string) string {
var ret string
for _, s := range a {
ret += strconv.Itoa((int)(s)) + delim
}
return ret
}
func Int64ArrayToString(a []int64, delim string) string {
var ret string
for _, s := range a {
ret += strconv.Itoa((int)(s)) + delim
}
return ret
}
func RandStr(l int) string {
b := make([]byte, l)
for i := range b {
b[i] = gcharset[RandInt31n(len(gcharset))]
}
return string(b)
}
type StrTableLine struct {
cols []string
}
type StrTable struct {
header []string
lines []StrTableLine
}
func (s *StrTable) AddHeader(h string) {
s.header = append(s.header, h)
}
func (s *StrTable) AddLine(l StrTableLine) {
s.lines = append(s.lines, l)
}
func (s *StrTableLine) AddData(d string) {
s.cols = append(s.cols, d)
}
func (s *StrTable) String(prefix string) string {
if len(s.header) <= 0 {
return ""
}
colmax := make([]int, 0)
for _, s := range s.header {
colmax = append(colmax, len(s))
}
totalcol := 0
for i := 0; i < len(colmax); i++ {
max := colmax[i]
for _, sl := range s.lines {
if i < len(sl.cols) {
max = MaxOfInt(max, len(sl.cols[i]))
}
}
colmax[i] = max
totalcol += max
}
totalcol += len(colmax) + 1
/*
-----------
| a | b |
-----------
| 1 | 2 |
-----------
*/
ret := prefix
ret += strings.Repeat("-", totalcol) + "\n" + prefix
for i, h := range s.header {
ret += "|" + WrapString(h, colmax[i])
}
ret += "|" + "\n" + prefix
for _, l := range s.lines {
ret += strings.Repeat("-", totalcol) + "\n" + prefix
for i, d := range l.cols {
ret += "|" + WrapString(d, colmax[i])
}
for i := len(l.cols); i < len(colmax); i++ {
ret += "|" + WrapString("", colmax[i])
}
ret += "|" + "\n" + prefix
}
ret += strings.Repeat("-", totalcol) + "\n"
return ret
}
func (s *StrTable) FromStruct(v interface{}, use func(name string) bool) {
ss := reflect.ValueOf(v).Elem()
typeOfT := ss.Type()
for i := 0; i < ss.NumField(); i++ {
name := typeOfT.Field(i).Name
if use != nil {
if !use(name) {
continue
}
}
s.AddHeader(name)
}
}
func (s *StrTableLine) FromStruct(st *StrTable, v interface{}, trans func(name string, v interface{}) interface{}) {
ss := reflect.ValueOf(v).Elem()
typeOfT := ss.Type()
for i := 0; i < ss.NumField(); i++ {
f := ss.Field(i)
name := typeOfT.Field(i).Name
if !ArrayContainString(st.header, name) {
continue
}
v := f.Interface()
if trans != nil {
v = trans(name, f.Interface())
}
if v != nil {
str := fmt.Sprintf("%v", v)
s.AddData(str)
} else {
s.AddData("")
}
}
}
func WrapString(s string, n int) string {
if n <= len(s) {
return s
}
l := (n - len(s)) / 2
r := (n - len(s)) - l
return strings.Repeat(" ", l) + s + strings.Repeat(" ", r)
}
func StructToTable(v interface{}) string {
t := StrTable{}
tl := StrTableLine{}
t.FromStruct(v, nil)
tl.FromStruct(&t, v, nil)
t.AddLine(tl)
return t.String("")
}
const num2char string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
LITTLE_LETTERS = 36
FULL_LETTERS = 62
)
func NumToHex(num, n int) string {
num_str := ""
for num != 0 {
yu := num % n
num_str = string(num2char[yu]) + num_str
num = num / n
}
return num_str
}
func Hex2Num(str string, n int) int {
v := 0.0
length := len(str)
for i := 0; i < length; i++ {
s := string(str[i])
index := strings.Index(num2char, s)
v += float64(index) * math.Pow(float64(n), float64(length-1-i))
}
return int(v)
}
func GzipString(data string) string {
var b bytes.Buffer
w := gzip.NewWriter(&b)
w.Write([]byte(data))
w.Close()
return string(b.Bytes())
}
func GzipStringBestCompression(data string) string {
var b bytes.Buffer
w, err := gzip.NewWriterLevel(&b, gzip.BestCompression)
if err != nil {
return ""
}
w.Write([]byte(data))
w.Close()
return string(b.Bytes())
}
func GzipStringBestSpeed(data string) string {
var b bytes.Buffer
w, err := gzip.NewWriterLevel(&b, gzip.BestSpeed)
if err != nil {
return ""
}
w.Write([]byte(data))
w.Close()
return string(b.Bytes())
}
func GunzipString(data string) string {
var b bytes.Buffer
b.WriteString(data)
r, err := gzip.NewReader(&b)
if err != nil {
return ""
}
r.Close()
ret, _ := ioutil.ReadAll(r)
return string(ret)
}

39
common/time.go Normal file
View File

@ -0,0 +1,39 @@
package common
import (
"time"
)
var gnowsecond time.Time
func init() {
gnowsecond = time.Now()
go updateNowInSecond()
}
func GetNowUpdateInSecond() time.Time {
return gnowsecond
}
func updateNowInSecond() {
defer CrashLog()
for {
gnowsecond = time.Now()
Sleep(1)
}
}
func Elapsed(f func(d time.Duration)) func() {
start := time.Now()
return func() {
f(time.Since(start))
}
}
func Sleep(sec int) {
last := time.Now()
for time.Now().Sub(last) < time.Second*time.Duration(sec) {
time.Sleep(time.Millisecond * 100)
}
}

138
congestion/bbcongestion.go Normal file
View File

@ -0,0 +1,138 @@
package congestion
import (
"fmt"
"math"
"strconv"
"time"
"spp/common"
"spp/rbuffergo"
)
const (
bbc_status_init = 0
bbc_status_prop = 1
bbc_win = 5
bbc_maxfly_grow = 2.1
bbc_maxfly_compare = float64(1.5)
)
var prop_seq = []float64{1, 1, 1.5, 1}
type BBCongestion struct {
status int
maxfly int
flyeddata int
lastflyeddata int
flyingdata int
rateflywin *rbuffergo.Rlistgo
flyedwin *rbuffergo.Rlistgo
propindex int
last time.Time
lastratewin float64
lastflyedwin int
}
func (bb *BBCongestion) Init() {
bb.status = bbc_status_init
bb.maxfly = 1024 * 1024
bb.rateflywin = rbuffergo.NewRList(bbc_win)
bb.flyedwin = rbuffergo.NewRList(bbc_win)
bb.last = time.Now()
}
func (bb *BBCongestion) RecvAck(id int, size int) {
bb.flyeddata += size
}
func (bb *BBCongestion) CanSend(id int, size int) bool {
if bb.flyingdata > bb.maxfly {
return false
}
bb.flyingdata += size
return true
}
func (bb *BBCongestion) Update() {
if bb.flyeddata <= 0 {
return
}
currate := float64(bb.flyingdata) / float64(bb.flyeddata)
if currate < 1 {
currate = 1
}
if bb.rateflywin.Full() {
bb.rateflywin.PopFront()
}
bb.rateflywin.PushBack(currate)
lastratewin := math.MaxFloat64
for e := bb.rateflywin.FrontInter(); e != nil; e = e.Next() {
rate := e.Value.(float64)
if rate < lastratewin {
lastratewin = rate
}
}
if bb.flyedwin.Full() {
bb.flyedwin.PopFront()
}
bb.flyedwin.PushBack(bb.flyeddata)
lastflyedwin := 0
for e := bb.flyedwin.FrontInter(); e != nil; e = e.Next() {
flyed := e.Value.(int)
if flyed > lastflyedwin {
lastflyedwin = flyed
}
}
if bb.status == bbc_status_init {
if float64(bb.flyeddata) <= bbc_maxfly_compare*float64(bb.lastflyeddata) {
oldmaxfly := bb.maxfly
bb.maxfly = int(float64(oldmaxfly) / bbc_maxfly_grow)
bb.status = bbc_status_prop
//loggo.Debug("bbc_status_init flyeddata %d maxfly %d change", bb.flyeddata, bb.maxfly)
} else {
oldmaxfly := bb.maxfly
bb.maxfly = int(float64(oldmaxfly) * bbc_maxfly_grow)
//loggo.Debug("bbc_status_init grow flyeddata %d oldmaxfly %d maxfly %d", bb.flyeddata, oldmaxfly, bb.maxfly)
}
bb.lastflyeddata = bb.flyeddata
} else if bb.status == bbc_status_prop {
maxfly := float64(lastflyedwin) * lastratewin
curmaxfly := int(maxfly)
if curmaxfly > bb.maxfly {
bb.maxfly = curmaxfly
} else {
if common.NearlyEqual(bb.flyingdata, bb.maxfly) {
bb.maxfly = curmaxfly
}
}
bb.maxfly = int(float64(bb.maxfly) * prop_seq[bb.propindex])
//loggo.Debug("bbc_status_prop lastflyedwin %v lastrate %v maxfly %d prop %v", lastflyedwin, lastrate, bb.maxfly, prop_seq[bb.propindex])
bb.propindex++
bb.propindex = bb.propindex % len(prop_seq)
} else {
panic("error status " + strconv.Itoa(bb.status))
}
bb.flyeddata = 0
bb.flyingdata = 0
bb.lastratewin = lastratewin
bb.lastflyedwin = lastflyedwin
if bb.maxfly < 1024*1024 {
bb.maxfly = 1024 * 1024
}
}
func (bb *BBCongestion) Info() string {
return fmt.Sprintf("status %v maxfly %v flyeddata %v lastratewin %v lastflyedwin %v", bb.status, bb.maxfly,
bb.flyeddata, bb.lastratewin, bb.lastflyedwin)
}

9
congestion/congestion.go Normal file
View File

@ -0,0 +1,9 @@
package congestion
type Congestion interface {
Init()
RecvAck(id int, size int)
CanSend(id int, size int) bool
Update()
Info() string
}

75
conn/conn.go Normal file
View File

@ -0,0 +1,75 @@
package conn
import (
"errors"
"io"
"strings"
"syscall"
"spp/common"
)
type Conn interface {
io.ReadWriteCloser
Name() string
Info() string
Dial(dst string) (Conn, error)
Listen(dst string) (Conn, error)
Accept() (Conn, error)
}
func NewConn(proto string) (Conn, error) {
proto = strings.ToLower(proto)
if proto == "tcp" {
return &TcpConn{}, nil
} else if proto == "udp" {
return &UdpConn{}, nil
} else if proto == "rudp" {
return &RudpConn{}, nil
} else if proto == "ricmp" {
return &RicmpConn{id: common.UniqueId()}, nil
} else if proto == "kcp" {
return &KcpConn{}, nil
} else if proto == "quic" {
return &QuicConn{}, nil
} else if proto == "rhttp" {
return &RhttpConn{}, nil
}
return nil, errors.New("undefined proto " + proto)
}
func SupportReliableProtos() []string {
ret := make([]string, 0)
ret = append(ret, "tcp")
ret = append(ret, "rudp")
ret = append(ret, "ricmp")
ret = append(ret, "kcp")
ret = append(ret, "quic")
ret = append(ret, "rhttp")
return ret
}
func SupportProtos() []string {
ret := make([]string, 0)
ret = append(ret, SupportReliableProtos()...)
ret = append(ret, "udp")
return ret
}
func HasReliableProto(proto string) bool {
return common.HasString(SupportReliableProtos(), proto)
}
func HasProto(proto string) bool {
return common.HasString(SupportProtos(), proto)
}
var gControlOnConnSetup func(network, address string, c syscall.RawConn) error
func RegisterDialerController(fn func(network, address string, c syscall.RawConn) error) {
gControlOnConnSetup = fn
}

Some files were not shown because too many files have changed in this diff Show More