mirror of https://github.com/qwqdanchun/spp.git
update
This commit is contained in:
parent
2a3b3597ea
commit
19a1007c9b
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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/
|
|
@ -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 ./
|
124
README_EN.md
124
README_EN.md
|
@ -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)
|
||||
|
|
@ -1 +0,0 @@
|
|||
theme: jekyll-theme-cayman
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../iperf -c 127.0.0.1 -p 8844 -f M -F ../data.bin -t 60
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../iperf -c 127.0.0.1 -p 8855 -f M -F ../data.bin -t 60
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../iperf -s -p 8844 -f M
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto kcp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto quic -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rhttp -compress 0
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto rudp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -name "test" -type proxy_client -server :8888 -fromaddr :8855 -toaddr :8844 -proxyproto tcp -proto tcp -compress 0
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp -compress 0 -encrypt=""
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
SER=`cat server`
|
||||
../iperf -c $SER -p 8844 -f M -F ../smalldata.bin -t 60
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../iperf -c 127.0.0.1 -p 8855 -f M -F ../smalldata.bin -t 60
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../iperf -s -p 8844 -f M
|
|
@ -1 +0,0 @@
|
|||
www.esrrhs.gq
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -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=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp -compress 0
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto kcp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto quic -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rhttp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen 0.0.0.0 -proto ricmp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto rudp -compress 0 -encrypt=""
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
../../spp -type server -listen :8888 -proto tcp -compress 0 -encrypt=""
|
|
@ -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()
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)))
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package congestion
|
||||
|
||||
type Congestion interface {
|
||||
Init()
|
||||
RecvAck(id int, size int)
|
||||
CanSend(id int, size int) bool
|
||||
Update()
|
||||
Info() string
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue