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