sing-box/transport/v2rayhttp/conn.go

252 lines
4.9 KiB
Go
Raw Normal View History

2022-08-22 14:19:25 +00:00
package v2rayhttp
import (
std_bufio "bufio"
2022-08-22 14:19:25 +00:00
"io"
"net"
"net/http"
"os"
"strings"
2023-01-04 07:19:39 +00:00
"sync"
2022-08-22 14:19:25 +00:00
"time"
2022-08-29 02:10:41 +00:00
"github.com/sagernet/sing-box/common/baderror"
2022-08-22 14:19:25 +00:00
"github.com/sagernet/sing/common"
2023-01-04 07:19:39 +00:00
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
2023-01-04 07:19:39 +00:00
N "github.com/sagernet/sing/common/network"
2022-08-22 14:19:25 +00:00
)
type HTTPConn struct {
net.Conn
request *http.Request
requestWritten bool
responseRead bool
responseCache *buf.Buffer
}
func NewHTTP1Conn(conn net.Conn, request *http.Request) *HTTPConn {
return &HTTPConn{
Conn: conn,
request: request,
}
}
func (c *HTTPConn) Read(b []byte) (n int, err error) {
if !c.responseRead {
reader := std_bufio.NewReader(c.Conn)
response, err := http.ReadResponse(reader, c.request)
if err != nil {
return 0, E.Cause(err, "read response")
}
if response.StatusCode != 200 {
return 0, E.New("unexpected status: ", response.Status)
}
if cacheLen := reader.Buffered(); cacheLen > 0 {
c.responseCache = buf.NewSize(cacheLen)
_, err = c.responseCache.ReadFullFrom(reader, cacheLen)
if err != nil {
c.responseCache.Release()
return 0, E.Cause(err, "read cache")
}
}
c.responseRead = true
}
if c.responseCache != nil {
n, err = c.responseCache.Read(b)
if err == io.EOF {
c.responseCache.Release()
c.responseCache = nil
}
if n > 0 {
return n, nil
}
}
return c.Conn.Read(b)
}
func (c *HTTPConn) Write(b []byte) (int, error) {
if !c.requestWritten {
err := c.writeRequest(b)
if err != nil {
return 0, E.Cause(err, "write request")
}
c.requestWritten = true
return len(b), nil
}
return c.Conn.Write(b)
}
func (c *HTTPConn) writeRequest(payload []byte) error {
writer := bufio.NewBufferedWriter(c.Conn, buf.New())
const CRLF = "\r\n"
_, err := writer.Write([]byte(F.ToString(c.request.Method, " ", c.request.URL.RequestURI(), " HTTP/1.1", CRLF)))
if err != nil {
return err
}
if c.request.Header.Get("Host") == "" {
c.request.Header.Set("Host", c.request.Host)
}
for key, value := range c.request.Header {
_, err = writer.Write([]byte(F.ToString(key, ": ", strings.Join(value, ", "), CRLF)))
if err != nil {
return err
}
}
_, err = writer.Write([]byte(CRLF))
if err != nil {
return err
}
_, err = writer.Write(payload)
if err != nil {
return err
}
err = writer.Fallthrough()
if err != nil {
return err
}
return nil
}
func (c *HTTPConn) ReaderReplaceable() bool {
return c.responseRead
}
func (c *HTTPConn) WriterReplaceable() bool {
return c.requestWritten
}
func (c *HTTPConn) NeedHandshake() bool {
return !c.requestWritten
}
func (c *HTTPConn) Upstream() any {
return c.Conn
}
type HTTP2Conn struct {
2022-08-22 14:19:25 +00:00
reader io.Reader
writer io.Writer
create chan struct{}
err error
}
func NewHTTPConn(reader io.Reader, writer io.Writer) HTTP2Conn {
return HTTP2Conn{
reader: reader,
writer: writer,
}
}
2023-04-21 09:49:43 +00:00
func NewLateHTTPConn(writer io.Writer) *HTTP2Conn {
return &HTTP2Conn{
create: make(chan struct{}),
writer: writer,
}
}
2023-04-21 09:49:43 +00:00
func (c *HTTP2Conn) Setup(reader io.Reader, err error) {
c.reader = reader
c.err = err
close(c.create)
2022-08-22 14:19:25 +00:00
}
func (c *HTTP2Conn) Read(b []byte) (n int, err error) {
if c.reader == nil {
<-c.create
if c.err != nil {
return 0, c.err
}
}
2022-08-25 02:56:57 +00:00
n, err = c.reader.Read(b)
2022-08-29 02:10:41 +00:00
return n, baderror.WrapH2(err)
2022-08-22 14:19:25 +00:00
}
func (c *HTTP2Conn) Write(b []byte) (n int, err error) {
2022-08-25 02:56:57 +00:00
n, err = c.writer.Write(b)
2022-08-29 02:10:41 +00:00
return n, baderror.WrapH2(err)
2022-08-22 14:19:25 +00:00
}
func (c *HTTP2Conn) Close() error {
2022-08-22 14:19:25 +00:00
return common.Close(c.reader, c.writer)
}
func (c *HTTP2Conn) LocalAddr() net.Addr {
2022-08-22 14:19:25 +00:00
return nil
}
func (c *HTTP2Conn) RemoteAddr() net.Addr {
2022-08-22 14:19:25 +00:00
return nil
}
func (c *HTTP2Conn) SetDeadline(t time.Time) error {
2022-11-23 06:56:31 +00:00
return os.ErrInvalid
2022-08-22 14:19:25 +00:00
}
func (c *HTTP2Conn) SetReadDeadline(t time.Time) error {
2022-11-23 06:56:31 +00:00
return os.ErrInvalid
2022-08-22 14:19:25 +00:00
}
func (c *HTTP2Conn) SetWriteDeadline(t time.Time) error {
2022-11-23 06:56:31 +00:00
return os.ErrInvalid
2022-08-22 14:19:25 +00:00
}
2023-04-19 13:48:54 +00:00
func (c *HTTP2Conn) NeedAdditionalReadDeadline() bool {
return true
}
2022-08-22 14:19:25 +00:00
type ServerHTTPConn struct {
HTTP2Conn
2022-08-22 14:19:25 +00:00
flusher http.Flusher
}
func (c *ServerHTTPConn) Write(b []byte) (n int, err error) {
n, err = c.writer.Write(b)
if err == nil {
c.flusher.Flush()
}
return
}
2023-01-04 07:19:39 +00:00
type HTTP2ConnWrapper struct {
N.ExtendedConn
access sync.Mutex
closed bool
}
func NewHTTP2Wrapper(conn net.Conn) *HTTP2ConnWrapper {
return &HTTP2ConnWrapper{
ExtendedConn: bufio.NewExtendedConn(conn),
}
}
func (w *HTTP2ConnWrapper) Write(p []byte) (n int, err error) {
w.access.Lock()
defer w.access.Unlock()
if w.closed {
return 0, net.ErrClosed
}
return w.ExtendedConn.Write(p)
}
func (w *HTTP2ConnWrapper) WriteBuffer(buffer *buf.Buffer) error {
w.access.Lock()
defer w.access.Unlock()
if w.closed {
return net.ErrClosed
}
return w.ExtendedConn.WriteBuffer(buffer)
}
func (w *HTTP2ConnWrapper) CloseWrapper() {
w.access.Lock()
defer w.access.Unlock()
w.closed = true
}
func (w *HTTP2ConnWrapper) Upstream() any {
return w.ExtendedConn
}