2018-06-26 16:15:48 +08:00
|
|
|
package conn
|
2017-07-13 21:55:41 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"time"
|
2018-06-26 16:15:48 +08:00
|
|
|
|
|
|
|
"github.com/nadoo/glider/common/log"
|
2017-07-13 21:55:41 +08:00
|
|
|
)
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
const UDPBufSize = 65536
|
|
|
|
|
|
|
|
type Conn struct {
|
2017-07-13 21:55:41 +08:00
|
|
|
r *bufio.Reader
|
|
|
|
net.Conn
|
|
|
|
}
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
func NewConn(c net.Conn) Conn {
|
|
|
|
return Conn{bufio.NewReader(c), c}
|
2017-07-13 21:55:41 +08:00
|
|
|
}
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
func NewConnSize(c net.Conn, n int) Conn {
|
|
|
|
return Conn{bufio.NewReaderSize(c, n), c}
|
2017-07-13 21:55:41 +08:00
|
|
|
}
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
func (c Conn) Peek(n int) ([]byte, error) {
|
2017-07-13 21:55:41 +08:00
|
|
|
return c.r.Peek(n)
|
|
|
|
}
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
func (c Conn) Read(p []byte) (int, error) {
|
2017-07-13 21:55:41 +08:00
|
|
|
return c.r.Read(p)
|
|
|
|
}
|
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
func Relay(left, right net.Conn) (int64, int64, error) {
|
2017-07-13 21:55:41 +08:00
|
|
|
type res struct {
|
|
|
|
N int64
|
|
|
|
Err error
|
|
|
|
}
|
|
|
|
ch := make(chan res)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
n, err := io.Copy(right, left)
|
|
|
|
right.SetDeadline(time.Now()) // wake up the other goroutine blocking on right
|
|
|
|
left.SetDeadline(time.Now()) // wake up the other goroutine blocking on left
|
|
|
|
ch <- res{n, err}
|
|
|
|
}()
|
|
|
|
|
|
|
|
n, err := io.Copy(left, right)
|
|
|
|
right.SetDeadline(time.Now()) // wake up the other goroutine blocking on right
|
|
|
|
left.SetDeadline(time.Now()) // wake up the other goroutine blocking on left
|
|
|
|
rs := <-ch
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
err = rs.Err
|
|
|
|
}
|
|
|
|
return n, rs.N, err
|
|
|
|
}
|
2018-01-08 18:14:57 +08:00
|
|
|
|
2018-06-26 16:15:48 +08:00
|
|
|
// TimedCopy copy from src to dst at target with read timeout
|
|
|
|
func TimedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error {
|
|
|
|
buf := make([]byte, UDPBufSize)
|
2018-01-08 18:14:57 +08:00
|
|
|
for {
|
|
|
|
src.SetReadDeadline(time.Now().Add(timeout))
|
2018-01-20 15:08:23 +08:00
|
|
|
n, _, err := src.ReadFrom(buf)
|
2018-01-08 18:14:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-01-20 15:08:23 +08:00
|
|
|
_, err = dst.WriteTo(buf[:n], target)
|
2018-01-08 18:14:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-13 13:20:15 +08:00
|
|
|
|
|
|
|
// OutboundIP returns preferred outbound ip of this machine
|
2018-01-13 14:34:49 +08:00
|
|
|
func OutboundIP() string {
|
2018-01-13 13:20:15 +08:00
|
|
|
conn, err := net.Dial("udp", "8.8.8.8:80")
|
|
|
|
if err != nil {
|
2018-06-26 16:15:48 +08:00
|
|
|
log.F("get outbound ip error: %s", err)
|
2018-01-13 14:34:49 +08:00
|
|
|
return ""
|
2018-01-13 13:20:15 +08:00
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
|
2018-01-13 14:34:49 +08:00
|
|
|
return conn.LocalAddr().(*net.UDPAddr).IP.String()
|
2018-01-13 13:20:15 +08:00
|
|
|
}
|