mirror of https://github.com/fatedier/frp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
1.2 KiB
68 lines
1.2 KiB
package net |
|
|
|
import ( |
|
"errors" |
|
"net" |
|
"net/http" |
|
"time" |
|
|
|
"golang.org/x/net/websocket" |
|
) |
|
|
|
var ErrWebsocketListenerClosed = errors.New("websocket listener closed") |
|
|
|
const ( |
|
FrpWebsocketPath = "/~!frp" |
|
) |
|
|
|
type WebsocketListener struct { |
|
ln net.Listener |
|
acceptCh chan net.Conn |
|
|
|
server *http.Server |
|
} |
|
|
|
// NewWebsocketListener to handle websocket connections |
|
// ln: tcp listener for websocket connections |
|
func NewWebsocketListener(ln net.Listener) (wl *WebsocketListener) { |
|
wl = &WebsocketListener{ |
|
acceptCh: make(chan net.Conn), |
|
} |
|
|
|
muxer := http.NewServeMux() |
|
muxer.Handle(FrpWebsocketPath, websocket.Handler(func(c *websocket.Conn) { |
|
notifyCh := make(chan struct{}) |
|
conn := WrapCloseNotifyConn(c, func() { |
|
close(notifyCh) |
|
}) |
|
wl.acceptCh <- conn |
|
<-notifyCh |
|
})) |
|
|
|
wl.server = &http.Server{ |
|
Addr: ln.Addr().String(), |
|
Handler: muxer, |
|
ReadHeaderTimeout: 60 * time.Second, |
|
} |
|
|
|
go func() { |
|
_ = wl.server.Serve(ln) |
|
}() |
|
return |
|
} |
|
|
|
func (p *WebsocketListener) Accept() (net.Conn, error) { |
|
c, ok := <-p.acceptCh |
|
if !ok { |
|
return nil, ErrWebsocketListenerClosed |
|
} |
|
return c, nil |
|
} |
|
|
|
func (p *WebsocketListener) Close() error { |
|
return p.server.Close() |
|
} |
|
|
|
func (p *WebsocketListener) Addr() net.Addr { |
|
return p.ln.Addr() |
|
}
|
|
|