|
@@ -17,6 +17,7 @@ import (
|
|
|
"github.com/xtls/xray-core/core"
|
|
|
"github.com/xtls/xray-core/features/dns"
|
|
|
"github.com/xtls/xray-core/features/policy"
|
|
|
+ "github.com/xtls/xray-core/features/stats"
|
|
|
"github.com/xtls/xray-core/transport"
|
|
|
"github.com/xtls/xray-core/transport/internet"
|
|
|
)
|
|
@@ -148,7 +149,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|
|
if destination.Network == net.Network_TCP {
|
|
|
writer = buf.NewWriter(conn)
|
|
|
} else {
|
|
|
- writer = &buf.SequentialWriter{Writer: conn}
|
|
|
+ writer = NewPacketWriter(conn)
|
|
|
}
|
|
|
|
|
|
if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil {
|
|
@@ -165,7 +166,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|
|
if destination.Network == net.Network_TCP {
|
|
|
reader = buf.NewReader(conn)
|
|
|
} else {
|
|
|
- reader = buf.NewPacketReader(conn)
|
|
|
+ reader = NewPacketReader(conn)
|
|
|
}
|
|
|
if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
|
|
|
return newError("failed to process response").Base(err)
|
|
@@ -180,3 +181,93 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
+
|
|
|
+func NewPacketReader(conn net.Conn) buf.Reader {
|
|
|
+ iConn := conn
|
|
|
+ statConn, ok := iConn.(*internet.StatCouterConnection)
|
|
|
+ if ok {
|
|
|
+ iConn = statConn.Connection
|
|
|
+ }
|
|
|
+ var counter stats.Counter
|
|
|
+ if statConn != nil {
|
|
|
+ counter = statConn.ReadCounter
|
|
|
+ }
|
|
|
+ if c, ok := iConn.(*internet.PacketConnWrapper); ok {
|
|
|
+ return &PacketReader{
|
|
|
+ PacketConnWrapper: c,
|
|
|
+ Counter: counter,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return &buf.PacketReader{Reader: conn}
|
|
|
+}
|
|
|
+
|
|
|
+type PacketReader struct {
|
|
|
+ *internet.PacketConnWrapper
|
|
|
+ stats.Counter
|
|
|
+}
|
|
|
+
|
|
|
+func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|
|
+ b := buf.New()
|
|
|
+ b.Resize(0, buf.Size)
|
|
|
+ n, d, err := r.PacketConnWrapper.ReadFrom(b.Bytes())
|
|
|
+ if err != nil {
|
|
|
+ b.Release()
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ b.Resize(0, int32(n))
|
|
|
+ b.UDP = d.(*net.UDPAddr)
|
|
|
+ if r.Counter != nil {
|
|
|
+ r.Counter.Add(int64(n))
|
|
|
+ }
|
|
|
+ return buf.MultiBuffer{b}, nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewPacketWriter(conn net.Conn) buf.Writer {
|
|
|
+ iConn := conn
|
|
|
+ statConn, ok := iConn.(*internet.StatCouterConnection)
|
|
|
+ if ok {
|
|
|
+ iConn = statConn.Connection
|
|
|
+ }
|
|
|
+ var counter stats.Counter
|
|
|
+ if statConn != nil {
|
|
|
+ counter = statConn.WriteCounter
|
|
|
+ }
|
|
|
+ if c, ok := iConn.(*internet.PacketConnWrapper); ok {
|
|
|
+ return &PacketWriter{
|
|
|
+ PacketConnWrapper: c,
|
|
|
+ Counter: counter,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return &buf.SequentialWriter{Writer: conn}
|
|
|
+}
|
|
|
+
|
|
|
+type PacketWriter struct {
|
|
|
+ *internet.PacketConnWrapper
|
|
|
+ stats.Counter
|
|
|
+}
|
|
|
+
|
|
|
+func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|
|
+ for {
|
|
|
+ mb2, b := buf.SplitFirst(mb)
|
|
|
+ mb = mb2
|
|
|
+ if b == nil {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ var n int
|
|
|
+ var err error
|
|
|
+ if b.UDP != nil {
|
|
|
+ n, err = w.PacketConnWrapper.WriteTo(b.Bytes(), b.UDP)
|
|
|
+ } else {
|
|
|
+ n, err = w.PacketConnWrapper.Write(b.Bytes())
|
|
|
+ }
|
|
|
+ b.Release()
|
|
|
+ if err != nil {
|
|
|
+ buf.ReleaseMulti(mb)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if w.Counter != nil {
|
|
|
+ w.Counter.Add(int64(n))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|