github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/http/hub.go (about) 1 // +build !confonly 2 3 package http 4 5 import ( 6 "context" 7 "io" 8 "net/http" 9 "strings" 10 "time" 11 12 "golang.org/x/net/http2" 13 "golang.org/x/net/http2/h2c" 14 15 "v2ray.com/core/common" 16 "v2ray.com/core/common/net" 17 http_proto "v2ray.com/core/common/protocol/http" 18 "v2ray.com/core/common/serial" 19 "v2ray.com/core/common/session" 20 "v2ray.com/core/common/signal/done" 21 "v2ray.com/core/transport/internet" 22 "v2ray.com/core/transport/internet/tls" 23 ) 24 25 type Listener struct { 26 server *http.Server 27 handler internet.ConnHandler 28 local net.Addr 29 config *Config 30 } 31 32 func (l *Listener) Addr() net.Addr { 33 return l.local 34 } 35 36 func (l *Listener) Close() error { 37 return l.server.Close() 38 } 39 40 type flushWriter struct { 41 w io.Writer 42 d *done.Instance 43 } 44 45 func (fw flushWriter) Write(p []byte) (n int, err error) { 46 if fw.d.Done() { 47 return 0, io.ErrClosedPipe 48 } 49 50 n, err = fw.w.Write(p) 51 if f, ok := fw.w.(http.Flusher); ok { 52 f.Flush() 53 } 54 return 55 } 56 57 func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request) { 58 host := request.Host 59 if !l.config.isValidHost(host) { 60 writer.WriteHeader(404) 61 return 62 } 63 path := l.config.getNormalizedPath() 64 if !strings.HasPrefix(request.URL.Path, path) { 65 writer.WriteHeader(404) 66 return 67 } 68 69 writer.Header().Set("Cache-Control", "no-store") 70 writer.WriteHeader(200) 71 if f, ok := writer.(http.Flusher); ok { 72 f.Flush() 73 } 74 75 remoteAddr := l.Addr() 76 dest, err := net.ParseDestination(request.RemoteAddr) 77 if err != nil { 78 newError("failed to parse request remote addr: ", request.RemoteAddr).Base(err).WriteToLog() 79 } else { 80 remoteAddr = &net.TCPAddr{ 81 IP: dest.Address.IP(), 82 Port: int(dest.Port), 83 } 84 } 85 86 forwardedAddrs := http_proto.ParseXForwardedFor(request.Header) 87 if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() { 88 remoteAddr.(*net.TCPAddr).IP = forwardedAddrs[0].IP() 89 } 90 91 done := done.New() 92 conn := net.NewConnection( 93 net.ConnectionOutput(request.Body), 94 net.ConnectionInput(flushWriter{w: writer, d: done}), 95 net.ConnectionOnClose(common.ChainedClosable{done, request.Body}), 96 net.ConnectionLocalAddr(l.Addr()), 97 net.ConnectionRemoteAddr(remoteAddr), 98 ) 99 l.handler(conn) 100 <-done.Wait() 101 } 102 103 func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) { 104 httpSettings := streamSettings.ProtocolSettings.(*Config) 105 listener := &Listener{ 106 handler: handler, 107 local: &net.TCPAddr{ 108 IP: address.IP(), 109 Port: int(port), 110 }, 111 config: httpSettings, 112 } 113 114 var server *http.Server 115 config := tls.ConfigFromStreamSettings(streamSettings) 116 if config == nil { 117 h2s := &http2.Server{} 118 119 server = &http.Server{ 120 Addr: serial.Concat(address, ":", port), 121 Handler: h2c.NewHandler(listener, h2s), 122 ReadHeaderTimeout: time.Second * 4, 123 } 124 } else { 125 server = &http.Server{ 126 Addr: serial.Concat(address, ":", port), 127 TLSConfig: config.GetTLSConfig(tls.WithNextProto("h2")), 128 Handler: listener, 129 ReadHeaderTimeout: time.Second * 4, 130 } 131 } 132 133 listener.server = server 134 go func() { 135 tcpListener, err := internet.ListenSystem(ctx, &net.TCPAddr{ 136 IP: address.IP(), 137 Port: int(port), 138 }, streamSettings.SocketSettings) 139 if err != nil { 140 newError("failed to listen on", address, ":", port).Base(err).WriteToLog(session.ExportIDToError(ctx)) 141 return 142 } 143 if config == nil { 144 err = server.Serve(tcpListener) 145 if err != nil { 146 newError("stoping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx)) 147 } 148 } else { 149 err = server.ServeTLS(tcpListener, "", "") 150 if err != nil { 151 newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx)) 152 } 153 } 154 }() 155 156 return listener, nil 157 } 158 159 func init() { 160 common.Must(internet.RegisterTransportListener(protocolName, Listen)) 161 }