sing/common/bufio/counter_conn.go
2023-04-25 20:27:20 +08:00

96 lines
2 KiB
Go

package bufio
import (
"io"
"net"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/atomic"
"github.com/sagernet/sing/common/buf"
N "github.com/sagernet/sing/common/network"
)
func NewInt64CounterConn(conn net.Conn, readCounter []*atomic.Int64, writeCounter []*atomic.Int64) *CounterConn {
return &CounterConn{
NewExtendedConn(conn),
common.Map(readCounter, func(it *atomic.Int64) N.CountFunc {
return func(n int64) {
it.Add(n)
}
}),
common.Map(writeCounter, func(it *atomic.Int64) N.CountFunc {
return func(n int64) {
it.Add(n)
}
}),
}
}
func NewCounterConn(conn net.Conn, readCounter []N.CountFunc, writeCounter []N.CountFunc) *CounterConn {
return &CounterConn{NewExtendedConn(conn), readCounter, writeCounter}
}
type CounterConn struct {
N.ExtendedConn
readCounter []N.CountFunc
writeCounter []N.CountFunc
}
func (c *CounterConn) Read(p []byte) (n int, err error) {
n, err = c.ExtendedConn.Read(p)
if n > 0 {
for _, counter := range c.readCounter {
counter(int64(n))
}
}
return n, err
}
func (c *CounterConn) ReadBuffer(buffer *buf.Buffer) error {
err := c.ExtendedConn.ReadBuffer(buffer)
if err != nil {
return err
}
if buffer.Len() > 0 {
for _, counter := range c.readCounter {
counter(int64(buffer.Len()))
}
}
return nil
}
func (c *CounterConn) Write(p []byte) (n int, err error) {
n, err = c.ExtendedConn.Write(p)
if n > 0 {
for _, counter := range c.writeCounter {
counter(int64(n))
}
}
return n, err
}
func (c *CounterConn) WriteBuffer(buffer *buf.Buffer) error {
dataLen := int64(buffer.Len())
err := c.ExtendedConn.WriteBuffer(buffer)
if err != nil {
return err
}
if dataLen > 0 {
for _, counter := range c.writeCounter {
counter(dataLen)
}
}
return nil
}
func (c *CounterConn) UnwrapReader() (io.Reader, []N.CountFunc) {
return c.ExtendedConn, c.readCounter
}
func (c *CounterConn) UnwrapWriter() (io.Writer, []N.CountFunc) {
return c.ExtendedConn, c.writeCounter
}
func (c *CounterConn) Upstream() any {
return c.ExtendedConn
}