github.com/sagernet/sing-box@v1.2.7/transport/v2rayhttp/conn.go (about) 1 package v2rayhttp 2 3 import ( 4 std_bufio "bufio" 5 "io" 6 "net" 7 "net/http" 8 "os" 9 "strings" 10 "sync" 11 "time" 12 13 "github.com/sagernet/sing-box/common/baderror" 14 "github.com/sagernet/sing/common" 15 "github.com/sagernet/sing/common/buf" 16 "github.com/sagernet/sing/common/bufio" 17 E "github.com/sagernet/sing/common/exceptions" 18 F "github.com/sagernet/sing/common/format" 19 N "github.com/sagernet/sing/common/network" 20 ) 21 22 type HTTPConn struct { 23 net.Conn 24 request *http.Request 25 requestWritten bool 26 responseRead bool 27 responseCache *buf.Buffer 28 } 29 30 func NewHTTP1Conn(conn net.Conn, request *http.Request) *HTTPConn { 31 return &HTTPConn{ 32 Conn: conn, 33 request: request, 34 } 35 } 36 37 func (c *HTTPConn) Read(b []byte) (n int, err error) { 38 if !c.responseRead { 39 reader := std_bufio.NewReader(c.Conn) 40 response, err := http.ReadResponse(reader, c.request) 41 if err != nil { 42 return 0, E.Cause(err, "read response") 43 } 44 if response.StatusCode != 200 { 45 return 0, E.New("unexpected status: ", response.Status) 46 } 47 if cacheLen := reader.Buffered(); cacheLen > 0 { 48 c.responseCache = buf.NewSize(cacheLen) 49 _, err = c.responseCache.ReadFullFrom(reader, cacheLen) 50 if err != nil { 51 c.responseCache.Release() 52 return 0, E.Cause(err, "read cache") 53 } 54 } 55 c.responseRead = true 56 } 57 if c.responseCache != nil { 58 n, err = c.responseCache.Read(b) 59 if err == io.EOF { 60 c.responseCache.Release() 61 c.responseCache = nil 62 } 63 if n > 0 { 64 return n, nil 65 } 66 } 67 return c.Conn.Read(b) 68 } 69 70 func (c *HTTPConn) Write(b []byte) (int, error) { 71 if !c.requestWritten { 72 err := c.writeRequest(b) 73 if err != nil { 74 return 0, E.Cause(err, "write request") 75 } 76 c.requestWritten = true 77 return len(b), nil 78 } 79 return c.Conn.Write(b) 80 } 81 82 func (c *HTTPConn) writeRequest(payload []byte) error { 83 writer := bufio.NewBufferedWriter(c.Conn, buf.New()) 84 const CRLF = "\r\n" 85 _, err := writer.Write([]byte(F.ToString(c.request.Method, " ", c.request.URL.RequestURI(), " HTTP/1.1", CRLF))) 86 if err != nil { 87 return err 88 } 89 if c.request.Header.Get("Host") == "" { 90 c.request.Header.Set("Host", c.request.Host) 91 } 92 for key, value := range c.request.Header { 93 _, err = writer.Write([]byte(F.ToString(key, ": ", strings.Join(value, ", "), CRLF))) 94 if err != nil { 95 return err 96 } 97 } 98 _, err = writer.Write([]byte(CRLF)) 99 if err != nil { 100 return err 101 } 102 _, err = writer.Write(payload) 103 if err != nil { 104 return err 105 } 106 err = writer.Fallthrough() 107 if err != nil { 108 return err 109 } 110 return nil 111 } 112 113 func (c *HTTPConn) ReaderReplaceable() bool { 114 return c.responseRead 115 } 116 117 func (c *HTTPConn) WriterReplaceable() bool { 118 return c.requestWritten 119 } 120 121 func (c *HTTPConn) NeedHandshake() bool { 122 return !c.requestWritten 123 } 124 125 func (c *HTTPConn) Upstream() any { 126 return c.Conn 127 } 128 129 type HTTP2Conn struct { 130 reader io.Reader 131 writer io.Writer 132 create chan struct{} 133 err error 134 } 135 136 func NewHTTPConn(reader io.Reader, writer io.Writer) HTTP2Conn { 137 return HTTP2Conn{ 138 reader: reader, 139 writer: writer, 140 } 141 } 142 143 func NewLateHTTPConn(writer io.Writer) *HTTP2Conn { 144 return &HTTP2Conn{ 145 create: make(chan struct{}), 146 writer: writer, 147 } 148 } 149 150 func (c *HTTP2Conn) Setup(reader io.Reader, err error) { 151 c.reader = reader 152 c.err = err 153 close(c.create) 154 } 155 156 func (c *HTTP2Conn) Read(b []byte) (n int, err error) { 157 if c.reader == nil { 158 <-c.create 159 if c.err != nil { 160 return 0, c.err 161 } 162 } 163 n, err = c.reader.Read(b) 164 return n, baderror.WrapH2(err) 165 } 166 167 func (c *HTTP2Conn) Write(b []byte) (n int, err error) { 168 n, err = c.writer.Write(b) 169 return n, baderror.WrapH2(err) 170 } 171 172 func (c *HTTP2Conn) Close() error { 173 return common.Close(c.reader, c.writer) 174 } 175 176 func (c *HTTP2Conn) LocalAddr() net.Addr { 177 return nil 178 } 179 180 func (c *HTTP2Conn) RemoteAddr() net.Addr { 181 return nil 182 } 183 184 func (c *HTTP2Conn) SetDeadline(t time.Time) error { 185 return os.ErrInvalid 186 } 187 188 func (c *HTTP2Conn) SetReadDeadline(t time.Time) error { 189 return os.ErrInvalid 190 } 191 192 func (c *HTTP2Conn) SetWriteDeadline(t time.Time) error { 193 return os.ErrInvalid 194 } 195 196 func (c *HTTP2Conn) NeedAdditionalReadDeadline() bool { 197 return true 198 } 199 200 type ServerHTTPConn struct { 201 HTTP2Conn 202 flusher http.Flusher 203 } 204 205 func (c *ServerHTTPConn) Write(b []byte) (n int, err error) { 206 n, err = c.writer.Write(b) 207 if err == nil { 208 c.flusher.Flush() 209 } 210 return 211 } 212 213 type HTTP2ConnWrapper struct { 214 N.ExtendedConn 215 access sync.Mutex 216 closed bool 217 } 218 219 func NewHTTP2Wrapper(conn net.Conn) *HTTP2ConnWrapper { 220 return &HTTP2ConnWrapper{ 221 ExtendedConn: bufio.NewExtendedConn(conn), 222 } 223 } 224 225 func (w *HTTP2ConnWrapper) Write(p []byte) (n int, err error) { 226 w.access.Lock() 227 defer w.access.Unlock() 228 if w.closed { 229 return 0, net.ErrClosed 230 } 231 return w.ExtendedConn.Write(p) 232 } 233 234 func (w *HTTP2ConnWrapper) WriteBuffer(buffer *buf.Buffer) error { 235 w.access.Lock() 236 defer w.access.Unlock() 237 if w.closed { 238 return net.ErrClosed 239 } 240 return w.ExtendedConn.WriteBuffer(buffer) 241 } 242 243 func (w *HTTP2ConnWrapper) CloseWrapper() { 244 w.access.Lock() 245 defer w.access.Unlock() 246 w.closed = true 247 } 248 249 func (w *HTTP2ConnWrapper) Upstream() any { 250 return w.ExtendedConn 251 }