mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
commit
51114f2afd
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,3 @@ bin/
|
|||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
*.swp
|
*.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",
|
"Comment": "v1.5.0-9-gfb7314f",
|
||||||
"Rev": "fb7314f8ac86b83ccd34386518d97cf2363e2ae5"
|
"Rev": "fb7314f8ac86b83ccd34386518d97cf2363e2ae5"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/docopt/docopt-go",
|
||||||
|
"Comment": "0.6.2",
|
||||||
|
"Rev": "784ddc588536785e7299f7272f39101f7faccc3f"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/vaughan0/go-ini",
|
"ImportPath": "github.com/vaughan0/go-ini",
|
||||||
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
|
"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:
|
godep:
|
||||||
@go get github.com/tools/godep
|
@go get github.com/tools/godep
|
||||||
godep restore
|
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
@GOPATH=$(NEW_GOPATH) godep go fmt ./...
|
GOPATH=$(NEW_GOPATH) godep go fmt ./...
|
||||||
|
|
||||||
frps:
|
frps:
|
||||||
GOPATH=$(NEW_GOPATH) godep go build -o bin/frps ./src/frp/cmd/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
|
GOPATH=$(NEW_GOPATH) godep go build -o bin/frpc ./src/frp/cmd/frpc
|
||||||
|
|
||||||
test:
|
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)
|
[![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]
|
[common]
|
||||||
server_addr = 127.0.0.1
|
server_addr = 0.0.0.0
|
||||||
server_port = 7000
|
server_port = 7000
|
||||||
log_file = ./frpc.log
|
# console or real logFile path like ./frpc.log
|
||||||
|
log_file = console
|
||||||
# debug, info, warn, error
|
# debug, info, warn, error
|
||||||
log_level = debug
|
log_level = debug
|
||||||
# file, console
|
|
||||||
log_way = console
|
|
||||||
|
|
||||||
# test1即为name
|
# test1 is the proxy name same as server's configuration
|
||||||
[test1]
|
[test1]
|
||||||
passwd = 123
|
passwd = 123
|
||||||
|
local_ip = 127.0.0.1
|
||||||
local_port = 22
|
local_port = 22
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
# common是必须的section
|
# [common] is integral section
|
||||||
[common]
|
[common]
|
||||||
bind_addr = 0.0.0.0
|
bind_addr = 0.0.0.0
|
||||||
bind_port = 7000
|
bind_port = 7000
|
||||||
log_file = ./frps.log
|
# console or real logFile path like ./frps.log
|
||||||
|
log_file = console
|
||||||
# debug, info, warn, error
|
# debug, info, warn, error
|
||||||
log_level = debug
|
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]
|
[test1]
|
||||||
passwd = 123
|
passwd = 123
|
||||||
bind_addr = 0.0.0.0
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -142,6 +156,7 @@ func startHeartBeat(c *conn.Conn) {
|
|||||||
for {
|
for {
|
||||||
time.Sleep(time.Duration(client.HeartBeatInterval) * time.Second)
|
time.Sleep(time.Duration(client.HeartBeatInterval) * time.Second)
|
||||||
if c != nil && !c.IsClosed() {
|
if c != nil && !c.IsClosed() {
|
||||||
|
log.Debug("Send heartbeat to server")
|
||||||
err = c.Write(string(request) + "\n")
|
err = c.Write(string(request) + "\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Send hearbeat to server failed! Err:%v", err)
|
log.Error("Send hearbeat to server failed! Err:%v", err)
|
||||||
@ -151,5 +166,5 @@ func startHeartBeat(c *conn.Conn) {
|
|||||||
break
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
docopt "github.com/docopt/docopt-go"
|
||||||
|
|
||||||
"frp/models/client"
|
"frp/models/client"
|
||||||
"frp/utils/log"
|
"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() {
|
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 {
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
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)
|
log.InitLog(client.LogWay, client.LogFile, client.LogLevel)
|
||||||
|
|
||||||
// wait until all control goroutine exit
|
// 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
|
package main
|
||||||
|
|
||||||
import (
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
docopt "github.com/docopt/docopt-go"
|
||||||
|
|
||||||
"frp/models/server"
|
"frp/models/server"
|
||||||
"frp/utils/conn"
|
"frp/utils/conn"
|
||||||
"frp/utils/log"
|
"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() {
|
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 {
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
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)
|
log.InitLog(server.LogWay, server.LogFile, server.LogLevel)
|
||||||
|
|
||||||
l, err := conn.Listen(server.BindAddr, server.BindPort)
|
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
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -12,11 +26,12 @@ import (
|
|||||||
type ProxyClient struct {
|
type ProxyClient struct {
|
||||||
Name string
|
Name string
|
||||||
Passwd string
|
Passwd string
|
||||||
|
LocalIp string
|
||||||
LocalPort int64
|
LocalPort int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyClient) GetLocalConn() (c *conn.Conn, err error) {
|
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 {
|
if err != nil {
|
||||||
log.Error("ProxyName [%s], connect to local port error, %v", p.Name, err)
|
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
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -11,11 +25,11 @@ import (
|
|||||||
var (
|
var (
|
||||||
ServerAddr string = "0.0.0.0"
|
ServerAddr string = "0.0.0.0"
|
||||||
ServerPort int64 = 7000
|
ServerPort int64 = 7000
|
||||||
LogFile string = "./frpc.log"
|
LogFile string = "console"
|
||||||
LogLevel string = "warn"
|
LogWay string = "console"
|
||||||
LogWay string = "file"
|
LogLevel string = "info"
|
||||||
HeartBeatInterval int64 = 5
|
HeartBeatInterval int64 = 20
|
||||||
HeartBeatTimeout int64 = 30
|
HeartBeatTimeout int64 = 90
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProxyClients map[string]*ProxyClient = make(map[string]*ProxyClient)
|
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")
|
tmpStr, ok = conf.Get("common", "log_file")
|
||||||
if ok {
|
if ok {
|
||||||
LogFile = tmpStr
|
LogFile = tmpStr
|
||||||
|
if LogFile == "console" {
|
||||||
|
LogWay = "console"
|
||||||
|
} else {
|
||||||
|
LogWay = "file"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "log_level")
|
tmpStr, ok = conf.Get("common", "log_level")
|
||||||
@ -50,12 +69,7 @@ func LoadConf(confFile string) (err error) {
|
|||||||
LogLevel = tmpStr
|
LogLevel = tmpStr
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "log_way")
|
// proxies
|
||||||
if ok {
|
|
||||||
LogWay = tmpStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// servers
|
|
||||||
for name, section := range conf {
|
for name, section := range conf {
|
||||||
if name != "common" {
|
if name != "common" {
|
||||||
proxyClient := &ProxyClient{}
|
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)
|
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"]
|
portStr, ok := section["local_port"]
|
||||||
if ok {
|
if ok {
|
||||||
proxyClient.LocalPort, err = strconv.ParseInt(portStr, 10, 64)
|
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
|
package consts
|
||||||
|
|
||||||
// server status
|
// 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
|
package msg
|
||||||
|
|
||||||
type GeneralRes struct {
|
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
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -10,11 +24,11 @@ import (
|
|||||||
// common config
|
// common config
|
||||||
var (
|
var (
|
||||||
BindAddr string = "0.0.0.0"
|
BindAddr string = "0.0.0.0"
|
||||||
BindPort int64 = 9527
|
BindPort int64 = 7000
|
||||||
LogFile string = "./frps.log"
|
LogFile string = "console"
|
||||||
LogLevel string = "warn"
|
LogWay string = "console" // console or file
|
||||||
LogWay string = "file"
|
LogLevel string = "info"
|
||||||
HeartBeatTimeout int64 = 30
|
HeartBeatTimeout int64 = 90
|
||||||
UserConnTimeout int64 = 10
|
UserConnTimeout int64 = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,6 +57,11 @@ func LoadConf(confFile string) (err error) {
|
|||||||
tmpStr, ok = conf.Get("common", "log_file")
|
tmpStr, ok = conf.Get("common", "log_file")
|
||||||
if ok {
|
if ok {
|
||||||
LogFile = tmpStr
|
LogFile = tmpStr
|
||||||
|
if LogFile == "console" {
|
||||||
|
LogWay = "console"
|
||||||
|
} else {
|
||||||
|
LogWay = "file"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "log_level")
|
tmpStr, ok = conf.Get("common", "log_level")
|
||||||
@ -50,11 +69,6 @@ func LoadConf(confFile string) (err error) {
|
|||||||
LogLevel = tmpStr
|
LogLevel = tmpStr
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpStr, ok = conf.Get("common", "log_way")
|
|
||||||
if ok {
|
|
||||||
LogWay = tmpStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// servers
|
// servers
|
||||||
for name, section := range conf {
|
for name, section := range conf {
|
||||||
if name != "common" {
|
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
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -128,7 +142,9 @@ func (p *ProxyServer) Start() (err error) {
|
|||||||
func (p *ProxyServer) Close() {
|
func (p *ProxyServer) Close() {
|
||||||
p.Lock()
|
p.Lock()
|
||||||
p.Status = consts.Idle
|
p.Status = consts.Idle
|
||||||
|
if p.listener != nil {
|
||||||
p.listener.Close()
|
p.listener.Close()
|
||||||
|
}
|
||||||
close(p.ctlMsgChan)
|
close(p.ctlMsgChan)
|
||||||
close(p.cliConnChan)
|
close(p.cliConnChan)
|
||||||
p.userConnList = list.New()
|
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
|
package broadcast
|
||||||
|
|
||||||
type Broadcast struct {
|
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
|
package broadcast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -15,7 +29,7 @@ var (
|
|||||||
func TestBroadcast(t *testing.T) {
|
func TestBroadcast(t *testing.T) {
|
||||||
b := NewBroadcast()
|
b := NewBroadcast()
|
||||||
if b == nil {
|
if b == nil {
|
||||||
t.Errorf("New Broadcast error, nil return")
|
t.Fatalf("New Broadcast error, nil return")
|
||||||
}
|
}
|
||||||
defer b.Close()
|
defer b.Close()
|
||||||
|
|
||||||
@ -31,7 +45,7 @@ func TestBroadcast(t *testing.T) {
|
|||||||
|
|
||||||
wait.Wait()
|
wait.Wait()
|
||||||
if succNum != totalNum {
|
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
|
package conn
|
||||||
|
|
||||||
import (
|
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
|
package log
|
||||||
|
|
||||||
import (
|
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
|
package pcrypto
|
||||||
|
|
||||||
import (
|
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
|
package pcrypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -11,7 +25,7 @@ func TestEncrypto(t *testing.T) {
|
|||||||
pp.Init([]byte("Hana"))
|
pp.Init([]byte("Hana"))
|
||||||
res, err := pp.Encrypto([]byte("Just One Test!"))
|
res, err := pp.Encrypto([]byte("Just One Test!"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("[%x]\n", res)
|
fmt.Printf("[%x]\n", res)
|
||||||
@ -22,12 +36,12 @@ func TestDecrypto(t *testing.T) {
|
|||||||
pp.Init([]byte("Hana"))
|
pp.Init([]byte("Hana"))
|
||||||
res, err := pp.Encrypto([]byte("Just One Test!"))
|
res, err := pp.Encrypto([]byte("Just One Test!"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err = pp.Decrypto(res)
|
res, err = pp.Decrypto(res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("[%s]\n", string(res))
|
fmt.Printf("[%s]\n", string(res))
|
||||||
@ -36,12 +50,12 @@ func TestDecrypto(t *testing.T) {
|
|||||||
func TestPKCS7Padding(t *testing.T) {
|
func TestPKCS7Padding(t *testing.T) {
|
||||||
ltt := []byte("Test_PKCS7Padding")
|
ltt := []byte("Test_PKCS7Padding")
|
||||||
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
||||||
fmt.Printf("[%x]\n", (ltt))
|
// fmt.Printf("[%x]\n", (ltt))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPKCS7UnPadding(t *testing.T) {
|
func TestPKCS7UnPadding(t *testing.T) {
|
||||||
ltt := []byte("Test_PKCS7Padding")
|
ltt := []byte("Test_PKCS7Padding")
|
||||||
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
ltt = PKCS7Padding(ltt, aes.BlockSize)
|
||||||
ltt = PKCS7UnPadding(ltt)
|
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