mirror of
https://github.com/fatedier/frp.git
synced 2024-11-08 17:14:27 +01:00
commit
51114f2afd
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,3 @@ bin/
|
||||
|
||||
# Cache
|
||||
*.swp
|
||||
*.swo
|
||||
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM golang:1.5
|
||||
|
||||
MAINTAINER fatedier
|
||||
|
||||
RUN echo "[common]\nbind_addr = 0.0.0.0\nbind_port = 7000\n[wiki]\npasswd = 123\nbind_addr = 0.0.0.0\nlisten_port = 80" > /usr/share/frps.ini
|
||||
|
||||
ADD ./ /usr/share/frp/
|
||||
|
||||
RUN cd /usr/share/frp && make
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 7000
|
||||
|
||||
CMD ["/usr/share/frp/bin/frps -c /usr/share/frps.ini"]
|
5
Godeps/Godeps.json
generated
5
Godeps/Godeps.json
generated
@ -10,6 +10,11 @@
|
||||
"Comment": "v1.5.0-9-gfb7314f",
|
||||
"Rev": "fb7314f8ac86b83ccd34386518d97cf2363e2ae5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docopt/docopt-go",
|
||||
"Comment": "0.6.2",
|
||||
"Rev": "784ddc588536785e7299f7272f39101f7faccc3f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vaughan0/go-ini",
|
||||
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
|
||||
|
25
Godeps/_workspace/src/github.com/docopt/docopt-go/.gitignore
generated
vendored
Normal file
25
Godeps/_workspace/src/github.com/docopt/docopt-go/.gitignore
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
# coverage droppings
|
||||
profile.cov
|
31
Godeps/_workspace/src/github.com/docopt/docopt-go/.travis.yml
generated
vendored
Normal file
31
Godeps/_workspace/src/github.com/docopt/docopt-go/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
# Travis CI (http://travis-ci.org/) is a continuous integration
|
||||
# service for open source projects. This file configures it
|
||||
# to run unit tests for docopt-go.
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/golang/lint/golint
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
install:
|
||||
- go get -d -v ./... && go build -v ./...
|
||||
|
||||
script:
|
||||
- go vet -x ./...
|
||||
- $HOME/gopath/bin/golint ./...
|
||||
- go test -v ./...
|
||||
- go test -covermode=count -coverprofile=profile.cov .
|
||||
|
||||
after_script:
|
||||
- $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci
|
20
Godeps/_workspace/src/github.com/docopt/docopt-go/LICENSE
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/docopt/docopt-go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Keith Batten
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
88
Godeps/_workspace/src/github.com/docopt/docopt-go/README.md
generated
vendored
Normal file
88
Godeps/_workspace/src/github.com/docopt/docopt-go/README.md
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
docopt-go
|
||||
=========
|
||||
|
||||
[![Build Status](https://travis-ci.org/docopt/docopt.go.svg?branch=master)](https://travis-ci.org/docopt/docopt.go)
|
||||
[![Coverage Status](https://coveralls.io/repos/docopt/docopt.go/badge.png)](https://coveralls.io/r/docopt/docopt.go)
|
||||
[![GoDoc](https://godoc.org/github.com/docopt/docopt.go?status.png)](https://godoc.org/github.com/docopt/docopt.go)
|
||||
|
||||
An implementation of [docopt](http://docopt.org/) in the
|
||||
[Go](http://golang.org/) programming language.
|
||||
|
||||
**docopt** helps you create *beautiful* command-line interfaces easily:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docopt/docopt-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
usage := `Naval Fate.
|
||||
|
||||
Usage:
|
||||
naval_fate ship new <name>...
|
||||
naval_fate ship <name> move <x> <y> [--speed=<kn>]
|
||||
naval_fate ship shoot <x> <y>
|
||||
naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
|
||||
naval_fate -h | --help
|
||||
naval_fate --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
--speed=<kn> Speed in knots [default: 10].
|
||||
--moored Moored (anchored) mine.
|
||||
--drifting Drifting mine.`
|
||||
|
||||
arguments, _ := docopt.Parse(usage, nil, true, "Naval Fate 2.0", false)
|
||||
fmt.Println(arguments)
|
||||
}
|
||||
```
|
||||
|
||||
**docopt** parses command-line arguments based on a help message. Don't
|
||||
write parser code: a good help message already has all the necessary
|
||||
information in it.
|
||||
|
||||
## Installation
|
||||
|
||||
⚠ Use the alias “docopt-go”. To use docopt in your Go code:
|
||||
|
||||
```go
|
||||
import "github.com/docopt/docopt-go"
|
||||
```
|
||||
|
||||
To install docopt according to your `$GOPATH`:
|
||||
|
||||
```console
|
||||
$ go get github.com/docopt/docopt-go
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```go
|
||||
func Parse(doc string, argv []string, help bool, version string,
|
||||
optionsFirst bool, exit ...bool) (map[string]interface{}, error)
|
||||
```
|
||||
Parse `argv` based on the command-line interface described in `doc`.
|
||||
|
||||
Given a conventional command-line help message, docopt creates a parser and
|
||||
processes the arguments. See
|
||||
https://github.com/docopt/docopt#help-message-format for a description of the
|
||||
help message format. If `argv` is `nil`, `os.Args[1:]` is used.
|
||||
|
||||
docopt returns a map of option names to the values parsed from `argv`, and an
|
||||
error or `nil`.
|
||||
|
||||
More documentation for docopt is available at
|
||||
[GoDoc.org](https://godoc.org/github.com/docopt/docopt.go).
|
||||
|
||||
## Testing
|
||||
|
||||
All tests from the Python version are implemented and passing
|
||||
at [Travis CI](https://travis-ci.org/docopt/docopt.go). New
|
||||
language-agnostic tests have been added
|
||||
to [test_golang.docopt](test_golang.docopt).
|
||||
|
||||
To run tests for docopt-go, use `go test`.
|
1239
Godeps/_workspace/src/github.com/docopt/docopt-go/docopt.go
generated
vendored
Normal file
1239
Godeps/_workspace/src/github.com/docopt/docopt-go/docopt.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
Godeps/_workspace/src/github.com/docopt/docopt-go/test_golang.docopt
generated
vendored
Normal file
9
Godeps/_workspace/src/github.com/docopt/docopt-go/test_golang.docopt
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
r"""usage: prog [NAME_-2]..."""
|
||||
$ prog 10 20
|
||||
{"NAME_-2": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME_-2": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME_-2": []}
|
957
Godeps/_workspace/src/github.com/docopt/docopt-go/testcases.docopt
generated
vendored
Normal file
957
Godeps/_workspace/src/github.com/docopt/docopt-go/testcases.docopt
generated
vendored
Normal file
@ -0,0 +1,957 @@
|
||||
r"""Usage: prog
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{}
|
||||
|
||||
$ prog --xxx
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -a All.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-a": false}
|
||||
|
||||
$ prog -a
|
||||
{"-a": true}
|
||||
|
||||
$ prog -x
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --all All.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--all": false}
|
||||
|
||||
$ prog --all
|
||||
{"--all": true}
|
||||
|
||||
$ prog --xxx
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -v, --verbose Verbose.
|
||||
|
||||
"""
|
||||
$ prog --verbose
|
||||
{"--verbose": true}
|
||||
|
||||
$ prog --ver
|
||||
{"--verbose": true}
|
||||
|
||||
$ prog -v
|
||||
{"--verbose": true}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p PATH
|
||||
|
||||
"""
|
||||
$ prog -p home/
|
||||
{"-p": "home/"}
|
||||
|
||||
$ prog -phome/
|
||||
{"-p": "home/"}
|
||||
|
||||
$ prog -p
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --path <path>
|
||||
|
||||
"""
|
||||
$ prog --path home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --path=home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --pa home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --pa=home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --path
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p PATH, --path=<path> Path to files.
|
||||
|
||||
"""
|
||||
$ prog -proot
|
||||
{"--path": "root"}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p --path PATH Path to files.
|
||||
|
||||
"""
|
||||
$ prog -p root
|
||||
{"--path": "root"}
|
||||
|
||||
$ prog --path root
|
||||
{"--path": "root"}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options:
|
||||
-p PATH Path to files [default: ./]
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-p": "./"}
|
||||
|
||||
$ prog -phome
|
||||
{"-p": "home"}
|
||||
|
||||
|
||||
r"""UsAgE: prog [options]
|
||||
|
||||
OpTiOnS: --path=<files> Path to files
|
||||
[dEfAuLt: /root]
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--path": "/root"}
|
||||
|
||||
$ prog --path=home
|
||||
{"--path": "home"}
|
||||
|
||||
|
||||
r"""usage: prog [options]
|
||||
|
||||
options:
|
||||
-a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a -r -m Hello
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "Hello"}
|
||||
|
||||
$ prog -armyourass
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "yourass"}
|
||||
|
||||
$ prog -a -r
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": null}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --version
|
||||
--verbose
|
||||
|
||||
"""
|
||||
$ prog --version
|
||||
{"--version": true,
|
||||
"--verbose": false}
|
||||
|
||||
$ prog --verbose
|
||||
{"--version": false,
|
||||
"--verbose": true}
|
||||
|
||||
$ prog --ver
|
||||
"user-error"
|
||||
|
||||
$ prog --verb
|
||||
{"--version": false,
|
||||
"--verbose": true}
|
||||
|
||||
|
||||
r"""usage: prog [-a -r -m <msg>]
|
||||
|
||||
options:
|
||||
-a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -armyourass
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "yourass"}
|
||||
|
||||
|
||||
r"""usage: prog [-armmsg]
|
||||
|
||||
options: -a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a -r -m Hello
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "Hello"}
|
||||
|
||||
|
||||
r"""usage: prog -a -b
|
||||
|
||||
options:
|
||||
-a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog (-a -b)
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [-a] -b
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [(-a -b)]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"-a": false, "-b": false}
|
||||
|
||||
|
||||
r"""usage: prog (-a|-b)
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
|
||||
r"""usage: prog [ -a | -b ]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"-a": false, "-b": false}
|
||||
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
|
||||
r"""usage: prog <arg>"""
|
||||
$ prog 10
|
||||
{"<arg>": "10"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<arg>]"""
|
||||
$ prog 10
|
||||
{"<arg>": "10"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"<arg>": null}
|
||||
|
||||
|
||||
r"""usage: prog <kind> <name> <type>"""
|
||||
$ prog 10 20 40
|
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog <kind> [<name> <type>]"""
|
||||
$ prog 10 20 40
|
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog 10 20
|
||||
{"<kind>": "10", "<name>": "20", "<type>": null}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<kind> | <name> <type>]"""
|
||||
$ prog 10 20 40
|
||||
"user-error"
|
||||
|
||||
$ prog 20 40
|
||||
{"<kind>": null, "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog
|
||||
{"<kind>": null, "<name>": null, "<type>": null}
|
||||
|
||||
|
||||
r"""usage: prog (<kind> --all | <name>)
|
||||
|
||||
options:
|
||||
--all
|
||||
|
||||
"""
|
||||
$ prog 10 --all
|
||||
{"<kind>": "10", "--all": true, "<name>": null}
|
||||
|
||||
$ prog 10
|
||||
{"<kind>": null, "--all": false, "<name>": "10"}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<name> <name>]"""
|
||||
$ prog 10 20
|
||||
{"<name>": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"<name>": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"<name>": []}
|
||||
|
||||
|
||||
r"""usage: prog [(<name> <name>)]"""
|
||||
$ prog 10 20
|
||||
{"<name>": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"<name>": []}
|
||||
|
||||
|
||||
r"""usage: prog NAME..."""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [NAME]..."""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog [NAME...]"""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog [NAME [NAME ...]]"""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo NAME)
|
||||
|
||||
options: --foo
|
||||
|
||||
"""
|
||||
$ prog 10
|
||||
{"NAME": "10", "--foo": false}
|
||||
|
||||
$ prog --foo 10
|
||||
{"NAME": "10", "--foo": true}
|
||||
|
||||
$ prog --foo=10
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo) [--bar | NAME]
|
||||
|
||||
options: --foo
|
||||
options: --bar
|
||||
|
||||
"""
|
||||
$ prog 10
|
||||
{"NAME": ["10"], "--foo": false, "--bar": false}
|
||||
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"], "--foo": false, "--bar": false}
|
||||
|
||||
$ prog --foo --bar
|
||||
{"NAME": [], "--foo": true, "--bar": true}
|
||||
|
||||
|
||||
r"""Naval Fate.
|
||||
|
||||
Usage:
|
||||
prog ship new <name>...
|
||||
prog ship [<name>] move <x> <y> [--speed=<kn>]
|
||||
prog ship shoot <x> <y>
|
||||
prog mine (set|remove) <x> <y> [--moored|--drifting]
|
||||
prog -h | --help
|
||||
prog --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
--speed=<kn> Speed in knots [default: 10].
|
||||
--moored Mored (anchored) mine.
|
||||
--drifting Drifting mine.
|
||||
|
||||
"""
|
||||
$ prog ship Guardian move 150 300 --speed=20
|
||||
{"--drifting": false,
|
||||
"--help": false,
|
||||
"--moored": false,
|
||||
"--speed": "20",
|
||||
"--version": false,
|
||||
"<name>": ["Guardian"],
|
||||
"<x>": "150",
|
||||
"<y>": "300",
|
||||
"mine": false,
|
||||
"move": true,
|
||||
"new": false,
|
||||
"remove": false,
|
||||
"set": false,
|
||||
"ship": true,
|
||||
"shoot": false}
|
||||
|
||||
|
||||
r"""usage: prog --hello"""
|
||||
$ prog --hello
|
||||
{"--hello": true}
|
||||
|
||||
|
||||
r"""usage: prog [--hello=<world>]"""
|
||||
$ prog
|
||||
{"--hello": null}
|
||||
|
||||
$ prog --hello wrld
|
||||
{"--hello": "wrld"}
|
||||
|
||||
|
||||
r"""usage: prog [-o]"""
|
||||
$ prog
|
||||
{"-o": false}
|
||||
|
||||
$ prog -o
|
||||
{"-o": true}
|
||||
|
||||
|
||||
r"""usage: prog [-opr]"""
|
||||
$ prog -op
|
||||
{"-o": true, "-p": true, "-r": false}
|
||||
|
||||
|
||||
r"""usage: prog --aabb | --aa"""
|
||||
$ prog --aa
|
||||
{"--aabb": false, "--aa": true}
|
||||
|
||||
$ prog --a
|
||||
"user-error" # not a unique prefix
|
||||
|
||||
#
|
||||
# Counting number of flags
|
||||
#
|
||||
|
||||
r"""Usage: prog -v"""
|
||||
$ prog -v
|
||||
{"-v": true}
|
||||
|
||||
|
||||
r"""Usage: prog [-v -v]"""
|
||||
$ prog
|
||||
{"-v": 0}
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
|
||||
r"""Usage: prog -v ..."""
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
$ prog -vvvvvv
|
||||
{"-v": 6}
|
||||
|
||||
|
||||
r"""Usage: prog [-v | -vv | -vvv]
|
||||
|
||||
This one is probably most readable user-friednly variant.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-v": 0}
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
$ prog -vvvv
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [--ver --ver]"""
|
||||
$ prog --ver --ver
|
||||
{"--ver": 2}
|
||||
|
||||
|
||||
#
|
||||
# Counting commands
|
||||
#
|
||||
|
||||
r"""usage: prog [go]"""
|
||||
$ prog go
|
||||
{"go": true}
|
||||
|
||||
|
||||
r"""usage: prog [go go]"""
|
||||
$ prog
|
||||
{"go": 0}
|
||||
|
||||
$ prog go
|
||||
{"go": 1}
|
||||
|
||||
$ prog go go
|
||||
{"go": 2}
|
||||
|
||||
$ prog go go go
|
||||
"user-error"
|
||||
|
||||
r"""usage: prog go..."""
|
||||
$ prog go go go go go
|
||||
{"go": 5}
|
||||
|
||||
#
|
||||
# [options] does not include options from usage-pattern
|
||||
#
|
||||
r"""usage: prog [options] [-a]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
"""
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -aa
|
||||
"user-error"
|
||||
|
||||
#
|
||||
# Test [options] shourtcut
|
||||
#
|
||||
|
||||
r"""Usage: prog [options] A
|
||||
Options:
|
||||
-q Be quiet
|
||||
-v Be verbose.
|
||||
|
||||
"""
|
||||
$ prog arg
|
||||
{"A": "arg", "-v": false, "-q": false}
|
||||
|
||||
$ prog -v arg
|
||||
{"A": "arg", "-v": true, "-q": false}
|
||||
|
||||
$ prog -q arg
|
||||
{"A": "arg", "-v": false, "-q": true}
|
||||
|
||||
#
|
||||
# Test single dash
|
||||
#
|
||||
|
||||
r"""usage: prog [-]"""
|
||||
|
||||
$ prog -
|
||||
{"-": true}
|
||||
|
||||
$ prog
|
||||
{"-": false}
|
||||
|
||||
#
|
||||
# If argument is repeated, its value should always be a list
|
||||
#
|
||||
|
||||
r"""usage: prog [NAME [NAME ...]]"""
|
||||
|
||||
$ prog a b
|
||||
{"NAME": ["a", "b"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
#
|
||||
# Option's argument defaults to null/None
|
||||
#
|
||||
|
||||
r"""usage: prog [options]
|
||||
options:
|
||||
-a Add
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a
|
||||
{"-m": null, "-a": true}
|
||||
|
||||
#
|
||||
# Test options without description
|
||||
#
|
||||
|
||||
r"""usage: prog --hello"""
|
||||
$ prog --hello
|
||||
{"--hello": true}
|
||||
|
||||
r"""usage: prog [--hello=<world>]"""
|
||||
$ prog
|
||||
{"--hello": null}
|
||||
|
||||
$ prog --hello wrld
|
||||
{"--hello": "wrld"}
|
||||
|
||||
r"""usage: prog [-o]"""
|
||||
$ prog
|
||||
{"-o": false}
|
||||
|
||||
$ prog -o
|
||||
{"-o": true}
|
||||
|
||||
r"""usage: prog [-opr]"""
|
||||
$ prog -op
|
||||
{"-o": true, "-p": true, "-r": false}
|
||||
|
||||
r"""usage: git [-v | --verbose]"""
|
||||
$ prog -v
|
||||
{"-v": true, "--verbose": false}
|
||||
|
||||
r"""usage: git remote [-v | --verbose]"""
|
||||
$ prog remote -v
|
||||
{"remote": true, "-v": true, "--verbose": false}
|
||||
|
||||
#
|
||||
# Test empty usage pattern
|
||||
#
|
||||
|
||||
r"""usage: prog"""
|
||||
$ prog
|
||||
{}
|
||||
|
||||
r"""usage: prog
|
||||
prog <a> <b>
|
||||
"""
|
||||
$ prog 1 2
|
||||
{"<a>": "1", "<b>": "2"}
|
||||
|
||||
$ prog
|
||||
{"<a>": null, "<b>": null}
|
||||
|
||||
r"""usage: prog <a> <b>
|
||||
prog
|
||||
"""
|
||||
$ prog
|
||||
{"<a>": null, "<b>": null}
|
||||
|
||||
#
|
||||
# Option's argument should not capture default value from usage pattern
|
||||
#
|
||||
|
||||
r"""usage: prog [--file=<f>]"""
|
||||
$ prog
|
||||
{"--file": null}
|
||||
|
||||
r"""usage: prog [--file=<f>]
|
||||
|
||||
options: --file <a>
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--file": null}
|
||||
|
||||
r"""Usage: prog [-a <host:port>]
|
||||
|
||||
Options: -a, --address <host:port> TCP address [default: localhost:6283].
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--address": "localhost:6283"}
|
||||
|
||||
#
|
||||
# If option with argument could be repeated,
|
||||
# its arguments should be accumulated into a list
|
||||
#
|
||||
|
||||
r"""usage: prog --long=<arg> ..."""
|
||||
|
||||
$ prog --long one
|
||||
{"--long": ["one"]}
|
||||
|
||||
$ prog --long one --long two
|
||||
{"--long": ["one", "two"]}
|
||||
|
||||
#
|
||||
# Test multiple elements repeated at once
|
||||
#
|
||||
|
||||
r"""usage: prog (go <direction> --speed=<km/h>)..."""
|
||||
$ prog go left --speed=5 go right --speed=9
|
||||
{"go": 2, "<direction>": ["left", "right"], "--speed": ["5", "9"]}
|
||||
|
||||
#
|
||||
# Required options should work with option shortcut
|
||||
#
|
||||
|
||||
r"""usage: prog [options] -a
|
||||
|
||||
options: -a
|
||||
|
||||
"""
|
||||
$ prog -a
|
||||
{"-a": true}
|
||||
|
||||
#
|
||||
# If option could be repeated its defaults should be split into a list
|
||||
#
|
||||
|
||||
r"""usage: prog [-o <o>]...
|
||||
|
||||
options: -o <o> [default: x]
|
||||
|
||||
"""
|
||||
$ prog -o this -o that
|
||||
{"-o": ["this", "that"]}
|
||||
|
||||
$ prog
|
||||
{"-o": ["x"]}
|
||||
|
||||
r"""usage: prog [-o <o>]...
|
||||
|
||||
options: -o <o> [default: x y]
|
||||
|
||||
"""
|
||||
$ prog -o this
|
||||
{"-o": ["this"]}
|
||||
|
||||
$ prog
|
||||
{"-o": ["x", "y"]}
|
||||
|
||||
#
|
||||
# Test stacked option's argument
|
||||
#
|
||||
|
||||
r"""usage: prog -pPATH
|
||||
|
||||
options: -p PATH
|
||||
|
||||
"""
|
||||
$ prog -pHOME
|
||||
{"-p": "HOME"}
|
||||
|
||||
#
|
||||
# Issue 56: Repeated mutually exclusive args give nested lists sometimes
|
||||
#
|
||||
|
||||
r"""Usage: foo (--xx=x|--yy=y)..."""
|
||||
$ prog --xx=1 --yy=2
|
||||
{"--xx": ["1"], "--yy": ["2"]}
|
||||
|
||||
#
|
||||
# POSIXly correct tokenization
|
||||
#
|
||||
|
||||
r"""usage: prog [<input file>]"""
|
||||
$ prog f.txt
|
||||
{"<input file>": "f.txt"}
|
||||
|
||||
r"""usage: prog [--input=<file name>]..."""
|
||||
$ prog --input a.txt --input=b.txt
|
||||
{"--input": ["a.txt", "b.txt"]}
|
||||
|
||||
#
|
||||
# Issue 85: `[options]` shourtcut with multiple subcommands
|
||||
#
|
||||
|
||||
r"""usage: prog good [options]
|
||||
prog fail [options]
|
||||
|
||||
options: --loglevel=N
|
||||
|
||||
"""
|
||||
$ prog fail --loglevel 5
|
||||
{"--loglevel": "5", "fail": true, "good": false}
|
||||
|
||||
#
|
||||
# Usage-section syntax
|
||||
#
|
||||
|
||||
r"""usage:prog --foo"""
|
||||
$ prog --foo
|
||||
{"--foo": true}
|
||||
|
||||
r"""PROGRAM USAGE: prog --foo"""
|
||||
$ prog --foo
|
||||
{"--foo": true}
|
||||
|
||||
r"""Usage: prog --foo
|
||||
prog --bar
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
r"""Usage:
|
||||
prog --foo
|
||||
prog --bar
|
||||
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
r"""Usage:
|
||||
prog --foo
|
||||
prog --bar
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
#
|
||||
# Options-section syntax
|
||||
#
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
global options: --foo
|
||||
local options: --baz
|
||||
--bar
|
||||
other options:
|
||||
--egg
|
||||
--spam
|
||||
-not-an-option-
|
||||
|
||||
"""
|
||||
$ prog --baz --egg
|
||||
{"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false}
|
5
Makefile
5
Makefile
@ -7,10 +7,9 @@ build: godep fmt frps frpc
|
||||
|
||||
godep:
|
||||
@go get github.com/tools/godep
|
||||
godep restore
|
||||
|
||||
fmt:
|
||||
@GOPATH=$(NEW_GOPATH) godep go fmt ./...
|
||||
GOPATH=$(NEW_GOPATH) godep go fmt ./...
|
||||
|
||||
frps:
|
||||
GOPATH=$(NEW_GOPATH) godep go build -o bin/frps ./src/frp/cmd/frps
|
||||
@ -19,4 +18,4 @@ frpc:
|
||||
GOPATH=$(NEW_GOPATH) godep go build -o bin/frpc ./src/frp/cmd/frpc
|
||||
|
||||
test:
|
||||
@GOPATH=$(NEW_GOPATH) godep go test ./...
|
||||
@GOPATH=$(NEW_GOPATH) godep go test -v ./...
|
||||
|
30
README.md
30
README.md
@ -2,4 +2,32 @@
|
||||
|
||||
[![Build Status](https://travis-ci.org/fatedier/frp.svg)](https://travis-ci.org/fatedier/frp)
|
||||
|
||||
A fast reverse proxy.
|
||||
## What is frp?
|
||||
|
||||
frp is a fast reverse proxy which can help you expose a local server behind a NAT or firewall to the internet.
|
||||
|
||||
## Status
|
||||
|
||||
frp is under development and you can try it with available version 0.1.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Read the [QuickStart](doc/quick_start_en.md) | [使用文档](doc/quick_start_zh.md)
|
||||
|
||||
## Architecture
|
||||
|
||||
![architecture](doc/pic/architecture.png)
|
||||
|
||||
## What can I do with frp?
|
||||
|
||||
* Expose any http service behind a NAT or firewall to the internet by a server with public IP address.
|
||||
* Expose any tcp service behind a NAT or firewall to the internet by a server with public IP address.
|
||||
* Inspect all http requests/responses that are transmitted over the tunnel(future).
|
||||
|
||||
## Contributing
|
||||
|
||||
Interested in getting involved? We would love to help you!
|
||||
|
||||
For simple bug fixes, just submit a PR with the fix and we can discuss the fix directly in the PR. If the fix is more complex, start with an issue.
|
||||
|
||||
If you have some wanderful ideas, send email to fatedier@gmail.com.
|
||||
|
@ -1,14 +1,14 @@
|
||||
# common是必须的section
|
||||
# [common] is integral section
|
||||
[common]
|
||||
server_addr = 127.0.0.1
|
||||
server_addr = 0.0.0.0
|
||||
server_port = 7000
|
||||
log_file = ./frpc.log
|
||||
# console or real logFile path like ./frpc.log
|
||||
log_file = console
|
||||
# debug, info, warn, error
|
||||
log_level = debug
|
||||
# file, console
|
||||
log_way = console
|
||||
|
||||
# test1即为name
|
||||
# test1 is the proxy name same as server's configuration
|
||||
[test1]
|
||||
passwd = 123
|
||||
local_ip = 127.0.0.1
|
||||
local_port = 22
|
||||
|
@ -1,14 +1,13 @@
|
||||
# common是必须的section
|
||||
# [common] is integral section
|
||||
[common]
|
||||
bind_addr = 0.0.0.0
|
||||
bind_port = 7000
|
||||
log_file = ./frps.log
|
||||
# console or real logFile path like ./frps.log
|
||||
log_file = console
|
||||
# debug, info, warn, error
|
||||
log_level = debug
|
||||
# file, console
|
||||
log_way = console
|
||||
|
||||
# test1即为name
|
||||
# test1 is the proxy name, client will use this name and passwd to connect to server
|
||||
[test1]
|
||||
passwd = 123
|
||||
bind_addr = 0.0.0.0
|
||||
|
BIN
doc/pic/architecture.png
Normal file
BIN
doc/pic/architecture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
68
doc/quick_start_en.md
Normal file
68
doc/quick_start_en.md
Normal file
@ -0,0 +1,68 @@
|
||||
# Quick Start
|
||||
|
||||
frp is easier to use compared with other similar projects.
|
||||
|
||||
We will use a simple demo to demonstrate how to create a connection to server A's ssh port by server B with public IP address x.x.x.x(replace to the real IP address of your server).
|
||||
|
||||
### Download SourceCode
|
||||
|
||||
`go get github.com/fatedier/frp` is recommended, then the code will be copied to the directory `$GOPATH/src/github.com/fatedier/frp`.
|
||||
|
||||
Or you can use `git clone https://github.com/fatedier/frp.git $GOPATH/src/github.com/fatedier/frp`.
|
||||
|
||||
### Compile
|
||||
|
||||
Enter the root directory and execute `make`, then wait until finished.
|
||||
|
||||
**bin** include all executable programs when **conf** include corresponding configuration files.
|
||||
|
||||
### Pre-requirement
|
||||
|
||||
* Go environment. Version of go >= 1.4.
|
||||
* Godep (if not exist, go get will be executed to download godep when compiling)
|
||||
|
||||
### Deploy
|
||||
|
||||
1. Move `./bin/frps` and `./conf/frps.ini` to any directory of server B.
|
||||
2. Move `./bin/frpc` and `./conf/frpc.ini` to any directory of server A.
|
||||
3. Modify all configuration files, details in next paragraph.
|
||||
4. Execute `nohup ./frps &` or `nohup ./frps -c ./frps.ini &` in server B.
|
||||
5. Execute `nohup ./frpc &` or `nohup ./frpc -c ./frpc.ini &` in server A.
|
||||
6. Use `ssh -oPort=6000 {user}@x.x.x.x` to test if frp is work(replace {user} to real username in server A).
|
||||
|
||||
### Configuration files
|
||||
|
||||
#### frps.ini
|
||||
|
||||
```ini
|
||||
[common]
|
||||
bind_addr = 0.0.0.0
|
||||
# for accept connections from frpc
|
||||
bind_port = 7000
|
||||
log_file = ./frps.log
|
||||
log_level = info
|
||||
|
||||
# test is the custom name of proxy and there can be many proxies with unique name in one configure file
|
||||
[test]
|
||||
passwd = 123
|
||||
bind_addr = 0.0.0.0
|
||||
# finally we connect to server A by this port
|
||||
listen_port = 6000
|
||||
```
|
||||
|
||||
#### frpc.ini
|
||||
|
||||
```ini
|
||||
[common]
|
||||
# server address of frps
|
||||
server_addr = x.x.x.x
|
||||
server_port = 7000
|
||||
log_file = ./frpc.log
|
||||
log_level = info
|
||||
|
||||
# test is proxy name same with configure in frps.ini
|
||||
[test]
|
||||
passwd = 123
|
||||
# local port which need to be transferred
|
||||
local_port = 22
|
||||
```
|
66
doc/quick_start_zh.md
Normal file
66
doc/quick_start_zh.md
Normal file
@ -0,0 +1,66 @@
|
||||
# frp 使用文档
|
||||
|
||||
frp 相比于其他项目而言非常易于部署和使用,这里我们用一个简单的示例演示如何通过一台拥有公网IP地址的服务器B,访问处于内网环境中的服务器A的ssh端口,服务器B的IP地址为 x.x.x.x(测试时替换为真实的IP地址)。
|
||||
|
||||
### 下载源码
|
||||
|
||||
推荐直接使用 `go get github.com/fatedier/frp` 下载源代码安装,执行命令后代码将会拷贝到 `$GOPATH/src/github.com/fatedier/frp` 目录下。
|
||||
|
||||
或者可以使用 `git clone https://github.com/fatedier/frp.git $GOPATH/src/github.com/fatedier/frp` 拷贝到相应目录下。
|
||||
|
||||
### 编译
|
||||
|
||||
进入下载后的源码根目录,执行 `make` 命令,等待编译完成。
|
||||
|
||||
编译完成后, **bin** 目录下是编译好的可执行文件,**conf** 目录下是示例配置文件。
|
||||
|
||||
### 依赖
|
||||
|
||||
* go 1.4 以上版本
|
||||
* godep (如果检查不存在,编译时会通过 go get 命令安装)
|
||||
|
||||
### 部署
|
||||
|
||||
1. 将 ./bin/frps 和 ./conf/frps.ini 拷贝至服务器B任意目录。
|
||||
2. 将 ./bin/frpc 和 ./conf/frpc.ini 拷贝至服务器A任意目录。
|
||||
3. 修改两边的配置文件,见下一节说明。
|
||||
4. 在服务器B执行 `nohup ./frps &` 或者 `nohup ./frps -c ./frps.ini &`。
|
||||
5. 在服务器A执行 `nohup ./frpc &` 或者 `nohup ./frpc -c ./frpc.ini &`。
|
||||
6. 通过 `ssh -oPort=6000 {user}@x.x.x.x` 测试是否能够成功连接服务器A({user}替换为服务器A上存在的真实用户)。
|
||||
|
||||
### 配置文件
|
||||
|
||||
#### frps.ini
|
||||
|
||||
```ini
|
||||
[common]
|
||||
bind_addr = 0.0.0.0
|
||||
# 用于接收 frpc 连接的端口
|
||||
bind_port = 7000
|
||||
log_file = ./frps.log
|
||||
log_level = info
|
||||
|
||||
# test 为代理的自定义名称,可以有多个,不能重复,和frpc中名称对应
|
||||
[test]
|
||||
passwd = 123
|
||||
bind_addr = 0.0.0.0
|
||||
# 最后将通过此端口访问后端服务
|
||||
listen_port = 6000
|
||||
```
|
||||
|
||||
#### frpc.ini
|
||||
|
||||
```ini
|
||||
[common]
|
||||
# frps 所在服务器绑定的IP地址
|
||||
server_addr = x.x.x.x
|
||||
server_port = 7000
|
||||
log_file = ./frpc.log
|
||||
log_level = info
|
||||
|
||||
# test需要和 frps.ini 中配置一致
|
||||
[test]
|
||||
passwd = 123
|
||||
# 需要转发的本地端口
|
||||
local_port = 22
|
||||
```
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -142,6 +156,7 @@ func startHeartBeat(c *conn.Conn) {
|
||||
for {
|
||||
time.Sleep(time.Duration(client.HeartBeatInterval) * time.Second)
|
||||
if c != nil && !c.IsClosed() {
|
||||
log.Debug("Send heartbeat to server")
|
||||
err = c.Write(string(request) + "\n")
|
||||
if err != nil {
|
||||
log.Error("Send hearbeat to server failed! Err:%v", err)
|
||||
@ -151,5 +166,5 @@ func startHeartBeat(c *conn.Conn) {
|
||||
break
|
||||
}
|
||||
}
|
||||
log.Debug("Heartbeat exit")
|
||||
log.Debug("Heartbeat goroutine exit")
|
||||
}
|
||||
|
@ -1,19 +1,93 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
docopt "github.com/docopt/docopt-go"
|
||||
|
||||
"frp/models/client"
|
||||
"frp/utils/log"
|
||||
"frp/utils/version"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile string = "./frpc.ini"
|
||||
)
|
||||
|
||||
var usage string = `frpc is the client of frp
|
||||
|
||||
Usage:
|
||||
frpc [-c config_file] [-L log_file] [--log-level=<log_level>] [--server-addr=<server_addr>]
|
||||
frpc -h | --help | --version
|
||||
|
||||
Options:
|
||||
-c config_file set config file
|
||||
-L log_file set output log file, including console
|
||||
--log-level=<log_level> set log level: debug, info, warn, error
|
||||
--server-addr=<server_addr> addr which frps is listening for, example: 0.0.0.0:7000
|
||||
-h --help show this screen
|
||||
--version show version
|
||||
`
|
||||
|
||||
func main() {
|
||||
err := client.LoadConf("./frpc.ini")
|
||||
// the configures parsed from file will be replaced by those from command line if exist
|
||||
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
|
||||
|
||||
if args["-c"] != nil {
|
||||
configFile = args["-c"].(string)
|
||||
}
|
||||
err = client.LoadConf(configFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
if args["-L"] != nil {
|
||||
if args["-L"].(string) == "console" {
|
||||
client.LogWay = "console"
|
||||
} else {
|
||||
client.LogWay = "file"
|
||||
client.LogFile = args["-L"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
if args["--log-level"] != nil {
|
||||
client.LogLevel = args["--log-level"].(string)
|
||||
}
|
||||
|
||||
if args["--server-addr"] != nil {
|
||||
addr := strings.Split(args["--server-addr"].(string), ":")
|
||||
if len(addr) != 2 {
|
||||
fmt.Println("--server-addr format error: example 0.0.0.0:7000")
|
||||
os.Exit(1)
|
||||
}
|
||||
serverPort, err := strconv.ParseInt(addr[1], 10, 64)
|
||||
if err != nil {
|
||||
fmt.Println("--server-addr format error, example 0.0.0.0:7000")
|
||||
os.Exit(1)
|
||||
}
|
||||
client.ServerAddr = addr[0]
|
||||
client.ServerPort = serverPort
|
||||
}
|
||||
|
||||
log.InitLog(client.LogWay, client.LogFile, client.LogLevel)
|
||||
|
||||
// wait until all control goroutine exit
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -1,19 +1,93 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
docopt "github.com/docopt/docopt-go"
|
||||
|
||||
"frp/models/server"
|
||||
"frp/utils/conn"
|
||||
"frp/utils/log"
|
||||
"frp/utils/version"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile string = "./frps.ini"
|
||||
)
|
||||
|
||||
var usage string = `frps is the server of frp
|
||||
|
||||
Usage:
|
||||
frps [-c config_file] [-L log_file] [--log-level=<log_level>] [--addr=<bind_addr>]
|
||||
frps -h | --help | --version
|
||||
|
||||
Options:
|
||||
-c config_file set config file
|
||||
-L log_file set output log file, including console
|
||||
--log-level=<log_level> set log level: debug, info, warn, error
|
||||
--addr=<bind_addr> listen addr for client, example: 0.0.0.0:7000
|
||||
-h --help show this screen
|
||||
--version show version
|
||||
`
|
||||
|
||||
func main() {
|
||||
err := server.LoadConf("./frps.ini")
|
||||
// the configures parsed from file will be replaced by those from command line if exist
|
||||
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
|
||||
|
||||
if args["-c"] != nil {
|
||||
configFile = args["-c"].(string)
|
||||
}
|
||||
err = server.LoadConf(configFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
if args["-L"] != nil {
|
||||
if args["-L"].(string) == "console" {
|
||||
server.LogWay = "console"
|
||||
} else {
|
||||
server.LogWay = "file"
|
||||
server.LogFile = args["-L"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
if args["--log-level"] != nil {
|
||||
server.LogLevel = args["--log-level"].(string)
|
||||
}
|
||||
|
||||
if args["--addr"] != nil {
|
||||
addr := strings.Split(args["--addr"].(string), ":")
|
||||
if len(addr) != 2 {
|
||||
fmt.Println("--addr format error: example 0.0.0.0:7000")
|
||||
os.Exit(1)
|
||||
}
|
||||
bindPort, err := strconv.ParseInt(addr[1], 10, 64)
|
||||
if err != nil {
|
||||
fmt.Println("--addr format error, example 0.0.0.0:7000")
|
||||
os.Exit(1)
|
||||
}
|
||||
server.BindAddr = addr[0]
|
||||
server.BindPort = bindPort
|
||||
}
|
||||
|
||||
log.InitLog(server.LogWay, server.LogFile, server.LogLevel)
|
||||
|
||||
l, err := conn.Listen(server.BindAddr, server.BindPort)
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
@ -12,11 +26,12 @@ import (
|
||||
type ProxyClient struct {
|
||||
Name string
|
||||
Passwd string
|
||||
LocalIp string
|
||||
LocalPort int64
|
||||
}
|
||||
|
||||
func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
|
||||
c, err = conn.ConnectServer("127.0.0.1", p.LocalPort)
|
||||
c, err = conn.ConnectServer(p.LocalIp, p.LocalPort)
|
||||
if err != nil {
|
||||
log.Error("ProxyName [%s], connect to local port error, %v", p.Name, err)
|
||||
}
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
@ -11,11 +25,11 @@ import (
|
||||
var (
|
||||
ServerAddr string = "0.0.0.0"
|
||||
ServerPort int64 = 7000
|
||||
LogFile string = "./frpc.log"
|
||||
LogLevel string = "warn"
|
||||
LogWay string = "file"
|
||||
HeartBeatInterval int64 = 5
|
||||
HeartBeatTimeout int64 = 30
|
||||
LogFile string = "console"
|
||||
LogWay string = "console"
|
||||
LogLevel string = "info"
|
||||
HeartBeatInterval int64 = 20
|
||||
HeartBeatTimeout int64 = 90
|
||||
)
|
||||
|
||||
var ProxyClients map[string]*ProxyClient = make(map[string]*ProxyClient)
|
||||
@ -43,6 +57,11 @@ func LoadConf(confFile string) (err error) {
|
||||
tmpStr, ok = conf.Get("common", "log_file")
|
||||
if ok {
|
||||
LogFile = tmpStr
|
||||
if LogFile == "console" {
|
||||
LogWay = "console"
|
||||
} else {
|
||||
LogWay = "file"
|
||||
}
|
||||
}
|
||||
|
||||
tmpStr, ok = conf.Get("common", "log_level")
|
||||
@ -50,12 +69,7 @@ func LoadConf(confFile string) (err error) {
|
||||
LogLevel = tmpStr
|
||||
}
|
||||
|
||||
tmpStr, ok = conf.Get("common", "log_way")
|
||||
if ok {
|
||||
LogWay = tmpStr
|
||||
}
|
||||
|
||||
// servers
|
||||
// proxies
|
||||
for name, section := range conf {
|
||||
if name != "common" {
|
||||
proxyClient := &ProxyClient{}
|
||||
@ -66,6 +80,12 @@ func LoadConf(confFile string) (err error) {
|
||||
return fmt.Errorf("Parse ini file error: proxy [%s] no passwd found", proxyClient.Name)
|
||||
}
|
||||
|
||||
proxyClient.LocalIp, ok = section["local_ip"]
|
||||
if !ok {
|
||||
// use 127.0.0.1 as default
|
||||
proxyClient.LocalIp = "127.0.0.1"
|
||||
}
|
||||
|
||||
portStr, ok := section["local_port"]
|
||||
if ok {
|
||||
proxyClient.LocalPort, err = strconv.ParseInt(portStr, 10, 64)
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package consts
|
||||
|
||||
// server status
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package msg
|
||||
|
||||
type GeneralRes struct {
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
@ -10,11 +24,11 @@ import (
|
||||
// common config
|
||||
var (
|
||||
BindAddr string = "0.0.0.0"
|
||||
BindPort int64 = 9527
|
||||
LogFile string = "./frps.log"
|
||||
LogLevel string = "warn"
|
||||
LogWay string = "file"
|
||||
HeartBeatTimeout int64 = 30
|
||||
BindPort int64 = 7000
|
||||
LogFile string = "console"
|
||||
LogWay string = "console" // console or file
|
||||
LogLevel string = "info"
|
||||
HeartBeatTimeout int64 = 90
|
||||
UserConnTimeout int64 = 10
|
||||
)
|
||||
|
||||
@ -43,6 +57,11 @@ func LoadConf(confFile string) (err error) {
|
||||
tmpStr, ok = conf.Get("common", "log_file")
|
||||
if ok {
|
||||
LogFile = tmpStr
|
||||
if LogFile == "console" {
|
||||
LogWay = "console"
|
||||
} else {
|
||||
LogWay = "file"
|
||||
}
|
||||
}
|
||||
|
||||
tmpStr, ok = conf.Get("common", "log_level")
|
||||
@ -50,11 +69,6 @@ func LoadConf(confFile string) (err error) {
|
||||
LogLevel = tmpStr
|
||||
}
|
||||
|
||||
tmpStr, ok = conf.Get("common", "log_way")
|
||||
if ok {
|
||||
LogWay = tmpStr
|
||||
}
|
||||
|
||||
// servers
|
||||
for name, section := range conf {
|
||||
if name != "common" {
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
@ -128,7 +142,9 @@ func (p *ProxyServer) Start() (err error) {
|
||||
func (p *ProxyServer) Close() {
|
||||
p.Lock()
|
||||
p.Status = consts.Idle
|
||||
if p.listener != nil {
|
||||
p.listener.Close()
|
||||
}
|
||||
close(p.ctlMsgChan)
|
||||
close(p.cliConnChan)
|
||||
p.userConnList = list.New()
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package broadcast
|
||||
|
||||
type Broadcast struct {
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package broadcast
|
||||
|
||||
import (
|
||||
@ -15,7 +29,7 @@ var (
|
||||
func TestBroadcast(t *testing.T) {
|
||||
b := NewBroadcast()
|
||||
if b == nil {
|
||||
t.Errorf("New Broadcast error, nil return")
|
||||
t.Fatalf("New Broadcast error, nil return")
|
||||
}
|
||||
defer b.Close()
|
||||
|
||||
@ -31,7 +45,7 @@ func TestBroadcast(t *testing.T) {
|
||||
|
||||
wait.Wait()
|
||||
if succNum != totalNum {
|
||||
t.Errorf("TotalNum %d, FailNum(timeout) %d", totalNum, totalNum-succNum)
|
||||
t.Fatalf("TotalNum %d, FailNum(timeout) %d", totalNum, totalNum-succNum)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pcrypto
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pcrypto
|
||||
|
||||
import (
|
||||
@ -11,7 +25,7 @@ func TestEncrypto(t *testing.T) {
|
||||
pp.Init([]byte("Hana"))
|
||||
res, err := pp.Encrypto([]byte("Just One Test!"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("[%x]\n", res)
|
||||
@ -22,12 +36,12 @@ func TestDecrypto(t *testing.T) {
|
||||
pp.Init([]byte("Hana"))
|
||||
res, err := pp.Encrypto([]byte("Just One Test!"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err = pp.Decrypto(res)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("[%s]\n", string(res))
|
||||
@ -36,12 +50,12 @@ func TestDecrypto(t *testing.T) {
|
||||
func TestPKCS7Padding(t *testing.T) {
|
||||
ltt := []byte("Test_PKCS7Padding")
|
||||
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
||||
fmt.Printf("[%x]\n", (ltt))
|
||||
// fmt.Printf("[%x]\n", (ltt))
|
||||
}
|
||||
|
||||
func TestPKCS7UnPadding(t *testing.T) {
|
||||
ltt := []byte("Test_PKCS7Padding")
|
||||
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
||||
ltt = PKCS7UnPadding(ltt)
|
||||
fmt.Printf("[%x]\n", ltt)
|
||||
// fmt.Printf("[%x]\n", ltt)
|
||||
}
|
||||
|
58
src/frp/utils/version/version.go
Normal file
58
src/frp/utils/version/version.go
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var version string = "0.2.0"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
}
|
||||
|
||||
func Proto(v string) int64 {
|
||||
arr := strings.Split(v, ".")
|
||||
if len(arr) < 2 {
|
||||
return 0
|
||||
}
|
||||
res, _ := strconv.ParseInt(arr[0], 10, 64)
|
||||
return res
|
||||
}
|
||||
|
||||
func Major(v string) int64 {
|
||||
arr := strings.Split(v, ".")
|
||||
if len(arr) < 2 {
|
||||
return 0
|
||||
}
|
||||
res, _ := strconv.ParseInt(arr[1], 10, 64)
|
||||
return res
|
||||
}
|
||||
|
||||
func Minor(v string) int64 {
|
||||
arr := strings.Split(v, ".")
|
||||
if len(arr) < 2 {
|
||||
return 0
|
||||
}
|
||||
res, _ := strconv.ParseInt(arr[2], 10, 64)
|
||||
return res
|
||||
}
|
||||
|
||||
// add every case there if server will not accept client's protocol and return false
|
||||
func Compat(client string, server string) bool {
|
||||
return true
|
||||
}
|
56
src/frp/utils/version/version_test.go
Normal file
56
src/frp/utils/version/version_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFull(t *testing.T) {
|
||||
version := Full()
|
||||
arr := strings.Split(version, ".")
|
||||
if len(arr) != 3 {
|
||||
t.Fatalf("Version string error: %s", version)
|
||||
}
|
||||
|
||||
proto, err := strconv.ParseInt(arr[0], 10, 64)
|
||||
if err != nil || proto < 0 {
|
||||
t.Fatalf("Version proto error")
|
||||
}
|
||||
|
||||
major, err := strconv.ParseInt(arr[1], 10, 64)
|
||||
if err != nil || major < 0 {
|
||||
t.Fatalf("Version major error")
|
||||
}
|
||||
|
||||
minor, err := strconv.ParseInt(arr[2], 10, 64)
|
||||
if err != nil || minor < 0 {
|
||||
t.Fatalf("Version minor error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
proto := Proto(Full())
|
||||
major := Major(Full())
|
||||
minor := Minor(Full())
|
||||
parseVerion := fmt.Sprintf("%d.%d.%d", proto, major, minor)
|
||||
version := Full()
|
||||
if parseVerion != version {
|
||||
t.Fatalf("Get version incorrect, version [%s], parseVerion [%s]", version, parseVerion)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user