├── .env ├── .gitignore ├── management ├── postgres │ ├── .gitignore │ ├── dump_schema.sh │ ├── dump_database.sh │ ├── Dockerfile │ └── create_schema.sql └── proxies │ ├── Dockerfile │ ├── nginx.conf │ └── envoy.yaml ├── webapp ├── src │ ├── react-app-env.d.ts │ ├── globals.d.ts │ ├── assets │ │ ├── cloudBlack.png │ │ └── cloudWhite.png │ ├── proto │ │ ├── .gitattributes │ │ ├── README.md │ │ ├── service_pb.d.ts │ │ ├── ServiceServiceClientPb.ts │ │ └── service_pb.js │ ├── index.tsx │ ├── styles │ │ ├── SearchBar.module.css │ │ ├── NavBar.module.css │ │ ├── Modal.module.css │ │ ├── Monitor.module.css │ │ ├── Documentation.module.css │ │ └── FrontPage.module.css │ ├── App.tsx │ ├── components │ │ ├── SearchBar.tsx │ │ ├── ChangeDecryptionPwd.tsx │ │ └── NavBar.tsx │ ├── services │ │ └── DecryptionService.ts │ └── pages │ │ ├── FrontPage.tsx │ │ ├── Documentation.tsx │ │ └── Monitor.tsx ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── .gitignore ├── .yarnclean ├── tsconfig.json ├── package.json └── README.md ├── service ├── internal │ ├── types.go │ └── storage │ │ └── psql.go ├── config.yaml ├── Dockerfile ├── start_service.sh ├── api │ ├── getClientById.go │ ├── proto │ │ ├── service.proto │ │ ├── service_grpc.pb.go │ │ └── service.pb.go │ ├── publish.go │ ├── service.go │ ├── subscribe.go │ └── registerClient.go ├── go.mod ├── main.go └── go.sum ├── cli └── cli2cloud │ ├── go.mod │ ├── streams │ └── collectStreams.go │ ├── crypto │ ├── generatePassword.go │ ├── decrypt.go │ └── encrypt.go │ ├── proto │ ├── cli.proto │ ├── cli_grpc.pb.go │ └── cli.pb.go │ ├── cli2cloud.go │ └── go.sum ├── .github └── dependabot.yml ├── docker-compose.yml ├── LICENSE.md └── README.md /.env: -------------------------------------------------------------------------------- 1 | DB_PWD=1234 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.idea 2 | .env 3 | -------------------------------------------------------------------------------- /management/postgres/.gitignore: -------------------------------------------------------------------------------- 1 | postgres_data/** 2 | -------------------------------------------------------------------------------- /webapp/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /webapp/src/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css'; 2 | declare module '*.scss'; 3 | -------------------------------------------------------------------------------- /webapp/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /webapp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonwind/cli2cloud/HEAD/webapp/public/favicon.ico -------------------------------------------------------------------------------- /service/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type Row struct { 4 | Content string 5 | Line int64 6 | } 7 | -------------------------------------------------------------------------------- /webapp/src/assets/cloudBlack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonwind/cli2cloud/HEAD/webapp/src/assets/cloudBlack.png -------------------------------------------------------------------------------- /webapp/src/assets/cloudWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonwind/cli2cloud/HEAD/webapp/src/assets/cloudWhite.png -------------------------------------------------------------------------------- /management/postgres/dump_schema.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | pg_dump cli2cloud --username=postgres -s > create_schema.sql 6 | -------------------------------------------------------------------------------- /service/config.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | port: ":50051" 3 | 4 | database: 5 | url: "postgres://cli2cloud:${POSTGRES_PASSWORD}@postgres:5432/cli2cloud" 6 | -------------------------------------------------------------------------------- /management/postgres/dump_database.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | pg_dump cli2cloud --username=postgres | gzip > cli2cloud_db_`date +%F-%T`.sql.gz 6 | -------------------------------------------------------------------------------- /webapp/src/proto/.gitattributes: -------------------------------------------------------------------------------- 1 | service_pb.d.ts linguist-documentation 2 | service_pb.js linguist-documentation 3 | ServiceServiceClientPb.ts linguist-documentation 4 | -------------------------------------------------------------------------------- /service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang 2 | 3 | WORKDIR /backend 4 | 5 | COPY . ./ 6 | RUN go mod download 7 | 8 | EXPOSE 50051 9 | CMD ["./start_service.sh"] 10 | 11 | -------------------------------------------------------------------------------- /management/proxies/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM envoyproxy/envoy:v1.20-latest 2 | 3 | COPY envoy.yaml /etc/envoy/envoy.yaml 4 | 5 | EXPOSE 8000 6 | RUN chmod go+r /etc/envoy/envoy.yaml 7 | -------------------------------------------------------------------------------- /service/start_service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | go build -o service 6 | 7 | # Wait 10s such that postgres is ready to connect clients 8 | sleep 15s 9 | 10 | ./service 11 | -------------------------------------------------------------------------------- /management/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres 2 | 3 | ENV POSTGRES_DB cli2cloud 4 | ENV POSTGRES_USER cli2cloud 5 | ENV POSTGRES_PASSWORD $POSTGRES_PASSWORD 6 | 7 | COPY create_schema.sql /docker-entrypoint-initdb.d 8 | -------------------------------------------------------------------------------- /cli/cli2cloud/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/leonwind/cli2cloud/cli/cli2cloud 2 | 3 | go 1.16 4 | 5 | require ( 6 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 7 | google.golang.org/grpc v1.44.0 8 | google.golang.org/protobuf v1.25.0 9 | ) 10 | -------------------------------------------------------------------------------- /webapp/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); -------------------------------------------------------------------------------- /webapp/src/styles/SearchBar.module.css: -------------------------------------------------------------------------------- 1 | .searchForm { 2 | margin: auto; 3 | color: #ffffff !important; 4 | background-color: #1c1c1c !important; 5 | border: 1px; 6 | border-radius: 10px; 7 | } 8 | 9 | .searchForm:focus { 10 | box-shadow: none; 11 | } -------------------------------------------------------------------------------- /webapp/src/styles/NavBar.module.css: -------------------------------------------------------------------------------- 1 | .body { 2 | top: 0; 3 | background-color: #282828; 4 | z-index: 999; 5 | } 6 | 7 | .brand { 8 | font-size: x-large; 9 | color: #e7e7e7; 10 | } 11 | 12 | .buttons { 13 | background-color:transparent; 14 | border: 0px; 15 | border-radius: 10px; 16 | } -------------------------------------------------------------------------------- /webapp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Cli2Cloud", 3 | "name": "Cli2Cloud", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /webapp/src/proto/README.md: -------------------------------------------------------------------------------- 1 | # Create Typescript gRPC Definitions: 2 | 3 | 1. Copy service.proto in this directory: 4 | ```bash 5 | cp ../../../service/api/proto/service.proto ./ 6 | ``` 7 | 2. Generate the gRPC files: 8 | ```bash 9 | protoc -I=./ service.proto \ 10 | --js_out=import_style=commonjs,binary:./ \ 11 | --grpc-web_out=import_style=typescript,mode=grpcwebtext:./ 12 | ``` 13 | -------------------------------------------------------------------------------- /webapp/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /cli/cli2cloud/streams/collectStreams.go: -------------------------------------------------------------------------------- 1 | package streams 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | ) 7 | 8 | func readFromStreams(messages chan interface{}, f *os.File) { 9 | scanner := bufio.NewScanner(f) 10 | for scanner.Scan() { 11 | row := scanner.Text() 12 | messages <- row 13 | } 14 | close(messages) 15 | } 16 | 17 | func CreateStreams(messages chan interface{}) { 18 | go readFromStreams(messages, os.Stdin) 19 | //go readFromStreams(messages, os.Stderr) 20 | } 21 | -------------------------------------------------------------------------------- /cli/cli2cloud/crypto/generatePassword.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/rand" 5 | "math/big" 6 | ) 7 | 8 | const base = 62 9 | 10 | func GeneratePassword(passwordLength int) (*string, error) { 11 | randomBytes := make([]byte, 32) 12 | _, err := rand.Read(randomBytes) 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | encoded := big.NewInt(0) 18 | encoded.SetBytes(randomBytes[:]) 19 | password := encoded.Text(base)[:passwordLength] 20 | return &password, nil 21 | } 22 | -------------------------------------------------------------------------------- /webapp/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | BrowserRouter, 3 | Routes, 4 | Route 5 | } from "react-router-dom"; 6 | import {FrontPage} from './pages/FrontPage' 7 | import {Monitor} from './pages/Monitor' 8 | 9 | export function App (){ 10 | return ( 11 | 12 | 13 | } /> 14 | } /> 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "npm" 13 | directory: "/webapp/" 14 | schedule: 15 | interval: "daily" 16 | -------------------------------------------------------------------------------- /service/api/getClientById.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "github.com/leonwind/cli2cloud/service/api/proto" 6 | "log" 7 | ) 8 | 9 | func (s *Service) GetClientById(_ context.Context, clientId *proto.ClientId) (*proto.Client, error) { 10 | encrypted, salt, iv, err := s.db.GetClientById(clientId.Id) 11 | if err != nil { 12 | log.Printf("Couldn't fetch client details for id %s.\n", clientId.Id) 13 | log.Println(err) 14 | return nil, err 15 | } 16 | 17 | client := proto.Client{ 18 | Encrypted: encrypted, 19 | Salt: salt, 20 | Iv: iv, 21 | Timestamp: nil, 22 | } 23 | return &client, nil 24 | } 25 | -------------------------------------------------------------------------------- /webapp/src/styles/Modal.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | background-color: #1c1c1c; 3 | opacity: 0.9; 4 | color: #ffffff; 5 | border-color: #000000; 6 | } 7 | 8 | .body { 9 | background-color: #1c1c1c; 10 | color: #ffffff; 11 | border-color: #000000; 12 | opacity: 0.8; 13 | } 14 | 15 | .textField { 16 | background-color: #000000 !important; 17 | border: 0px; 18 | color: #ffffff !important; 19 | } 20 | 21 | .submitButton { 22 | background-color: orange; 23 | color: #1c1c1c; 24 | opacity: 0.9; 25 | border: 0px; 26 | } 27 | .submitButton:hover{ 28 | background-color: orange; 29 | color: #1c1c1c; 30 | opacity: 0.6; 31 | } -------------------------------------------------------------------------------- /webapp/.yarnclean: -------------------------------------------------------------------------------- 1 | # test directories 2 | __tests__ 3 | test 4 | tests 5 | powered-test 6 | 7 | # asset directories 8 | docs 9 | doc 10 | website 11 | images 12 | assets 13 | 14 | # examples 15 | example 16 | examples 17 | 18 | # code coverage directories 19 | coverage 20 | .nyc_output 21 | 22 | # build scripts 23 | Makefile 24 | Gulpfile.js 25 | Gruntfile.js 26 | 27 | # configs 28 | appveyor.yml 29 | circle.yml 30 | codeship-services.yml 31 | codeship-steps.yml 32 | wercker.yml 33 | .tern-project 34 | .gitattributes 35 | .editorconfig 36 | .*ignore 37 | .eslintrc 38 | .jshintrc 39 | .flowconfig 40 | .documentup.json 41 | .yarn-metadata.json 42 | .travis.yml 43 | 44 | # misc 45 | *.md 46 | -------------------------------------------------------------------------------- /cli/cli2cloud/proto/cli.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/leonwind/cli2cloud/cli/cli2cloud/proto"; 4 | 5 | package proto; 6 | 7 | service Cli2Cloud { 8 | rpc RegisterClient(Client) returns (ClientId); 9 | rpc Publish(stream PublishRequest) returns (Empty); 10 | } 11 | 12 | message Client { 13 | bool encrypted = 1; 14 | optional string salt = 2; 15 | optional string iv = 3; 16 | optional int64 timestamp = 4; 17 | } 18 | 19 | message ClientId { 20 | string Id = 1; 21 | } 22 | 23 | message PublishRequest { 24 | ClientId clientId = 1; 25 | Payload payload = 2; 26 | } 27 | 28 | message Payload { 29 | string body = 1; 30 | } 31 | 32 | message Empty{} -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | postgres: 4 | container_name: postgres 5 | hostname: postgres 6 | volumes: 7 | - ./management/postgres/postgres_data:/var/lib/postgresql/data 8 | build: ./management/postgres/ 9 | expose: 10 | - "5432" 11 | environment: 12 | - POSTGRES_USER=cli2cloud 13 | - POSTGRES_PASSWORD=$DB_PWD 14 | - POSTGRES_DB=cli2cloud 15 | 16 | backend: 17 | container_name: backend 18 | ports: 19 | - "50051:50051" 20 | depends_on: 21 | - postgres 22 | build: ./service 23 | environment: 24 | - POSTGRES_PASSWORD=$DB_PWD 25 | 26 | envoy: 27 | build: ./management/proxies 28 | ports: 29 | - "8000:8000" 30 | 31 | -------------------------------------------------------------------------------- /webapp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "plugins": [{ "name": "typescript-plugin-css-modules" }], 10 | "allowJs": true, 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "strict": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "module": "esnext", 18 | "moduleResolution": "node", 19 | "resolveJsonModule": true, 20 | "isolatedModules": true, 21 | "noImplicitAny": false, 22 | "noEmit": true, 23 | "jsx": "react-jsx", 24 | }, 25 | "include": [ 26 | "src" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /service/api/proto/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/leonwind/service/api/proto"; 4 | 5 | package proto; 6 | 7 | service Cli2Cloud { 8 | rpc RegisterClient(Client) returns (ClientId); 9 | rpc GetClientById(ClientId) returns (Client); 10 | rpc Publish(stream PublishRequest) returns (Empty); 11 | rpc Subscribe(ClientId) returns (stream Payload); 12 | } 13 | 14 | message Client { 15 | bool encrypted = 1; 16 | optional string salt = 2; 17 | optional string iv = 3; 18 | optional int64 timestamp = 4; 19 | } 20 | 21 | message ClientId { 22 | string Id = 1; 23 | } 24 | 25 | message PublishRequest { 26 | ClientId clientId = 1; 27 | Payload payload = 2; 28 | } 29 | 30 | message Payload { 31 | string body = 1; 32 | } 33 | 34 | message Empty{} -------------------------------------------------------------------------------- /service/api/publish.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/leonwind/cli2cloud/service/api/proto" 6 | . "github.com/leonwind/cli2cloud/service/internal" 7 | "io" 8 | "log" 9 | ) 10 | 11 | func (s *Service) Publish(stream proto.Cli2Cloud_PublishServer) error { 12 | var line int64 = 0 13 | 14 | for { 15 | var request *proto.PublishRequest 16 | request, err := stream.Recv() 17 | 18 | if err == io.EOF { 19 | return stream.SendAndClose(&proto.Empty{}) 20 | } 21 | 22 | if err != nil { 23 | return err 24 | } 25 | 26 | row := Row{ 27 | Content: request.Payload.Body, 28 | Line: line, 29 | } 30 | 31 | message := fmt.Sprintf("Received from client %s, line %d: %s", request.ClientId.Id, line, row.Content) 32 | log.Println(message) 33 | 34 | if err := s.db.WriteContent(request.ClientId.Id, row); err != nil { 35 | log.Println("Couldn't write content to psql", err) 36 | return err 37 | } 38 | 39 | line++ 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /service/api/service.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "github.com/leonwind/cli2cloud/service/api/proto" 5 | "github.com/leonwind/cli2cloud/service/internal/storage" 6 | "google.golang.org/grpc" 7 | "log" 8 | "net" 9 | ) 10 | 11 | type Service struct { 12 | proto.UnimplementedCli2CloudServer 13 | db storage.Database 14 | } 15 | 16 | func NewServer(dbUrl string) (*Service, error) { 17 | psql, err := storage.InitPostgres(dbUrl) 18 | if err != nil { 19 | return nil, err 20 | } 21 | log.Println("Connected to database") 22 | 23 | service := Service{ 24 | db: psql, 25 | } 26 | 27 | return &service, nil 28 | } 29 | 30 | func (s *Service) Start(ip string) error { 31 | lis, err := net.Listen("tcp", ip) 32 | if err != nil { 33 | return err 34 | } 35 | 36 | server := grpc.NewServer() 37 | proto.RegisterCli2CloudServer(server, s) 38 | log.Println("Registered server...") 39 | 40 | if err := server.Serve(lis); err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /webapp/src/styles/Monitor.module.css: -------------------------------------------------------------------------------- 1 | .body { 2 | height: 100%; 3 | min-height: 100vh; 4 | background-color: #1c1c1c; 5 | } 6 | 7 | .outputArea { 8 | font-family: monospace; 9 | color: #e7e7e7; 10 | } 11 | 12 | .row { 13 | display: flex; 14 | clear: both; 15 | } 16 | 17 | .row:hover { 18 | opacity: 0.8; 19 | color: yellow; 20 | } 21 | 22 | .selectedRow { 23 | background-color: yellow; 24 | opacity: 0.8; 25 | color: #000000; 26 | display: flex; 27 | clear: both; 28 | } 29 | 30 | .line { 31 | min-width: 5%; 32 | float: left; 33 | text-align: right; 34 | opacity: 0.6; 35 | cursor: pointer; 36 | /* Make line numbers non-copyable */ 37 | user-select: none; 38 | } 39 | 40 | .content { 41 | padding-left: 3%; 42 | text-align: left; 43 | opacity: 0.87; 44 | white-space: pre; 45 | } 46 | 47 | .emptyRows { 48 | padding-top: 1%; 49 | padding-left: 1%; 50 | text-align: left; 51 | opacity: 0.87; 52 | } -------------------------------------------------------------------------------- /webapp/src/styles/Documentation.module.css: -------------------------------------------------------------------------------- 1 | .body { 2 | width: 50%; 3 | margin: auto; 4 | min-width: 350px; 5 | } 6 | 7 | .docsTitle { 8 | cursor: pointer; 9 | color: orange; 10 | opacity: 0.75; 11 | font-weight: bold; 12 | }:target { 13 | opacity: 1; 14 | font-weight: bolder; 15 | } 16 | 17 | .docsSubTitle { 18 | cursor: pointer; 19 | color: orange; 20 | opacity: 0.6; 21 | font-weight: bold; 22 | }:target { 23 | opacity: 1; 24 | font-weight: bolder; 25 | } 26 | 27 | .instruction { 28 | color: #ffffff; 29 | opacity: 0.85; 30 | padding-bottom: 1.5em; 31 | } 32 | 33 | .codeBlock { 34 | padding-left: 5%; 35 | padding-top: 3%; 36 | } 37 | 38 | .codeStyle { 39 | font-family: monospace; 40 | color: #e7e7e7; 41 | opacity: 0.8; 42 | } 43 | 44 | .spaceToBottom { 45 | padding-bottom: 3em; 46 | } 47 | 48 | a { 49 | color: orange; 50 | opacity: 0.6; 51 | } 52 | 53 | a:hover { 54 | color: orange; 55 | opacity: 1; 56 | } -------------------------------------------------------------------------------- /webapp/src/styles/FrontPage.module.css: -------------------------------------------------------------------------------- 1 | .body { 2 | height: 100%; 3 | min-height: 100vh; 4 | background-color: #1c1c1c; 5 | } 6 | 7 | .logo { 8 | padding-top: 5%; 9 | text-align: center; 10 | color: #e7e7e7; 11 | opacity: 0.87; 12 | } 13 | 14 | .headline { 15 | color: #e7e7e7; 16 | opacity: 0.87; 17 | text-align: center; 18 | } 19 | 20 | .mediumText { 21 | color: #e7e7e7; 22 | opacity: 0.6; 23 | text-align: center; 24 | margin: auto; 25 | max-width: 700px; 26 | } 27 | 28 | .searchForm { 29 | width: 50%; 30 | min-width: 350px; 31 | margin: auto; 32 | color: #ffffff !important; 33 | background-color: #333333 !important; 34 | border: 0px !important; 35 | border-radius: 25px !important; 36 | } 37 | 38 | .searchLogo { 39 | color: #ffffff !important; 40 | background-color: #333333 !important; 41 | opacity: 0.66; 42 | border: 0px !important; 43 | border-radius: 25px !important; 44 | } 45 | 46 | .searchForm:focus { 47 | box-shadow: none !important; 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Leon Windheuser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /service/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/leonwind/cli2cloud/service 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/jackc/pgx/v4 v4.15.0 7 | google.golang.org/grpc v1.44.0 8 | google.golang.org/protobuf v1.27.1 9 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c 10 | ) 11 | 12 | require ( 13 | github.com/golang/protobuf v1.5.0 // indirect 14 | github.com/jackc/chunkreader/v2 v2.0.1 // indirect 15 | github.com/jackc/pgconn v1.11.0 // indirect 16 | github.com/jackc/pgio v1.0.0 // indirect 17 | github.com/jackc/pgpassfile v1.0.0 // indirect 18 | github.com/jackc/pgproto3/v2 v2.2.0 // indirect 19 | github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect 20 | github.com/jackc/pgtype v1.10.0 // indirect 21 | github.com/jackc/puddle v1.2.1 // indirect 22 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect 23 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 24 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect 25 | golang.org/x/text v0.3.6 // indirect 26 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /service/api/subscribe.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/leonwind/cli2cloud/service/api/proto" 6 | "log" 7 | "time" 8 | ) 9 | 10 | func (s *Service) Subscribe(clientId *proto.ClientId, stream proto.Cli2Cloud_SubscribeServer) error { 11 | ctx := stream.Context() 12 | var line int64 = 0 13 | 14 | for { 15 | select { 16 | 17 | case <-ctx.Done(): 18 | return nil 19 | 20 | default: 21 | rows, err := s.db.ReadContent(clientId.Id, line) 22 | if err != nil { 23 | log.Printf("Couldn't get content from database for client %s\n", clientId.Id) 24 | log.Println(err) 25 | return err 26 | } 27 | 28 | if line == 0 && (rows == nil || len(rows) == 0) { 29 | return fmt.Errorf("no output for client %s found", clientId.Id) 30 | } 31 | 32 | for _, row := range rows { 33 | if err := stream.Send(&proto.Payload{Body: row.Content}); err != nil { 34 | return err 35 | } 36 | 37 | log.Printf("Sending %s for client %s\n", row.Content, clientId.Id) 38 | } 39 | 40 | // Prevent database system calls spamming 41 | time.Sleep(500 * time.Millisecond) 42 | 43 | line += int64(len(rows)) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /service/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/leonwind/cli2cloud/service/api" 5 | "gopkg.in/yaml.v3" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | ) 10 | 11 | const configFile = "config.yaml" 12 | 13 | type Config struct { 14 | Service *ServiceConfig `yaml:"service"` 15 | Database *DatabaseConfig `yaml:"database"` 16 | } 17 | 18 | type ServiceConfig struct { 19 | Port string `yaml:"port"` 20 | } 21 | 22 | type DatabaseConfig struct { 23 | Url string `yaml:"url"` 24 | } 25 | 26 | func readConfig() Config { 27 | var config = Config{} 28 | 29 | yamlFile, err := ioutil.ReadFile(configFile) 30 | if err != nil { 31 | log.Fatalf("Can't read %s %v\n", configFile, err) 32 | } 33 | 34 | err = yaml.Unmarshal(yamlFile, &config) 35 | if err != nil { 36 | log.Fatal("Error while unmarshalling", err) 37 | } 38 | 39 | return config 40 | } 41 | 42 | func createPostgresUrl(dC *DatabaseConfig) string { 43 | return os.ExpandEnv(dC.Url) 44 | } 45 | 46 | func main() { 47 | config := readConfig() 48 | dbUrl := createPostgresUrl(config.Database) 49 | port := (*config.Service).Port 50 | 51 | service, err := api.NewServer(dbUrl) 52 | if err != nil { 53 | log.Fatal("Cant create server", err) 54 | } 55 | 56 | if err := service.Start(port); err != nil { 57 | log.Fatal("Can't start server", err) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /webapp/src/components/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | import {FormEvent, useState} from "react"; 2 | import styles from "../styles/SearchBar.module.css"; 3 | import SearchIcon from "@material-ui/icons/Search"; 4 | import { useNavigate } from "react-router-dom"; 5 | import { Form } from "react-bootstrap"; 6 | import { InputGroup } from "react-bootstrap"; 7 | 8 | export const SearchBar = () => { 9 | const navigate = useNavigate(); 10 | const [clientID, setClientID] = useState(""); 11 | 12 | const handleSubmit = (event: FormEvent) => { 13 | event.preventDefault(); 14 | navigate("/" + clientID); 15 | window.location.reload(); 16 | } 17 | 18 | return ( 19 |
20 |
21 | 22 | 23 | setClientID(e.target.value)} type="text" 25 | placeholder="Search your client ID..."/> 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 | ) 34 | } -------------------------------------------------------------------------------- /webapp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Cli2Cloud 28 | 29 | 30 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /webapp/src/services/DecryptionService.ts: -------------------------------------------------------------------------------- 1 | import * as cryptoJS from "crypto-js" 2 | 3 | export class DecryptionService { 4 | private keyLength: number = 8; 5 | private numPBKDF2Iterations: number = 1024; 6 | 7 | private key: cryptoJS.lib.WordArray; 8 | private salt: cryptoJS.lib.WordArray; 9 | private iv: cryptoJS.lib.WordArray; 10 | private decryptor: any; // crypto.Cipher 11 | 12 | public constructor(password: string, salt: string, iv: string) { 13 | this.salt = cryptoJS.enc.Hex.parse(salt); 14 | this.iv = cryptoJS.enc.Hex.parse(iv); 15 | this.key = this.kdf(password, this.salt) 16 | 17 | this.createDecryptor() 18 | } 19 | 20 | private kdf(password: string, salt: cryptoJS.lib.WordArray): cryptoJS.lib.WordArray { 21 | return cryptoJS.PBKDF2(password, salt, { 22 | keySize: this.keyLength, 23 | iterations: this.numPBKDF2Iterations, 24 | hasher: cryptoJS.algo.SHA256 25 | }); 26 | } 27 | 28 | public createDecryptor() { 29 | this.decryptor = cryptoJS.algo.AES.createDecryptor(this.key, { 30 | mode: cryptoJS.mode.CBC, 31 | iv: this.iv, 32 | padding: cryptoJS.pad.Pkcs7, 33 | }); 34 | } 35 | 36 | public decrypt(encryptedStr: string): string { 37 | const encrypted = cryptoJS.enc.Hex.parse(encryptedStr); 38 | return this.decryptor.finalize(encrypted).toString(cryptoJS.enc.Latin1); 39 | } 40 | } -------------------------------------------------------------------------------- /management/proxies/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | location / { 3 | grpc_pass grpc://localhost:8000; 4 | } 5 | 6 | listen 1443 ssl; # managed by Certbot 7 | ssl_certificate /etc/letsencrypt/live/cli2cloud.com/fullchain.pem; # managed by Certbot 8 | ssl_certificate_key /etc/letsencrypt/live/cli2cloud.com/privkey.pem; # managed by Certbot 9 | include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot 10 | ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot 11 | } 12 | 13 | server { 14 | root /var/www/cli2cloud.com/html; 15 | index index.html index.htm index.nginx-debian.html; 16 | 17 | server_name cli2cloud.com www.cli2cloud.com; 18 | 19 | location / { 20 | try_files $uri $uri/ /index.html$is_args$args; 21 | } 22 | 23 | listen 443 ssl; # managed by Certbot 24 | ssl_certificate /etc/letsencrypt/live/cli2cloud.com/fullchain.pem; # managed by Certbot 25 | ssl_certificate_key /etc/letsencrypt/live/cli2cloud.com/privkey.pem; # managed by Certbot 26 | include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot 27 | ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot 28 | } 29 | 30 | server { 31 | if ($host = www.cli2cloud.com) { 32 | return 301 https://$host$request_uri; 33 | } # managed by Certbot 34 | 35 | 36 | if ($host = cli2cloud.com) { 37 | return 301 https://$host$request_uri; 38 | } # managed by Certbot 39 | 40 | 41 | listen 80; 42 | 43 | server_name cli2cloud.com www.cli2cloud.com; 44 | return 404; # managed by Certbot 45 | } 46 | 47 | -------------------------------------------------------------------------------- /webapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webapp", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": ".", 6 | "dependencies": { 7 | "@emotion/react": "^11.9.3", 8 | "@emotion/styled": "^11.9.3", 9 | "@material-ui/core": "^4.12.4", 10 | "@material-ui/icons": "^4.11.3", 11 | "@mui/icons-material": "^5.8.4", 12 | "@mui/material": "^5.9.2", 13 | "@types/crypto-js": "^4.1.1", 14 | "@types/jest": "^28.1.6", 15 | "@types/node": "^18.6.2", 16 | "@types/react": "^18.0.9", 17 | "@types/react-dom": "^18.0.3", 18 | "ansi-to-react": "^6.1.6", 19 | "bootstrap": "^5.2.0", 20 | "crypto-js": "^4.1.1", 21 | "css-loader": "^6.7.1", 22 | "google-protobuf": "^3.21.0", 23 | "grpc-web": "^1.3.1", 24 | "has-ansi": "^5.0.1", 25 | "react": "^17.0.2", 26 | "react-bootstrap": "^2.4.0", 27 | "react-dom": "^17.0.2", 28 | "react-router-dom": "^6.3.0", 29 | "react-scripts": "5.0.1", 30 | "sass": "^1.54.0", 31 | "style-loader": "^3.3.1", 32 | "ts-loader": "^9.3.1", 33 | "typescript": "^4.7.4", 34 | "web-vitals": "^2.1.4", 35 | "webpack-cli": "^4.10.0" 36 | }, 37 | "scripts": { 38 | "start": "react-scripts start", 39 | "build": "react-scripts build", 40 | "eject": "react-scripts eject" 41 | }, 42 | "eslintConfig": { 43 | "extends": [ 44 | "react-app", 45 | "react-app/jest" 46 | ] 47 | }, 48 | "browserslist": { 49 | "production": [ 50 | ">0.2%", 51 | "not dead", 52 | "not op_mini all" 53 | ], 54 | "development": [ 55 | "last 1 chrome version", 56 | "last 1 firefox version", 57 | "last 1 safari version" 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /service/api/registerClient.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "crypto/md5" 6 | "fmt" 7 | "github.com/leonwind/cli2cloud/service/api/proto" 8 | "google.golang.org/grpc/peer" 9 | "log" 10 | "math/big" 11 | "strconv" 12 | "time" 13 | ) 14 | 15 | const idLength = 6 16 | 17 | func (s *Service) RegisterClient(ctx context.Context, client *proto.Client) (*proto.ClientId, error) { 18 | p, ok := peer.FromContext(ctx) 19 | if !ok { 20 | return nil, fmt.Errorf("failed to extract peer-info") 21 | } 22 | 23 | clientId := proto.ClientId{Id: createNewID(p.Addr.String())} 24 | 25 | if err := s.db.RegisterClient(clientId.Id, client.Encrypted, client.Salt, client.Iv); err != nil { 26 | log.Println("Couldn't insert into clients", err) 27 | return nil, err 28 | } 29 | log.Printf("Registered new user %s\n", clientId.Id) 30 | 31 | return &clientId, nil 32 | } 33 | 34 | // Create valid and unique ID for a client based on ones ip address and the current timestamp. 35 | func createNewID(ipAddr string) string { 36 | // Create a unique ID for the client by hashing the ip address and the current 37 | // timestamp and encode the hash using base62 ([0-9][A-Z][a-z]). 38 | // Use MD5 since since it is significantly faster than SHA2 and not security relevant. 39 | timestamp := strconv.FormatInt(time.Now().Unix(), 10) 40 | hash := md5.Sum([]byte(ipAddr + timestamp)) 41 | 42 | // Encode hash into base62 and use the first 6 characters as the ID: 43 | // 62^6 ~ 56E9 different unique IDs 44 | uniqueID := encodeBase62(hash)[:idLength] 45 | return uniqueID 46 | } 47 | 48 | func encodeBase62(toEncode [16]byte) string { 49 | encoded := big.NewInt(0) 50 | encoded.SetBytes(toEncode[:]) 51 | return encoded.Text(62) 52 | } 53 | -------------------------------------------------------------------------------- /cli/cli2cloud/crypto/decrypt.go: -------------------------------------------------------------------------------- 1 | // This code is just for testing and verification of the encryption functions. 2 | // They are not required to the actual workflow since the decryption will happen in the browser. 3 | 4 | package crypto 5 | 6 | import ( 7 | "crypto/aes" 8 | "crypto/cipher" 9 | "crypto/hmac" 10 | "crypto/sha256" 11 | "encoding/hex" 12 | "golang.org/x/crypto/pbkdf2" 13 | "hash" 14 | ) 15 | 16 | type StreamDecrypter struct { 17 | Block cipher.Block 18 | Stream cipher.Stream 19 | Mac hash.Hash 20 | } 21 | 22 | // KdfWithSalt derives a new key with a length of 32 bytes based on the user password and an existing salt. 23 | func kdfWithSalt(password string, salt []byte) []byte { 24 | return pbkdf2.Key([]byte(password), salt, numPBKDF2Iterations, keyLength, sha256.New) 25 | } 26 | 27 | // NewStreamDecrypter provides a struct with all required information to decrypt the encrypted data stream. 28 | func NewStreamDecrypter(password string, salt []byte, iv []byte) (*StreamDecrypter, error) { 29 | key := kdfWithSalt(password, salt) 30 | 31 | block, err := aes.NewCipher(key) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | stream := cipher.NewCTR(block, iv) 37 | mac := hmac.New(sha256.New, key) 38 | 39 | return &StreamDecrypter{ 40 | Block: block, 41 | Stream: stream, 42 | Mac: mac, 43 | }, nil 44 | } 45 | 46 | // Decrypt decrypts the encrypted rows which are encoded as a hex string. 47 | func (s *StreamDecrypter) Decrypt(row string) (*string, error) { 48 | encrypted, err := hex.DecodeString(row) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | if err := writeHash(encrypted, s.Mac); err != nil { 54 | return nil, err 55 | } 56 | 57 | bytePlaintext := make([]byte, len(encrypted)) 58 | s.Stream.XORKeyStream(bytePlaintext, encrypted) 59 | 60 | plaintext := string(bytePlaintext) 61 | return &plaintext, nil 62 | } 63 | -------------------------------------------------------------------------------- /webapp/src/components/ChangeDecryptionPwd.tsx: -------------------------------------------------------------------------------- 1 | import {useState} from "react"; 2 | import Modal from "react-bootstrap/Modal"; 3 | import styles from "../styles/Modal.module.css"; 4 | import { Button } from "react-bootstrap"; 5 | import { Form } from "react-bootstrap"; 6 | 7 | 8 | export const ChangeDecryptionPwd = ({onSubmit, onClose, show}) => { 9 | const [password, setPassword] = useState(""); 10 | 11 | if (!show) { 12 | return null; 13 | } 14 | 15 | const submitAndClose = (password: string) => { 16 | onSubmit(password); 17 | setPassword(""); 18 | onClose(); 19 | } 20 | 21 | return ( 22 | 23 | 24 | Enter Password 25 | 26 | 27 | 28 |
29 | 30 | Enter your Password to decrypt the output: 31 | setPassword(e.target.value)}/> 34 | 35 |
36 |
37 | 38 | 39 | 42 | 43 | 46 | 47 |
48 | ) 49 | } -------------------------------------------------------------------------------- /webapp/src/components/NavBar.tsx: -------------------------------------------------------------------------------- 1 | import styles from "../styles/NavBar.module.css"; 2 | import {SearchBar} from "./SearchBar"; 3 | import { Navbar } from "react-bootstrap"; 4 | import { Nav } from "react-bootstrap"; 5 | import { Button, Container } from "react-bootstrap"; 6 | import { useState } from "react"; 7 | import {ChangeDecryptionPwd} from "./ChangeDecryptionPwd" 8 | import logo from "../assets/cloudWhite.png"; 9 | 10 | export const NavBar = ({showPasswordBtn, onPasswordSubmit, switchToRawData}) => { 11 | const [showModal, setShowModal] = useState(false); 12 | 13 | const handleShowModal = () => setShowModal(true); 14 | const handleCloseModal = () => setShowModal(false); 15 | 16 | return ( 17 | <> 18 | 19 | 20 | 21 | {"Cli2Cloud"} 22 | 23 | 24 | 25 | 26 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ) 46 | } -------------------------------------------------------------------------------- /management/proxies/envoy.yaml: -------------------------------------------------------------------------------- 1 | admin: 2 | access_log_path: /tmp/admin_access.log 3 | address: 4 | socket_address: { address: 0.0.0.0, port_value: 9901 } 5 | 6 | static_resources: 7 | listeners: 8 | - name: listener_0 9 | address: 10 | socket_address: { address: 0.0.0.0, port_value: 8000 } 11 | filter_chains: 12 | - filters: 13 | - name: envoy.filters.network.http_connection_manager 14 | typed_config: 15 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 16 | codec_type: auto 17 | stat_prefix: ingress_http 18 | route_config: 19 | name: local_route 20 | virtual_hosts: 21 | - name: local_service 22 | domains: ["*"] 23 | routes: 24 | - match: { prefix: "/" } 25 | route: 26 | cluster: grpc_server 27 | timeout: 0s 28 | max_stream_duration: 29 | grpc_timeout_header_max: 0s 30 | cors: 31 | allow_origin_string_match: 32 | - prefix: "*" 33 | allow_methods: GET, PUT, DELETE, POST, OPTIONS 34 | allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout 35 | max_age: "1728000" 36 | expose_headers: custom-header-1,grpc-status,grpc-message 37 | http_filters: 38 | - name: envoy.filters.http.grpc_web 39 | - name: envoy.filters.http.cors 40 | - name: envoy.filters.http.router 41 | clusters: 42 | - name: grpc_server 43 | connect_timeout: 0.25s 44 | type: logical_dns 45 | http2_protocol_options: {} 46 | lb_policy: round_robin 47 | load_assignment: 48 | cluster_name: cluster_0 49 | endpoints: 50 | - lb_endpoints: 51 | - endpoint: 52 | address: 53 | socket_address: 54 | address: backend 55 | port_value: 50051 56 | -------------------------------------------------------------------------------- /webapp/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cli2Cloud 2 | 3 | 4 |

5 | Cli2Cloud Logo 6 | Cli2Cloud Logo 7 |
8 | Monitor and Share Your Terminal Output with Everyone from Everywhere in Realtime. 9 |

10 | 11 | ## Installation 12 | Install the terminal client directly from the source by running 13 | ```bash 14 | go install github.com/leonwind/cli2cloud/cli/cli2cloud@latest 15 | ``` 16 | 17 | ## Examples 18 | ### Normal usage 19 | To just pipe your terminal output from any arbitrary command, run 20 | ```bash 21 | $ ping google.com | cli2cloud 22 | Your client ID: 4sYe3G 23 | Share and monitor it live from https://cli2cloud.com/4sYe3G 24 | 25 | PING google.com (172.217.22.142): 56 data bytes 26 | 64 bytes from 172.217.22.142: icmp_seq=0 ttl=112 time=12.306 ms 27 | 64 bytes from 172.217.22.142: icmp_seq=1 ttl=112 time=14.317 ms 28 | ... 29 | ``` 30 | 31 | and open `https://cli2cloud.com/{your ID}` on any browser you have. 32 | It will pipe both your `Stdout` and your `Stderr` output to the web. 33 | 34 | ### End-to-End encryption 35 | Use the `-encrypt {password}` option to encrypt your data End-to-End using the AES CBC Mode and a 256 bit key generated based on your password using the PBKDF2 function. 36 | ```bash 37 | $ ping google.com | cli2cloud -encrypt 1234 38 | Your client ID: CGYWdD 39 | Share and monitor it live from https://cli2cloud.com/CGYWdD#key=1234 40 | 41 | PING google.com (172.217.22.142): 56 data bytes 42 | 64 bytes from 172.217.22.142: icmp_seq=0 ttl=112 time=14.154 ms 43 | 64 bytes from 172.217.22.142: icmp_seq=1 ttl=112 time=12.565 ms 44 | ... 45 | ``` 46 | 47 | To decrypt the data on the web, you need to enter the same password again. The server does not store your password or the hash of it and thus can't validate if your password is either correct or incorrect. You will see complete garbage if you enter a wrong password :) 48 | 49 | Use the option `-encrypt-random` to generate a random secure password with 16 symbols. 50 | ```bash 51 | $ ping google.com | cli2cloud -encrypt-random 52 | Your password: mruI3ubFXTww1QYf 53 | Your client ID: 56xY35 54 | Share and monitor it live from https://cli2cloud.com/56xY35#key=mruI3ubFXTww1QYf 55 | 56 | PING google.com (142.250.201.174): 56 data bytes 57 | 64 bytes from 142.250.201.174: icmp_seq=0 ttl=116 time=3.322 ms 58 | 64 bytes from 142.250.201.174: icmp_seq=1 ttl=116 time=2.648 ms 59 | ... 60 | ``` 61 | 62 | ## Feedback 63 | Feel free to open a new [Issue](https://github.com/leonwind/cli2cloud/issues) regarding any feedback, bugs or feature requests. 64 | -------------------------------------------------------------------------------- /webapp/src/pages/FrontPage.tsx: -------------------------------------------------------------------------------- 1 | import React, {ChangeEvent, Component, FormEvent} from "react"; 2 | import styles from "../styles/FrontPage.module.css"; 3 | import 'bootstrap/dist/css/bootstrap.min.css'; 4 | import { Form } from "react-bootstrap"; 5 | import { Navigate } from "react-router-dom"; 6 | import logo from "../assets/cloudWhite.png"; 7 | import SearchIcon from "@material-ui/icons/Search"; 8 | import { InputGroup } from "react-bootstrap"; 9 | import {Documentation} from "./Documentation" 10 | 11 | interface State { 12 | clientID: string, 13 | redirect: boolean 14 | } 15 | 16 | export class FrontPage extends Component<{}, State> { 17 | 18 | constructor(props: any) { 19 | super(props); 20 | this.state = { 21 | clientID: "", 22 | redirect: false 23 | }; 24 | 25 | this.handleClientIDChange = this.handleClientIDChange.bind(this); 26 | this.handleSubmit = this.handleSubmit.bind(this); 27 | } 28 | 29 | private handleClientIDChange(event: ChangeEvent) { 30 | this.setState({clientID: event.target.value}); 31 | } 32 | 33 | private handleSubmit(event: FormEvent) { 34 | event.preventDefault(); 35 | this.setState({redirect: true}) 36 | } 37 | 38 | render() { 39 | if (this.state.redirect) { 40 | return ( 41 | 42 | ) 43 | } 44 | 45 | return ( 46 |
47 |

48 | {"Logo"} 49 |

50 | 51 |

52 | Cli2Cloud 53 |

54 | 55 |
56 |
57 | 58 |
59 |
60 | 61 | 62 | 63 | 66 | 67 | 68 | 69 | 70 | 71 |
72 |
73 | 74 |
75 |
76 | 77 |
78 | Monitor and Share Your Terminal Output with Everyone from Everywhere in Realtime. 79 |
80 | 81 |
82 |
83 |
84 | 85 | 86 |
87 | ) 88 | } 89 | } -------------------------------------------------------------------------------- /cli/cli2cloud/crypto/encrypt.go: -------------------------------------------------------------------------------- 1 | // Encrypt the data stream using the AES128-CBC Mode. 2 | 3 | package crypto 4 | 5 | import ( 6 | "bytes" 7 | "crypto/aes" 8 | "crypto/cipher" 9 | "crypto/hmac" 10 | "crypto/rand" 11 | "crypto/sha256" 12 | "encoding/hex" 13 | "fmt" 14 | "golang.org/x/crypto/pbkdf2" 15 | "hash" 16 | ) 17 | 18 | type StreamEncrypter struct { 19 | Block cipher.Block 20 | Mode cipher.BlockMode 21 | IV []byte 22 | Salt []byte 23 | Mac hash.Hash 24 | } 25 | 26 | const ( 27 | numPBKDF2Iterations = 1024 28 | keyLength = 32 // bytes = 256 bits 29 | saltLength = 32 // bytes = 256 bits 30 | ) 31 | 32 | // Kdf derives a new key with a length of 32 bytes based on the user password and on a newly created salt. 33 | func kdf(password []byte) ([]byte, []byte, error) { 34 | salt := make([]byte, saltLength) 35 | if _, err := rand.Read(salt); err != nil { 36 | return nil, nil, err 37 | } 38 | 39 | key := pbkdf2.Key(password, salt, numPBKDF2Iterations, keyLength, sha256.New) 40 | return key, salt, nil 41 | } 42 | 43 | // NewStreamEncrypter provides a struct with all required information to encrypt a data stream. 44 | func NewStreamEncrypter(password string) (*StreamEncrypter, error) { 45 | key, salt, err := kdf([]byte(password)) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | block, err := aes.NewCipher(key) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | iv := make([]byte, block.BlockSize()) 56 | 57 | _, err = rand.Read(iv) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | blockMode := cipher.NewCBCEncrypter(block, iv) 63 | mac := hmac.New(sha256.New, key) 64 | 65 | return &StreamEncrypter{ 66 | Block: block, 67 | Mode: blockMode, 68 | IV: iv, 69 | Salt: salt, 70 | Mac: mac, 71 | }, nil 72 | } 73 | 74 | // Encrypt encrypts the given row and returns the byte array encoded as a Hex string. 75 | func (s *StreamEncrypter) Encrypt(row string) (*string, error) { 76 | plaintext := pkcs7Padding([]byte(row), s.Block.BlockSize()) 77 | encrypted := make([]byte, len(plaintext)) 78 | s.Mode.CryptBlocks(encrypted, plaintext) 79 | 80 | hexString := hex.EncodeToString(encrypted) 81 | return &hexString, nil 82 | } 83 | 84 | func pkcs7Padding(src []byte, blockSize int) []byte { 85 | paddingLength := blockSize - (len(src) % blockSize) 86 | padding := bytes.Repeat([]byte{byte(paddingLength)}, paddingLength) 87 | return append(src, padding...) 88 | } 89 | 90 | func writeHash(encrypted []byte, mac hash.Hash) error { 91 | m, err := mac.Write(encrypted) 92 | if err != nil { 93 | return err 94 | } 95 | 96 | if m != len(encrypted) { 97 | return fmt.Errorf("can't write all bytes to HMAC") 98 | } 99 | 100 | return nil 101 | } 102 | 103 | func (s *StreamEncrypter) GetSaltAsHex() *string { 104 | if s == nil { 105 | return nil 106 | } 107 | hexSalt := hex.EncodeToString(s.Salt) 108 | return &hexSalt 109 | } 110 | 111 | func (s *StreamEncrypter) GetIVAsHex() *string { 112 | if s == nil { 113 | return nil 114 | } 115 | hexIV := hex.EncodeToString(s.IV) 116 | return &hexIV 117 | } 118 | -------------------------------------------------------------------------------- /management/postgres/create_schema.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 14.2 (Debian 14.2-1.pgdg110+1) 6 | -- Dumped by pg_dump version 14.1 7 | 8 | SET statement_timeout = 0; 9 | SET lock_timeout = 0; 10 | SET idle_in_transaction_session_timeout = 0; 11 | SET client_encoding = 'UTF8'; 12 | SET standard_conforming_strings = on; 13 | SELECT pg_catalog.set_config('search_path', '', false); 14 | SET check_function_bodies = false; 15 | SET xmloption = content; 16 | SET client_min_messages = warning; 17 | SET row_security = off; 18 | 19 | SET default_tablespace = ''; 20 | 21 | SET default_table_access_method = heap; 22 | 23 | -- 24 | -- Name: cli_storage; Type: TABLE; Schema: public; Owner: cli2cloud 25 | -- 26 | 27 | CREATE TABLE IF NOT EXISTS public.cli_storage ( 28 | clientid text NOT NULL, 29 | content text NOT NULL, 30 | line integer NOT NULL 31 | ); 32 | 33 | 34 | ALTER TABLE public.cli_storage OWNER TO cli2cloud; 35 | 36 | -- 37 | -- Data for Name: cli_storage; Type: TABLE DATA; Schema: public; Owner: cli2cloud 38 | -- 39 | 40 | COPY public.cli_storage (clientid, content, line) FROM stdin; 41 | \. 42 | 43 | 44 | -- 45 | -- PostgreSQL database dump complete 46 | -- 47 | 48 | -- 49 | -- PostgreSQL database dump 50 | -- 51 | 52 | -- Dumped from database version 14.2 (Debian 14.2-1.pgdg110+1) 53 | -- Dumped by pg_dump version 14.1 54 | 55 | SET statement_timeout = 0; 56 | SET lock_timeout = 0; 57 | SET idle_in_transaction_session_timeout = 0; 58 | SET client_encoding = 'UTF8'; 59 | SET standard_conforming_strings = on; 60 | SELECT pg_catalog.set_config('search_path', '', false); 61 | SET check_function_bodies = false; 62 | SET xmloption = content; 63 | SET client_min_messages = warning; 64 | SET row_security = off; 65 | 66 | SET default_tablespace = ''; 67 | 68 | SET default_table_access_method = heap; 69 | 70 | -- 71 | -- Name: cli_storage; Type: TABLE; Schema: public; Owner: cli2cloud 72 | -- 73 | 74 | CREATE TABLE IF NOT EXISTS public.cli_storage ( 75 | clientid text NOT NULL, 76 | content text NOT NULL, 77 | line integer NOT NULL 78 | ); 79 | 80 | 81 | ALTER TABLE public.cli_storage OWNER TO cli2cloud; 82 | 83 | -- 84 | -- Name: clients; Type: TABLE; Schema: public; Owner: cli2cloud 85 | -- 86 | 87 | CREATE TABLE public.clients ( 88 | id text NOT NULL, 89 | encrypted boolean NOT NULL, 90 | salt text, 91 | iv text, 92 | created timestamp with time zone NOT NULL 93 | ); 94 | 95 | 96 | ALTER TABLE public.clients OWNER TO cli2cloud; 97 | 98 | -- 99 | -- Data for Name: cli_storage; Type: TABLE DATA; Schema: public; Owner: cli2cloud 100 | -- 101 | 102 | COPY public.cli_storage (clientid, content, line) FROM stdin; 103 | \. 104 | 105 | 106 | -- 107 | -- Data for Name: clients; Type: TABLE DATA; Schema: public; Owner: cli2cloud 108 | -- 109 | 110 | COPY public.clients (id, encrypted, salt, iv, created) FROM stdin; 111 | \. 112 | 113 | 114 | -- 115 | -- Name: clients clients_pkey; Type: CONSTRAINT; Schema: public; Owner: cli2cloud 116 | -- 117 | 118 | ALTER TABLE ONLY public.clients 119 | ADD CONSTRAINT clients_pkey PRIMARY KEY (id); 120 | 121 | 122 | -- 123 | -- Name: cli_storage cli_storage_clientid_fkey; Type: FK CONSTRAINT; Schema: public; Owner: cli2cloud 124 | -- 125 | 126 | ALTER TABLE ONLY public.cli_storage 127 | ADD CONSTRAINT cli_storage_clientid_fkey FOREIGN KEY (clientid) REFERENCES public.clients(id); 128 | 129 | 130 | -- 131 | -- PostgreSQL database dump complete 132 | -- 133 | 134 | -------------------------------------------------------------------------------- /webapp/src/proto/service_pb.d.ts: -------------------------------------------------------------------------------- 1 | import * as jspb from 'google-protobuf' 2 | 3 | 4 | 5 | export class Client extends jspb.Message { 6 | getEncrypted(): boolean; 7 | setEncrypted(value: boolean): Client; 8 | 9 | getSalt(): string; 10 | setSalt(value: string): Client; 11 | hasSalt(): boolean; 12 | clearSalt(): Client; 13 | 14 | getIv(): string; 15 | setIv(value: string): Client; 16 | hasIv(): boolean; 17 | clearIv(): Client; 18 | 19 | getTimestamp(): number; 20 | setTimestamp(value: number): Client; 21 | hasTimestamp(): boolean; 22 | clearTimestamp(): Client; 23 | 24 | serializeBinary(): Uint8Array; 25 | toObject(includeInstance?: boolean): Client.AsObject; 26 | static toObject(includeInstance: boolean, msg: Client): Client.AsObject; 27 | static serializeBinaryToWriter(message: Client, writer: jspb.BinaryWriter): void; 28 | static deserializeBinary(bytes: Uint8Array): Client; 29 | static deserializeBinaryFromReader(message: Client, reader: jspb.BinaryReader): Client; 30 | } 31 | 32 | export namespace Client { 33 | export type AsObject = { 34 | encrypted: boolean, 35 | salt?: string, 36 | iv?: string, 37 | timestamp?: number, 38 | } 39 | 40 | export enum SaltCase { 41 | _SALT_NOT_SET = 0, 42 | SALT = 2, 43 | } 44 | 45 | export enum IvCase { 46 | _IV_NOT_SET = 0, 47 | IV = 3, 48 | } 49 | 50 | export enum TimestampCase { 51 | _TIMESTAMP_NOT_SET = 0, 52 | TIMESTAMP = 4, 53 | } 54 | } 55 | 56 | export class ClientId extends jspb.Message { 57 | getId(): string; 58 | setId(value: string): ClientId; 59 | 60 | serializeBinary(): Uint8Array; 61 | toObject(includeInstance?: boolean): ClientId.AsObject; 62 | static toObject(includeInstance: boolean, msg: ClientId): ClientId.AsObject; 63 | static serializeBinaryToWriter(message: ClientId, writer: jspb.BinaryWriter): void; 64 | static deserializeBinary(bytes: Uint8Array): ClientId; 65 | static deserializeBinaryFromReader(message: ClientId, reader: jspb.BinaryReader): ClientId; 66 | } 67 | 68 | export namespace ClientId { 69 | export type AsObject = { 70 | id: string, 71 | } 72 | } 73 | 74 | export class PublishRequest extends jspb.Message { 75 | getClientid(): ClientId | undefined; 76 | setClientid(value?: ClientId): PublishRequest; 77 | hasClientid(): boolean; 78 | clearClientid(): PublishRequest; 79 | 80 | getPayload(): Payload | undefined; 81 | setPayload(value?: Payload): PublishRequest; 82 | hasPayload(): boolean; 83 | clearPayload(): PublishRequest; 84 | 85 | serializeBinary(): Uint8Array; 86 | toObject(includeInstance?: boolean): PublishRequest.AsObject; 87 | static toObject(includeInstance: boolean, msg: PublishRequest): PublishRequest.AsObject; 88 | static serializeBinaryToWriter(message: PublishRequest, writer: jspb.BinaryWriter): void; 89 | static deserializeBinary(bytes: Uint8Array): PublishRequest; 90 | static deserializeBinaryFromReader(message: PublishRequest, reader: jspb.BinaryReader): PublishRequest; 91 | } 92 | 93 | export namespace PublishRequest { 94 | export type AsObject = { 95 | clientid?: ClientId.AsObject, 96 | payload?: Payload.AsObject, 97 | } 98 | } 99 | 100 | export class Payload extends jspb.Message { 101 | getBody(): string; 102 | setBody(value: string): Payload; 103 | 104 | serializeBinary(): Uint8Array; 105 | toObject(includeInstance?: boolean): Payload.AsObject; 106 | static toObject(includeInstance: boolean, msg: Payload): Payload.AsObject; 107 | static serializeBinaryToWriter(message: Payload, writer: jspb.BinaryWriter): void; 108 | static deserializeBinary(bytes: Uint8Array): Payload; 109 | static deserializeBinaryFromReader(message: Payload, reader: jspb.BinaryReader): Payload; 110 | } 111 | 112 | export namespace Payload { 113 | export type AsObject = { 114 | body: string, 115 | } 116 | } 117 | 118 | export class Empty extends jspb.Message { 119 | serializeBinary(): Uint8Array; 120 | toObject(includeInstance?: boolean): Empty.AsObject; 121 | static toObject(includeInstance: boolean, msg: Empty): Empty.AsObject; 122 | static serializeBinaryToWriter(message: Empty, writer: jspb.BinaryWriter): void; 123 | static deserializeBinary(bytes: Uint8Array): Empty; 124 | static deserializeBinaryFromReader(message: Empty, reader: jspb.BinaryReader): Empty; 125 | } 126 | 127 | export namespace Empty { 128 | export type AsObject = { 129 | } 130 | } 131 | 132 | -------------------------------------------------------------------------------- /service/internal/storage/psql.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "github.com/jackc/pgx/v4/pgxpool" 7 | . "github.com/leonwind/cli2cloud/service/internal" 8 | ) 9 | 10 | type Database interface { 11 | RegisterClient(clientId string, encrypted bool, salt *string, iv *string) error 12 | GetClientById(clientId string) (bool, *string, *string, error) 13 | WriteContent(clientId string, row Row) error 14 | ReadContent(clientId string, line int64) ([]Row, error) 15 | } 16 | 17 | type Psql struct { 18 | conn *pgxpool.Pool 19 | } 20 | 21 | // InitPostgres by connecting a pool to the cli2cloud database. 22 | // Use a pool for concurrent usage. 23 | func InitPostgres(url string) (*Psql, error) { 24 | poolConn, err := pgxpool.Connect(context.Background(), url) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | psql := Psql{ 30 | conn: poolConn, 31 | } 32 | return &psql, nil 33 | } 34 | 35 | // RegisterClient Register a new Client in the database and store the ID, if encrypted, and timestamp. 36 | // Encryption is yet not implemented 37 | func (psql *Psql) RegisterClient(clientId string, encrypted bool, salt *string, iv *string) error { 38 | queryString := "INSERT INTO clients (id, encrypted, salt, iv, created) " + 39 | "VALUES ($1, $2, $3, $4, now());" 40 | 41 | _, err := psql.runQueryNoReturn(queryString, clientId, encrypted, ptrToNullString(salt), ptrToNullString(iv)) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | return nil 47 | } 48 | 49 | // GetClientById fetches if the client, based on its Id, encrypted the data, and if so then returns 50 | // the salt and the IV required for the decryption. 51 | func (psql *Psql) GetClientById(clientId string) (bool, *string, *string, error) { 52 | queryString := "SELECT encrypted, salt, iv FROM clients " + 53 | "WHERE id = $1;" 54 | 55 | queriedRow, err := psql.conn.Query(context.Background(), queryString, clientId) 56 | if err != nil { 57 | return false, nil, nil, err 58 | } 59 | 60 | var encrypted bool 61 | var salt sql.NullString 62 | var iv sql.NullString 63 | 64 | for queriedRow.Next() { 65 | if err := queriedRow.Scan(&encrypted, &salt, &iv); err != nil { 66 | return false, nil, nil, err 67 | } 68 | } 69 | return encrypted, nullStringToPtr(salt), nullStringToPtr(iv), nil 70 | } 71 | 72 | // WriteContent Write new content to the database with its respected row 73 | func (psql *Psql) WriteContent(clientId string, row Row) error { 74 | queryString := "INSERT INTO cli_storage (clientId, content, line) " + 75 | "VALUES ($1, $2, $3);" 76 | 77 | _, err := psql.runQueryNoReturn(queryString, clientId, row.Content, row.Line) 78 | 79 | if err != nil { 80 | return err 81 | } 82 | 83 | return nil 84 | } 85 | 86 | // ReadContent Return all rows of the client which are newer (greater) than the given row. 87 | func (psql *Psql) ReadContent(clientId string, line int64) ([]Row, error) { 88 | queryString := "SELECT content, line FROM cli_storage " + 89 | "WHERE clientId = $1 AND line >= $2 " + 90 | "ORDER BY line " + 91 | "LIMIT 100;" 92 | 93 | queriedRows, err := psql.conn.Query(context.Background(), queryString, clientId, line) 94 | if err != nil { 95 | return nil, err 96 | } 97 | 98 | var rows []Row 99 | 100 | for queriedRows.Next() { 101 | var curr Row 102 | 103 | if err := queriedRows.Scan(&curr.Content, &curr.Line); err != nil { 104 | return nil, err 105 | } 106 | 107 | rows = append(rows, curr) 108 | } 109 | 110 | return rows, nil 111 | } 112 | 113 | // runQueryNoReturns executes a query with its arguments and returns the number of lines it affected 114 | func (psql *Psql) runQueryNoReturn(query string, arguments ...interface{}) (int64, error) { 115 | cmdTag, err := psql.conn.Exec(context.Background(), query, arguments...) 116 | if err != nil { 117 | return -1, err 118 | } 119 | 120 | return cmdTag.RowsAffected(), nil 121 | } 122 | 123 | // ptrToNullString checks if the given string is nil or empty and returns a NullString. 124 | // Pgx then stores the string as NULL in postgres. 125 | func ptrToNullString(s *string) sql.NullString { 126 | if s == nil || len(*s) == 0 { 127 | return sql.NullString{} 128 | } 129 | return sql.NullString{ 130 | String: *s, 131 | Valid: true, 132 | } 133 | } 134 | 135 | // Returns nil if the NullString is null, else the pointer to the string value 136 | func nullStringToPtr(s sql.NullString) *string { 137 | if s.Valid { 138 | return &(s.String) 139 | } 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /webapp/src/proto/ServiceServiceClientPb.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview gRPC-Web generated client stub for proto 3 | * @enhanceable 4 | * @public 5 | */ 6 | 7 | // GENERATED CODE -- DO NOT EDIT! 8 | 9 | 10 | /* eslint-disable */ 11 | // @ts-nocheck 12 | 13 | 14 | import * as grpcWeb from 'grpc-web'; 15 | 16 | import * as service_pb from './service_pb'; 17 | 18 | 19 | export class Cli2CloudClient { 20 | client_: grpcWeb.AbstractClientBase; 21 | hostname_: string; 22 | credentials_: null | { [index: string]: string; }; 23 | options_: null | { [index: string]: any; }; 24 | 25 | constructor (hostname: string, 26 | credentials?: null | { [index: string]: string; }, 27 | options?: null | { [index: string]: any; }) { 28 | if (!options) options = {}; 29 | if (!credentials) credentials = {}; 30 | options['format'] = 'text'; 31 | 32 | this.client_ = new grpcWeb.GrpcWebClientBase(options); 33 | this.hostname_ = hostname; 34 | this.credentials_ = credentials; 35 | this.options_ = options; 36 | } 37 | 38 | methodDescriptorRegisterClient = new grpcWeb.MethodDescriptor( 39 | '/proto.Cli2Cloud/RegisterClient', 40 | grpcWeb.MethodType.UNARY, 41 | service_pb.Client, 42 | service_pb.ClientId, 43 | (request: service_pb.Client) => { 44 | return request.serializeBinary(); 45 | }, 46 | service_pb.ClientId.deserializeBinary 47 | ); 48 | 49 | registerClient( 50 | request: service_pb.Client, 51 | metadata: grpcWeb.Metadata | null): Promise; 52 | 53 | registerClient( 54 | request: service_pb.Client, 55 | metadata: grpcWeb.Metadata | null, 56 | callback: (err: grpcWeb.RpcError, 57 | response: service_pb.ClientId) => void): grpcWeb.ClientReadableStream; 58 | 59 | registerClient( 60 | request: service_pb.Client, 61 | metadata: grpcWeb.Metadata | null, 62 | callback?: (err: grpcWeb.RpcError, 63 | response: service_pb.ClientId) => void) { 64 | if (callback !== undefined) { 65 | return this.client_.rpcCall( 66 | this.hostname_ + 67 | '/proto.Cli2Cloud/RegisterClient', 68 | request, 69 | metadata || {}, 70 | this.methodDescriptorRegisterClient, 71 | callback); 72 | } 73 | return this.client_.unaryCall( 74 | this.hostname_ + 75 | '/proto.Cli2Cloud/RegisterClient', 76 | request, 77 | metadata || {}, 78 | this.methodDescriptorRegisterClient); 79 | } 80 | 81 | methodDescriptorGetClientById = new grpcWeb.MethodDescriptor( 82 | '/proto.Cli2Cloud/GetClientById', 83 | grpcWeb.MethodType.UNARY, 84 | service_pb.ClientId, 85 | service_pb.Client, 86 | (request: service_pb.ClientId) => { 87 | return request.serializeBinary(); 88 | }, 89 | service_pb.Client.deserializeBinary 90 | ); 91 | 92 | getClientById( 93 | request: service_pb.ClientId, 94 | metadata: grpcWeb.Metadata | null): Promise; 95 | 96 | getClientById( 97 | request: service_pb.ClientId, 98 | metadata: grpcWeb.Metadata | null, 99 | callback: (err: grpcWeb.RpcError, 100 | response: service_pb.Client) => void): grpcWeb.ClientReadableStream; 101 | 102 | getClientById( 103 | request: service_pb.ClientId, 104 | metadata: grpcWeb.Metadata | null, 105 | callback?: (err: grpcWeb.RpcError, 106 | response: service_pb.Client) => void) { 107 | if (callback !== undefined) { 108 | return this.client_.rpcCall( 109 | this.hostname_ + 110 | '/proto.Cli2Cloud/GetClientById', 111 | request, 112 | metadata || {}, 113 | this.methodDescriptorGetClientById, 114 | callback); 115 | } 116 | return this.client_.unaryCall( 117 | this.hostname_ + 118 | '/proto.Cli2Cloud/GetClientById', 119 | request, 120 | metadata || {}, 121 | this.methodDescriptorGetClientById); 122 | } 123 | 124 | methodDescriptorSubscribe = new grpcWeb.MethodDescriptor( 125 | '/proto.Cli2Cloud/Subscribe', 126 | grpcWeb.MethodType.SERVER_STREAMING, 127 | service_pb.ClientId, 128 | service_pb.Payload, 129 | (request: service_pb.ClientId) => { 130 | return request.serializeBinary(); 131 | }, 132 | service_pb.Payload.deserializeBinary 133 | ); 134 | 135 | subscribe( 136 | request: service_pb.ClientId, 137 | metadata?: grpcWeb.Metadata): grpcWeb.ClientReadableStream { 138 | return this.client_.serverStreaming( 139 | this.hostname_ + 140 | '/proto.Cli2Cloud/Subscribe', 141 | request, 142 | metadata || {}, 143 | this.methodDescriptorSubscribe); 144 | } 145 | 146 | } 147 | 148 | -------------------------------------------------------------------------------- /cli/cli2cloud/cli2cloud.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "github.com/leonwind/cli2cloud/cli/cli2cloud/crypto" 8 | "github.com/leonwind/cli2cloud/cli/cli2cloud/proto" 9 | "github.com/leonwind/cli2cloud/cli/cli2cloud/streams" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/credentials/insecure" 12 | "log" 13 | "strconv" 14 | "time" 15 | ) 16 | 17 | const ( 18 | //serverIP = "localhost:50051" // local dev 19 | serverIP = "cli2cloud.com:50051" // production 20 | randomPasswordLength = 16 21 | defaultDelayLength = 3 22 | ) 23 | 24 | type stringFlag struct { 25 | set bool 26 | value string 27 | } 28 | 29 | func (sf *stringFlag) Set(x string) error { 30 | sf.value = x 31 | sf.set = true 32 | return nil 33 | } 34 | 35 | func (sf *stringFlag) String() string { 36 | return sf.value 37 | } 38 | 39 | func sendPipedMessages(c proto.Cli2CloudClient, ctx context.Context, password *string, delay time.Duration) error { 40 | stream, err := c.Publish(ctx) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | var s *crypto.StreamEncrypter 46 | if password != nil { 47 | s, err = crypto.NewStreamEncrypter(*password) 48 | if err != nil { 49 | log.Fatal("Can't create a Stream Encrypter.", err) 50 | } 51 | } 52 | 53 | client := proto.Client{ 54 | Encrypted: s != nil, 55 | Salt: s.GetSaltAsHex(), 56 | Iv: s.GetIVAsHex(), 57 | } 58 | 59 | clientId, err := c.RegisterClient(ctx, &client) 60 | fmt.Printf("Your client ID: %s\n", clientId.Id) 61 | 62 | keyURLSuffix := "" 63 | if password != nil { 64 | keyURLSuffix = fmt.Sprintf("#key=%s", *password) 65 | } 66 | 67 | fmt.Printf("Share and monitor it live from https://cli2cloud.com/%s%s\n\n", clientId.Id, keyURLSuffix) 68 | // Wait delay seconds for user to copy the client ID 69 | time.Sleep(delay * time.Second) 70 | 71 | // Create a messages stream which is reading from both Stdout and Stdin 72 | streamMessages := make(chan interface{}) 73 | //defer close(streamMessages) 74 | go streams.CreateStreams(streamMessages) 75 | 76 | for res := range streamMessages { 77 | switch res.(type) { 78 | case bool: 79 | fmt.Println("Close channel") 80 | //_, err = stream.CloseAndRecv() 81 | //return err 82 | break 83 | default: 84 | row := res.(string) 85 | // Print original input to client as well 86 | fmt.Println(row) 87 | 88 | if s != nil { 89 | encryptedRow, err := s.Encrypt(row) 90 | if err != nil { 91 | log.Println("Can't encrypt the data.", err) 92 | return err 93 | } 94 | row = *encryptedRow 95 | } 96 | 97 | content := proto.PublishRequest{ 98 | Payload: &proto.Payload{Body: row}, 99 | ClientId: clientId, 100 | } 101 | 102 | if err := stream.Send(&content); err != nil { 103 | return err 104 | } 105 | } 106 | } 107 | 108 | _, err = stream.CloseAndRecv() 109 | return err 110 | } 111 | 112 | func parseFlags() (*string, time.Duration) { 113 | var passwordFlag stringFlag 114 | flag.Var(&passwordFlag, "encrypt", "Password to encrypt your data with.") 115 | generatePassword := flag.Bool("encrypt-random", false, "Generate a random password to encrypt your data.") 116 | 117 | var delayFlag stringFlag 118 | flag.Var(&delayFlag, "delay", "Delay before printing the command output to copy the client ID.") 119 | 120 | flag.Parse() 121 | 122 | if passwordFlag.set && passwordFlag.value == "" { 123 | log.Fatal("Password can not be empty.") 124 | } 125 | 126 | if passwordFlag.set && *generatePassword { 127 | log.Fatal("Can't set a password and generate one.") 128 | } 129 | 130 | var password *string = nil 131 | var err error = nil 132 | 133 | if passwordFlag.set { 134 | password = &passwordFlag.value 135 | } else if *generatePassword { 136 | password, err = crypto.GeneratePassword(randomPasswordLength) 137 | if err != nil { 138 | log.Fatal("Error while generating the random password", err) 139 | } 140 | fmt.Printf("Your password: %s\n", *password) 141 | } 142 | 143 | var delay int 144 | if delayFlag.set { 145 | delay, err = strconv.Atoi(delayFlag.value) 146 | if err != nil || delay < 0 { 147 | log.Fatal("Delay parameter argument is non parseable ", err) 148 | } 149 | } else { 150 | delay = defaultDelayLength 151 | } 152 | 153 | return password, time.Duration(delay) 154 | } 155 | 156 | func main() { 157 | password, delay := parseFlags() 158 | 159 | conn, err := grpc.Dial(serverIP, grpc.WithTransportCredentials(insecure.NewCredentials())) 160 | if err != nil { 161 | log.Fatal("Unable to connect to gRPC server.", err) 162 | } 163 | 164 | client := proto.NewCli2CloudClient(conn) 165 | ctx, cancel := context.WithCancel(context.Background()) 166 | defer cancel() 167 | 168 | if err := sendPipedMessages(client, ctx, password, delay); err != nil { 169 | log.Fatal("Error while sending to server.", err) 170 | } 171 | 172 | if err := conn.Close(); err != nil { 173 | log.Fatal("Unable to close connection.", err) 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /webapp/src/pages/Documentation.tsx: -------------------------------------------------------------------------------- 1 | import styles from "../styles/Documentation.module.css"; 2 | 3 | export const Documentation = () => { 4 | 5 | const highlightElement = (id: string) => { 6 | window.location.hash = id; 7 | } 8 | 9 | return ( 10 |
11 |

{highlightElement("installation")}}> 12 | # Installation 13 |

14 | 15 |
16 | Install the terminal client directly from the source by running 17 |
18 | 19 | $ go install github.com/leonwind/cli2cloud/cli/cli2cloud@latest 20 | 21 |
22 |
23 | 24 |

{highlightElement("examples")}}> 25 | # Examples 26 |

27 | 28 |
{highlightElement("normal-usage")}}> 29 | ## Normal usage 30 |
31 | 32 |
33 | To just pipe your terminal output from any arbitrary command, run 34 |
35 | 36 | $ ping google.com | cli2cloud
37 | Your client ID: 4sYe3G
38 | Share and monitor it live from https://cli2cloud.com/4sYe3G
39 |
40 | PING google.com (172.217.22.142): 56 data bytes
41 | 64 bytes from 172.217.22.142: icmp_seq=0 ttl=112 time=12.306 ms
42 | 64 bytes from 172.217.22.142: icmp_seq=1 ttl=112 time=14.317 ms
43 | ... 44 |
45 |
46 |
47 | and open https://cli2cloud.com/{"{your ID}"} on any browser you have. 48 | It will pipe both your Stdout and your Stderr output to the web. 49 |
50 | 51 |
{highlightElement("e2ee")}}> 52 | ## End-to-End encryption 53 |
54 | 55 |
56 | Use the -encrypt {"{password}"} option 57 | to encrypt your data End-to-End using the AES CBC Mode { } 58 | and a 256 bit key generated based on your password using the PBKDF2 function. 59 | 60 |
61 | 62 | $ ping google.com | cli2cloud -encrypt 1234
63 | Your client ID: CGYWdD
64 | Share and monitor it live from https://cli2cloud.com/CGYWdD?key=1234
65 |
66 | PING google.com (172.217.22.142): 56 data bytes
67 | 64 bytes from 172.217.22.142: icmp_seq=0 ttl=112 time=14.154 ms
68 | 64 bytes from 172.217.22.142: icmp_seq=1 ttl=112 time=12.565 ms
69 | ... 70 |
71 |
72 |
73 | 74 | To decrypt the data on the web, you need to enter the same password again. 75 | The server does not store your password or the hash of it and thus can't validate if your password is either correct or incorrect. 76 | You will see complete garbage if you enter a wrong password :) 77 |
78 |
79 | Use the option -encrypt-random to generate a random secure password with 16 symbols. 80 |
81 | 82 | $ ping google.com | cli2cloud -encrypt-random
83 | Your password: mruI3ubFXTww1QYf
84 | Your client ID: 56xY35
85 | Share and monitor it live from https://cli2cloud.com/56xY35?key=mruI3ubFXTww1QYf
86 |
87 | PING google.com (142.250.201.174): 56 data bytes
88 | 64 bytes from 142.250.201.174: icmp_seq=0 ttl=116 time=3.322 ms
89 | 64 bytes from 142.250.201.174: icmp_seq=1 ttl=116 time=2.648 ms
90 | ... 91 |
92 |
93 |
94 | 95 |

{highlightElement("feedback")}}> 96 | # Feedback 97 |

98 |
99 | The code is open-source available on GitHub. 100 | Feel free to open a new Issue regarding any feedback, bugs or feature requests. 101 |
102 | 103 |
104 |
105 | ) 106 | } -------------------------------------------------------------------------------- /cli/cli2cloud/proto/cli_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: cli.proto 6 | 7 | package proto 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // Cli2CloudClient is the client API for Cli2Cloud service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type Cli2CloudClient interface { 25 | RegisterClient(ctx context.Context, in *Client, opts ...grpc.CallOption) (*ClientId, error) 26 | Publish(ctx context.Context, opts ...grpc.CallOption) (Cli2Cloud_PublishClient, error) 27 | } 28 | 29 | type cli2CloudClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewCli2CloudClient(cc grpc.ClientConnInterface) Cli2CloudClient { 34 | return &cli2CloudClient{cc} 35 | } 36 | 37 | func (c *cli2CloudClient) RegisterClient(ctx context.Context, in *Client, opts ...grpc.CallOption) (*ClientId, error) { 38 | out := new(ClientId) 39 | err := c.cc.Invoke(ctx, "/proto.Cli2Cloud/RegisterClient", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | func (c *cli2CloudClient) Publish(ctx context.Context, opts ...grpc.CallOption) (Cli2Cloud_PublishClient, error) { 47 | stream, err := c.cc.NewStream(ctx, &Cli2Cloud_ServiceDesc.Streams[0], "/proto.Cli2Cloud/Publish", opts...) 48 | if err != nil { 49 | return nil, err 50 | } 51 | x := &cli2CloudPublishClient{stream} 52 | return x, nil 53 | } 54 | 55 | type Cli2Cloud_PublishClient interface { 56 | Send(*PublishRequest) error 57 | CloseAndRecv() (*Empty, error) 58 | grpc.ClientStream 59 | } 60 | 61 | type cli2CloudPublishClient struct { 62 | grpc.ClientStream 63 | } 64 | 65 | func (x *cli2CloudPublishClient) Send(m *PublishRequest) error { 66 | return x.ClientStream.SendMsg(m) 67 | } 68 | 69 | func (x *cli2CloudPublishClient) CloseAndRecv() (*Empty, error) { 70 | if err := x.ClientStream.CloseSend(); err != nil { 71 | return nil, err 72 | } 73 | m := new(Empty) 74 | if err := x.ClientStream.RecvMsg(m); err != nil { 75 | return nil, err 76 | } 77 | return m, nil 78 | } 79 | 80 | // Cli2CloudServer is the server API for Cli2Cloud service. 81 | // All implementations must embed UnimplementedCli2CloudServer 82 | // for forward compatibility 83 | type Cli2CloudServer interface { 84 | RegisterClient(context.Context, *Client) (*ClientId, error) 85 | Publish(Cli2Cloud_PublishServer) error 86 | mustEmbedUnimplementedCli2CloudServer() 87 | } 88 | 89 | // UnimplementedCli2CloudServer must be embedded to have forward compatible implementations. 90 | type UnimplementedCli2CloudServer struct { 91 | } 92 | 93 | func (UnimplementedCli2CloudServer) RegisterClient(context.Context, *Client) (*ClientId, error) { 94 | return nil, status.Errorf(codes.Unimplemented, "method RegisterClient not implemented") 95 | } 96 | func (UnimplementedCli2CloudServer) Publish(Cli2Cloud_PublishServer) error { 97 | return status.Errorf(codes.Unimplemented, "method Publish not implemented") 98 | } 99 | func (UnimplementedCli2CloudServer) mustEmbedUnimplementedCli2CloudServer() {} 100 | 101 | // UnsafeCli2CloudServer may be embedded to opt out of forward compatibility for this service. 102 | // Use of this interface is not recommended, as added methods to Cli2CloudServer will 103 | // result in compilation errors. 104 | type UnsafeCli2CloudServer interface { 105 | mustEmbedUnimplementedCli2CloudServer() 106 | } 107 | 108 | func RegisterCli2CloudServer(s grpc.ServiceRegistrar, srv Cli2CloudServer) { 109 | s.RegisterService(&Cli2Cloud_ServiceDesc, srv) 110 | } 111 | 112 | func _Cli2Cloud_RegisterClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 113 | in := new(Client) 114 | if err := dec(in); err != nil { 115 | return nil, err 116 | } 117 | if interceptor == nil { 118 | return srv.(Cli2CloudServer).RegisterClient(ctx, in) 119 | } 120 | info := &grpc.UnaryServerInfo{ 121 | Server: srv, 122 | FullMethod: "/proto.Cli2Cloud/RegisterClient", 123 | } 124 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 125 | return srv.(Cli2CloudServer).RegisterClient(ctx, req.(*Client)) 126 | } 127 | return interceptor(ctx, in, info, handler) 128 | } 129 | 130 | func _Cli2Cloud_Publish_Handler(srv interface{}, stream grpc.ServerStream) error { 131 | return srv.(Cli2CloudServer).Publish(&cli2CloudPublishServer{stream}) 132 | } 133 | 134 | type Cli2Cloud_PublishServer interface { 135 | SendAndClose(*Empty) error 136 | Recv() (*PublishRequest, error) 137 | grpc.ServerStream 138 | } 139 | 140 | type cli2CloudPublishServer struct { 141 | grpc.ServerStream 142 | } 143 | 144 | func (x *cli2CloudPublishServer) SendAndClose(m *Empty) error { 145 | return x.ServerStream.SendMsg(m) 146 | } 147 | 148 | func (x *cli2CloudPublishServer) Recv() (*PublishRequest, error) { 149 | m := new(PublishRequest) 150 | if err := x.ServerStream.RecvMsg(m); err != nil { 151 | return nil, err 152 | } 153 | return m, nil 154 | } 155 | 156 | // Cli2Cloud_ServiceDesc is the grpc.ServiceDesc for Cli2Cloud service. 157 | // It's only intended for direct use with grpc.RegisterService, 158 | // and not to be introspected or modified (even as a copy) 159 | var Cli2Cloud_ServiceDesc = grpc.ServiceDesc{ 160 | ServiceName: "proto.Cli2Cloud", 161 | HandlerType: (*Cli2CloudServer)(nil), 162 | Methods: []grpc.MethodDesc{ 163 | { 164 | MethodName: "RegisterClient", 165 | Handler: _Cli2Cloud_RegisterClient_Handler, 166 | }, 167 | }, 168 | Streams: []grpc.StreamDesc{ 169 | { 170 | StreamName: "Publish", 171 | Handler: _Cli2Cloud_Publish_Handler, 172 | ClientStreams: true, 173 | }, 174 | }, 175 | Metadata: "cli.proto", 176 | } 177 | -------------------------------------------------------------------------------- /service/api/proto/service_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.19.4 5 | // source: service.proto 6 | 7 | package proto 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // Cli2CloudClient is the client API for Cli2Cloud service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type Cli2CloudClient interface { 25 | RegisterClient(ctx context.Context, in *Client, opts ...grpc.CallOption) (*ClientId, error) 26 | GetClientById(ctx context.Context, in *ClientId, opts ...grpc.CallOption) (*Client, error) 27 | Publish(ctx context.Context, opts ...grpc.CallOption) (Cli2Cloud_PublishClient, error) 28 | Subscribe(ctx context.Context, in *ClientId, opts ...grpc.CallOption) (Cli2Cloud_SubscribeClient, error) 29 | } 30 | 31 | type cli2CloudClient struct { 32 | cc grpc.ClientConnInterface 33 | } 34 | 35 | func NewCli2CloudClient(cc grpc.ClientConnInterface) Cli2CloudClient { 36 | return &cli2CloudClient{cc} 37 | } 38 | 39 | func (c *cli2CloudClient) RegisterClient(ctx context.Context, in *Client, opts ...grpc.CallOption) (*ClientId, error) { 40 | out := new(ClientId) 41 | err := c.cc.Invoke(ctx, "/proto.Cli2Cloud/RegisterClient", in, out, opts...) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return out, nil 46 | } 47 | 48 | func (c *cli2CloudClient) GetClientById(ctx context.Context, in *ClientId, opts ...grpc.CallOption) (*Client, error) { 49 | out := new(Client) 50 | err := c.cc.Invoke(ctx, "/proto.Cli2Cloud/GetClientById", in, out, opts...) 51 | if err != nil { 52 | return nil, err 53 | } 54 | return out, nil 55 | } 56 | 57 | func (c *cli2CloudClient) Publish(ctx context.Context, opts ...grpc.CallOption) (Cli2Cloud_PublishClient, error) { 58 | stream, err := c.cc.NewStream(ctx, &Cli2Cloud_ServiceDesc.Streams[0], "/proto.Cli2Cloud/Publish", opts...) 59 | if err != nil { 60 | return nil, err 61 | } 62 | x := &cli2CloudPublishClient{stream} 63 | return x, nil 64 | } 65 | 66 | type Cli2Cloud_PublishClient interface { 67 | Send(*PublishRequest) error 68 | CloseAndRecv() (*Empty, error) 69 | grpc.ClientStream 70 | } 71 | 72 | type cli2CloudPublishClient struct { 73 | grpc.ClientStream 74 | } 75 | 76 | func (x *cli2CloudPublishClient) Send(m *PublishRequest) error { 77 | return x.ClientStream.SendMsg(m) 78 | } 79 | 80 | func (x *cli2CloudPublishClient) CloseAndRecv() (*Empty, error) { 81 | if err := x.ClientStream.CloseSend(); err != nil { 82 | return nil, err 83 | } 84 | m := new(Empty) 85 | if err := x.ClientStream.RecvMsg(m); err != nil { 86 | return nil, err 87 | } 88 | return m, nil 89 | } 90 | 91 | func (c *cli2CloudClient) Subscribe(ctx context.Context, in *ClientId, opts ...grpc.CallOption) (Cli2Cloud_SubscribeClient, error) { 92 | stream, err := c.cc.NewStream(ctx, &Cli2Cloud_ServiceDesc.Streams[1], "/proto.Cli2Cloud/Subscribe", opts...) 93 | if err != nil { 94 | return nil, err 95 | } 96 | x := &cli2CloudSubscribeClient{stream} 97 | if err := x.ClientStream.SendMsg(in); err != nil { 98 | return nil, err 99 | } 100 | if err := x.ClientStream.CloseSend(); err != nil { 101 | return nil, err 102 | } 103 | return x, nil 104 | } 105 | 106 | type Cli2Cloud_SubscribeClient interface { 107 | Recv() (*Payload, error) 108 | grpc.ClientStream 109 | } 110 | 111 | type cli2CloudSubscribeClient struct { 112 | grpc.ClientStream 113 | } 114 | 115 | func (x *cli2CloudSubscribeClient) Recv() (*Payload, error) { 116 | m := new(Payload) 117 | if err := x.ClientStream.RecvMsg(m); err != nil { 118 | return nil, err 119 | } 120 | return m, nil 121 | } 122 | 123 | // Cli2CloudServer is the server API for Cli2Cloud service. 124 | // All implementations must embed UnimplementedCli2CloudServer 125 | // for forward compatibility 126 | type Cli2CloudServer interface { 127 | RegisterClient(context.Context, *Client) (*ClientId, error) 128 | GetClientById(context.Context, *ClientId) (*Client, error) 129 | Publish(Cli2Cloud_PublishServer) error 130 | Subscribe(*ClientId, Cli2Cloud_SubscribeServer) error 131 | mustEmbedUnimplementedCli2CloudServer() 132 | } 133 | 134 | // UnimplementedCli2CloudServer must be embedded to have forward compatible implementations. 135 | type UnimplementedCli2CloudServer struct { 136 | } 137 | 138 | func (UnimplementedCli2CloudServer) RegisterClient(context.Context, *Client) (*ClientId, error) { 139 | return nil, status.Errorf(codes.Unimplemented, "method RegisterClient not implemented") 140 | } 141 | func (UnimplementedCli2CloudServer) GetClientById(context.Context, *ClientId) (*Client, error) { 142 | return nil, status.Errorf(codes.Unimplemented, "method GetClientById not implemented") 143 | } 144 | func (UnimplementedCli2CloudServer) Publish(Cli2Cloud_PublishServer) error { 145 | return status.Errorf(codes.Unimplemented, "method Publish not implemented") 146 | } 147 | func (UnimplementedCli2CloudServer) Subscribe(*ClientId, Cli2Cloud_SubscribeServer) error { 148 | return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") 149 | } 150 | func (UnimplementedCli2CloudServer) mustEmbedUnimplementedCli2CloudServer() {} 151 | 152 | // UnsafeCli2CloudServer may be embedded to opt out of forward compatibility for this service. 153 | // Use of this interface is not recommended, as added methods to Cli2CloudServer will 154 | // result in compilation errors. 155 | type UnsafeCli2CloudServer interface { 156 | mustEmbedUnimplementedCli2CloudServer() 157 | } 158 | 159 | func RegisterCli2CloudServer(s grpc.ServiceRegistrar, srv Cli2CloudServer) { 160 | s.RegisterService(&Cli2Cloud_ServiceDesc, srv) 161 | } 162 | 163 | func _Cli2Cloud_RegisterClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 164 | in := new(Client) 165 | if err := dec(in); err != nil { 166 | return nil, err 167 | } 168 | if interceptor == nil { 169 | return srv.(Cli2CloudServer).RegisterClient(ctx, in) 170 | } 171 | info := &grpc.UnaryServerInfo{ 172 | Server: srv, 173 | FullMethod: "/proto.Cli2Cloud/RegisterClient", 174 | } 175 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 176 | return srv.(Cli2CloudServer).RegisterClient(ctx, req.(*Client)) 177 | } 178 | return interceptor(ctx, in, info, handler) 179 | } 180 | 181 | func _Cli2Cloud_GetClientById_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 182 | in := new(ClientId) 183 | if err := dec(in); err != nil { 184 | return nil, err 185 | } 186 | if interceptor == nil { 187 | return srv.(Cli2CloudServer).GetClientById(ctx, in) 188 | } 189 | info := &grpc.UnaryServerInfo{ 190 | Server: srv, 191 | FullMethod: "/proto.Cli2Cloud/GetClientById", 192 | } 193 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 194 | return srv.(Cli2CloudServer).GetClientById(ctx, req.(*ClientId)) 195 | } 196 | return interceptor(ctx, in, info, handler) 197 | } 198 | 199 | func _Cli2Cloud_Publish_Handler(srv interface{}, stream grpc.ServerStream) error { 200 | return srv.(Cli2CloudServer).Publish(&cli2CloudPublishServer{stream}) 201 | } 202 | 203 | type Cli2Cloud_PublishServer interface { 204 | SendAndClose(*Empty) error 205 | Recv() (*PublishRequest, error) 206 | grpc.ServerStream 207 | } 208 | 209 | type cli2CloudPublishServer struct { 210 | grpc.ServerStream 211 | } 212 | 213 | func (x *cli2CloudPublishServer) SendAndClose(m *Empty) error { 214 | return x.ServerStream.SendMsg(m) 215 | } 216 | 217 | func (x *cli2CloudPublishServer) Recv() (*PublishRequest, error) { 218 | m := new(PublishRequest) 219 | if err := x.ServerStream.RecvMsg(m); err != nil { 220 | return nil, err 221 | } 222 | return m, nil 223 | } 224 | 225 | func _Cli2Cloud_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { 226 | m := new(ClientId) 227 | if err := stream.RecvMsg(m); err != nil { 228 | return err 229 | } 230 | return srv.(Cli2CloudServer).Subscribe(m, &cli2CloudSubscribeServer{stream}) 231 | } 232 | 233 | type Cli2Cloud_SubscribeServer interface { 234 | Send(*Payload) error 235 | grpc.ServerStream 236 | } 237 | 238 | type cli2CloudSubscribeServer struct { 239 | grpc.ServerStream 240 | } 241 | 242 | func (x *cli2CloudSubscribeServer) Send(m *Payload) error { 243 | return x.ServerStream.SendMsg(m) 244 | } 245 | 246 | // Cli2Cloud_ServiceDesc is the grpc.ServiceDesc for Cli2Cloud service. 247 | // It's only intended for direct use with grpc.RegisterService, 248 | // and not to be introspected or modified (even as a copy) 249 | var Cli2Cloud_ServiceDesc = grpc.ServiceDesc{ 250 | ServiceName: "proto.Cli2Cloud", 251 | HandlerType: (*Cli2CloudServer)(nil), 252 | Methods: []grpc.MethodDesc{ 253 | { 254 | MethodName: "RegisterClient", 255 | Handler: _Cli2Cloud_RegisterClient_Handler, 256 | }, 257 | { 258 | MethodName: "GetClientById", 259 | Handler: _Cli2Cloud_GetClientById_Handler, 260 | }, 261 | }, 262 | Streams: []grpc.StreamDesc{ 263 | { 264 | StreamName: "Publish", 265 | Handler: _Cli2Cloud_Publish_Handler, 266 | ClientStreams: true, 267 | }, 268 | { 269 | StreamName: "Subscribe", 270 | Handler: _Cli2Cloud_Subscribe_Handler, 271 | ServerStreams: true, 272 | }, 273 | }, 274 | Metadata: "service.proto", 275 | } 276 | -------------------------------------------------------------------------------- /webapp/src/pages/Monitor.tsx: -------------------------------------------------------------------------------- 1 | import {Component} from "react"; 2 | import Ansi from "ansi-to-react"; 3 | import hasAnsi from "has-ansi"; 4 | import styles from "../styles/Monitor.module.css"; 5 | import {Cli2CloudClient} from "../proto/ServiceServiceClientPb" 6 | import {Client, ClientId, Payload} from "../proto/service_pb" 7 | import {DecryptionService} from "../services/DecryptionService" 8 | import {NavBar} from "../components/NavBar" 9 | import { ChangeDecryptionPwd } from "../components/ChangeDecryptionPwd"; 10 | 11 | 12 | interface Row { 13 | content: string, 14 | line: number, 15 | } 16 | 17 | interface State { 18 | encrypted: boolean, 19 | enterPwdFirstTime: boolean, 20 | password: string | null, 21 | decryptor: DecryptionService | null, 22 | rows: Row[], 23 | raw: boolean, 24 | highlightRow: string, 25 | } 26 | 27 | export class Monitor extends Component<{}, State> { 28 | private numLines: number; 29 | private cli2CloudService: Cli2CloudClient; 30 | private clientId: ClientId; 31 | private client: Promise; 32 | 33 | constructor(props: any) { 34 | super(props); 35 | 36 | // Redirect due to backward compatibility with old client which set the 37 | // key as a query parameter(?key=) and not as a hash parameter (#key=) 38 | let params = new URLSearchParams(new URL(window.location.href).search); 39 | if (params.has("key")) { 40 | const password = params.get("key"); 41 | if (password !== null) { 42 | this.addToHashParam("key", password); 43 | } 44 | params.delete("key"); 45 | window.location.search = params.toString() 46 | } 47 | 48 | let password = this.extractFromHash(window.location.hash, "key"); 49 | let highlightRowId = this.extractFromHash(window.location.hash, "row"); 50 | 51 | this.state = { 52 | encrypted: false, 53 | enterPwdFirstTime: password === null, 54 | password: password, 55 | decryptor: null, 56 | rows: [], 57 | raw: params.has("raw"), 58 | highlightRow: highlightRowId === null ? "" : highlightRowId, 59 | }; 60 | 61 | this.numLines = 1; 62 | this.cli2CloudService = new Cli2CloudClient("https://cli2cloud.com:1443", null, null); // production 63 | //this.cli2CloudService = new Cli2CloudClient("http://localhost:8000", null, null); // local dev 64 | 65 | this.clientId = new ClientId(); 66 | const id = window.location.pathname.substring(1); 67 | this.clientId.setId(id); 68 | 69 | this.client = this.cli2CloudService.getClientById(this.clientId, {}) 70 | } 71 | 72 | componentDidMount() { 73 | this.loadContent = this.loadContent.bind(this); 74 | this.highlightRow = this.highlightRow.bind(this); 75 | this.updatePassword = this.updatePassword.bind(this); 76 | this.afterFirstTimePassword = this.afterFirstTimePassword.bind(this); 77 | this.switchToRawData = this.switchToRawData.bind(this); 78 | 79 | this.client.then((client) => {this.setState({encrypted: client.getEncrypted()})}); 80 | 81 | if (!this.state.enterPwdFirstTime) { 82 | this.createDecryptor(this.state.password); 83 | } 84 | 85 | this.loadContent(); 86 | } 87 | 88 | private extractFromHash(hash: string, key: string): string | null { 89 | const params: string = hash.substring(1, hash.length); 90 | let value: string | null = null; 91 | 92 | params.split("&").forEach((parts, _) => { 93 | let kv = parts.split("="); 94 | if (kv !== [] && kv[0] === key) { 95 | value = kv[1]; 96 | } 97 | }); 98 | return value; 99 | } 100 | 101 | private addToHashParam(key: string, value: string, remove: boolean=false) { 102 | const newParamPair = key + "=" + value; 103 | const currHash = window.location.hash.substring(1, window.location.hash.length); 104 | let newHash = ""; 105 | let exists: boolean = false; 106 | 107 | currHash.split("&").forEach((parts, _) => { 108 | let kv = parts.split("="); 109 | if (kv.length !== 0 && kv[0] !== '') { 110 | if (kv[0] === key) { 111 | exists = true; 112 | if (remove) { 113 | return; 114 | } 115 | newHash += newParamPair; 116 | } else { 117 | newHash += parts; 118 | } 119 | newHash += '&'; 120 | } 121 | }); 122 | 123 | if (!exists) { 124 | newHash += newParamPair; 125 | } 126 | 127 | window.location.hash = newHash; 128 | } 129 | 130 | private updatePassword(newPassword: string) { 131 | this.addToHashParam("key", newPassword); 132 | this.setState({password: newPassword}); 133 | this.createDecryptor(newPassword); 134 | } 135 | 136 | private createDecryptor(password: string | null) { 137 | if (password === null) { 138 | console.log("Can't create decryptor"); 139 | return; 140 | } 141 | this.client.then((client: Client) => { 142 | this.setState({decryptor: new DecryptionService(password!, client.getSalt(), client.getIv())}); 143 | }); 144 | } 145 | 146 | private loadContent() { 147 | const stream = this.cli2CloudService.subscribe(this.clientId, {}); 148 | 149 | stream.on("data", (response: Payload) => { 150 | this.addNewContent(response.getBody()) 151 | }); 152 | 153 | stream.on("error", (error: Error): void => { 154 | console.error(error); 155 | }); 156 | 157 | 158 | } 159 | 160 | private addNewContent(content: string) { 161 | let newRows: Row[] = this.state.rows; 162 | newRows.push({ 163 | content: content, 164 | line: this.numLines, 165 | }); 166 | this.numLines += 1 167 | this.setState({rows: newRows}); 168 | } 169 | 170 | private highlightRow(line: number) { 171 | if (this.state.highlightRow === line.toString()) { 172 | this.setState({highlightRow: ""}); 173 | // delete the hash parameter again if set 174 | this.addToHashParam("row", "", true); 175 | } else { 176 | this.addToHashParam("row", line.toString()); 177 | this.setState({highlightRow: line.toString()}); 178 | } 179 | } 180 | 181 | private decryptRowIfEncrypted(content: string): string { 182 | if (this.state.encrypted && this.state.decryptor !== null) { 183 | return this.state.decryptor.decrypt(content); 184 | } 185 | return content; 186 | } 187 | 188 | private createNewDecryptorIfEncrypted() { 189 | // Since we decrypt everything again from the beginning, 190 | // we need to init the decryptor from the beginning as well. 191 | if (this.state.decryptor !== null) { 192 | this.state.decryptor.createDecryptor(); 193 | } 194 | } 195 | 196 | private createAnsiElementIfNeeded(line: string): JSX.Element | string { 197 | if (hasAnsi(line)) { 198 | return {line}; 199 | } else { 200 | return line; 201 | } 202 | } 203 | 204 | private createDivsForAllRows(): JSX.Element[] | JSX.Element { 205 | if (this.state.rows.length === 0) { 206 | return [
207 | No output found for client "{this.clientId.getId()}". 208 |
]; 209 | } 210 | 211 | this.createNewDecryptorIfEncrypted() 212 | return this.state.rows.map((row: Row) => { 213 | let rowStyle = row.line.toString() === this.state.highlightRow ? styles.selectedRow : styles.row; 214 | 215 | return
216 | this.highlightRow(row.line)}> 217 | {row.line} 218 | 219 | 220 | {this.createAnsiElementIfNeeded(this.decryptRowIfEncrypted(row.content))} 221 | 222 |
223 | }); 224 | } 225 | 226 | private createDivsForRawOutput(): JSX.Element[] | JSX.Element { 227 | if (this.state.rows.length === 0) { 228 | return
No output found for client "{this.clientId.getId()}."
229 | } 230 | 231 | this.createNewDecryptorIfEncrypted() 232 | return this.state.rows.map((row: Row) => 233 |
{this.decryptRowIfEncrypted(row.content)}
234 | ); 235 | } 236 | 237 | private setURLParams(key: string, value: string) { 238 | let params = new URLSearchParams(new URL(window.location.href).search); 239 | params.set(key, value); 240 | window.location.search = params.toString() 241 | } 242 | 243 | private switchToRawData() { 244 | this.setURLParams("raw", "true"); 245 | this.setState({raw: true}); 246 | } 247 | 248 | private afterFirstTimePassword() { 249 | this.setState({enterPwdFirstTime: false}); 250 | } 251 | 252 | render() { 253 | if (this.state.raw) { 254 | return this.createDivsForRawOutput() 255 | } 256 | 257 | return ( 258 | <> 259 | {this.state.encrypted && this.state.decryptor === null && 260 | } 261 | 262 | 263 |
264 |
265 | {this.createDivsForAllRows()} 266 |
267 |
268 | 269 | ); 270 | } 271 | } -------------------------------------------------------------------------------- /cli/cli2cloud/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 5 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 6 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 8 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 9 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 10 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 11 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 12 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 13 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 14 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 15 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 16 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 17 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 18 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 19 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 20 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 21 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 22 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 23 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 24 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 25 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 26 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 27 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 28 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 29 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 30 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 31 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 32 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 33 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 34 | github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 35 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 36 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 37 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 38 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 39 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 40 | github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= 41 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 42 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 43 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 44 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 45 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 46 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 47 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 48 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 49 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 50 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 51 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 52 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 53 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= 54 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 55 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 56 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 57 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 58 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 59 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 60 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 61 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 62 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 63 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 64 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 65 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 66 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 67 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 68 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 69 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 70 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 72 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 73 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 74 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 75 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 76 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 77 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 78 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 79 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 80 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 81 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 82 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 83 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= 84 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 85 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 86 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 87 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 88 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 89 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 90 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 91 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 92 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 93 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 94 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 95 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 96 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 97 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 98 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 99 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 100 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 101 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 102 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 103 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 104 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 105 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 106 | google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= 107 | google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 108 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 109 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 110 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 111 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 112 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 113 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 114 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 115 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 116 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 117 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 118 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 119 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 120 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 121 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 122 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 123 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 124 | -------------------------------------------------------------------------------- /cli/cli2cloud/proto/cli.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.27.1 4 | // protoc v3.19.4 5 | // source: cli.proto 6 | 7 | package proto 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type Client struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | Encrypted bool `protobuf:"varint,1,opt,name=encrypted,proto3" json:"encrypted,omitempty"` 29 | Salt *string `protobuf:"bytes,2,opt,name=salt,proto3,oneof" json:"salt,omitempty"` 30 | Iv *string `protobuf:"bytes,3,opt,name=iv,proto3,oneof" json:"iv,omitempty"` 31 | Timestamp *int64 `protobuf:"varint,4,opt,name=timestamp,proto3,oneof" json:"timestamp,omitempty"` 32 | } 33 | 34 | func (x *Client) Reset() { 35 | *x = Client{} 36 | if protoimpl.UnsafeEnabled { 37 | mi := &file_cli_proto_msgTypes[0] 38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 39 | ms.StoreMessageInfo(mi) 40 | } 41 | } 42 | 43 | func (x *Client) String() string { 44 | return protoimpl.X.MessageStringOf(x) 45 | } 46 | 47 | func (*Client) ProtoMessage() {} 48 | 49 | func (x *Client) ProtoReflect() protoreflect.Message { 50 | mi := &file_cli_proto_msgTypes[0] 51 | if protoimpl.UnsafeEnabled && x != nil { 52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 53 | if ms.LoadMessageInfo() == nil { 54 | ms.StoreMessageInfo(mi) 55 | } 56 | return ms 57 | } 58 | return mi.MessageOf(x) 59 | } 60 | 61 | // Deprecated: Use Client.ProtoReflect.Descriptor instead. 62 | func (*Client) Descriptor() ([]byte, []int) { 63 | return file_cli_proto_rawDescGZIP(), []int{0} 64 | } 65 | 66 | func (x *Client) GetEncrypted() bool { 67 | if x != nil { 68 | return x.Encrypted 69 | } 70 | return false 71 | } 72 | 73 | func (x *Client) GetSalt() string { 74 | if x != nil && x.Salt != nil { 75 | return *x.Salt 76 | } 77 | return "" 78 | } 79 | 80 | func (x *Client) GetIv() string { 81 | if x != nil && x.Iv != nil { 82 | return *x.Iv 83 | } 84 | return "" 85 | } 86 | 87 | func (x *Client) GetTimestamp() int64 { 88 | if x != nil && x.Timestamp != nil { 89 | return *x.Timestamp 90 | } 91 | return 0 92 | } 93 | 94 | type ClientId struct { 95 | state protoimpl.MessageState 96 | sizeCache protoimpl.SizeCache 97 | unknownFields protoimpl.UnknownFields 98 | 99 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` 100 | } 101 | 102 | func (x *ClientId) Reset() { 103 | *x = ClientId{} 104 | if protoimpl.UnsafeEnabled { 105 | mi := &file_cli_proto_msgTypes[1] 106 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 107 | ms.StoreMessageInfo(mi) 108 | } 109 | } 110 | 111 | func (x *ClientId) String() string { 112 | return protoimpl.X.MessageStringOf(x) 113 | } 114 | 115 | func (*ClientId) ProtoMessage() {} 116 | 117 | func (x *ClientId) ProtoReflect() protoreflect.Message { 118 | mi := &file_cli_proto_msgTypes[1] 119 | if protoimpl.UnsafeEnabled && x != nil { 120 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 121 | if ms.LoadMessageInfo() == nil { 122 | ms.StoreMessageInfo(mi) 123 | } 124 | return ms 125 | } 126 | return mi.MessageOf(x) 127 | } 128 | 129 | // Deprecated: Use ClientId.ProtoReflect.Descriptor instead. 130 | func (*ClientId) Descriptor() ([]byte, []int) { 131 | return file_cli_proto_rawDescGZIP(), []int{1} 132 | } 133 | 134 | func (x *ClientId) GetId() string { 135 | if x != nil { 136 | return x.Id 137 | } 138 | return "" 139 | } 140 | 141 | type PublishRequest struct { 142 | state protoimpl.MessageState 143 | sizeCache protoimpl.SizeCache 144 | unknownFields protoimpl.UnknownFields 145 | 146 | ClientId *ClientId `protobuf:"bytes,1,opt,name=clientId,proto3" json:"clientId,omitempty"` 147 | Payload *Payload `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` 148 | } 149 | 150 | func (x *PublishRequest) Reset() { 151 | *x = PublishRequest{} 152 | if protoimpl.UnsafeEnabled { 153 | mi := &file_cli_proto_msgTypes[2] 154 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 155 | ms.StoreMessageInfo(mi) 156 | } 157 | } 158 | 159 | func (x *PublishRequest) String() string { 160 | return protoimpl.X.MessageStringOf(x) 161 | } 162 | 163 | func (*PublishRequest) ProtoMessage() {} 164 | 165 | func (x *PublishRequest) ProtoReflect() protoreflect.Message { 166 | mi := &file_cli_proto_msgTypes[2] 167 | if protoimpl.UnsafeEnabled && x != nil { 168 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 169 | if ms.LoadMessageInfo() == nil { 170 | ms.StoreMessageInfo(mi) 171 | } 172 | return ms 173 | } 174 | return mi.MessageOf(x) 175 | } 176 | 177 | // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. 178 | func (*PublishRequest) Descriptor() ([]byte, []int) { 179 | return file_cli_proto_rawDescGZIP(), []int{2} 180 | } 181 | 182 | func (x *PublishRequest) GetClientId() *ClientId { 183 | if x != nil { 184 | return x.ClientId 185 | } 186 | return nil 187 | } 188 | 189 | func (x *PublishRequest) GetPayload() *Payload { 190 | if x != nil { 191 | return x.Payload 192 | } 193 | return nil 194 | } 195 | 196 | type Payload struct { 197 | state protoimpl.MessageState 198 | sizeCache protoimpl.SizeCache 199 | unknownFields protoimpl.UnknownFields 200 | 201 | Body string `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` 202 | } 203 | 204 | func (x *Payload) Reset() { 205 | *x = Payload{} 206 | if protoimpl.UnsafeEnabled { 207 | mi := &file_cli_proto_msgTypes[3] 208 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 209 | ms.StoreMessageInfo(mi) 210 | } 211 | } 212 | 213 | func (x *Payload) String() string { 214 | return protoimpl.X.MessageStringOf(x) 215 | } 216 | 217 | func (*Payload) ProtoMessage() {} 218 | 219 | func (x *Payload) ProtoReflect() protoreflect.Message { 220 | mi := &file_cli_proto_msgTypes[3] 221 | if protoimpl.UnsafeEnabled && x != nil { 222 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 223 | if ms.LoadMessageInfo() == nil { 224 | ms.StoreMessageInfo(mi) 225 | } 226 | return ms 227 | } 228 | return mi.MessageOf(x) 229 | } 230 | 231 | // Deprecated: Use Payload.ProtoReflect.Descriptor instead. 232 | func (*Payload) Descriptor() ([]byte, []int) { 233 | return file_cli_proto_rawDescGZIP(), []int{3} 234 | } 235 | 236 | func (x *Payload) GetBody() string { 237 | if x != nil { 238 | return x.Body 239 | } 240 | return "" 241 | } 242 | 243 | type Empty struct { 244 | state protoimpl.MessageState 245 | sizeCache protoimpl.SizeCache 246 | unknownFields protoimpl.UnknownFields 247 | } 248 | 249 | func (x *Empty) Reset() { 250 | *x = Empty{} 251 | if protoimpl.UnsafeEnabled { 252 | mi := &file_cli_proto_msgTypes[4] 253 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 254 | ms.StoreMessageInfo(mi) 255 | } 256 | } 257 | 258 | func (x *Empty) String() string { 259 | return protoimpl.X.MessageStringOf(x) 260 | } 261 | 262 | func (*Empty) ProtoMessage() {} 263 | 264 | func (x *Empty) ProtoReflect() protoreflect.Message { 265 | mi := &file_cli_proto_msgTypes[4] 266 | if protoimpl.UnsafeEnabled && x != nil { 267 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 268 | if ms.LoadMessageInfo() == nil { 269 | ms.StoreMessageInfo(mi) 270 | } 271 | return ms 272 | } 273 | return mi.MessageOf(x) 274 | } 275 | 276 | // Deprecated: Use Empty.ProtoReflect.Descriptor instead. 277 | func (*Empty) Descriptor() ([]byte, []int) { 278 | return file_cli_proto_rawDescGZIP(), []int{4} 279 | } 280 | 281 | var File_cli_proto protoreflect.FileDescriptor 282 | 283 | var file_cli_proto_rawDesc = []byte{ 284 | 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 285 | 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 286 | 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 287 | 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x73, 288 | 0x61, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x73, 0x61, 0x6c, 289 | 0x74, 0x88, 0x01, 0x01, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 290 | 0x48, 0x01, 0x52, 0x02, 0x69, 0x76, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x74, 0x69, 0x6d, 291 | 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x09, 292 | 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 293 | 0x5f, 0x73, 0x61, 0x6c, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x76, 0x42, 0x0c, 0x0a, 0x0a, 294 | 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1a, 0x0a, 0x08, 0x43, 0x6c, 295 | 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 296 | 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x0e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 297 | 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 298 | 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 299 | 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x08, 0x63, 0x6c, 0x69, 300 | 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 301 | 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 302 | 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 303 | 0x1d, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 304 | 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x07, 305 | 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x6f, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x32, 0x43, 306 | 0x6c, 0x6f, 0x75, 0x64, 0x12, 0x30, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 307 | 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 308 | 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 309 | 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x07, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 310 | 0x68, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 311 | 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 312 | 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 313 | 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x6f, 0x6e, 0x77, 0x69, 0x6e, 0x64, 0x2f, 314 | 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 315 | 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 316 | } 317 | 318 | var ( 319 | file_cli_proto_rawDescOnce sync.Once 320 | file_cli_proto_rawDescData = file_cli_proto_rawDesc 321 | ) 322 | 323 | func file_cli_proto_rawDescGZIP() []byte { 324 | file_cli_proto_rawDescOnce.Do(func() { 325 | file_cli_proto_rawDescData = protoimpl.X.CompressGZIP(file_cli_proto_rawDescData) 326 | }) 327 | return file_cli_proto_rawDescData 328 | } 329 | 330 | var file_cli_proto_msgTypes = make([]protoimpl.MessageInfo, 5) 331 | var file_cli_proto_goTypes = []interface{}{ 332 | (*Client)(nil), // 0: proto.Client 333 | (*ClientId)(nil), // 1: proto.ClientId 334 | (*PublishRequest)(nil), // 2: proto.PublishRequest 335 | (*Payload)(nil), // 3: proto.Payload 336 | (*Empty)(nil), // 4: proto.Empty 337 | } 338 | var file_cli_proto_depIdxs = []int32{ 339 | 1, // 0: proto.PublishRequest.clientId:type_name -> proto.ClientId 340 | 3, // 1: proto.PublishRequest.payload:type_name -> proto.Payload 341 | 0, // 2: proto.Cli2Cloud.RegisterClient:input_type -> proto.Client 342 | 2, // 3: proto.Cli2Cloud.Publish:input_type -> proto.PublishRequest 343 | 1, // 4: proto.Cli2Cloud.RegisterClient:output_type -> proto.ClientId 344 | 4, // 5: proto.Cli2Cloud.Publish:output_type -> proto.Empty 345 | 4, // [4:6] is the sub-list for method output_type 346 | 2, // [2:4] is the sub-list for method input_type 347 | 2, // [2:2] is the sub-list for extension type_name 348 | 2, // [2:2] is the sub-list for extension extendee 349 | 0, // [0:2] is the sub-list for field type_name 350 | } 351 | 352 | func init() { file_cli_proto_init() } 353 | func file_cli_proto_init() { 354 | if File_cli_proto != nil { 355 | return 356 | } 357 | if !protoimpl.UnsafeEnabled { 358 | file_cli_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 359 | switch v := v.(*Client); i { 360 | case 0: 361 | return &v.state 362 | case 1: 363 | return &v.sizeCache 364 | case 2: 365 | return &v.unknownFields 366 | default: 367 | return nil 368 | } 369 | } 370 | file_cli_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 371 | switch v := v.(*ClientId); i { 372 | case 0: 373 | return &v.state 374 | case 1: 375 | return &v.sizeCache 376 | case 2: 377 | return &v.unknownFields 378 | default: 379 | return nil 380 | } 381 | } 382 | file_cli_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 383 | switch v := v.(*PublishRequest); i { 384 | case 0: 385 | return &v.state 386 | case 1: 387 | return &v.sizeCache 388 | case 2: 389 | return &v.unknownFields 390 | default: 391 | return nil 392 | } 393 | } 394 | file_cli_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 395 | switch v := v.(*Payload); i { 396 | case 0: 397 | return &v.state 398 | case 1: 399 | return &v.sizeCache 400 | case 2: 401 | return &v.unknownFields 402 | default: 403 | return nil 404 | } 405 | } 406 | file_cli_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { 407 | switch v := v.(*Empty); i { 408 | case 0: 409 | return &v.state 410 | case 1: 411 | return &v.sizeCache 412 | case 2: 413 | return &v.unknownFields 414 | default: 415 | return nil 416 | } 417 | } 418 | } 419 | file_cli_proto_msgTypes[0].OneofWrappers = []interface{}{} 420 | type x struct{} 421 | out := protoimpl.TypeBuilder{ 422 | File: protoimpl.DescBuilder{ 423 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 424 | RawDescriptor: file_cli_proto_rawDesc, 425 | NumEnums: 0, 426 | NumMessages: 5, 427 | NumExtensions: 0, 428 | NumServices: 1, 429 | }, 430 | GoTypes: file_cli_proto_goTypes, 431 | DependencyIndexes: file_cli_proto_depIdxs, 432 | MessageInfos: file_cli_proto_msgTypes, 433 | }.Build() 434 | File_cli_proto = out.File 435 | file_cli_proto_rawDesc = nil 436 | file_cli_proto_goTypes = nil 437 | file_cli_proto_depIdxs = nil 438 | } 439 | -------------------------------------------------------------------------------- /service/api/proto/service.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.27.1 4 | // protoc v3.19.4 5 | // source: service.proto 6 | 7 | package proto 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type Client struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | Encrypted bool `protobuf:"varint,1,opt,name=encrypted,proto3" json:"encrypted,omitempty"` 29 | Salt *string `protobuf:"bytes,2,opt,name=salt,proto3,oneof" json:"salt,omitempty"` 30 | Iv *string `protobuf:"bytes,3,opt,name=iv,proto3,oneof" json:"iv,omitempty"` 31 | Timestamp *int64 `protobuf:"varint,4,opt,name=timestamp,proto3,oneof" json:"timestamp,omitempty"` 32 | } 33 | 34 | func (x *Client) Reset() { 35 | *x = Client{} 36 | if protoimpl.UnsafeEnabled { 37 | mi := &file_service_proto_msgTypes[0] 38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 39 | ms.StoreMessageInfo(mi) 40 | } 41 | } 42 | 43 | func (x *Client) String() string { 44 | return protoimpl.X.MessageStringOf(x) 45 | } 46 | 47 | func (*Client) ProtoMessage() {} 48 | 49 | func (x *Client) ProtoReflect() protoreflect.Message { 50 | mi := &file_service_proto_msgTypes[0] 51 | if protoimpl.UnsafeEnabled && x != nil { 52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 53 | if ms.LoadMessageInfo() == nil { 54 | ms.StoreMessageInfo(mi) 55 | } 56 | return ms 57 | } 58 | return mi.MessageOf(x) 59 | } 60 | 61 | // Deprecated: Use Client.ProtoReflect.Descriptor instead. 62 | func (*Client) Descriptor() ([]byte, []int) { 63 | return file_service_proto_rawDescGZIP(), []int{0} 64 | } 65 | 66 | func (x *Client) GetEncrypted() bool { 67 | if x != nil { 68 | return x.Encrypted 69 | } 70 | return false 71 | } 72 | 73 | func (x *Client) GetSalt() string { 74 | if x != nil && x.Salt != nil { 75 | return *x.Salt 76 | } 77 | return "" 78 | } 79 | 80 | func (x *Client) GetIv() string { 81 | if x != nil && x.Iv != nil { 82 | return *x.Iv 83 | } 84 | return "" 85 | } 86 | 87 | func (x *Client) GetTimestamp() int64 { 88 | if x != nil && x.Timestamp != nil { 89 | return *x.Timestamp 90 | } 91 | return 0 92 | } 93 | 94 | type ClientId struct { 95 | state protoimpl.MessageState 96 | sizeCache protoimpl.SizeCache 97 | unknownFields protoimpl.UnknownFields 98 | 99 | Id string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` 100 | } 101 | 102 | func (x *ClientId) Reset() { 103 | *x = ClientId{} 104 | if protoimpl.UnsafeEnabled { 105 | mi := &file_service_proto_msgTypes[1] 106 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 107 | ms.StoreMessageInfo(mi) 108 | } 109 | } 110 | 111 | func (x *ClientId) String() string { 112 | return protoimpl.X.MessageStringOf(x) 113 | } 114 | 115 | func (*ClientId) ProtoMessage() {} 116 | 117 | func (x *ClientId) ProtoReflect() protoreflect.Message { 118 | mi := &file_service_proto_msgTypes[1] 119 | if protoimpl.UnsafeEnabled && x != nil { 120 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 121 | if ms.LoadMessageInfo() == nil { 122 | ms.StoreMessageInfo(mi) 123 | } 124 | return ms 125 | } 126 | return mi.MessageOf(x) 127 | } 128 | 129 | // Deprecated: Use ClientId.ProtoReflect.Descriptor instead. 130 | func (*ClientId) Descriptor() ([]byte, []int) { 131 | return file_service_proto_rawDescGZIP(), []int{1} 132 | } 133 | 134 | func (x *ClientId) GetId() string { 135 | if x != nil { 136 | return x.Id 137 | } 138 | return "" 139 | } 140 | 141 | type PublishRequest struct { 142 | state protoimpl.MessageState 143 | sizeCache protoimpl.SizeCache 144 | unknownFields protoimpl.UnknownFields 145 | 146 | ClientId *ClientId `protobuf:"bytes,1,opt,name=clientId,proto3" json:"clientId,omitempty"` 147 | Payload *Payload `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` 148 | } 149 | 150 | func (x *PublishRequest) Reset() { 151 | *x = PublishRequest{} 152 | if protoimpl.UnsafeEnabled { 153 | mi := &file_service_proto_msgTypes[2] 154 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 155 | ms.StoreMessageInfo(mi) 156 | } 157 | } 158 | 159 | func (x *PublishRequest) String() string { 160 | return protoimpl.X.MessageStringOf(x) 161 | } 162 | 163 | func (*PublishRequest) ProtoMessage() {} 164 | 165 | func (x *PublishRequest) ProtoReflect() protoreflect.Message { 166 | mi := &file_service_proto_msgTypes[2] 167 | if protoimpl.UnsafeEnabled && x != nil { 168 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 169 | if ms.LoadMessageInfo() == nil { 170 | ms.StoreMessageInfo(mi) 171 | } 172 | return ms 173 | } 174 | return mi.MessageOf(x) 175 | } 176 | 177 | // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. 178 | func (*PublishRequest) Descriptor() ([]byte, []int) { 179 | return file_service_proto_rawDescGZIP(), []int{2} 180 | } 181 | 182 | func (x *PublishRequest) GetClientId() *ClientId { 183 | if x != nil { 184 | return x.ClientId 185 | } 186 | return nil 187 | } 188 | 189 | func (x *PublishRequest) GetPayload() *Payload { 190 | if x != nil { 191 | return x.Payload 192 | } 193 | return nil 194 | } 195 | 196 | type Payload struct { 197 | state protoimpl.MessageState 198 | sizeCache protoimpl.SizeCache 199 | unknownFields protoimpl.UnknownFields 200 | 201 | Body string `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` 202 | } 203 | 204 | func (x *Payload) Reset() { 205 | *x = Payload{} 206 | if protoimpl.UnsafeEnabled { 207 | mi := &file_service_proto_msgTypes[3] 208 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 209 | ms.StoreMessageInfo(mi) 210 | } 211 | } 212 | 213 | func (x *Payload) String() string { 214 | return protoimpl.X.MessageStringOf(x) 215 | } 216 | 217 | func (*Payload) ProtoMessage() {} 218 | 219 | func (x *Payload) ProtoReflect() protoreflect.Message { 220 | mi := &file_service_proto_msgTypes[3] 221 | if protoimpl.UnsafeEnabled && x != nil { 222 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 223 | if ms.LoadMessageInfo() == nil { 224 | ms.StoreMessageInfo(mi) 225 | } 226 | return ms 227 | } 228 | return mi.MessageOf(x) 229 | } 230 | 231 | // Deprecated: Use Payload.ProtoReflect.Descriptor instead. 232 | func (*Payload) Descriptor() ([]byte, []int) { 233 | return file_service_proto_rawDescGZIP(), []int{3} 234 | } 235 | 236 | func (x *Payload) GetBody() string { 237 | if x != nil { 238 | return x.Body 239 | } 240 | return "" 241 | } 242 | 243 | type Empty struct { 244 | state protoimpl.MessageState 245 | sizeCache protoimpl.SizeCache 246 | unknownFields protoimpl.UnknownFields 247 | } 248 | 249 | func (x *Empty) Reset() { 250 | *x = Empty{} 251 | if protoimpl.UnsafeEnabled { 252 | mi := &file_service_proto_msgTypes[4] 253 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 254 | ms.StoreMessageInfo(mi) 255 | } 256 | } 257 | 258 | func (x *Empty) String() string { 259 | return protoimpl.X.MessageStringOf(x) 260 | } 261 | 262 | func (*Empty) ProtoMessage() {} 263 | 264 | func (x *Empty) ProtoReflect() protoreflect.Message { 265 | mi := &file_service_proto_msgTypes[4] 266 | if protoimpl.UnsafeEnabled && x != nil { 267 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 268 | if ms.LoadMessageInfo() == nil { 269 | ms.StoreMessageInfo(mi) 270 | } 271 | return ms 272 | } 273 | return mi.MessageOf(x) 274 | } 275 | 276 | // Deprecated: Use Empty.ProtoReflect.Descriptor instead. 277 | func (*Empty) Descriptor() ([]byte, []int) { 278 | return file_service_proto_rawDescGZIP(), []int{4} 279 | } 280 | 281 | var File_service_proto protoreflect.FileDescriptor 282 | 283 | var file_service_proto_rawDesc = []byte{ 284 | 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 285 | 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x43, 0x6c, 0x69, 0x65, 0x6e, 286 | 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 287 | 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 288 | 0x17, 0x0a, 0x04, 0x73, 0x61, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 289 | 0x04, 0x73, 0x61, 0x6c, 0x74, 0x88, 0x01, 0x01, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x76, 0x18, 0x03, 290 | 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x02, 0x69, 0x76, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 291 | 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 292 | 0x48, 0x02, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, 293 | 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x73, 0x61, 0x6c, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x76, 294 | 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1a, 295 | 0x0a, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 296 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x64, 0x22, 0x67, 0x0a, 0x0e, 0x50, 0x75, 297 | 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x08, 298 | 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 299 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x52, 300 | 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x70, 0x61, 0x79, 301 | 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 302 | 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 303 | 0x6f, 0x61, 0x64, 0x22, 0x1d, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x12, 304 | 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 305 | 0x64, 0x79, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xd0, 0x01, 0x0a, 0x09, 306 | 0x43, 0x6c, 0x69, 0x32, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x12, 0x30, 0x0a, 0x0e, 0x52, 0x65, 0x67, 307 | 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x0d, 0x2e, 0x70, 0x72, 308 | 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 309 | 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x0d, 0x47, 310 | 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x12, 0x0f, 0x2e, 0x70, 311 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x0d, 0x2e, 312 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x07, 313 | 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 314 | 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 315 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x2e, 316 | 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x0f, 0x2e, 0x70, 0x72, 317 | 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x1a, 0x0e, 0x2e, 0x70, 318 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x30, 0x01, 0x42, 0x27, 319 | 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x6f, 320 | 0x6e, 0x77, 0x69, 0x6e, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, 321 | 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 322 | } 323 | 324 | var ( 325 | file_service_proto_rawDescOnce sync.Once 326 | file_service_proto_rawDescData = file_service_proto_rawDesc 327 | ) 328 | 329 | func file_service_proto_rawDescGZIP() []byte { 330 | file_service_proto_rawDescOnce.Do(func() { 331 | file_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_proto_rawDescData) 332 | }) 333 | return file_service_proto_rawDescData 334 | } 335 | 336 | var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 5) 337 | var file_service_proto_goTypes = []interface{}{ 338 | (*Client)(nil), // 0: proto.Client 339 | (*ClientId)(nil), // 1: proto.ClientId 340 | (*PublishRequest)(nil), // 2: proto.PublishRequest 341 | (*Payload)(nil), // 3: proto.Payload 342 | (*Empty)(nil), // 4: proto.Empty 343 | } 344 | var file_service_proto_depIdxs = []int32{ 345 | 1, // 0: proto.PublishRequest.clientId:type_name -> proto.ClientId 346 | 3, // 1: proto.PublishRequest.payload:type_name -> proto.Payload 347 | 0, // 2: proto.Cli2Cloud.RegisterClient:input_type -> proto.Client 348 | 1, // 3: proto.Cli2Cloud.GetClientById:input_type -> proto.ClientId 349 | 2, // 4: proto.Cli2Cloud.Publish:input_type -> proto.PublishRequest 350 | 1, // 5: proto.Cli2Cloud.Subscribe:input_type -> proto.ClientId 351 | 1, // 6: proto.Cli2Cloud.RegisterClient:output_type -> proto.ClientId 352 | 0, // 7: proto.Cli2Cloud.GetClientById:output_type -> proto.Client 353 | 4, // 8: proto.Cli2Cloud.Publish:output_type -> proto.Empty 354 | 3, // 9: proto.Cli2Cloud.Subscribe:output_type -> proto.Payload 355 | 6, // [6:10] is the sub-list for method output_type 356 | 2, // [2:6] is the sub-list for method input_type 357 | 2, // [2:2] is the sub-list for extension type_name 358 | 2, // [2:2] is the sub-list for extension extendee 359 | 0, // [0:2] is the sub-list for field type_name 360 | } 361 | 362 | func init() { file_service_proto_init() } 363 | func file_service_proto_init() { 364 | if File_service_proto != nil { 365 | return 366 | } 367 | if !protoimpl.UnsafeEnabled { 368 | file_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 369 | switch v := v.(*Client); i { 370 | case 0: 371 | return &v.state 372 | case 1: 373 | return &v.sizeCache 374 | case 2: 375 | return &v.unknownFields 376 | default: 377 | return nil 378 | } 379 | } 380 | file_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 381 | switch v := v.(*ClientId); i { 382 | case 0: 383 | return &v.state 384 | case 1: 385 | return &v.sizeCache 386 | case 2: 387 | return &v.unknownFields 388 | default: 389 | return nil 390 | } 391 | } 392 | file_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 393 | switch v := v.(*PublishRequest); i { 394 | case 0: 395 | return &v.state 396 | case 1: 397 | return &v.sizeCache 398 | case 2: 399 | return &v.unknownFields 400 | default: 401 | return nil 402 | } 403 | } 404 | file_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 405 | switch v := v.(*Payload); i { 406 | case 0: 407 | return &v.state 408 | case 1: 409 | return &v.sizeCache 410 | case 2: 411 | return &v.unknownFields 412 | default: 413 | return nil 414 | } 415 | } 416 | file_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { 417 | switch v := v.(*Empty); i { 418 | case 0: 419 | return &v.state 420 | case 1: 421 | return &v.sizeCache 422 | case 2: 423 | return &v.unknownFields 424 | default: 425 | return nil 426 | } 427 | } 428 | } 429 | file_service_proto_msgTypes[0].OneofWrappers = []interface{}{} 430 | type x struct{} 431 | out := protoimpl.TypeBuilder{ 432 | File: protoimpl.DescBuilder{ 433 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 434 | RawDescriptor: file_service_proto_rawDesc, 435 | NumEnums: 0, 436 | NumMessages: 5, 437 | NumExtensions: 0, 438 | NumServices: 1, 439 | }, 440 | GoTypes: file_service_proto_goTypes, 441 | DependencyIndexes: file_service_proto_depIdxs, 442 | MessageInfos: file_service_proto_msgTypes, 443 | }.Build() 444 | File_service_proto = out.File 445 | file_service_proto_rawDesc = nil 446 | file_service_proto_goTypes = nil 447 | file_service_proto_depIdxs = nil 448 | } 449 | -------------------------------------------------------------------------------- /service/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= 5 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 6 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 7 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 8 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 9 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 10 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 11 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 12 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 13 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 14 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 15 | github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= 16 | github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= 17 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 18 | github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 19 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 20 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 22 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 24 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 25 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 26 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 27 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 28 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 29 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 30 | github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 31 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 32 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 33 | github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= 34 | github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 35 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 36 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 37 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 38 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 39 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 40 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 41 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 42 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 43 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 44 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 45 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 46 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 47 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 48 | github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= 49 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 50 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 51 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 52 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 53 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 54 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 55 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 56 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 57 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 58 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 59 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 60 | github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= 61 | github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= 62 | github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= 63 | github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= 64 | github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= 65 | github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= 66 | github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= 67 | github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= 68 | github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= 69 | github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= 70 | github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= 71 | github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= 72 | github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= 73 | github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= 74 | github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= 75 | github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= 76 | github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= 77 | github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= 78 | github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= 79 | github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= 80 | github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 81 | github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= 82 | github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= 83 | github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= 84 | github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= 85 | github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= 86 | github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= 87 | github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= 88 | github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= 89 | github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= 90 | github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= 91 | github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= 92 | github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= 93 | github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= 94 | github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= 95 | github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= 96 | github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= 97 | github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= 98 | github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= 99 | github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= 100 | github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= 101 | github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= 102 | github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= 103 | github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= 104 | github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= 105 | github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 106 | github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 107 | github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 108 | github.com/jackc/puddle v1.2.1 h1:gI8os0wpRXFd4FiAY2dWiqRK037tjj3t7rKFeO4X5iw= 109 | github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= 110 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 111 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 112 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 113 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 114 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 115 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 116 | github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 117 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 118 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 119 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 120 | github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 121 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 122 | github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= 123 | github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= 124 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 125 | github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 126 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 127 | github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 128 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 129 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 130 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 131 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 132 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 133 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 134 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 135 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 136 | github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= 137 | github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= 138 | github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= 139 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 140 | github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= 141 | github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= 142 | github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 143 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 144 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 145 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 146 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 147 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 148 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 149 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 150 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 151 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 152 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 153 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 154 | github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= 155 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 156 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 157 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 158 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 159 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 160 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 161 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 162 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 163 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 164 | go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 165 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 166 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 167 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 168 | golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= 169 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 170 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 171 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 172 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 173 | golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 174 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 175 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= 176 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 177 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 178 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 179 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 180 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 181 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 182 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 183 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 184 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 185 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 186 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 187 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 188 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 189 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 190 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 191 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 192 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 193 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 194 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 195 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 196 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 197 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 198 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 199 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 200 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 201 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 202 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 203 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 204 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 205 | golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 206 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 207 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 208 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 209 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 210 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 211 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 212 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 213 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 214 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 215 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 216 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 217 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 218 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 219 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 220 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 221 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 222 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 223 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 224 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 225 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 226 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 227 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 228 | golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 229 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 230 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 231 | golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 232 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 233 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 234 | golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 235 | golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 236 | golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 237 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 238 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 239 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 240 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 241 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 242 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 243 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 244 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 245 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 246 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 247 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= 248 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 249 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 250 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 251 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 252 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 253 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 254 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 255 | google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= 256 | google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 257 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 258 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 259 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 260 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 261 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 262 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 263 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 264 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 265 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 266 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 267 | google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 268 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 269 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 270 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 271 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 272 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 273 | gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= 274 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 275 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 276 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 277 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 278 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 279 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 280 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 281 | -------------------------------------------------------------------------------- /webapp/src/proto/service_pb.js: -------------------------------------------------------------------------------- 1 | // source: service.proto 2 | /** 3 | * @fileoverview 4 | * @enhanceable 5 | * @suppress {missingRequire} reports error on implicit type usages. 6 | * @suppress {messageConventions} JS Compiler reports an error if a variable or 7 | * field starts with 'MSG_' and isn't a translatable message. 8 | * @public 9 | */ 10 | // GENERATED CODE -- DO NOT EDIT! 11 | /* eslint-disable */ 12 | // @ts-nocheck 13 | 14 | var jspb = require('google-protobuf'); 15 | var goog = jspb; 16 | var global = (function() { 17 | if (this) { return this; } 18 | if (typeof window !== 'undefined') { return window; } 19 | if (typeof global !== 'undefined') { return global; } 20 | if (typeof self !== 'undefined') { return self; } 21 | return Function('return this')(); 22 | }.call(null)); 23 | 24 | goog.exportSymbol('proto.proto.Client', null, global); 25 | goog.exportSymbol('proto.proto.ClientId', null, global); 26 | goog.exportSymbol('proto.proto.Empty', null, global); 27 | goog.exportSymbol('proto.proto.Payload', null, global); 28 | goog.exportSymbol('proto.proto.PublishRequest', null, global); 29 | /** 30 | * Generated by JsPbCodeGenerator. 31 | * @param {Array=} opt_data Optional initial data array, typically from a 32 | * server response, or constructed directly in Javascript. The array is used 33 | * in place and becomes part of the constructed object. It is not cloned. 34 | * If no data is provided, the constructed object will be empty, but still 35 | * valid. 36 | * @extends {jspb.Message} 37 | * @constructor 38 | */ 39 | proto.proto.Client = function(opt_data) { 40 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 41 | }; 42 | goog.inherits(proto.proto.Client, jspb.Message); 43 | if (goog.DEBUG && !COMPILED) { 44 | /** 45 | * @public 46 | * @override 47 | */ 48 | proto.proto.Client.displayName = 'proto.proto.Client'; 49 | } 50 | /** 51 | * Generated by JsPbCodeGenerator. 52 | * @param {Array=} opt_data Optional initial data array, typically from a 53 | * server response, or constructed directly in Javascript. The array is used 54 | * in place and becomes part of the constructed object. It is not cloned. 55 | * If no data is provided, the constructed object will be empty, but still 56 | * valid. 57 | * @extends {jspb.Message} 58 | * @constructor 59 | */ 60 | proto.proto.ClientId = function(opt_data) { 61 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 62 | }; 63 | goog.inherits(proto.proto.ClientId, jspb.Message); 64 | if (goog.DEBUG && !COMPILED) { 65 | /** 66 | * @public 67 | * @override 68 | */ 69 | proto.proto.ClientId.displayName = 'proto.proto.ClientId'; 70 | } 71 | /** 72 | * Generated by JsPbCodeGenerator. 73 | * @param {Array=} opt_data Optional initial data array, typically from a 74 | * server response, or constructed directly in Javascript. The array is used 75 | * in place and becomes part of the constructed object. It is not cloned. 76 | * If no data is provided, the constructed object will be empty, but still 77 | * valid. 78 | * @extends {jspb.Message} 79 | * @constructor 80 | */ 81 | proto.proto.PublishRequest = function(opt_data) { 82 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 83 | }; 84 | goog.inherits(proto.proto.PublishRequest, jspb.Message); 85 | if (goog.DEBUG && !COMPILED) { 86 | /** 87 | * @public 88 | * @override 89 | */ 90 | proto.proto.PublishRequest.displayName = 'proto.proto.PublishRequest'; 91 | } 92 | /** 93 | * Generated by JsPbCodeGenerator. 94 | * @param {Array=} opt_data Optional initial data array, typically from a 95 | * server response, or constructed directly in Javascript. The array is used 96 | * in place and becomes part of the constructed object. It is not cloned. 97 | * If no data is provided, the constructed object will be empty, but still 98 | * valid. 99 | * @extends {jspb.Message} 100 | * @constructor 101 | */ 102 | proto.proto.Payload = function(opt_data) { 103 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 104 | }; 105 | goog.inherits(proto.proto.Payload, jspb.Message); 106 | if (goog.DEBUG && !COMPILED) { 107 | /** 108 | * @public 109 | * @override 110 | */ 111 | proto.proto.Payload.displayName = 'proto.proto.Payload'; 112 | } 113 | /** 114 | * Generated by JsPbCodeGenerator. 115 | * @param {Array=} opt_data Optional initial data array, typically from a 116 | * server response, or constructed directly in Javascript. The array is used 117 | * in place and becomes part of the constructed object. It is not cloned. 118 | * If no data is provided, the constructed object will be empty, but still 119 | * valid. 120 | * @extends {jspb.Message} 121 | * @constructor 122 | */ 123 | proto.proto.Empty = function(opt_data) { 124 | jspb.Message.initialize(this, opt_data, 0, -1, null, null); 125 | }; 126 | goog.inherits(proto.proto.Empty, jspb.Message); 127 | if (goog.DEBUG && !COMPILED) { 128 | /** 129 | * @public 130 | * @override 131 | */ 132 | proto.proto.Empty.displayName = 'proto.proto.Empty'; 133 | } 134 | 135 | 136 | 137 | if (jspb.Message.GENERATE_TO_OBJECT) { 138 | /** 139 | * Creates an object representation of this proto. 140 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 141 | * Optional fields that are not set will be set to undefined. 142 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 143 | * For the list of reserved names please see: 144 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 145 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 146 | * JSPB instance for transitional soy proto support: 147 | * http://goto/soy-param-migration 148 | * @return {!Object} 149 | */ 150 | proto.proto.Client.prototype.toObject = function(opt_includeInstance) { 151 | return proto.proto.Client.toObject(opt_includeInstance, this); 152 | }; 153 | 154 | 155 | /** 156 | * Static version of the {@see toObject} method. 157 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 158 | * the JSPB instance for transitional soy proto support: 159 | * http://goto/soy-param-migration 160 | * @param {!proto.proto.Client} msg The msg instance to transform. 161 | * @return {!Object} 162 | * @suppress {unusedLocalVariables} f is only used for nested messages 163 | */ 164 | proto.proto.Client.toObject = function(includeInstance, msg) { 165 | var f, obj = { 166 | encrypted: jspb.Message.getBooleanFieldWithDefault(msg, 1, false), 167 | salt: jspb.Message.getFieldWithDefault(msg, 2, ""), 168 | iv: jspb.Message.getFieldWithDefault(msg, 3, ""), 169 | timestamp: jspb.Message.getFieldWithDefault(msg, 4, 0) 170 | }; 171 | 172 | if (includeInstance) { 173 | obj.$jspbMessageInstance = msg; 174 | } 175 | return obj; 176 | }; 177 | } 178 | 179 | 180 | /** 181 | * Deserializes binary data (in protobuf wire format). 182 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 183 | * @return {!proto.proto.Client} 184 | */ 185 | proto.proto.Client.deserializeBinary = function(bytes) { 186 | var reader = new jspb.BinaryReader(bytes); 187 | var msg = new proto.proto.Client; 188 | return proto.proto.Client.deserializeBinaryFromReader(msg, reader); 189 | }; 190 | 191 | 192 | /** 193 | * Deserializes binary data (in protobuf wire format) from the 194 | * given reader into the given message object. 195 | * @param {!proto.proto.Client} msg The message object to deserialize into. 196 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 197 | * @return {!proto.proto.Client} 198 | */ 199 | proto.proto.Client.deserializeBinaryFromReader = function(msg, reader) { 200 | while (reader.nextField()) { 201 | if (reader.isEndGroup()) { 202 | break; 203 | } 204 | var field = reader.getFieldNumber(); 205 | switch (field) { 206 | case 1: 207 | var value = /** @type {boolean} */ (reader.readBool()); 208 | msg.setEncrypted(value); 209 | break; 210 | case 2: 211 | var value = /** @type {string} */ (reader.readString()); 212 | msg.setSalt(value); 213 | break; 214 | case 3: 215 | var value = /** @type {string} */ (reader.readString()); 216 | msg.setIv(value); 217 | break; 218 | case 4: 219 | var value = /** @type {number} */ (reader.readInt64()); 220 | msg.setTimestamp(value); 221 | break; 222 | default: 223 | reader.skipField(); 224 | break; 225 | } 226 | } 227 | return msg; 228 | }; 229 | 230 | 231 | /** 232 | * Serializes the message to binary data (in protobuf wire format). 233 | * @return {!Uint8Array} 234 | */ 235 | proto.proto.Client.prototype.serializeBinary = function() { 236 | var writer = new jspb.BinaryWriter(); 237 | proto.proto.Client.serializeBinaryToWriter(this, writer); 238 | return writer.getResultBuffer(); 239 | }; 240 | 241 | 242 | /** 243 | * Serializes the given message to binary data (in protobuf wire 244 | * format), writing to the given BinaryWriter. 245 | * @param {!proto.proto.Client} message 246 | * @param {!jspb.BinaryWriter} writer 247 | * @suppress {unusedLocalVariables} f is only used for nested messages 248 | */ 249 | proto.proto.Client.serializeBinaryToWriter = function(message, writer) { 250 | var f = undefined; 251 | f = message.getEncrypted(); 252 | if (f) { 253 | writer.writeBool( 254 | 1, 255 | f 256 | ); 257 | } 258 | f = /** @type {string} */ (jspb.Message.getField(message, 2)); 259 | if (f != null) { 260 | writer.writeString( 261 | 2, 262 | f 263 | ); 264 | } 265 | f = /** @type {string} */ (jspb.Message.getField(message, 3)); 266 | if (f != null) { 267 | writer.writeString( 268 | 3, 269 | f 270 | ); 271 | } 272 | f = /** @type {number} */ (jspb.Message.getField(message, 4)); 273 | if (f != null) { 274 | writer.writeInt64( 275 | 4, 276 | f 277 | ); 278 | } 279 | }; 280 | 281 | 282 | /** 283 | * optional bool encrypted = 1; 284 | * @return {boolean} 285 | */ 286 | proto.proto.Client.prototype.getEncrypted = function() { 287 | return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false)); 288 | }; 289 | 290 | 291 | /** 292 | * @param {boolean} value 293 | * @return {!proto.proto.Client} returns this 294 | */ 295 | proto.proto.Client.prototype.setEncrypted = function(value) { 296 | return jspb.Message.setProto3BooleanField(this, 1, value); 297 | }; 298 | 299 | 300 | /** 301 | * optional string salt = 2; 302 | * @return {string} 303 | */ 304 | proto.proto.Client.prototype.getSalt = function() { 305 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); 306 | }; 307 | 308 | 309 | /** 310 | * @param {string} value 311 | * @return {!proto.proto.Client} returns this 312 | */ 313 | proto.proto.Client.prototype.setSalt = function(value) { 314 | return jspb.Message.setField(this, 2, value); 315 | }; 316 | 317 | 318 | /** 319 | * Clears the field making it undefined. 320 | * @return {!proto.proto.Client} returns this 321 | */ 322 | proto.proto.Client.prototype.clearSalt = function() { 323 | return jspb.Message.setField(this, 2, undefined); 324 | }; 325 | 326 | 327 | /** 328 | * Returns whether this field is set. 329 | * @return {boolean} 330 | */ 331 | proto.proto.Client.prototype.hasSalt = function() { 332 | return jspb.Message.getField(this, 2) != null; 333 | }; 334 | 335 | 336 | /** 337 | * optional string iv = 3; 338 | * @return {string} 339 | */ 340 | proto.proto.Client.prototype.getIv = function() { 341 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); 342 | }; 343 | 344 | 345 | /** 346 | * @param {string} value 347 | * @return {!proto.proto.Client} returns this 348 | */ 349 | proto.proto.Client.prototype.setIv = function(value) { 350 | return jspb.Message.setField(this, 3, value); 351 | }; 352 | 353 | 354 | /** 355 | * Clears the field making it undefined. 356 | * @return {!proto.proto.Client} returns this 357 | */ 358 | proto.proto.Client.prototype.clearIv = function() { 359 | return jspb.Message.setField(this, 3, undefined); 360 | }; 361 | 362 | 363 | /** 364 | * Returns whether this field is set. 365 | * @return {boolean} 366 | */ 367 | proto.proto.Client.prototype.hasIv = function() { 368 | return jspb.Message.getField(this, 3) != null; 369 | }; 370 | 371 | 372 | /** 373 | * optional int64 timestamp = 4; 374 | * @return {number} 375 | */ 376 | proto.proto.Client.prototype.getTimestamp = function() { 377 | return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); 378 | }; 379 | 380 | 381 | /** 382 | * @param {number} value 383 | * @return {!proto.proto.Client} returns this 384 | */ 385 | proto.proto.Client.prototype.setTimestamp = function(value) { 386 | return jspb.Message.setField(this, 4, value); 387 | }; 388 | 389 | 390 | /** 391 | * Clears the field making it undefined. 392 | * @return {!proto.proto.Client} returns this 393 | */ 394 | proto.proto.Client.prototype.clearTimestamp = function() { 395 | return jspb.Message.setField(this, 4, undefined); 396 | }; 397 | 398 | 399 | /** 400 | * Returns whether this field is set. 401 | * @return {boolean} 402 | */ 403 | proto.proto.Client.prototype.hasTimestamp = function() { 404 | return jspb.Message.getField(this, 4) != null; 405 | }; 406 | 407 | 408 | 409 | 410 | 411 | if (jspb.Message.GENERATE_TO_OBJECT) { 412 | /** 413 | * Creates an object representation of this proto. 414 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 415 | * Optional fields that are not set will be set to undefined. 416 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 417 | * For the list of reserved names please see: 418 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 419 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 420 | * JSPB instance for transitional soy proto support: 421 | * http://goto/soy-param-migration 422 | * @return {!Object} 423 | */ 424 | proto.proto.ClientId.prototype.toObject = function(opt_includeInstance) { 425 | return proto.proto.ClientId.toObject(opt_includeInstance, this); 426 | }; 427 | 428 | 429 | /** 430 | * Static version of the {@see toObject} method. 431 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 432 | * the JSPB instance for transitional soy proto support: 433 | * http://goto/soy-param-migration 434 | * @param {!proto.proto.ClientId} msg The msg instance to transform. 435 | * @return {!Object} 436 | * @suppress {unusedLocalVariables} f is only used for nested messages 437 | */ 438 | proto.proto.ClientId.toObject = function(includeInstance, msg) { 439 | var f, obj = { 440 | id: jspb.Message.getFieldWithDefault(msg, 1, "") 441 | }; 442 | 443 | if (includeInstance) { 444 | obj.$jspbMessageInstance = msg; 445 | } 446 | return obj; 447 | }; 448 | } 449 | 450 | 451 | /** 452 | * Deserializes binary data (in protobuf wire format). 453 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 454 | * @return {!proto.proto.ClientId} 455 | */ 456 | proto.proto.ClientId.deserializeBinary = function(bytes) { 457 | var reader = new jspb.BinaryReader(bytes); 458 | var msg = new proto.proto.ClientId; 459 | return proto.proto.ClientId.deserializeBinaryFromReader(msg, reader); 460 | }; 461 | 462 | 463 | /** 464 | * Deserializes binary data (in protobuf wire format) from the 465 | * given reader into the given message object. 466 | * @param {!proto.proto.ClientId} msg The message object to deserialize into. 467 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 468 | * @return {!proto.proto.ClientId} 469 | */ 470 | proto.proto.ClientId.deserializeBinaryFromReader = function(msg, reader) { 471 | while (reader.nextField()) { 472 | if (reader.isEndGroup()) { 473 | break; 474 | } 475 | var field = reader.getFieldNumber(); 476 | switch (field) { 477 | case 1: 478 | var value = /** @type {string} */ (reader.readString()); 479 | msg.setId(value); 480 | break; 481 | default: 482 | reader.skipField(); 483 | break; 484 | } 485 | } 486 | return msg; 487 | }; 488 | 489 | 490 | /** 491 | * Serializes the message to binary data (in protobuf wire format). 492 | * @return {!Uint8Array} 493 | */ 494 | proto.proto.ClientId.prototype.serializeBinary = function() { 495 | var writer = new jspb.BinaryWriter(); 496 | proto.proto.ClientId.serializeBinaryToWriter(this, writer); 497 | return writer.getResultBuffer(); 498 | }; 499 | 500 | 501 | /** 502 | * Serializes the given message to binary data (in protobuf wire 503 | * format), writing to the given BinaryWriter. 504 | * @param {!proto.proto.ClientId} message 505 | * @param {!jspb.BinaryWriter} writer 506 | * @suppress {unusedLocalVariables} f is only used for nested messages 507 | */ 508 | proto.proto.ClientId.serializeBinaryToWriter = function(message, writer) { 509 | var f = undefined; 510 | f = message.getId(); 511 | if (f.length > 0) { 512 | writer.writeString( 513 | 1, 514 | f 515 | ); 516 | } 517 | }; 518 | 519 | 520 | /** 521 | * optional string Id = 1; 522 | * @return {string} 523 | */ 524 | proto.proto.ClientId.prototype.getId = function() { 525 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); 526 | }; 527 | 528 | 529 | /** 530 | * @param {string} value 531 | * @return {!proto.proto.ClientId} returns this 532 | */ 533 | proto.proto.ClientId.prototype.setId = function(value) { 534 | return jspb.Message.setProto3StringField(this, 1, value); 535 | }; 536 | 537 | 538 | 539 | 540 | 541 | if (jspb.Message.GENERATE_TO_OBJECT) { 542 | /** 543 | * Creates an object representation of this proto. 544 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 545 | * Optional fields that are not set will be set to undefined. 546 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 547 | * For the list of reserved names please see: 548 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 549 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 550 | * JSPB instance for transitional soy proto support: 551 | * http://goto/soy-param-migration 552 | * @return {!Object} 553 | */ 554 | proto.proto.PublishRequest.prototype.toObject = function(opt_includeInstance) { 555 | return proto.proto.PublishRequest.toObject(opt_includeInstance, this); 556 | }; 557 | 558 | 559 | /** 560 | * Static version of the {@see toObject} method. 561 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 562 | * the JSPB instance for transitional soy proto support: 563 | * http://goto/soy-param-migration 564 | * @param {!proto.proto.PublishRequest} msg The msg instance to transform. 565 | * @return {!Object} 566 | * @suppress {unusedLocalVariables} f is only used for nested messages 567 | */ 568 | proto.proto.PublishRequest.toObject = function(includeInstance, msg) { 569 | var f, obj = { 570 | clientid: (f = msg.getClientid()) && proto.proto.ClientId.toObject(includeInstance, f), 571 | payload: (f = msg.getPayload()) && proto.proto.Payload.toObject(includeInstance, f) 572 | }; 573 | 574 | if (includeInstance) { 575 | obj.$jspbMessageInstance = msg; 576 | } 577 | return obj; 578 | }; 579 | } 580 | 581 | 582 | /** 583 | * Deserializes binary data (in protobuf wire format). 584 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 585 | * @return {!proto.proto.PublishRequest} 586 | */ 587 | proto.proto.PublishRequest.deserializeBinary = function(bytes) { 588 | var reader = new jspb.BinaryReader(bytes); 589 | var msg = new proto.proto.PublishRequest; 590 | return proto.proto.PublishRequest.deserializeBinaryFromReader(msg, reader); 591 | }; 592 | 593 | 594 | /** 595 | * Deserializes binary data (in protobuf wire format) from the 596 | * given reader into the given message object. 597 | * @param {!proto.proto.PublishRequest} msg The message object to deserialize into. 598 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 599 | * @return {!proto.proto.PublishRequest} 600 | */ 601 | proto.proto.PublishRequest.deserializeBinaryFromReader = function(msg, reader) { 602 | while (reader.nextField()) { 603 | if (reader.isEndGroup()) { 604 | break; 605 | } 606 | var field = reader.getFieldNumber(); 607 | switch (field) { 608 | case 1: 609 | var value = new proto.proto.ClientId; 610 | reader.readMessage(value,proto.proto.ClientId.deserializeBinaryFromReader); 611 | msg.setClientid(value); 612 | break; 613 | case 2: 614 | var value = new proto.proto.Payload; 615 | reader.readMessage(value,proto.proto.Payload.deserializeBinaryFromReader); 616 | msg.setPayload(value); 617 | break; 618 | default: 619 | reader.skipField(); 620 | break; 621 | } 622 | } 623 | return msg; 624 | }; 625 | 626 | 627 | /** 628 | * Serializes the message to binary data (in protobuf wire format). 629 | * @return {!Uint8Array} 630 | */ 631 | proto.proto.PublishRequest.prototype.serializeBinary = function() { 632 | var writer = new jspb.BinaryWriter(); 633 | proto.proto.PublishRequest.serializeBinaryToWriter(this, writer); 634 | return writer.getResultBuffer(); 635 | }; 636 | 637 | 638 | /** 639 | * Serializes the given message to binary data (in protobuf wire 640 | * format), writing to the given BinaryWriter. 641 | * @param {!proto.proto.PublishRequest} message 642 | * @param {!jspb.BinaryWriter} writer 643 | * @suppress {unusedLocalVariables} f is only used for nested messages 644 | */ 645 | proto.proto.PublishRequest.serializeBinaryToWriter = function(message, writer) { 646 | var f = undefined; 647 | f = message.getClientid(); 648 | if (f != null) { 649 | writer.writeMessage( 650 | 1, 651 | f, 652 | proto.proto.ClientId.serializeBinaryToWriter 653 | ); 654 | } 655 | f = message.getPayload(); 656 | if (f != null) { 657 | writer.writeMessage( 658 | 2, 659 | f, 660 | proto.proto.Payload.serializeBinaryToWriter 661 | ); 662 | } 663 | }; 664 | 665 | 666 | /** 667 | * optional ClientId clientId = 1; 668 | * @return {?proto.proto.ClientId} 669 | */ 670 | proto.proto.PublishRequest.prototype.getClientid = function() { 671 | return /** @type{?proto.proto.ClientId} */ ( 672 | jspb.Message.getWrapperField(this, proto.proto.ClientId, 1)); 673 | }; 674 | 675 | 676 | /** 677 | * @param {?proto.proto.ClientId|undefined} value 678 | * @return {!proto.proto.PublishRequest} returns this 679 | */ 680 | proto.proto.PublishRequest.prototype.setClientid = function(value) { 681 | return jspb.Message.setWrapperField(this, 1, value); 682 | }; 683 | 684 | 685 | /** 686 | * Clears the message field making it undefined. 687 | * @return {!proto.proto.PublishRequest} returns this 688 | */ 689 | proto.proto.PublishRequest.prototype.clearClientid = function() { 690 | return this.setClientid(undefined); 691 | }; 692 | 693 | 694 | /** 695 | * Returns whether this field is set. 696 | * @return {boolean} 697 | */ 698 | proto.proto.PublishRequest.prototype.hasClientid = function() { 699 | return jspb.Message.getField(this, 1) != null; 700 | }; 701 | 702 | 703 | /** 704 | * optional Payload payload = 2; 705 | * @return {?proto.proto.Payload} 706 | */ 707 | proto.proto.PublishRequest.prototype.getPayload = function() { 708 | return /** @type{?proto.proto.Payload} */ ( 709 | jspb.Message.getWrapperField(this, proto.proto.Payload, 2)); 710 | }; 711 | 712 | 713 | /** 714 | * @param {?proto.proto.Payload|undefined} value 715 | * @return {!proto.proto.PublishRequest} returns this 716 | */ 717 | proto.proto.PublishRequest.prototype.setPayload = function(value) { 718 | return jspb.Message.setWrapperField(this, 2, value); 719 | }; 720 | 721 | 722 | /** 723 | * Clears the message field making it undefined. 724 | * @return {!proto.proto.PublishRequest} returns this 725 | */ 726 | proto.proto.PublishRequest.prototype.clearPayload = function() { 727 | return this.setPayload(undefined); 728 | }; 729 | 730 | 731 | /** 732 | * Returns whether this field is set. 733 | * @return {boolean} 734 | */ 735 | proto.proto.PublishRequest.prototype.hasPayload = function() { 736 | return jspb.Message.getField(this, 2) != null; 737 | }; 738 | 739 | 740 | 741 | 742 | 743 | if (jspb.Message.GENERATE_TO_OBJECT) { 744 | /** 745 | * Creates an object representation of this proto. 746 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 747 | * Optional fields that are not set will be set to undefined. 748 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 749 | * For the list of reserved names please see: 750 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 751 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 752 | * JSPB instance for transitional soy proto support: 753 | * http://goto/soy-param-migration 754 | * @return {!Object} 755 | */ 756 | proto.proto.Payload.prototype.toObject = function(opt_includeInstance) { 757 | return proto.proto.Payload.toObject(opt_includeInstance, this); 758 | }; 759 | 760 | 761 | /** 762 | * Static version of the {@see toObject} method. 763 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 764 | * the JSPB instance for transitional soy proto support: 765 | * http://goto/soy-param-migration 766 | * @param {!proto.proto.Payload} msg The msg instance to transform. 767 | * @return {!Object} 768 | * @suppress {unusedLocalVariables} f is only used for nested messages 769 | */ 770 | proto.proto.Payload.toObject = function(includeInstance, msg) { 771 | var f, obj = { 772 | body: jspb.Message.getFieldWithDefault(msg, 1, "") 773 | }; 774 | 775 | if (includeInstance) { 776 | obj.$jspbMessageInstance = msg; 777 | } 778 | return obj; 779 | }; 780 | } 781 | 782 | 783 | /** 784 | * Deserializes binary data (in protobuf wire format). 785 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 786 | * @return {!proto.proto.Payload} 787 | */ 788 | proto.proto.Payload.deserializeBinary = function(bytes) { 789 | var reader = new jspb.BinaryReader(bytes); 790 | var msg = new proto.proto.Payload; 791 | return proto.proto.Payload.deserializeBinaryFromReader(msg, reader); 792 | }; 793 | 794 | 795 | /** 796 | * Deserializes binary data (in protobuf wire format) from the 797 | * given reader into the given message object. 798 | * @param {!proto.proto.Payload} msg The message object to deserialize into. 799 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 800 | * @return {!proto.proto.Payload} 801 | */ 802 | proto.proto.Payload.deserializeBinaryFromReader = function(msg, reader) { 803 | while (reader.nextField()) { 804 | if (reader.isEndGroup()) { 805 | break; 806 | } 807 | var field = reader.getFieldNumber(); 808 | switch (field) { 809 | case 1: 810 | var value = /** @type {string} */ (reader.readString()); 811 | msg.setBody(value); 812 | break; 813 | default: 814 | reader.skipField(); 815 | break; 816 | } 817 | } 818 | return msg; 819 | }; 820 | 821 | 822 | /** 823 | * Serializes the message to binary data (in protobuf wire format). 824 | * @return {!Uint8Array} 825 | */ 826 | proto.proto.Payload.prototype.serializeBinary = function() { 827 | var writer = new jspb.BinaryWriter(); 828 | proto.proto.Payload.serializeBinaryToWriter(this, writer); 829 | return writer.getResultBuffer(); 830 | }; 831 | 832 | 833 | /** 834 | * Serializes the given message to binary data (in protobuf wire 835 | * format), writing to the given BinaryWriter. 836 | * @param {!proto.proto.Payload} message 837 | * @param {!jspb.BinaryWriter} writer 838 | * @suppress {unusedLocalVariables} f is only used for nested messages 839 | */ 840 | proto.proto.Payload.serializeBinaryToWriter = function(message, writer) { 841 | var f = undefined; 842 | f = message.getBody(); 843 | if (f.length > 0) { 844 | writer.writeString( 845 | 1, 846 | f 847 | ); 848 | } 849 | }; 850 | 851 | 852 | /** 853 | * optional string body = 1; 854 | * @return {string} 855 | */ 856 | proto.proto.Payload.prototype.getBody = function() { 857 | return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); 858 | }; 859 | 860 | 861 | /** 862 | * @param {string} value 863 | * @return {!proto.proto.Payload} returns this 864 | */ 865 | proto.proto.Payload.prototype.setBody = function(value) { 866 | return jspb.Message.setProto3StringField(this, 1, value); 867 | }; 868 | 869 | 870 | 871 | 872 | 873 | if (jspb.Message.GENERATE_TO_OBJECT) { 874 | /** 875 | * Creates an object representation of this proto. 876 | * Field names that are reserved in JavaScript and will be renamed to pb_name. 877 | * Optional fields that are not set will be set to undefined. 878 | * To access a reserved field use, foo.pb_, eg, foo.pb_default. 879 | * For the list of reserved names please see: 880 | * net/proto2/compiler/js/internal/generator.cc#kKeyword. 881 | * @param {boolean=} opt_includeInstance Deprecated. whether to include the 882 | * JSPB instance for transitional soy proto support: 883 | * http://goto/soy-param-migration 884 | * @return {!Object} 885 | */ 886 | proto.proto.Empty.prototype.toObject = function(opt_includeInstance) { 887 | return proto.proto.Empty.toObject(opt_includeInstance, this); 888 | }; 889 | 890 | 891 | /** 892 | * Static version of the {@see toObject} method. 893 | * @param {boolean|undefined} includeInstance Deprecated. Whether to include 894 | * the JSPB instance for transitional soy proto support: 895 | * http://goto/soy-param-migration 896 | * @param {!proto.proto.Empty} msg The msg instance to transform. 897 | * @return {!Object} 898 | * @suppress {unusedLocalVariables} f is only used for nested messages 899 | */ 900 | proto.proto.Empty.toObject = function(includeInstance, msg) { 901 | var f, obj = { 902 | 903 | }; 904 | 905 | if (includeInstance) { 906 | obj.$jspbMessageInstance = msg; 907 | } 908 | return obj; 909 | }; 910 | } 911 | 912 | 913 | /** 914 | * Deserializes binary data (in protobuf wire format). 915 | * @param {jspb.ByteSource} bytes The bytes to deserialize. 916 | * @return {!proto.proto.Empty} 917 | */ 918 | proto.proto.Empty.deserializeBinary = function(bytes) { 919 | var reader = new jspb.BinaryReader(bytes); 920 | var msg = new proto.proto.Empty; 921 | return proto.proto.Empty.deserializeBinaryFromReader(msg, reader); 922 | }; 923 | 924 | 925 | /** 926 | * Deserializes binary data (in protobuf wire format) from the 927 | * given reader into the given message object. 928 | * @param {!proto.proto.Empty} msg The message object to deserialize into. 929 | * @param {!jspb.BinaryReader} reader The BinaryReader to use. 930 | * @return {!proto.proto.Empty} 931 | */ 932 | proto.proto.Empty.deserializeBinaryFromReader = function(msg, reader) { 933 | while (reader.nextField()) { 934 | if (reader.isEndGroup()) { 935 | break; 936 | } 937 | var field = reader.getFieldNumber(); 938 | switch (field) { 939 | default: 940 | reader.skipField(); 941 | break; 942 | } 943 | } 944 | return msg; 945 | }; 946 | 947 | 948 | /** 949 | * Serializes the message to binary data (in protobuf wire format). 950 | * @return {!Uint8Array} 951 | */ 952 | proto.proto.Empty.prototype.serializeBinary = function() { 953 | var writer = new jspb.BinaryWriter(); 954 | proto.proto.Empty.serializeBinaryToWriter(this, writer); 955 | return writer.getResultBuffer(); 956 | }; 957 | 958 | 959 | /** 960 | * Serializes the given message to binary data (in protobuf wire 961 | * format), writing to the given BinaryWriter. 962 | * @param {!proto.proto.Empty} message 963 | * @param {!jspb.BinaryWriter} writer 964 | * @suppress {unusedLocalVariables} f is only used for nested messages 965 | */ 966 | proto.proto.Empty.serializeBinaryToWriter = function(message, writer) { 967 | var f = undefined; 968 | }; 969 | 970 | 971 | goog.object.extend(exports, proto.proto); 972 | --------------------------------------------------------------------------------