1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-22 18:17:52 -05:00
v2fly/transport/internet/http/hub.go

208 lines
5.1 KiB
Go
Raw Normal View History

2018-03-01 07:16:52 -05:00
package http
import (
"context"
"io"
"net/http"
2018-03-01 08:22:33 -05:00
"strings"
"time"
2018-03-01 07:16:52 -05:00
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/net"
http_proto "github.com/v2fly/v2ray-core/v5/common/protocol/http"
"github.com/v2fly/v2ray-core/v5/common/serial"
"github.com/v2fly/v2ray-core/v5/common/session"
"github.com/v2fly/v2ray-core/v5/common/signal/done"
"github.com/v2fly/v2ray-core/v5/transport/internet"
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
2018-03-01 07:16:52 -05:00
)
type Listener struct {
server *http.Server
handler internet.ConnHandler
local net.Addr
2020-08-26 07:35:33 -04:00
config *Config
2020-10-29 03:30:38 -04:00
locker *internet.FileLocker // for unix domain socket
2018-03-01 07:16:52 -05:00
}
func (l *Listener) Addr() net.Addr {
return l.local
}
func (l *Listener) Close() error {
2020-10-29 03:30:38 -04:00
if l.locker != nil {
l.locker.Release()
}
return l.server.Close()
2018-03-01 07:16:52 -05:00
}
type flushWriter struct {
w io.Writer
2018-05-27 08:42:53 -04:00
d *done.Instance
2018-03-01 07:16:52 -05:00
}
func (fw flushWriter) Write(p []byte) (n int, err error) {
2018-03-21 07:53:57 -04:00
if fw.d.Done() {
return 0, io.ErrClosedPipe
}
2018-03-01 07:16:52 -05:00
n, err = fw.w.Write(p)
if f, ok := fw.w.(http.Flusher); ok {
f.Flush()
}
return
}
func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
2018-03-01 08:22:33 -05:00
host := request.Host
if !l.config.isValidHost(host) {
writer.WriteHeader(404)
return
}
path := l.config.getNormalizedPath()
if !strings.HasPrefix(request.URL.Path, path) {
writer.WriteHeader(404)
return
}
writer.Header().Set("Cache-Control", "no-store")
2021-03-02 06:36:02 -05:00
for _, httpHeader := range l.config.Header {
for _, httpHeaderValue := range httpHeader.Value {
writer.Header().Set(httpHeader.Name, httpHeaderValue)
}
}
2018-03-01 07:16:52 -05:00
writer.WriteHeader(200)
if f, ok := writer.(http.Flusher); ok {
f.Flush()
}
remoteAddr := l.Addr()
dest, err := net.ParseDestination(request.RemoteAddr)
if err != nil {
newError("failed to parse request remote addr: ", request.RemoteAddr).Base(err).WriteToLog()
} else {
remoteAddr = &net.TCPAddr{
IP: dest.Address.IP(),
Port: int(dest.Port),
}
}
forwardedAddress := http_proto.ParseXForwardedFor(request.Header)
if len(forwardedAddress) > 0 && forwardedAddress[0].Family().IsIP() {
2020-10-29 03:30:38 -04:00
remoteAddr = &net.TCPAddr{
IP: forwardedAddress[0].IP(),
Port: 0,
2020-10-29 03:30:38 -04:00
}
}
2018-05-27 08:42:53 -04:00
done := done.New()
conn := net.NewConnection(
net.ConnectionOutput(request.Body),
net.ConnectionInput(flushWriter{w: writer, d: done}),
2019-01-01 14:16:04 -05:00
net.ConnectionOnClose(common.ChainedClosable{done, request.Body}),
net.ConnectionLocalAddr(l.Addr()),
net.ConnectionRemoteAddr(remoteAddr),
)
l.handler(conn)
2018-04-15 14:40:47 -04:00
<-done.Wait()
2018-03-01 07:16:52 -05:00
}
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
httpSettings := streamSettings.ProtocolSettings.(*Config)
2020-10-29 03:30:38 -04:00
var listener *Listener
if port == net.Port(0) { // unix
listener = &Listener{
handler: handler,
local: &net.UnixAddr{
Name: address.Domain(),
Net: "unix",
},
config: httpSettings,
}
} else { // tcp
listener = &Listener{
handler: handler,
local: &net.TCPAddr{
IP: address.IP(),
Port: int(port),
},
config: httpSettings,
}
2018-03-01 07:16:52 -05:00
}
2019-07-04 23:18:00 -04:00
var server *http.Server
config := tls.ConfigFromStreamSettings(streamSettings)
2018-03-01 07:16:52 -05:00
if config == nil {
2019-07-04 23:18:00 -04:00
h2s := &http2.Server{}
2018-03-01 07:16:52 -05:00
2019-07-04 23:18:00 -04:00
server = &http.Server{
Addr: serial.Concat(address, ":", port),
Handler: h2c.NewHandler(listener, h2s),
ReadHeaderTimeout: time.Second * 4,
}
} else {
server = &http.Server{
Addr: serial.Concat(address, ":", port),
TLSConfig: config.GetTLSConfig(tls.WithNextProto("h2")),
Handler: listener,
ReadHeaderTimeout: time.Second * 4,
}
2018-03-01 07:16:52 -05:00
}
2020-10-29 03:30:38 -04:00
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
2018-03-01 07:16:52 -05:00
listener.server = server
2018-03-21 18:38:49 -04:00
go func() {
2020-10-29 03:30:38 -04:00
var streamListener net.Listener
var err error
if port == net.Port(0) { // unix
streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{
Name: address.Domain(),
Net: "unix",
}, streamSettings.SocketSettings)
if err != nil {
newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
2020-10-29 03:30:38 -04:00
return
}
locker := ctx.Value(address.Domain())
if locker != nil {
listener.locker = locker.(*internet.FileLocker)
}
} else { // tcp
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
IP: address.IP(),
Port: int(port),
}, streamSettings.SocketSettings)
if err != nil {
newError("failed to listen on ", address, ":", port).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
2020-10-29 03:30:38 -04:00
return
}
2018-09-10 07:23:27 -04:00
}
2020-10-29 03:30:38 -04:00
2019-07-04 23:18:00 -04:00
if config == nil {
2020-10-29 03:30:38 -04:00
err = server.Serve(streamListener)
2019-07-04 23:18:00 -04:00
if err != nil {
newError("stopping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
2019-07-04 23:18:00 -04:00
}
} else {
2020-10-29 03:30:38 -04:00
err = server.ServeTLS(streamListener, "", "")
2019-07-04 23:18:00 -04:00
if err != nil {
newError("stopping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
2019-07-04 23:18:00 -04:00
}
2018-03-21 18:38:49 -04:00
}
}()
2018-03-01 07:16:52 -05:00
return listener, nil
}
func init() {
2018-08-06 07:48:35 -04:00
common.Must(internet.RegisterTransportListener(protocolName, Listen))
2018-03-01 07:16:52 -05:00
}