├── frontend ├── .gitignore ├── public │ ├── favicon.png │ ├── fonts │ │ ├── shicon.ttf │ │ ├── shicon.woff │ │ ├── OpenSans │ │ │ ├── OpenSans-Bold.ttf │ │ │ ├── OpenSans-Italic.ttf │ │ │ ├── OpenSans-Light.ttf │ │ │ ├── OpenSans-Medium.ttf │ │ │ ├── OpenSans-ExtraBold.ttf │ │ │ ├── OpenSans-Regular.ttf │ │ │ ├── OpenSans-SemiBold.ttf │ │ │ ├── OpenSans-BoldItalic.ttf │ │ │ ├── OpenSans-LightItalic.ttf │ │ │ ├── OpenSans-MediumItalic.ttf │ │ │ ├── OpenSans-SemiBoldItalic.ttf │ │ │ └── OpenSans-ExtraBoldItalic.ttf │ │ └── shicon.svg │ ├── index.html │ └── global.css ├── src │ ├── main.js │ ├── protobuf_decoder │ │ ├── varintUtils.js │ │ ├── hexUtils.js │ │ ├── protobufPartDecoder.js │ │ └── protobufDecoder.js │ ├── Packet.svelte │ ├── proto_raw_decoder.js │ └── App.svelte ├── package.json ├── rollup.config.js ├── README.md └── scripts │ └── setupTypeScript.js ├── .gitignore ├── config.json ├── .idea ├── vcs.xml ├── .gitignore ├── modules.xml └── IridiumNG.iml ├── makefile ├── README-zh.md ├── README.md ├── .github └── workflows │ └── build.yml ├── util.go ├── mt19937_64.go ├── main.go ├── go.mod ├── frontend_server.go ├── proto_service.go ├── sniffer.go └── go.sum /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /vendor 3 | 4 | /data 5 | 6 | .DS_Store 7 | 8 | *.pcapng -------------------------------------------------------------------------------- /frontend/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/favicon.png -------------------------------------------------------------------------------- /frontend/public/fonts/shicon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/shicon.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/shicon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/shicon.woff -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "deviceName" : "", 3 | "packetFilter" : [ 4 | "" 5 | ], 6 | "autoSavePcapFiles" : true 7 | } -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-Light.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-Medium.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-SemiBold.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-MediumItalic.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /frontend/public/fonts/OpenSans/OpenSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akka0/Iridium-NG/HEAD/frontend/public/fonts/OpenSans/OpenSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: { 6 | name: 'world' 7 | } 8 | }); 9 | 10 | export default app; -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/IridiumNG.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Iridium frontend 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | BINARY=IridiumNG 2 | 3 | build-win: 4 | CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -o build/${BINARY}_windows_amd64.exe 5 | build-darwin: 6 | CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -o build/${BINARY}_darwin_amd64 7 | build-linux: 8 | CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o build/${BINARY}_linux_amd64 9 | 10 | build-arm64: 11 | CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -o build/${BINARY}_darwin_arm64 12 | CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o build/${BINARY}_linux_arm64 13 | 14 | pre-build: 15 | mkdir build 16 | mkdir data 17 | cp ./config.json ./build/config.json 18 | -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | # Iridium-NG 2 | 3 | A KCP packet sniffer + visualizer in one, backend rewritten in Go. 4 | 5 | ![Build](https://github.com/Akka0/Iridium-NG/actions/workflows/build.yml/badge.svg) 6 | 7 | # 用法 8 | 9 | 你可以从Actions中下载到编译好的,或者自己从源码构建。 10 | 11 | 0. 往 `data/` 目录放入 `packetIds.json`, `Keys.json` 和 `proto/` 文件. 12 | 1. 确保你已安装 [Npcap driver](https://npcap.com/#download) 或 wireshark. 13 | 2. 使用命令 `-l` 列出电脑上所有网卡,编辑 `config.json` 设置网卡设备, 或者使用命令 `-ip 192.x.x.x` 自动通过ip寻找设备. 14 | 3. 打开 http://localhost:1984/, 15 | 16 | **注意:在进门之前开始抓包** 17 | 18 | # Config.json 19 | 20 | ```json 21 | { 22 | "deviceName" : "", // 网络设备名称, 例如 eth0 23 | "packetFilter" : [ // 这里列出的包名将不会在前端显示 24 | "" 25 | ], 26 | "autoSavePcapFiles" : true // 自动保存抓包记录文件 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "rollup -c -w", 8 | "start": "sirv public --no-clear" 9 | }, 10 | "devDependencies": { 11 | "@rollup/plugin-commonjs": "^17.1.0", 12 | "@rollup/plugin-node-resolve": "^11.2.1", 13 | "rollup": "^2.75.6", 14 | "rollup-plugin-css-only": "^3.1.0", 15 | "rollup-plugin-livereload": "^2.0.5", 16 | "rollup-plugin-svelte": "^7.1.0", 17 | "rollup-plugin-terser": "^7.0.2", 18 | "svelte": "^3.49.0", 19 | "svelte-highlight": "^5.3.2" 20 | }, 21 | "dependencies": { 22 | "buffer": "^6.0.3", 23 | "jsbi": "^4.3.0", 24 | "sirv-cli": "^2.0.2", 25 | "svelte-jsoneditor": "^0.3.60", 26 | "svelte-virtual-list-ce": "^3.1.0-beta.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Iridium-NG 2 | 3 | A KCP packet sniffer + visualizer in one, backend rewritten in Go. 4 | 5 | ![Build](https://github.com/Akka0/Iridium-NG/actions/workflows/build.yml/badge.svg) 6 | 7 | [中文说明](/README-zh.md) 8 | 9 | # Usage 10 | 11 | You can download the binary(win/linux) from Actions, or build from source 12 | 13 | 0. Bring your `packetIds.json`, `Keys.json` and `proto/` to the `data/` folder. 14 | 1. Make sure you have installed [Npcap driver](https://npcap.com/#download) or wireshark. 15 | 2. Use cmd `-l` to list the network devices on your computer and edit `config.json` to set the device by its name, or use cmd `-ip 192.x.x.x` to let it auto find the device by its ip. 16 | 3. Open http://localhost:1984/ 17 | 18 | **Notice: START CAPTURE BEFORE YOU ENTER THE DOOR** 19 | 20 | # Config.json 21 | 22 | ```json 23 | { 24 | "deviceName" : "", // network device name, such as eth0 25 | "packetFilter" : [ // the packets listed here will not show in frontend 26 | "" 27 | ], 28 | "autoSavePcapFiles" : true // auto save capture to current folder 29 | } 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v3 18 | with: 19 | go-version: 1.18 20 | cache: true 21 | 22 | - name: Setup Node.js environment 23 | uses: actions/setup-node@v3.3.0 24 | with: 25 | node-version: 16.x 26 | cache: npm 27 | cache-dependency-path: ./frontend/package-lock.json 28 | 29 | - name: Build Frontend 30 | run: cd frontend && npm i && npm run build 31 | 32 | - name: Set up libpcap 33 | run: sudo apt-get install -y libpcap-dev 34 | 35 | - name: Build 36 | run: make pre-build && make build-win && make build-linux 37 | 38 | - name: Upload a Build Artifact 39 | uses: actions/upload-artifact@v3.1.0 40 | with: 41 | # Artifact name 42 | name: IridiumNG 43 | # A file, directory or wildcard pattern that describes what to upload 44 | path: ./build 45 | -------------------------------------------------------------------------------- /frontend/src/protobuf_decoder/varintUtils.js: -------------------------------------------------------------------------------- 1 | /* 2 | Source: https://github.com/pawitp/protobuf-decoder by pawitp 3 | Modified to adapt common-js 4 | */ 5 | const JSBI = require("jsbi"); 6 | 7 | const BIGINT_1 = JSBI.BigInt(1); 8 | const BIGINT_2 = JSBI.BigInt(2); 9 | 10 | function interpretAsSignedType(n) { 11 | // see https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/wire_format_lite.h#L857-L876 12 | // however, this is a simpler equivalent formula 13 | const isEven = JSBI.equal(JSBI.bitwiseAnd(n, JSBI.BigInt(1)), JSBI.BigInt(0)); 14 | if (isEven) { 15 | return JSBI.divide(n, BIGINT_2); 16 | } else { 17 | return JSBI.multiply( 18 | JSBI.BigInt(-1), 19 | JSBI.divide(JSBI.add(n, BIGINT_1), BIGINT_2) 20 | ); 21 | } 22 | } 23 | 24 | function decodeVarint(buffer, offset) { 25 | let res = JSBI.BigInt(0); 26 | let shift = 0; 27 | let byte = 0; 28 | 29 | do { 30 | if (offset >= buffer.length) { 31 | throw new RangeError("Index out of bound decoding varint"); 32 | } 33 | 34 | byte = buffer[offset++]; 35 | 36 | const multiplier = JSBI.exponentiate(BIGINT_2, JSBI.BigInt(shift)); 37 | const thisByteValue = JSBI.multiply(JSBI.BigInt(byte & 0x7f), multiplier); 38 | shift += 7; 39 | res = JSBI.add(res, thisByteValue); 40 | } while (byte >= 0x80); 41 | 42 | return { 43 | value: res, 44 | length: shift / 7 45 | }; 46 | } 47 | 48 | module.exports = { 49 | interpretAsSignedType, decodeVarint 50 | } 51 | -------------------------------------------------------------------------------- /frontend/src/protobuf_decoder/hexUtils.js: -------------------------------------------------------------------------------- 1 | /* 2 | Source: https://github.com/pawitp/protobuf-decoder by pawitp 3 | Modified to adapt common-js 4 | */ 5 | const Buffer = require('buffer/').Buffer 6 | 7 | function parseInput(input) { 8 | const normalizedInput = input.replace(/\s/g, ""); 9 | const normalizedHexInput = normalizedInput.replace(/0x/g, "").toLowerCase(); 10 | if (isHex(normalizedHexInput)) { 11 | return Buffer.from(normalizedHexInput, "hex"); 12 | } else { 13 | return Buffer.from(normalizedInput, "base64"); 14 | } 15 | } 16 | 17 | function isHex(string) { 18 | let result = true; 19 | for (const char of string) { 20 | if (!((char >= "a" && char <= "f") || (char >= "0" && char <= "9"))) { 21 | result = false; 22 | } 23 | } 24 | return result; 25 | } 26 | 27 | function bufferToPrettyHex(buffer) { 28 | let output = ""; 29 | for (const v of buffer) { 30 | if (output !== "") { 31 | output += " "; 32 | } 33 | 34 | const hex = v.toString(16); 35 | if (hex.length === 1) { 36 | output += "0" + hex; 37 | } else { 38 | output += hex; 39 | } 40 | } 41 | return output; 42 | } 43 | 44 | function bufferLeToBeHex(buffer) { 45 | let output = ""; 46 | for (const v of buffer) { 47 | const hex = v.toString(16); 48 | if (hex.length === 1) { 49 | output = "0" + hex + output; 50 | } else { 51 | output = hex + output; 52 | } 53 | } 54 | return output; 55 | } 56 | 57 | module.exports = { 58 | parseInput, isHex, bufferToPrettyHex, bufferLeToBeHex 59 | } -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | ) 7 | 8 | func removeMagic(data []byte) []byte { 9 | cut := data[5] 10 | data = data[8+2:] // Removes token + two byte magic 11 | data = data[0 : len(data)-2] // Removes two byte magic at the end 12 | data = data[cut:] 13 | return data 14 | } 15 | 16 | func removeHeaderForParse(data []byte) []byte { 17 | cut := data[6] 18 | data = removeMagic(data) 19 | return data[cut:] 20 | } 21 | 22 | func xorDecrypt(data []byte, key []byte) { 23 | for i := 0; i < len(data); i++ { 24 | data[i] = data[i] ^ key[i%len(key)] 25 | } 26 | } 27 | 28 | func reformData(data []byte) []byte { 29 | i := 0 30 | tokenSizeTotal := 0 31 | var messages [][]byte 32 | for i < len(data) { 33 | convId := data[i : i+4] 34 | remainingHeader := data[i+8 : i+28] 35 | contentLen := int(binary.LittleEndian.Uint32(data[i+24 : i+28])) 36 | content := data[i+28 : (i + 28 + contentLen)] 37 | 38 | formattedMessage := make([]byte, 24+contentLen) 39 | copy(formattedMessage, convId) 40 | copy(formattedMessage[4:], remainingHeader) 41 | copy(formattedMessage[24:], content) 42 | i += 28 + contentLen 43 | tokenSizeTotal += 4 44 | messages = append(messages, formattedMessage) 45 | } 46 | 47 | return bytes.Join(messages, []byte{}) 48 | } 49 | 50 | func createXorPad(seed uint64) []byte { 51 | first := New() 52 | first.Seed(int64(seed)) 53 | generator := New() 54 | generator.Seed(first.Generate()) 55 | generator.Generate() 56 | xorPad := make([]byte, 4096) 57 | 58 | for i := 0; i < 4096; i += 8 { 59 | value := generator.Generate() 60 | binary.BigEndian.PutUint64(xorPad[i:i+8], uint64(value)) 61 | } 62 | return xorPad 63 | } 64 | -------------------------------------------------------------------------------- /mt19937_64.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const N = 312 4 | const M = 156 5 | const MATRIX_A = 0xB5026F5AA96619E9 6 | const UPPER_MASK = 0xFFFFFFFF80000000 7 | const LOWER_MASK = 0x7FFFFFFF 8 | 9 | type MT19937_64 struct { 10 | array [312]uint64 //state vector 11 | index uint64 // array index 12 | } 13 | 14 | func New() *MT19937_64 { 15 | return &MT19937_64{ 16 | index: N + 1, 17 | } 18 | } 19 | 20 | func (m *MT19937_64) Seed(seed int64) { 21 | m.array[0] = uint64(seed) 22 | for m.index = 1; m.index < N; m.index++ { 23 | m.array[m.index] = (6364136223846793005*(m.array[m.index-1]^(m.array[m.index-1]>>62)) + m.index) 24 | } 25 | } 26 | 27 | func (m *MT19937_64) Generate() int64 { 28 | return m.Int63() 29 | } 30 | 31 | func (m *MT19937_64) Int63() int64 { 32 | var i int 33 | var x uint64 34 | mag01 := []uint64{0, MATRIX_A} 35 | if m.index >= N { 36 | /* Initialize with a default Seed if Seed() not previously called */ 37 | if m.index == N+1 { 38 | m.Seed(int64(5489)) 39 | } 40 | 41 | for i = 0; i < N-M; i++ { 42 | x = (m.array[i] & UPPER_MASK) | (m.array[i+1] & LOWER_MASK) 43 | m.array[i] = m.array[i+(M)] ^ (x >> 1) ^ mag01[int(x&uint64(1))] 44 | } 45 | for ; i < N-1; i++ { 46 | x = (m.array[i] & UPPER_MASK) | (m.array[i+1] & LOWER_MASK) 47 | m.array[i] = m.array[i+(M-N)] ^ (x >> 1) ^ mag01[int(x&uint64(1))] 48 | } 49 | x = (m.array[N-1] & UPPER_MASK) | (m.array[0] & LOWER_MASK) 50 | m.array[N-1] = m.array[M-1] ^ (x >> 1) ^ mag01[int(x&uint64(1))] 51 | m.index = 0 52 | 53 | } 54 | x = m.array[m.index] 55 | m.index++ 56 | x ^= (x >> 29) & 0x5555555555555555 57 | x ^= (x << 17) & 0x71D67FFFEDA60000 58 | x ^= (x << 37) & 0xFFF7EEE000000000 59 | x ^= (x >> 43) 60 | 61 | return int64(x) 62 | } 63 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "github.com/fatih/color" 7 | "github.com/google/gopacket/pcap" 8 | "io/ioutil" 9 | "log" 10 | "os" 11 | ) 12 | 13 | type Config struct { 14 | DeviceName string `json:"deviceName"` 15 | PacketFilter []string `json:"packetFilter"` 16 | AutoSavePcapFiles bool `json:"autoSavePcapFiles"` 17 | } 18 | 19 | var config *Config 20 | var listDevice = flag.Bool("l", false, "List the network devices on this machine") 21 | var ip = flag.String("ip", "", "Designate the network devices to capture by IP") 22 | 23 | func main() { 24 | bytes, err := ioutil.ReadFile("./config.json") 25 | if err != nil { 26 | log.Fatalln("Could not load ./config.json", err) 27 | } 28 | err = json.Unmarshal(bytes, &config) 29 | if err != nil { 30 | log.Fatalln("Could not load ./config.json", err) 31 | } 32 | for packet := range config.PacketFilter { 33 | packetFilter[config.PacketFilter[packet]] = true 34 | } 35 | 36 | flag.Parse() 37 | 38 | if *listDevice { 39 | devices, err := pcap.FindAllDevs() 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | 44 | log.Println(color.RedString("Name"), "\tDescription\t", color.CyanString("IP address"), "\tSubnet mask") 45 | for _, device := range devices { 46 | log.Println(color.RedString(device.Name), "\t", device.Description, "\t") 47 | for _, address := range device.Addresses { 48 | log.Println("\t\t\t", color.CyanString(address.IP.String()), "\t", address.Netmask) 49 | } 50 | } 51 | os.Exit(0) 52 | } 53 | 54 | if len(*ip) > 0 { 55 | devices, err := pcap.FindAllDevs() 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | 60 | for _, device := range devices { 61 | for _, address := range device.Addresses { 62 | if address.IP.String() == *ip { 63 | log.Println("Device ", device.Name, " is chose") 64 | config.DeviceName = device.Name 65 | break 66 | } 67 | } 68 | } 69 | } 70 | 71 | go InitProto() 72 | startServer() 73 | } 74 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Akka0/Iridium-NG 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/fatih/color v1.13.0 7 | github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19 8 | github.com/gin-gonic/gin v1.8.0 9 | github.com/google/gopacket v1.1.19 10 | github.com/jhump/protoreflect v1.12.0 11 | github.com/xtaci/kcp-go v5.4.20+incompatible 12 | ) 13 | 14 | require ( 15 | github.com/gin-contrib/sse v0.1.0 // indirect 16 | github.com/go-playground/locales v0.14.0 // indirect 17 | github.com/go-playground/universal-translator v0.18.0 // indirect 18 | github.com/go-playground/validator/v10 v10.11.0 // indirect 19 | github.com/goccy/go-json v0.9.7 // indirect 20 | github.com/golang/protobuf v1.5.2 // indirect 21 | github.com/json-iterator/go v1.1.12 // indirect 22 | github.com/klauspost/cpuid/v2 v2.0.6 // indirect 23 | github.com/klauspost/reedsolomon v1.9.16 // indirect 24 | github.com/leodido/go-urn v1.2.1 // indirect 25 | github.com/mattn/go-colorable v0.1.9 // indirect 26 | github.com/mattn/go-isatty v0.0.14 // indirect 27 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 28 | github.com/modern-go/reflect2 v1.0.2 // indirect 29 | github.com/pelletier/go-toml/v2 v2.0.1 // indirect 30 | github.com/pkg/errors v0.9.1 // indirect 31 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect 32 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect 33 | github.com/tjfoc/gmsm v1.4.1 // indirect 34 | github.com/ugorji/go/codec v1.2.7 // indirect 35 | github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 // indirect 36 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect 37 | golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect 38 | golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect 39 | golang.org/x/text v0.3.7 // indirect 40 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 41 | google.golang.org/protobuf v1.28.0 // indirect 42 | gopkg.in/yaml.v2 v2.4.0 // indirect 43 | ) 44 | -------------------------------------------------------------------------------- /frontend_server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "embed" 5 | "github.com/gin-gonic/contrib/static" 6 | "github.com/gin-gonic/gin" 7 | "io" 8 | "io/fs" 9 | "log" 10 | "net/http" 11 | "os" 12 | ) 13 | 14 | var eventStream = make(chan string) 15 | 16 | //go:embed frontend/public 17 | var staticFolder embed.FS 18 | 19 | func startServer() { 20 | r := gin.Default() 21 | r.GET("/api/start", apiStart) 22 | r.GET("/api/stop", apiStop) 23 | r.POST("/api/upload", apiUpload) 24 | r.GET("/api/stream", stream) 25 | r.Use(static.Serve("/", EmbedFolder(staticFolder, "frontend/public"))) 26 | 27 | defer close(eventStream) 28 | err := r.Run(":1984") 29 | if err != nil { 30 | log.Fatalln("Could not start http server", err) 31 | } 32 | } 33 | 34 | func apiStart(c *gin.Context) { 35 | go openCapture() 36 | } 37 | 38 | func apiStop(c *gin.Context) { 39 | go closeHandle() 40 | } 41 | 42 | func apiUpload(c *gin.Context) { 43 | file, err := c.FormFile("file") 44 | if err != nil { 45 | log.Println("Could not handle upload file", err) 46 | return 47 | } 48 | err = c.SaveUploadedFile(file, os.TempDir()+file.Filename) 49 | if err != nil { 50 | log.Println("Could not handle upload file", err) 51 | return 52 | } 53 | go openPcap(os.TempDir() + file.Filename) 54 | } 55 | 56 | func stream(c *gin.Context) { 57 | c.Stream(func(w io.Writer) bool { 58 | c.SSEvent("packetNotify", <-eventStream) 59 | return true 60 | }) 61 | } 62 | 63 | func sendStreamMsg(msg string) { 64 | go func() { 65 | eventStream <- msg 66 | }() 67 | } 68 | 69 | type embedFileSystem struct { 70 | http.FileSystem 71 | } 72 | 73 | func (e embedFileSystem) Exists(prefix string, path string) bool { 74 | _, err := e.Open(path) 75 | if err != nil { 76 | return false 77 | } 78 | return true 79 | } 80 | 81 | func EmbedFolder(fsEmbed embed.FS, targetPath string) static.ServeFileSystem { 82 | fsys, err := fs.Sub(fsEmbed, targetPath) 83 | if err != nil { 84 | panic(err) 85 | } 86 | return embedFileSystem{ 87 | FileSystem: http.FS(fsys), 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /frontend/src/Packet.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |
13 | {#if packet.reltime}{packet.reltime.toFixed(3)}{/if} 14 |
15 |
{idx}
16 |
17 | {packet.source ? "CLIENT" : "SERVER"} 20 |
21 |
{packet.packetID}
22 |
{packet.protoName}
23 |
{packetLength || ""}
24 |
{packetString}
25 |
26 | 27 | 84 | -------------------------------------------------------------------------------- /frontend/src/protobuf_decoder/protobufPartDecoder.js: -------------------------------------------------------------------------------- 1 | /* 2 | Source: https://github.com/pawitp/protobuf-decoder by pawitp 3 | Modified to adapt common-js 4 | */ 5 | const JSBI = require("jsbi"); 6 | const { bufferLeToBeHex } = require( "./hexUtils"); 7 | const { interpretAsSignedType } = require( "./varintUtils"); 8 | 9 | function decodeFixed32(value) { 10 | const floatValue = value.readFloatLE(0); 11 | const intValue = value.readInt32LE(0); 12 | const uintValue = value.readUInt32LE(0); 13 | 14 | const result = []; 15 | 16 | result.push({ type: "Int", value: intValue }); 17 | 18 | if (intValue !== uintValue) { 19 | result.push({ type: "Unsigned Int", value: uintValue }); 20 | } 21 | 22 | result.push({ type: "Float", value: floatValue }); 23 | 24 | return result; 25 | } 26 | 27 | function decodeFixed64(value) { 28 | const floatValue = value.readDoubleLE(0); 29 | const uintValue = JSBI.BigInt("0x" + bufferLeToBeHex(value)); 30 | const intValue = twoComplements(uintValue); 31 | 32 | const result = []; 33 | 34 | result.push({ type: "Int", value: intValue.toString() }); 35 | 36 | if (intValue !== uintValue) { 37 | result.push({ type: "Unsigned Int", value: uintValue.toString() }); 38 | } 39 | 40 | result.push({ type: "Double", value: floatValue }); 41 | 42 | return result; 43 | } 44 | 45 | function decodeVarintParts(value) { 46 | const result = []; 47 | const intVal = JSBI.BigInt(value); 48 | result.push({ type: "Int", value: intVal.toString() }); 49 | 50 | const signedIntVal = interpretAsSignedType(intVal); 51 | if (signedIntVal !== intVal) { 52 | result.push({ type: "Signed Int", value: signedIntVal.toString() }); 53 | } 54 | return result; 55 | } 56 | 57 | const maxLong = JSBI.BigInt("0x7fffffffffffffff"); 58 | const longForComplement = JSBI.BigInt("0x10000000000000000"); 59 | 60 | function twoComplements(uintValue) { 61 | if (JSBI.greaterThan(uintValue, maxLong)) { 62 | return JSBI.subtract(uintValue, longForComplement); 63 | } else { 64 | return uintValue; 65 | } 66 | } 67 | 68 | module.exports = { 69 | decodeFixed32, decodeFixed64, decodeVarintParts 70 | } -------------------------------------------------------------------------------- /frontend/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import resolve from '@rollup/plugin-node-resolve'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | import css from 'rollup-plugin-css-only'; 7 | 8 | const production = !process.env.ROLLUP_WATCH; 9 | 10 | function serve() { 11 | let server; 12 | 13 | function toExit() { 14 | if (server) server.kill(0); 15 | } 16 | 17 | return { 18 | writeBundle() { 19 | if (server) return; 20 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { 21 | stdio: ['ignore', 'inherit', 'inherit'], 22 | shell: true 23 | }); 24 | 25 | process.on('SIGTERM', toExit); 26 | process.on('exit', toExit); 27 | } 28 | }; 29 | } 30 | 31 | export default { 32 | input: 'src/main.js', 33 | output: { 34 | sourcemap: true, 35 | format: 'iife', 36 | name: 'app', 37 | file: 'public/build/bundle.js', 38 | inlineDynamicImports: true, 39 | }, 40 | plugins: [ 41 | svelte({ 42 | compilerOptions: { 43 | // enable run-time checks when not in production 44 | dev: !production 45 | } 46 | }), 47 | // we'll extract any component CSS out into 48 | // a separate file - better for performance 49 | css({ output: 'bundle.css' }), 50 | 51 | // If you have external dependencies installed from 52 | // npm, you'll most likely need these plugins. In 53 | // some cases you'll need additional configuration - 54 | // consult the documentation for details: 55 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 56 | resolve({ 57 | browser: true, 58 | dedupe: ['svelte'] 59 | }), 60 | commonjs(), 61 | 62 | // In dev mode, call `npm run start` once 63 | // the bundle has been generated 64 | !production && serve(), 65 | 66 | // Watch the `public` directory and refresh the 67 | // browser on changes when not in production 68 | !production && livereload('public'), 69 | 70 | // If we're building for production (npm run build 71 | // instead of npm run dev), minify 72 | production && terser() 73 | ], 74 | watch: { 75 | clearScreen: false 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /proto_service.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/jhump/protoreflect/desc" 7 | "github.com/jhump/protoreflect/desc/protoparse" 8 | "github.com/jhump/protoreflect/dynamic" 9 | "io/ioutil" 10 | "log" 11 | ) 12 | 13 | var msgMap = make(map[string]*desc.MessageDescriptor) 14 | var packetIdMap map[uint16]string 15 | var packetNameMap = make(map[string]uint16) 16 | var protoParser = protoparse.Parser{} 17 | 18 | func InitProto() { 19 | packetIdFile, _ := ioutil.ReadFile("./data/packetIds.json") 20 | err := json.Unmarshal(packetIdFile, &packetIdMap) 21 | if err != nil { 22 | log.Fatalln("Could not load ./data/packetIds.json", err) 23 | } 24 | 25 | for k, v := range packetIdMap { 26 | packetNameMap[v] = k 27 | } 28 | 29 | protoParser.ImportPaths = []string{"./data/proto/"} 30 | for _, v := range packetIdMap { 31 | LoadProto(v) 32 | } 33 | 34 | } 35 | 36 | func LoadProto(protoName string) { 37 | fileDesc, err := protoParser.ParseFiles(protoName + ".proto") 38 | if err != nil { 39 | log.Println("Could not load proto file", protoName, err) 40 | return 41 | } 42 | 43 | msgMap[protoName] = fileDesc[0].FindMessage(protoName) 44 | } 45 | 46 | func GetProtoById(id uint16) *desc.MessageDescriptor { 47 | protoName, ok := packetIdMap[id] 48 | if !ok { 49 | return nil 50 | } 51 | return msgMap[protoName] 52 | } 53 | 54 | func GetProtoNameById(id uint16) string { 55 | protoName, ok := packetIdMap[id] 56 | if !ok { 57 | return "" 58 | } 59 | return protoName 60 | } 61 | 62 | func parseProto(id uint16, data []byte) (*dynamic.Message, error) { 63 | msg := GetProtoById(id) 64 | if msg == nil { 65 | return nil, errors.New("not found") 66 | } 67 | dMsg := dynamic.NewMessage(msg) 68 | 69 | err := dMsg.Unmarshal(data) 70 | return dMsg, err 71 | } 72 | 73 | func parseProtoToJson(id uint16, data []byte) string { 74 | dMsg, err := parseProto(id, data) 75 | if err != nil { 76 | return "" 77 | } 78 | 79 | marshalJSON, err := dMsg.MarshalJSON() 80 | if err != nil { 81 | return "" 82 | } 83 | 84 | return string(marshalJSON) 85 | } 86 | 87 | func parseProtoToInterface(id uint16, data []byte) *interface{} { 88 | object := parseProtoToJson(id, data) 89 | 90 | var result *interface{} 91 | err := json.Unmarshal([]byte(object), &result) 92 | if err != nil { 93 | return nil 94 | } 95 | 96 | return result 97 | } 98 | -------------------------------------------------------------------------------- /frontend/src/proto_raw_decoder.js: -------------------------------------------------------------------------------- 1 | const { decodeProto, TYPES } = require("./protobuf_decoder/protobufDecoder"); 2 | const { 3 | decodeFixed32, 4 | decodeFixed64, 5 | decodeVarintParts, 6 | } = require("./protobuf_decoder/protobufPartDecoder"); 7 | const { parseInput } = require("./protobuf_decoder/hexUtils"); 8 | const { 9 | decodeVarint, 10 | interpretAsSignedType, 11 | } = require("./protobuf_decoder/varintUtils"); 12 | 13 | function parseType(decodeList) { 14 | return decodeList.reduce((pre, cur, index, arr) => { 15 | if (index === 0) { 16 | return `${cur.type}:${cur.value}`; 17 | } else { 18 | } 19 | return `${pre}, ${cur.type}:${cur.value}`; 20 | }, ""); 21 | } 22 | 23 | function getNextIndex(key, repeatedMap) { 24 | if (!repeatedMap[key]) { 25 | repeatedMap[key] = 0; 26 | } 27 | repeatedMap[key]++; 28 | return repeatedMap[key] < 2 ? key : `${key}#${repeatedMap[key].toString()}`; 29 | } 30 | 31 | function processProtoPart(raw) { 32 | const data = decodeProto(parseInput(raw)); 33 | const result = {}; 34 | const repeatedMap = {}; 35 | data.parts.forEach((e) => { 36 | let key; 37 | let res; 38 | switch (e.type) { 39 | case TYPES.FIXED32: 40 | const fixed32 = decodeFixed32(e.value); 41 | key = getNextIndex(`${e.index}:32b`, repeatedMap); 42 | res = parseType(fixed32); 43 | break; 44 | 45 | case TYPES.FIXED64: 46 | const fixed64 = decodeFixed64(e.value); 47 | key = getNextIndex(`${e.index}:64b`, repeatedMap); 48 | res = parseType(fixed64); 49 | break; 50 | 51 | case TYPES.VARINT: 52 | const varint = decodeVarintParts(e.value); 53 | key = getNextIndex(`${e.index}:varint`, repeatedMap); 54 | res = parseType(varint); 55 | break; 56 | 57 | case TYPES.STRING: 58 | const str = processProtoPart(e.value.toString("base64")); 59 | key = getNextIndex(`${e.index}:ld`, repeatedMap); 60 | 61 | if (e.value.length > 0 && !str.leftOver) { 62 | res = str; 63 | } else { 64 | res = []; 65 | decodeRepeated(e, res); 66 | 67 | res.push( 68 | `String:${e.value.toString()}, Raw:${e.value.toString("hex")}` 69 | ); 70 | } 71 | 72 | break; 73 | } 74 | result[key] = res; 75 | }); 76 | 77 | if (data.leftOver && data.leftOver.length > 0) { 78 | result.leftOver = data.leftOver.toString("base64"); 79 | } 80 | 81 | return result; 82 | } 83 | 84 | function decodeRepeated(e, res) { 85 | try { 86 | let list = []; 87 | let len = 0; 88 | while (len < e.value.length) { 89 | const reslove = decodeVarint(e.value, len); 90 | len += reslove.length; 91 | list.push(reslove.value); 92 | } 93 | 94 | if (list.length > 0) { 95 | res.push(`Repeated Int:[${list.toString()}]`); 96 | 97 | if (list[0] !== interpretAsSignedType(list[0])) { 98 | const newList = list.map((i) => interpretAsSignedType(i)); 99 | res.push(`Repeated Signed Int:[${newList.toString()}]`); 100 | } 101 | } 102 | } catch (ex) { 103 | // it must be not this type 104 | } 105 | } 106 | 107 | function protoRawDecode(raw) { 108 | return processProtoPart(raw); 109 | } 110 | 111 | module.exports = { 112 | protoRawDecode, 113 | }; 114 | -------------------------------------------------------------------------------- /frontend/src/protobuf_decoder/protobufDecoder.js: -------------------------------------------------------------------------------- 1 | /* 2 | Source: https://github.com/pawitp/protobuf-decoder by pawitp 3 | Modified to adapt common-js 4 | */ 5 | const { decodeVarint } = require("./varintUtils"); 6 | 7 | class BufferReader { 8 | constructor(buffer) { 9 | this.buffer = buffer; 10 | this.offset = 0; 11 | } 12 | 13 | readVarInt() { 14 | const result = decodeVarint(this.buffer, this.offset); 15 | this.offset += result.length; 16 | 17 | return result.value; 18 | } 19 | 20 | readBuffer(length) { 21 | this.checkByte(length); 22 | const result = this.buffer.slice(this.offset, this.offset + length); 23 | this.offset += length; 24 | 25 | return result; 26 | } 27 | 28 | // gRPC has some additional header - remove it 29 | trySkipGrpcHeader() { 30 | const backupOffset = this.offset; 31 | 32 | if (this.buffer[this.offset] === 0) { 33 | this.offset++; 34 | const length = this.buffer.readInt32BE(this.offset); 35 | this.offset += 4; 36 | 37 | if (length > this.leftBytes()) { 38 | // Something is wrong, revert 39 | this.offset = backupOffset; 40 | } 41 | } 42 | } 43 | 44 | leftBytes() { 45 | return this.buffer.length - this.offset; 46 | } 47 | 48 | checkByte(length) { 49 | const bytesAvailable = this.leftBytes(); 50 | if (length > bytesAvailable) { 51 | throw new Error( 52 | "Not enough bytes left. Requested: " + 53 | length + 54 | " left: " + 55 | bytesAvailable 56 | ); 57 | } 58 | } 59 | 60 | checkpoint() { 61 | this.savedOffset = this.offset; 62 | } 63 | 64 | resetToCheckpoint() { 65 | this.offset = this.savedOffset; 66 | } 67 | } 68 | 69 | const TYPES = { 70 | VARINT: 0, 71 | FIXED64: 1, 72 | STRING: 2, 73 | FIXED32: 5 74 | }; 75 | 76 | function decodeProto(buffer) { 77 | const reader = new BufferReader(buffer); 78 | const parts = []; 79 | 80 | reader.trySkipGrpcHeader(); 81 | 82 | try { 83 | while (reader.leftBytes() > 0) { 84 | reader.checkpoint(); 85 | 86 | const indexType = parseInt(reader.readVarInt().toString()); 87 | const type = indexType & 0b111; 88 | const index = indexType >> 3; 89 | 90 | let value; 91 | if (type === TYPES.VARINT) { 92 | value = reader.readVarInt().toString(); 93 | } else if (type === TYPES.STRING) { 94 | const length = parseInt(reader.readVarInt().toString()); 95 | value = reader.readBuffer(length); 96 | } else if (type === TYPES.FIXED32) { 97 | value = reader.readBuffer(4); 98 | } else if (type === TYPES.FIXED64) { 99 | value = reader.readBuffer(8); 100 | } else { 101 | throw new Error("Unknown type: " + type); 102 | } 103 | 104 | parts.push({ 105 | index, 106 | type, 107 | value 108 | }); 109 | } 110 | } catch (err) { 111 | reader.resetToCheckpoint(); 112 | } 113 | 114 | return { 115 | parts, 116 | leftOver: reader.readBuffer(reader.leftBytes()) 117 | }; 118 | } 119 | 120 | function typeToString(type) { 121 | switch (type) { 122 | case TYPES.VARINT: 123 | return "varint"; 124 | case TYPES.STRING: 125 | return "string"; 126 | case TYPES.FIXED32: 127 | return "fixed32"; 128 | case TYPES.FIXED64: 129 | return "fixed64"; 130 | default: 131 | return "unknown"; 132 | } 133 | } 134 | 135 | module.exports = { 136 | TYPES, decodeProto, typeToString 137 | } -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | *Psst — looking for a more complete solution? Check out [SvelteKit](https://kit.svelte.dev), the official framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.* 2 | 3 | *Looking for a shareable component template instead? You can [use SvelteKit for that as well](https://kit.svelte.dev/docs#packaging) or the older [sveltejs/component-template](https://github.com/sveltejs/component-template)* 4 | 5 | --- 6 | 7 | # svelte app 8 | 9 | This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. 10 | 11 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): 12 | 13 | ```bash 14 | npx degit sveltejs/template svelte-app 15 | cd svelte-app 16 | ``` 17 | 18 | *Note that you will need to have [Node.js](https://nodejs.org) installed.* 19 | 20 | 21 | ## Get started 22 | 23 | Install the dependencies... 24 | 25 | ```bash 26 | cd svelte-app 27 | npm install 28 | ``` 29 | 30 | ...then start [Rollup](https://rollupjs.org): 31 | 32 | ```bash 33 | npm run dev 34 | ``` 35 | 36 | Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. 37 | 38 | By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. 39 | 40 | If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. 41 | 42 | ## Building and running in production mode 43 | 44 | To create an optimised version of the app: 45 | 46 | ```bash 47 | npm run build 48 | ``` 49 | 50 | You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). 51 | 52 | 53 | ## Single-page app mode 54 | 55 | By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. 56 | 57 | If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: 58 | 59 | ```js 60 | "start": "sirv public --single" 61 | ``` 62 | 63 | ## Using TypeScript 64 | 65 | This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: 66 | 67 | ```bash 68 | node scripts/setupTypeScript.js 69 | ``` 70 | 71 | Or remove the script via: 72 | 73 | ```bash 74 | rm scripts/setupTypeScript.js 75 | ``` 76 | 77 | If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). 78 | 79 | ## Deploying to the web 80 | 81 | ### With [Vercel](https://vercel.com) 82 | 83 | Install `vercel` if you haven't already: 84 | 85 | ```bash 86 | npm install -g vercel 87 | ``` 88 | 89 | Then, from within your project folder: 90 | 91 | ```bash 92 | cd public 93 | vercel deploy --name my-project 94 | ``` 95 | 96 | ### With [surge](https://surge.sh/) 97 | 98 | Install `surge` if you haven't already: 99 | 100 | ```bash 101 | npm install -g surge 102 | ``` 103 | 104 | Then, from within your project folder: 105 | 106 | ```bash 107 | npm run build 108 | surge public my-project.surge.sh 109 | ``` 110 | -------------------------------------------------------------------------------- /frontend/scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** This script modifies the project to support TS code in .svelte files like: 4 | 5 | 8 | 9 | As well as validating the code for CI. 10 | */ 11 | 12 | /** To work on this script: 13 | rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 | */ 15 | 16 | const fs = require("fs") 17 | const path = require("path") 18 | const { argv } = require("process") 19 | 20 | const projectRoot = argv[2] || path.join(__dirname, "..") 21 | 22 | // Add deps to pkg.json 23 | const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) 24 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 25 | "svelte-check": "^2.0.0", 26 | "svelte-preprocess": "^4.0.0", 27 | "@rollup/plugin-typescript": "^8.0.0", 28 | "typescript": "^4.0.0", 29 | "tslib": "^2.0.0", 30 | "@tsconfig/svelte": "^2.0.0" 31 | }) 32 | 33 | // Add script for checking 34 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 35 | "check": "svelte-check --tsconfig ./tsconfig.json" 36 | }) 37 | 38 | // Write the package JSON 39 | fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) 40 | 41 | // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 42 | const beforeMainJSPath = path.join(projectRoot, "src", "main.js") 43 | const afterMainTSPath = path.join(projectRoot, "src", "main.ts") 44 | fs.renameSync(beforeMainJSPath, afterMainTSPath) 45 | 46 | // Switch the app.svelte file to use TS 47 | const appSveltePath = path.join(projectRoot, "src", "App.svelte") 48 | let appFile = fs.readFileSync(appSveltePath, "utf8") 49 | appFile = appFile.replace(" 270 | 271 | 272 | {@html materialDarker} 273 | 274 | 275 | 339 |
340 |
341 |
342 | 343 |
(orand = !orand)}> 344 | AND 345 | OR 346 |
347 | 348 |
349 |
350 |
351 |
352 |
Time
353 |
#
354 |
Sender
355 |
ID
356 |
Proto Name
357 |
Length
358 |
JSON
359 |
360 |
361 | 367 | { 372 | showPacketDetails(packet); 373 | scrollToIndex(Math.max(currentPacket.index - 5, 0)); 374 | }} 375 | /> 376 | 377 |
378 |
379 |
380 |
381 |
382 |
383 |
Time
384 |
#
385 |
Sender
386 |
ID
387 |
Proto Name
388 |
Length
389 |
JSON
390 |
391 |
392 | 398 | 399 | showPacketDetails(packet)} 404 | /> 405 | 406 |
407 |
408 |
409 |
410 |
411 |
412 | {#if currentPacket} 413 | {#if currentPacket.object} 414 |
415 | 420 |
421 | {/if} 422 | {#if currentPacket.decode && showDecode} 423 |
424 | 425 |
426 | {/if} 427 | {/if} 428 |
429 |
430 | 431 | 641 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 4 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 5 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 6 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 7 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 12 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 13 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 14 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 15 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 16 | github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= 17 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 18 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 19 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 20 | github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19 h1:J2LPEOcQmWaooBnBtUDV9KHFEnP5LYTZY03GiQ0oQBw= 21 | github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg= 22 | github.com/gin-gonic/gin v1.8.0 h1:4WFH5yycBMA3za5Hnl425yd9ymdw1XPm4666oab+hv4= 23 | github.com/gin-gonic/gin v1.8.0/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= 24 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 25 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 26 | github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= 27 | github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= 28 | github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= 29 | github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 30 | github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw= 31 | github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= 32 | github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= 33 | github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 34 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 35 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 36 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 37 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 38 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 39 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 40 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 41 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 42 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 43 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 44 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 45 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 46 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 47 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 48 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 49 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 50 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 51 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 52 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 53 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 54 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 55 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 56 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 57 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 58 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 59 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 60 | github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= 61 | github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= 62 | github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= 63 | github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= 64 | github.com/jhump/protoreflect v1.12.0 h1:1NQ4FpWMgn3by/n1X0fbeKEUxP1wBt7+Oitpv01HR10= 65 | github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= 66 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 67 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 68 | github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI= 69 | github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 70 | github.com/klauspost/reedsolomon v1.9.16 h1:mR0AwphBwqFv/I3B9AHtNKvzuowI1vrj8/3UX4XRmHA= 71 | github.com/klauspost/reedsolomon v1.9.16/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= 72 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 73 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 74 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 75 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 76 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 77 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 78 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 79 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 80 | github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 81 | github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 82 | github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= 83 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 84 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 85 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 86 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 87 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 88 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 89 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 90 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 91 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 92 | github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= 93 | github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= 94 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 95 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 96 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 97 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 98 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 99 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 100 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 101 | github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= 102 | github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= 103 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 104 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 105 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 106 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 107 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 108 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 109 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 110 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= 111 | github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= 112 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= 113 | github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= 114 | github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= 115 | github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= 116 | github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 117 | github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= 118 | github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= 119 | github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= 120 | github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= 121 | github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= 122 | github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= 123 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 124 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 125 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 126 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 127 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 128 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= 129 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 130 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 131 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 132 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 133 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 134 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 135 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 136 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 137 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 138 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 139 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 140 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 141 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 142 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 143 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 144 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 145 | golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= 146 | golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 147 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 148 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 149 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 150 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 151 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 152 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 153 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 154 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 155 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 156 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 157 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 158 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 159 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 160 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 161 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 162 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 163 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 164 | golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0= 165 | golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 166 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 167 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 168 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 169 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 170 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 171 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 172 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 173 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 174 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 175 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 176 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 177 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 178 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 179 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 180 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 181 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 182 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 183 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 184 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 185 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 186 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 187 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 188 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 189 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 190 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 191 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 192 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 193 | google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= 194 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 195 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 196 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 197 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 198 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 199 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 200 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 201 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 202 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 203 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 204 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 205 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 206 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 207 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 208 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 209 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 210 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 211 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 212 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 213 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 214 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 215 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 216 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 217 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 218 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 219 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 220 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 221 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 222 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 223 | -------------------------------------------------------------------------------- /frontend/public/fonts/shicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | --------------------------------------------------------------------------------