glider/common/conn/conn.go

113 lines
2.2 KiB
Go
Raw Normal View History

package conn
2017-07-13 21:55:41 +08:00
import (
"bufio"
2020-08-25 22:14:08 +08:00
"errors"
2017-07-13 21:55:41 +08:00
"io"
"net"
2020-08-25 22:14:08 +08:00
"os"
"sync"
2017-07-13 21:55:41 +08:00
"time"
2020-04-19 17:03:39 +08:00
"github.com/nadoo/glider/common/pool"
2017-07-13 21:55:41 +08:00
)
2020-04-19 17:03:39 +08:00
const (
2020-08-25 22:14:08 +08:00
// TCPBufSize is the size of tcp buffer.
2020-04-19 17:03:39 +08:00
TCPBufSize = 16 << 10
2020-08-25 22:14:08 +08:00
// UDPBufSize is the size of udp buffer.
2020-04-19 17:03:39 +08:00
UDPBufSize = 64 << 10
)
2020-08-25 22:14:08 +08:00
// Conn is a connection with buffered reader.
type Conn struct {
2017-07-13 21:55:41 +08:00
r *bufio.Reader
net.Conn
}
// NewConn returns a new conn.
2018-12-14 00:02:25 +08:00
func NewConn(c net.Conn) *Conn {
return &Conn{bufio.NewReader(c), c}
2017-07-13 21:55:41 +08:00
}
// Peek returns the next n bytes without advancing the reader.
2018-12-14 00:02:25 +08:00
func (c *Conn) Peek(n int) ([]byte, error) {
2017-07-13 21:55:41 +08:00
return c.r.Peek(n)
}
2018-12-14 00:02:25 +08:00
func (c *Conn) Read(p []byte) (int, error) {
2017-07-13 21:55:41 +08:00
return c.r.Read(p)
}
// Reader returns the internal bufio.Reader.
2018-12-14 00:02:25 +08:00
func (c *Conn) Reader() *bufio.Reader {
return c.r
}
// Relay relays between left and right.
2020-08-25 22:14:08 +08:00
func Relay(left, right net.Conn) error {
var err, err1 error
var wg sync.WaitGroup
var wait = 5 * time.Second
2017-07-13 21:55:41 +08:00
2020-08-25 22:14:08 +08:00
wg.Add(1)
2017-07-13 21:55:41 +08:00
go func() {
2020-08-25 22:14:08 +08:00
defer wg.Done()
_, err1 = Copy(right, left)
right.SetReadDeadline(time.Now().Add(wait)) // unblock read on right
2017-07-13 21:55:41 +08:00
}()
2020-08-25 22:14:08 +08:00
_, err = Copy(left, right)
left.SetReadDeadline(time.Now().Add(wait)) // unblock read on left
wg.Wait()
2020-04-19 17:03:39 +08:00
2020-08-25 22:14:08 +08:00
if err1 != nil && !errors.Is(err1, os.ErrDeadlineExceeded) { // requires Go 1.15+
return err1
}
2017-07-13 21:55:41 +08:00
2020-08-25 22:14:08 +08:00
if err != nil && !errors.Is(err, os.ErrDeadlineExceeded) {
return err
2017-07-13 21:55:41 +08:00
}
2020-08-25 22:14:08 +08:00
return nil
}
// Copy copies from src to dst.
func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
buf := pool.GetBuffer(TCPBufSize)
defer pool.PutBuffer(buf)
return io.CopyBuffer(dst, src, buf)
2017-07-13 21:55:41 +08:00
}
2018-01-08 18:14:57 +08:00
// RelayUDP copys from src to dst at target with read timeout.
func RelayUDP(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error {
2020-04-19 23:20:15 +08:00
b := pool.GetBuffer(UDPBufSize)
defer pool.PutBuffer(b)
2020-04-19 17:03:39 +08:00
2018-01-08 18:14:57 +08:00
for {
src.SetReadDeadline(time.Now().Add(timeout))
2020-04-19 23:20:15 +08:00
n, _, err := src.ReadFrom(b)
2018-01-08 18:14:57 +08:00
if err != nil {
return err
}
2020-04-19 23:20:15 +08:00
_, err = dst.WriteTo(b[:n], target)
2018-01-08 18:14:57 +08:00
if err != nil {
return err
}
}
}
// OutboundIP returns preferred outbound ip of this machine.
func OutboundIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return ""
}
defer conn.Close()
return conn.LocalAddr().(*net.UDPAddr).IP.String()
}