First available commit

This commit is contained in:
fatedier
2016-01-27 21:24:36 +08:00
parent 7ea8751e56
commit 7030d16e80
31 changed files with 2295 additions and 0 deletions

89
cmd/frpc/config.go Normal file
View File

@ -0,0 +1,89 @@
package main
import (
"fmt"
"strconv"
"frp/pkg/models"
ini "github.com/vaughan0/go-ini"
)
// common config
var (
ServerAddr string = "0.0.0.0"
ServerPort int64 = 7000
LogFile string = "./frpc.log"
LogLevel string = "warn"
LogWay string = "file"
)
var ProxyClients map[string]*models.ProxyClient = make(map[string]*models.ProxyClient)
func LoadConf(confFile string) (err error) {
var tmpStr string
var ok bool
conf, err := ini.LoadFile(confFile)
if err != nil {
return err
}
// common
tmpStr, ok = conf.Get("common", "server_addr")
if ok {
ServerAddr = tmpStr
}
tmpStr, ok = conf.Get("common", "server_port")
if ok {
ServerPort, _ = strconv.ParseInt(tmpStr, 10, 64)
}
tmpStr, ok = conf.Get("common", "log_file")
if ok {
LogFile = tmpStr
}
tmpStr, ok = conf.Get("common", "log_level")
if ok {
LogLevel = tmpStr
}
tmpStr, ok = conf.Get("common", "log_way")
if ok {
LogWay = tmpStr
}
// servers
for name, section := range conf {
if name != "common" {
proxyClient := &models.ProxyClient{}
proxyClient.Name = name
proxyClient.Passwd, ok = section["passwd"]
if !ok {
return fmt.Errorf("Parse ini file error: proxy [%s] no passwd found", proxyClient.Name)
}
portStr, ok := section["local_port"]
if ok {
proxyClient.LocalPort, err = strconv.ParseInt(portStr, 10, 64)
if err != nil {
return fmt.Errorf("Parse ini file error: proxy [%s] local_port error", proxyClient.Name)
}
} else {
return fmt.Errorf("Parse ini file error: proxy [%s] local_port not found", proxyClient.Name)
}
ProxyClients[proxyClient.Name] = proxyClient
}
}
if len(ProxyClients) == 0 {
return fmt.Errorf("Parse ini file error: no proxy config found")
}
return nil
}

67
cmd/frpc/control.go Normal file
View File

@ -0,0 +1,67 @@
package main
import (
"io"
"sync"
"encoding/json"
"frp/pkg/models"
"frp/pkg/utils/conn"
"frp/pkg/utils/log"
)
func ControlProcess(cli *models.ProxyClient, wait *sync.WaitGroup) {
defer wait.Done()
c := &conn.Conn{}
err := c.ConnectServer(ServerAddr, ServerPort)
if err != nil {
log.Error("ProxyName [%s], connect to server [%s:%d] error, %v", cli.Name, ServerAddr, ServerPort, err)
return
}
defer c.Close()
req := &models.ClientCtlReq{
Type: models.ControlConn,
ProxyName: cli.Name,
Passwd: cli.Passwd,
}
buf, _ := json.Marshal(req)
err = c.Write(string(buf) + "\n")
if err != nil {
log.Error("ProxyName [%s], write to server error, %v", cli.Name, err)
return
}
res, err := c.ReadLine()
if err != nil {
log.Error("ProxyName [%s], read from server error, %v", cli.Name, err)
return
}
log.Debug("ProxyName [%s], read [%s]", cli.Name, res)
clientCtlRes := &models.ClientCtlRes{}
if err = json.Unmarshal([]byte(res), &clientCtlRes); err != nil {
log.Error("ProxyName [%s], format server response error, %v", cli.Name, err)
return
}
if clientCtlRes.Code != 0 {
log.Error("ProxyName [%s], start proxy error, %s", cli.Name, clientCtlRes.Msg)
return
}
for {
// ignore response content now
_, err := c.ReadLine()
if err == io.EOF {
log.Debug("ProxyName [%s], server close this control conn", cli.Name)
break
} else if err != nil {
log.Warn("ProxyName [%s], read from server error, %v", cli.Name, err)
continue
}
cli.StartTunnel(ServerAddr, ServerPort)
}
}

30
cmd/frpc/main.go Normal file
View File

@ -0,0 +1,30 @@
package main
import (
"os"
"sync"
"frp/pkg/utils/log"
)
func main() {
err := LoadConf("./frpc.ini")
if err != nil {
os.Exit(-1)
}
log.InitLog(LogWay, LogFile, LogLevel)
// wait until all control goroutine exit
var wait sync.WaitGroup
wait.Add(len(ProxyClients))
for _, client := range ProxyClients {
go ControlProcess(client, &wait)
}
log.Info("Start frpc success")
wait.Wait()
log.Warn("All proxy exit!")
}

95
cmd/frps/config.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
"fmt"
"strconv"
"frp/pkg/models"
ini "github.com/vaughan0/go-ini"
)
// common config
var (
BindAddr string = "0.0.0.0"
BindPort int64 = 9527
LogFile string = "./frps.log"
LogLevel string = "warn"
LogWay string = "file"
)
var ProxyServers map[string]*models.ProxyServer = make(map[string]*models.ProxyServer)
func LoadConf(confFile string) (err error) {
var tmpStr string
var ok bool
conf, err := ini.LoadFile(confFile)
if err != nil {
return err
}
// common
tmpStr, ok = conf.Get("common", "bind_addr")
if ok {
BindAddr = tmpStr
}
tmpStr, ok = conf.Get("common", "bind_port")
if ok {
BindPort, _ = strconv.ParseInt(tmpStr, 10, 64)
}
tmpStr, ok = conf.Get("common", "log_file")
if ok {
LogFile = tmpStr
}
tmpStr, ok = conf.Get("common", "log_level")
if ok {
LogLevel = tmpStr
}
tmpStr, ok = conf.Get("common", "log_way")
if ok {
LogWay = tmpStr
}
// servers
for name, section := range conf {
if name != "common" {
proxyServer := &models.ProxyServer{}
proxyServer.Name = name
proxyServer.Passwd, ok = section["passwd"]
if !ok {
return fmt.Errorf("Parse ini file error: proxy [%s] no passwd found", proxyServer.Name)
}
proxyServer.BindAddr, ok = section["bind_addr"]
if !ok {
proxyServer.BindAddr = "0.0.0.0"
}
portStr, ok := section["listen_port"]
if ok {
proxyServer.ListenPort, err = strconv.ParseInt(portStr, 10, 64)
if err != nil {
return fmt.Errorf("Parse ini file error: proxy [%s] listen_port error", proxyServer.Name)
}
} else {
return fmt.Errorf("Parse ini file error: proxy [%s] listen_port not found", proxyServer.Name)
}
proxyServer.Init()
ProxyServers[proxyServer.Name] = proxyServer
}
}
if len(ProxyServers) == 0 {
return fmt.Errorf("Parse ini file error: no proxy config found")
}
return nil
}

134
cmd/frps/control.go Normal file
View File

@ -0,0 +1,134 @@
package main
import (
"fmt"
"encoding/json"
"frp/pkg/utils/log"
"frp/pkg/utils/conn"
"frp/pkg/models"
)
func ProcessControlConn(l *conn.Listener) {
for {
c := l.GetConn()
log.Debug("Get one new conn, %v", c.GetRemoteAddr())
go controlWorker(c)
}
}
// control connection from every client and server
func controlWorker(c *conn.Conn) {
// the first message is from client to server
// if error, close connection
res, err := c.ReadLine()
if err != nil {
log.Warn("Read error, %v", err)
return
}
log.Debug("get: %s", res)
clientCtlReq := &models.ClientCtlReq{}
clientCtlRes := &models.ClientCtlRes{}
if err := json.Unmarshal([]byte(res), &clientCtlReq); err != nil {
log.Warn("Parse err: %v : %s", err, res)
return
}
// check
succ, msg, needRes := checkProxy(clientCtlReq, c)
if !succ {
clientCtlRes.Code = 1
clientCtlRes.Msg = msg
}
if needRes {
buf, _ := json.Marshal(clientCtlRes)
err = c.Write(string(buf) + "\n")
if err != nil {
log.Warn("Write error, %v", err)
}
} else {
// work conn, just return
return
}
defer c.Close()
// others is from server to client
server, ok := ProxyServers[clientCtlReq.ProxyName]
if !ok {
log.Warn("ProxyName [%s] is not exist", clientCtlReq.ProxyName)
return
}
serverCtlReq := &models.ClientCtlReq{}
serverCtlReq.Type = models.WorkConn
for {
server.WaitUserConn()
buf, _ := json.Marshal(serverCtlReq)
err = c.Write(string(buf) + "\n")
if err != nil {
log.Warn("ProxyName [%s], write to client error, proxy exit", server.Name)
server.Close()
return
}
log.Debug("ProxyName [%s], write to client to add work conn success", server.Name)
}
return
}
func checkProxy(req *models.ClientCtlReq, c *conn.Conn) (succ bool, msg string, needRes bool) {
succ = false
needRes = true
// check if proxy name exist
server, ok := ProxyServers[req.ProxyName]
if !ok {
msg = fmt.Sprintf("ProxyName [%s] is not exist", req.ProxyName)
log.Warn(msg)
return
}
// check password
if req.Passwd != server.Passwd {
msg = fmt.Sprintf("ProxyName [%s], password is not correct", req.ProxyName)
log.Warn(msg)
return
}
// control conn
if req.Type == models.ControlConn {
if server.Status != models.Idle {
msg = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName)
log.Warn(msg)
return
}
// start proxy and listen for user conn, no block
err := server.Start()
if err != nil {
msg = fmt.Sprintf("ProxyName [%s], start proxy error: %v", req.ProxyName, err.Error())
log.Warn(msg)
return
}
log.Info("ProxyName [%s], start proxy success", req.ProxyName)
} else if req.Type == models.WorkConn {
// work conn
needRes = false
if server.Status != models.Working {
log.Warn("ProxyName [%s], is not working when it gets one new work conn", req.ProxyName)
return
}
server.CliConnChan <- c
} else {
msg = fmt.Sprintf("ProxyName [%s], type [%d] unsupport", req.ProxyName)
log.Warn(msg)
return
}
succ = true
return
}

26
cmd/frps/main.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"os"
"frp/pkg/utils/log"
"frp/pkg/utils/conn"
)
func main() {
err := LoadConf("./frps.ini")
if err != nil {
os.Exit(-1)
}
log.InitLog(LogWay, LogFile, LogLevel)
l, err := conn.Listen(BindAddr, BindPort)
if err != nil {
log.Error("Create listener error, %v", err)
os.Exit(-1)
}
log.Info("Start frps success")
ProcessControlConn(l)
}