make e2e echoserver support more protocals

This commit is contained in:
yuyulei 2021-01-27 16:37:23 +08:00
parent 3621aad1c1
commit 6db422957e
6 changed files with 258 additions and 23 deletions

View File

@ -23,7 +23,6 @@ import (
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
) )
// Visitor // Visitor
var ( var (
visitorConfTypeMap = map[string]reflect.Type{ visitorConfTypeMap = map[string]reflect.Type{
@ -64,7 +63,6 @@ type XTCPVisitorConf struct {
BaseVisitorConf `ini:",extends" json:"inline"` BaseVisitorConf `ini:",extends" json:"inline"`
} }
// DefaultVisitorConf creates a empty VisitorConf object by visitorType. // DefaultVisitorConf creates a empty VisitorConf object by visitorType.
// If visitorType doesn't exist, return nil. // If visitorType doesn't exist, return nil.
func DefaultVisitorConf(visitorType string) VisitorConf { func DefaultVisitorConf(visitorType string) VisitorConf {

View File

@ -19,8 +19,8 @@ import (
"github.com/fatedier/frp/pkg/consts" "github.com/fatedier/frp/pkg/consts"
"gopkg.in/ini.v1"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"gopkg.in/ini.v1"
) )
const testVisitorPrefix = "test." const testVisitorPrefix = "test."

19
test/e2e/e2e.crt Normal file
View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDGDCCAgCgAwIBAgIJAP/5mYzCo9TZMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
BAMMDmV4YW1wbGUuY2EuY29tMB4XDTIxMDEyNzA4MDUyNFoXDTMxMDEyNTA4MDUy
NFowVTELMAkGA1UEBhMCWFgxEDAOBgNVBAgMB0RFRkFVTFQxEDAOBgNVBAcMB0RF
RkFVTFQxEDAOBgNVBAoMB0RFRkFVTFQxEDAOBgNVBAMMB2UyZS5jb20wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHzTaYcphSLOsV/PEWkv0XK2+hriyj
+GegXct3H7K6KxWoHMSAjmSpdGgm2/D7r4hAtAid9WpAZXExG++LGR5G/wFDMAia
FZiE+GwU20fGRsBhJVItIHVf/KwYSPBFHKCuqV0kY9Mkw1GOYZ9N33eaI4ouCSc6
QphOgF7jRaaycXUaOLIHAYK/+QlEHi+qj5CzVqshI0YkWHY30Mvf1FmgdkCidJUC
R8OLsnc8/OJMjb+7s7rL7vdKBoRau1G1vdRwH26Xk3dq5K5BTwtCYiXjR8JmDQMS
4VoTg9BzGujd7IhTG3BVWNHo93FkmUfLaBEAdLVctBdC9J0sQviwBIV7AgMBAAGj
JzAlMCMGA1UdEQQcMBqCCWxvY2FsaG9zdIcEfwAAAYIHZTJlLmNvbTANBgkqhkiG
9w0BAQUFAAOCAQEA1blvgPF2Ey1sflkqKKJBzq8Vvh4UnHrsY1v01zAZHe6iJvTL
UfkBSiU4eYE5EAOHPCilLjmG1sqdnCeXdglOqYZB0SOrBsIYhqKbfn+IlfQCS34l
i8xDVzRFzotrzTiPk3HpSk2i6JMwGUegBhVxqYlvRyw3Od0UA18xVvxaFrHPczSl
iRx8dMchvfNpqD4PgbUeAUO+sQEB3xZlPDetYG6uk47teKaQ4ZCT/cTSeuhvoPZ0
477E+r1KWe/kI9zeHNQ+L1GsZuwQYFGFfDpSBs8PLtyciZtPvjsZEzJrmpoq1JXT
KqkdBTZ4qElFMleV59Qtc9SRVsPbRHwT0O/cLQ==
-----END CERTIFICATE-----

27
test/e2e/e2e.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAx802mHKYUizrFfzxFpL9Fytvoa4so/hnoF3Ldx+yuisVqBzE
gI5kqXRoJtvw+6+IQLQInfVqQGVxMRvvixkeRv8BQzAImhWYhPhsFNtHxkbAYSVS
LSB1X/ysGEjwRRygrqldJGPTJMNRjmGfTd93miOKLgknOkKYToBe40WmsnF1Gjiy
BwGCv/kJRB4vqo+Qs1arISNGJFh2N9DL39RZoHZAonSVAkfDi7J3PPziTI2/u7O6
y+73SgaEWrtRtb3UcB9ul5N3auSuQU8LQmIl40fCZg0DEuFaE4PQcxro3eyIUxtw
VVjR6PdxZJlHy2gRAHS1XLQXQvSdLEL4sASFewIDAQABAoIBAF/PnYWfNkH5vkXO
BMJhfDJXJvHuNwPuQ6sYL1CRh8BUls8F9Ij9P3IvGx6/S6E1vG3ip1sv62K0AoKd
NdKLGgTLlgxlBUr2XiwtgI7D1HhVRz2OiwiOzxpXbSM8HtPVdYwsNTkVEZRIgVx4
nc7XAWCN+F45D3GVq7nBPz9XECfy/Aanrq4bwqGDjvw0vIRiy/M8gnJdL+1g0K1b
Cp6JkYexV5v9pnCtvYRJYqKrRxxZU90JRSb8/wNtuLeaIM/aAoUzPkUj+1owglL8
HXUeeHsAK527gZxubYAQOCP9NGZeMEE9vAyQDxpQ+wTC5i5zhT4xkH4F/P1aYQES
fdVl86ECgYEA/NE3KgKBm5nUHOZwtZ+YiAmEkbMWXrkpYCRzQPbcMMMphMZQT4Pd
aSdtzv1qRu95qnsY/cFceyOLbiNRF+uwYJwn2PmPW7jsUQG5vHsFn12edcWxnz6k
sRRfU8HiVYoaipQD06aMUCZYKQJV4jfvcqKpVwj9b3fiN8/oDgx2AWsCgYEAylEj
Tznw54mrOFYOLbLlwwpYbVuUHWFi9WjLGLVfOHQY03CCH+PMIFPnaYRAS3SqUL8s
e5AQvNdez7HyPfGeUtXmTaEPgA8YRHTcmtfIuNn/jxjwbpcaGQn6kzB/TYdte4Pb
CXwS3Yt1LqUgC1EqkUUpszn+O6d2mnnrq1aawDECgYEAh0tvOgwdUCgCW3T23DuM
ZUCysUYlsotkmQ7ontt8+pt2nJeEYwkudBelrB/xwARoF9PIjAPuefeLpmVAAI0g
1pK6wGLNVUihLri9rSAo4iA3rM8fPxlHCXzdhvU7Kou9qGuNoLaAYGQkyc12KJnG
ipKCDRHCjuSZK0UX6mzAugECgYEAxYgw1GK67iXBEZEb6Mx5flO0gJlgZMs35mn5
mddD8AeSUabQtbghDhM9pw0kBUgUHiB5mu7PGMGi5WBVJtuofDIx2Ot/CcYzKGt9
FIXIiYr29M0huqg3J+lRSLKaKKUoZOcZTgphFQPbVr6MKeCGki2YCFCAA9h+eVa+
nZxCHZECgYBJjNqhR9pc+56Mor6oBGnRbBCQn2naNuPx4AoZ8JWXU8Q8GRoI5son
F7MGeuVwLDFvyQOAiDxqyrHM+PCPLcMBdfH8rMt7GQpBsSSA09WYtQ9Sj97QhbTy
Zrq8EtPvRBmeGfZd8BDGVGunVZnNi3NaOV0fCOK6yQEtJN0J9BREbw==
-----END RSA PRIVATE KEY-----

View File

@ -12,18 +12,31 @@ const (
TCPEchoServerPort = "TCPEchoServerPort" TCPEchoServerPort = "TCPEchoServerPort"
UDPEchoServerPort = "UDPEchoServerPort" UDPEchoServerPort = "UDPEchoServerPort"
UDSEchoServerAddr = "UDSEchoServerAddr" UDSEchoServerAddr = "UDSEchoServerAddr"
HTTPEchoServerPort = "HTTPEchoServerPort"
HTTPSEchoServerPort = "HTTPSEchoServerPort"
WSEchoServerPort = "WSEchoServerPort"
WSSEchoServerPort = "WSSEchoServerPort"
) )
type MockServers struct { type MockServers struct {
tcpEchoServer *echoserver.Server tcpEchoServer *echoserver.Server
udpEchoServer *echoserver.Server udpEchoServer *echoserver.Server
udsEchoServer *echoserver.Server udsEchoServer *echoserver.Server
httpEchoServer *echoserver.Server
httpsEchoServer *echoserver.Server
wsEchoServer *echoserver.Server
wssEchoServer *echoserver.Server
} }
func NewMockServers(portAllocator *port.Allocator) *MockServers { func NewMockServers(portAllocator *port.Allocator) *MockServers {
s := &MockServers{} s := &MockServers{}
tcpPort := portAllocator.Get() tcpPort := portAllocator.Get()
udpPort := portAllocator.Get() udpPort := portAllocator.Get()
httpPort := portAllocator.Get()
httpsPort := portAllocator.Get()
wsPort := portAllocator.Get()
wssPort := portAllocator.Get()
s.tcpEchoServer = echoserver.New(echoserver.Options{ s.tcpEchoServer = echoserver.New(echoserver.Options{
Type: echoserver.TCP, Type: echoserver.TCP,
BindAddr: "127.0.0.1", BindAddr: "127.0.0.1",
@ -45,6 +58,34 @@ func NewMockServers(portAllocator *port.Allocator) *MockServers {
BindAddr: udsAddr, BindAddr: udsAddr,
RepeatNum: 1, RepeatNum: 1,
}) })
s.httpEchoServer = echoserver.New(echoserver.Options{
Type: echoserver.HTTP,
BindAddr: "127.0.0.1",
BindPort: int32(httpPort),
RepeatNum: 1,
})
s.httpsEchoServer = echoserver.New(echoserver.Options{
Type: echoserver.HTTPS,
BindAddr: "127.0.0.1",
BindPort: int32(httpsPort),
RepeatNum: 1,
})
s.wsEchoServer = echoserver.New(echoserver.Options{
Type: echoserver.WS,
BindAddr: "127.0.0.1",
BindPort: int32(wsPort),
RepeatNum: 1,
})
s.wssEchoServer = echoserver.New(echoserver.Options{
Type: echoserver.WSS,
BindAddr: "127.0.0.1",
BindPort: int32(wssPort),
RepeatNum: 1,
})
return s return s
} }
@ -58,6 +99,18 @@ func (m *MockServers) Run() error {
if err := m.udsEchoServer.Run(); err != nil { if err := m.udsEchoServer.Run(); err != nil {
return err return err
} }
if err := m.httpEchoServer.Run(); err != nil {
return err
}
if err := m.httpsEchoServer.Run(); err != nil {
return err
}
if err := m.wsEchoServer.Run(); err != nil {
return err
}
if err := m.wssEchoServer.Run(); err != nil {
return err
}
return nil return nil
} }
@ -65,6 +118,10 @@ func (m *MockServers) Close() {
m.tcpEchoServer.Close() m.tcpEchoServer.Close()
m.udpEchoServer.Close() m.udpEchoServer.Close()
m.udsEchoServer.Close() m.udsEchoServer.Close()
m.httpEchoServer.Close()
m.httpsEchoServer.Close()
m.wsEchoServer.Close()
m.wssEchoServer.Close()
os.Remove(m.udsEchoServer.GetOptions().BindAddr) os.Remove(m.udsEchoServer.GetOptions().BindAddr)
} }
@ -73,6 +130,10 @@ func (m *MockServers) GetTemplateParams() map[string]interface{} {
ret[TCPEchoServerPort] = m.tcpEchoServer.GetOptions().BindPort ret[TCPEchoServerPort] = m.tcpEchoServer.GetOptions().BindPort
ret[UDPEchoServerPort] = m.udpEchoServer.GetOptions().BindPort ret[UDPEchoServerPort] = m.udpEchoServer.GetOptions().BindPort
ret[UDSEchoServerAddr] = m.udsEchoServer.GetOptions().BindAddr ret[UDSEchoServerAddr] = m.udsEchoServer.GetOptions().BindAddr
ret[HTTPEchoServerPort] = m.httpEchoServer.GetOptions().BindPort
ret[HTTPSEchoServerPort] = m.httpsEchoServer.GetOptions().BindPort
ret[WSEchoServerPort] = m.wsEchoServer.GetOptions().BindPort
ret[WSSEchoServerPort] = m.wssEchoServer.GetOptions().BindPort
return ret return ret
} }

View File

@ -1,11 +1,15 @@
package echoserver package echoserver
import ( import (
"encoding/json"
"fmt" "fmt"
"net" "net"
"net/http"
"strings" "strings"
fnet "github.com/fatedier/frp/pkg/util/net" fnet "github.com/fatedier/frp/pkg/util/net"
"github.com/gorilla/websocket"
) )
type ServerType string type ServerType string
@ -14,6 +18,10 @@ const (
TCP ServerType = "tcp" TCP ServerType = "tcp"
UDP ServerType = "udp" UDP ServerType = "udp"
Unix ServerType = "unix" Unix ServerType = "unix"
HTTP ServerType = "http"
HTTPS ServerType = "https"
WS ServerType = "ws"
WSS ServerType = "wss"
) )
type Options struct { type Options struct {
@ -28,6 +36,10 @@ type Server struct {
opt Options opt Options
l net.Listener l net.Listener
httpServer *http.Server
httpsServer *http.Server
wsServer *http.Server
wssServer *http.Server
} }
func New(opt Options) *Server { func New(opt Options) *Server {
@ -50,10 +62,12 @@ func (s *Server) GetOptions() Options {
} }
func (s *Server) Run() error { func (s *Server) Run() error {
if err := s.initListener(); err != nil { if err := s.init(); err != nil {
return err return err
} }
switch s.opt.Type {
case TCP, UDP, Unix:
go func() { go func() {
for { for {
c, err := s.l.Accept() c, err := s.l.Accept()
@ -63,6 +77,38 @@ func (s *Server) Run() error {
go s.handle(c) go s.handle(c)
} }
}() }()
case HTTP:
go func() {
err := s.httpServer.ListenAndServe()
if err != nil {
fmt.Printf("echo http server exited error: %v\n", err)
}
}()
case HTTPS:
go func() {
err := s.httpsServer.ListenAndServeTLS("e2e.crt", "e2e.key")
if err != nil {
fmt.Printf("echo https server exited error: %v\n", err)
}
}()
case WS:
go func() {
err := s.wsServer.ListenAndServe()
if err != nil {
fmt.Printf("echo ws server exited error: %v\n", err)
}
}()
case WSS:
go func() {
err := s.wssServer.ListenAndServeTLS("e2e.crt", "e2e.key")
if err != nil {
fmt.Printf("echo wss server exited error: %v\n", err)
}
}()
default:
return fmt.Errorf("unknown server type: %s", s.opt.Type)
}
return nil return nil
} }
@ -70,10 +116,22 @@ func (s *Server) Close() error {
if s.l != nil { if s.l != nil {
return s.l.Close() return s.l.Close()
} }
if s.httpServer != nil {
s.httpServer.Close()
}
if s.httpsServer != nil {
s.httpsServer.Close()
}
if s.wsServer != nil {
s.wsServer.Close()
}
if s.wssServer != nil {
s.wssServer.Close()
}
return nil return nil
} }
func (s *Server) initListener() (err error) { func (s *Server) init() (err error) {
switch s.opt.Type { switch s.opt.Type {
case TCP: case TCP:
s.l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort)) s.l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort))
@ -81,6 +139,30 @@ func (s *Server) initListener() (err error) {
s.l, err = fnet.ListenUDP(s.opt.BindAddr, int(s.opt.BindPort)) s.l, err = fnet.ListenUDP(s.opt.BindAddr, int(s.opt.BindPort))
case Unix: case Unix:
s.l, err = net.Listen("unix", s.opt.BindAddr) s.l, err = net.Listen("unix", s.opt.BindAddr)
case HTTP:
s.httpServer = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort),
Handler: http.HandlerFunc(echo),
}
fmt.Println("http echo server listen port", s.opt.BindPort)
case HTTPS:
s.httpsServer = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort),
Handler: http.HandlerFunc(echo),
}
fmt.Println("https echo server listen port", s.opt.BindPort)
case WS:
s.wsServer = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort),
Handler: http.HandlerFunc(ws),
}
fmt.Println("ws echo server listen port", s.opt.BindPort)
case WSS:
s.wssServer = &http.Server{
Addr: fmt.Sprintf("%s:%d", s.opt.BindAddr, s.opt.BindPort),
Handler: http.HandlerFunc(ws),
}
fmt.Println("wss echo server listen port", s.opt.BindPort)
default: default:
return fmt.Errorf("unknown server type: %s", s.opt.Type) return fmt.Errorf("unknown server type: %s", s.opt.Type)
} }
@ -109,3 +191,51 @@ func (s *Server) handle(c net.Conn) {
c.Write([]byte(response)) c.Write([]byte(response))
} }
} }
func echo(w http.ResponseWriter, r *http.Request) {
rh := make(map[string]string)
for key, _ := range r.Header {
rh[key] = r.Header.Get(key)
}
rh["Host"] = r.Host
rh["Path"] = r.URL.Path
data, err := json.Marshal(rh)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write(data)
return
}
var (
upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
)
func ws(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok {
fmt.Println(err)
}
return
}
go func() {
for {
_, data, err := conn.ReadMessage()
if err != nil {
fmt.Printf("reading message error: %v\n", err)
}
if err = conn.WriteMessage(websocket.TextMessage, data); err != nil {
fmt.Printf("writing message error: %v\n", err)
}
}
}()
}