1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-07-01 11:35:23 +00:00
v2fly/transport/internet/http/hub.go

118 lines
2.4 KiB
Go
Raw Normal View History

2018-03-01 12:16:52 +00:00
package http
import (
"context"
"io"
"net/http"
2018-03-01 13:22:33 +00:00
"strings"
2018-03-01 12:16:52 +00:00
"v2ray.com/core/common"
"v2ray.com/core/common/net"
"v2ray.com/core/common/serial"
"v2ray.com/core/common/signal"
"v2ray.com/core/transport/internet"
"v2ray.com/core/transport/internet/tls"
)
type Listener struct {
server *http.Server
handler internet.ConnHandler
local net.Addr
2018-03-01 13:22:33 +00:00
config Config
2018-03-01 12:16:52 +00:00
}
func (l *Listener) Addr() net.Addr {
return l.local
}
func (l *Listener) Close() error {
return l.server.Close()
2018-03-01 12:16:52 +00:00
}
type flushWriter struct {
w io.Writer
2018-03-21 11:53:57 +00:00
d *signal.Done
2018-03-01 12:16:52 +00:00
}
func (fw flushWriter) Write(p []byte) (n int, err error) {
2018-03-21 11:53:57 +00:00
if fw.d.Done() {
return 0, io.ErrClosedPipe
}
2018-03-01 12:16:52 +00: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 13:22:33 +00: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")
2018-03-01 12:16:52 +00:00
writer.WriteHeader(200)
if f, ok := writer.(http.Flusher); ok {
f.Flush()
}
done := signal.NewDone()
l.handler(&Connection{
Reader: request.Body,
2018-03-21 11:53:57 +00:00
Writer: flushWriter{w: writer, d: done},
Closer: common.NewChainedClosable(done, request.Body),
2018-03-01 12:16:52 +00:00
Local: l.Addr(),
Remote: l.Addr(),
})
<-done.C()
}
func Listen(ctx context.Context, address net.Address, port net.Port, handler internet.ConnHandler) (internet.Listener, error) {
2018-03-01 13:22:33 +00:00
rawSettings := internet.TransportSettingsFromContext(ctx)
httpSettings, ok := rawSettings.(*Config)
if !ok {
return nil, newError("HTTP config is not set.").AtError()
}
2018-03-01 12:16:52 +00:00
listener := &Listener{
handler: handler,
local: &net.TCPAddr{
IP: address.IP(),
Port: int(port),
},
2018-03-01 13:22:33 +00:00
config: *httpSettings,
2018-03-01 12:16:52 +00:00
}
config := tls.ConfigFromContext(ctx)
if config == nil {
return nil, newError("TLS must be enabled for http transport.").AtWarning()
}
server := &http.Server{
Addr: serial.Concat(address, ":", port),
TLSConfig: config.GetTLSConfig(tls.WithNextProto("h2")),
Handler: listener,
}
listener.server = server
2018-03-21 22:38:49 +00:00
go func() {
err := server.ListenAndServeTLS("", "")
if err != nil {
newError("stoping serving TLS").Base(err).WriteToLog()
}
}()
2018-03-01 12:16:52 +00:00
return listener, nil
}
func init() {
common.Must(internet.RegisterTransportListener(internet.TransportProtocol_HTTP, Listen))
}