add associate test

fix client implement frame
This commit is contained in:
mo 2020-08-06 14:31:36 +08:00
parent 880274af1f
commit 2fcdcb8a43
15 changed files with 560 additions and 340 deletions

View File

@ -0,0 +1,70 @@
package main
import (
"io"
"log"
"net"
"os"
"time"
"github.com/thinkgos/go-socks5"
"github.com/thinkgos/go-socks5/client_socks5"
)
func handleErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
locIP := net.ParseIP("127.0.0.1")
// Create a local listener
lAddr := &net.UDPAddr{IP: locIP, Port: 12398}
l, err := net.ListenUDP("udp", lAddr)
handleErr(err)
defer l.Close()
go func() {
buf := make([]byte, 2048)
for {
n, remote, err := l.ReadFrom(buf)
if err != nil {
log.Printf("server: %v", err)
return
}
log.Printf("server: %+v", string(buf[:n]))
l.WriteTo([]byte("pong"), remote) // nolint: errcheck
}
}()
go func() {
time.Sleep(time.Second)
c, err := client_socks5.NewClient("127.0.0.1:10809")
handleErr(err)
con, err := c.Dial("udp", lAddr.String())
handleErr(err)
for {
con.Write([]byte("ping")) // nolint: errcheck
out := make([]byte, 4)
con.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(con, out)
con.SetDeadline(time.Time{}) // nolint: errcheck
if err != nil {
log.Printf("client: %v", err)
} else {
log.Printf("client: %+v", string(out))
}
time.Sleep(time.Second * 2)
}
}()
// Create a SOCKS5 server
server := socks5.NewServer(socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))))
// Create SOCKS5 proxy on localhost port 8000
if err := server.ListenAndServe("tcp", "127.0.0.1:10809"); err != nil {
panic(err)
}
}

70
_testing/connect/main.go Normal file
View File

@ -0,0 +1,70 @@
package main
import (
"io"
"log"
"net"
"os"
"time"
"github.com/thinkgos/go-socks5"
"github.com/thinkgos/go-socks5/client_socks5"
)
func handleErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
handleErr(err)
go func() {
conn, err := l.Accept()
handleErr(err)
defer conn.Close()
for {
buf := make([]byte, 4)
_, err = io.ReadAtLeast(conn, buf, 4)
handleErr(err)
log.Printf("server: %+v", string(buf))
conn.Write([]byte("pong")) // nolint: errcheck
}
}()
lAddr := l.Addr().(*net.TCPAddr)
go func() {
time.Sleep(time.Second * 1)
c, err := client_socks5.NewClient("127.0.0.1:10808")
handleErr(err)
con, err := c.Dial("tcp", lAddr.String())
handleErr(err)
for {
con.Write([]byte("ping")) // nolint: errcheck
out := make([]byte, 4)
con.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(con, out)
con.SetDeadline(time.Time{}) // nolint: errcheck
if err != nil {
log.Printf("client: %+v", err)
} else {
log.Printf("client: %+v", string(out))
}
time.Sleep(time.Second * 2)
}
}()
// Create a SOCKS5 server
server := socks5.NewServer(socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))))
// Create SOCKS5 proxy on localhost port 8000
if err := server.ListenAndServe("tcp", "127.0.0.1:10808"); err != nil {
panic(err)
}
}

View File

@ -1,60 +0,0 @@
package main
import (
"io"
"log"
"net"
"os"
"time"
"github.com/thinkgos/go-socks5"
"github.com/thinkgos/go-socks5/client"
)
func handleErr(err error) {
if err != nil {
panic(err)
}
}
func main() {
// Create a local listener
l, err := net.Listen("tcp", "127.0.0.1:0")
handleErr(err)
go func() {
conn, err := l.Accept()
handleErr(err)
defer conn.Close()
buf := make([]byte, 4)
_, err = io.ReadAtLeast(conn, buf, 4)
handleErr(err)
log.Printf("server: %+v", string(buf))
conn.Write([]byte("pong"))
}()
lAddr := l.Addr().(*net.TCPAddr)
go func() {
time.Sleep(time.Second * 1)
c, err := client.NewClient("127.0.0.1:10809")
handleErr(err)
con, err := c.Dial("tcp", lAddr.String())
handleErr(err)
con.Write([]byte("ping"))
out := make([]byte, 4)
_ = con.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(con, out)
log.Printf("client: %+v", string(out))
}()
// Create a SOCKS5 server
server := socks5.NewServer(socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))))
// Create SOCKS5 proxy on localhost port 8000
if err := server.ListenAndServe("tcp", "127.0.0.1:10809"); err != nil {
panic(err)
}
}

View File

@ -1,12 +1,12 @@
package socks5
package bufferpool
import (
"sync"
)
// A BufferPool is an interface for getting and returning temporary
// BufPool is an interface for getting and returning temporary
// byte slices for use by io.CopyBuffer.
type BufferPool interface {
type BufPool interface {
Get() []byte
Put([]byte)
}
@ -18,7 +18,7 @@ type pool struct {
// NewPool new buffer pool for getting and returning temporary
// byte slices for use by io.CopyBuffer.
func NewPool(size int) BufferPool {
func NewPool(size int) BufPool {
return &pool{
size,
&sync.Pool{
@ -26,12 +26,12 @@ func NewPool(size int) BufferPool {
}
}
// Get implement interface BufferPool
// Get implement interface BufPool
func (sf *pool) Get() []byte {
return sf.pool.Get().([]byte)
}
// Put implement interface BufferPool
// Put implement interface BufPool
func (sf *pool) Put(b []byte) {
if cap(b) != sf.size {
panic("invalid buffer size that's put into leaky buffer")

View File

@ -1,4 +1,4 @@
package socks5
package bufferpool
import (
"sync"

View File

@ -1,261 +0,0 @@
package client
import (
"errors"
"net"
"time"
"golang.org/x/net/proxy"
"github.com/thinkgos/go-socks5/statute"
)
// Client is socks5 client wrapper
type Client struct {
Server string
Auth *proxy.Auth
// On command UDP, let server control the tcp and udp connection relationship
TCPConn *net.TCPConn
UDPConn *net.UDPConn
RemoteAddress net.Addr
TCPDeadline time.Duration
TCPTimeout time.Duration
UDPDeadline time.Duration
}
// This is just create a client, you need to use Dial to create conn
func NewClient(addr string, opts ...Option) (*Client, error) {
c := &Client{
Server: addr,
TCPTimeout: time.Second,
TCPDeadline: time.Second,
UDPDeadline: time.Second,
}
for _, opt := range opts {
opt(c)
}
return c, nil
}
func (c *Client) Close() error {
if c.UDPConn == nil {
return c.TCPConn.Close()
}
if c.TCPConn != nil {
c.TCPConn.Close()
}
return c.UDPConn.Close()
}
func (c *Client) LocalAddr() net.Addr {
if c.UDPConn == nil {
return c.TCPConn.LocalAddr()
}
return c.UDPConn.LocalAddr()
}
func (c *Client) RemoteAddr() net.Addr {
return c.RemoteAddress
}
func (c *Client) SetDeadline(t time.Time) error {
if c.UDPConn == nil {
return c.TCPConn.SetDeadline(t)
}
return c.UDPConn.SetDeadline(t)
}
func (c *Client) SetReadDeadline(t time.Time) error {
if c.UDPConn == nil {
return c.TCPConn.SetReadDeadline(t)
}
return c.UDPConn.SetReadDeadline(t)
}
func (c *Client) SetWriteDeadline(t time.Time) error {
if c.UDPConn == nil {
return c.TCPConn.SetWriteDeadline(t)
}
return c.UDPConn.SetWriteDeadline(t)
}
func (c *Client) Read(b []byte) (int, error) {
if c.UDPConn == nil {
return c.TCPConn.Read(b)
}
b1 := make([]byte, 65535)
n, err := c.UDPConn.Read(b1)
if err != nil {
return 0, err
}
pkt, err := statute.ParseDatagram(b1[:n])
if err != nil {
return 0, err
}
n = copy(b, pkt.Data)
return n, nil
}
func (c *Client) Write(b []byte) (int, error) {
if c.UDPConn == nil {
return c.TCPConn.Write(b)
}
pkt, err := statute.NewDatagram(c.RemoteAddress.String(), b)
if err != nil {
return 0, err
}
return c.UDPConn.Write(pkt.Bytes())
}
func (c *Client) Dial(network, addr string) (net.Conn, error) {
var err error
conn := *c // clone a client
if network == "tcp" {
conn.RemoteAddress, err = net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
conn.TCPConn, err = conn.dialServer()
if err != nil {
return nil, err
}
if err := conn.handshake(); err != nil {
return nil, err
}
a, err := statute.ParseAddrSpec(addr)
if err != nil {
return nil, err
}
head := statute.Request{
Version: statute.VersionSocks5,
Command: statute.CommandConnect,
DstAddress: a,
}
if _, err := conn.Write(head.Bytes()); err != nil {
return nil, err
}
rspHead, err := statute.ParseRequest(conn.TCPConn)
if err != nil {
return nil, err
}
if rspHead.Command != statute.RepSuccess {
return nil, errors.New("host unreachable")
}
return &conn, nil
}
if network == "udp" {
conn.RemoteAddress, err = net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
conn.TCPConn, err = conn.dialServer()
if err != nil {
return nil, err
}
if err := conn.handshake(); err != nil {
return nil, err
}
laddr := &net.UDPAddr{
IP: conn.TCPConn.LocalAddr().(*net.TCPAddr).IP,
Port: conn.TCPConn.LocalAddr().(*net.TCPAddr).Port,
Zone: conn.TCPConn.LocalAddr().(*net.TCPAddr).Zone,
}
a, err := statute.ParseAddrSpec(laddr.String())
if err != nil {
return nil, err
}
head := statute.Request{
Version: statute.VersionSocks5,
Command: statute.CommandConnect,
DstAddress: a,
}
if _, err := conn.Write(head.Bytes()); err != nil {
return nil, err
}
rspHead, err := statute.ParseRequest(conn.TCPConn)
if err != nil {
return nil, err
}
if rspHead.Command != statute.RepSuccess {
return nil, errors.New("host unreachable")
}
raddr, err := net.ResolveUDPAddr("udp", rspHead.DstAddress.String())
if err != nil {
return nil, err
}
conn.UDPConn, err = net.DialUDP("udp", laddr, raddr)
if err != nil {
return nil, err
}
return &conn, nil
}
return nil, errors.New("not support network")
}
func (c *Client) handshake() error {
methods := statute.MethodNoAuth
if c.Auth != nil {
methods = statute.MethodUserPassAuth
}
_, err := c.TCPConn.Write(statute.NewMethodRequest(statute.VersionSocks5, []byte{methods}).Bytes())
if err != nil {
return err
}
reply, err := statute.ParseMethodReply(c.TCPConn)
if err != nil {
return err
}
if reply.Ver != statute.VersionSocks5 {
return statute.ErrNotSupportVersion
}
if reply.Method != methods {
return statute.ErrNotSupportMethod
}
if methods == statute.MethodUserPassAuth {
_, err = c.TCPConn.Write(statute.NewUserPassRequest(statute.UserPassAuthVersion, []byte(c.Auth.User), []byte(c.Auth.Password)).Bytes())
if err != nil {
return err
}
rsp, err := statute.ParseUserPassReply(c.TCPConn)
if err != nil {
return err
}
if rsp.Ver != statute.UserPassAuthVersion {
return statute.ErrNotSupportMethod
}
if rsp.Status != statute.RepSuccess {
return statute.ErrUserAuthFailed
}
}
return nil
}
func (c *Client) dialServer() (*net.TCPConn, error) {
conn, err := net.Dial("tcp", c.Server)
if err != nil {
return nil, err
}
TCPConn := conn.(*net.TCPConn)
if c.TCPTimeout != 0 {
if err := TCPConn.SetKeepAlivePeriod(c.TCPTimeout); err != nil {
return nil, err
}
}
if c.TCPDeadline != 0 {
if err := TCPConn.SetDeadline(time.Now().Add(c.TCPTimeout)); err != nil {
return nil, err
}
}
return TCPConn, nil
}

51
client_socks5/Connect.go Normal file
View File

@ -0,0 +1,51 @@
package client_socks5
import (
"io"
"os"
"time"
)
type Connect struct {
*Client
}
func (sf *Connect) SetReadBuffer(bytes int) error {
return sf.tcpConn.SetReadBuffer(bytes)
}
func (sf *Connect) SetWriteBuffer(bytes int) error {
return sf.tcpConn.SetWriteBuffer(bytes)
}
func (sf *Connect) SetKeepAlive(keepalive bool) error {
return sf.tcpConn.SetKeepAlive(keepalive)
}
func (sf *Connect) SetKeepAlivePeriod(d time.Duration) error {
return sf.tcpConn.SetKeepAlivePeriod(d)
}
func (sf *Connect) SetLinger(sec int) error {
return sf.tcpConn.SetLinger(sec)
}
func (sf *Connect) SetNoDelay(noDelay bool) error {
return sf.tcpConn.SetNoDelay(noDelay)
}
func (sf *Connect) ReadFrom(r io.Reader) (int64, error) {
return sf.tcpConn.ReadFrom(r)
}
func (sf *Connect) CloseRead() error {
return sf.tcpConn.CloseRead()
}
func (sf *Connect) CloseWrite() error {
return sf.tcpConn.CloseWrite()
}
func (sf *Connect) File() (f *os.File, err error) {
return sf.tcpConn.File()
}

View File

@ -0,0 +1,43 @@
package client_socks5
import (
"net"
"os"
)
type Associate struct {
*Client
}
func (sf *Associate) getUDPConn() *net.UDPConn {
return sf.underConn.(*underUDPConn).udpConn
}
func (sf *Associate) SetReadBuffer(bytes int) error {
return sf.getUDPConn().SetReadBuffer(bytes)
}
func (sf *Associate) SetWriteBuffer(bytes int) error {
return sf.getUDPConn().SetWriteBuffer(bytes)
}
func (sf *Associate) ReadFrom(b []byte) (int, net.Addr, error) {
return sf.getUDPConn().ReadFrom(b)
}
func (sf *Associate) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
return sf.getUDPConn().ReadFromUDP(b)
}
func (sf *Associate) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) {
return sf.getUDPConn().ReadMsgUDP(b, oob)
}
func (sf *Associate) WriteTo(b []byte, addr net.Addr) (int, error) {
return sf.getUDPConn().WriteTo(b, addr)
}
func (sf *Associate) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) {
return sf.getUDPConn().WriteToUDP(b, addr)
}
func (sf *Associate) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) {
return sf.getUDPConn().WriteMsgUDP(b, oob, addr)
}
func (sf *Associate) File() (f *os.File, err error) {
return sf.getUDPConn().File()
}

229
client_socks5/client.go Normal file
View File

@ -0,0 +1,229 @@
package client_socks5
import (
"errors"
"net"
"time"
"golang.org/x/net/proxy"
"github.com/thinkgos/go-socks5/bufferpool"
"github.com/thinkgos/go-socks5/statute"
)
// Client is socks5 client wrapper
type Client struct {
proxyAddr string
auth *proxy.Auth
// On command UDP, let server control the tcp and udp connection relationship
tcpConn *net.TCPConn
underConn net.Conn
TCPDeadline time.Duration
KeepAlivePeriod time.Duration
UDPDeadline time.Duration
bufferPool bufferpool.BufPool
}
// This is just create a client, you need to use Dial to create conn
func NewClient(proxyAddr string, opts ...Option) (*Client, error) {
c := &Client{
proxyAddr: proxyAddr,
KeepAlivePeriod: time.Second,
TCPDeadline: time.Second,
UDPDeadline: time.Second,
bufferPool: bufferpool.NewPool(32 * 1024),
}
for _, opt := range opts {
opt(c)
}
return c, nil
}
func (sf *Client) Read(b []byte) (int, error) {
return sf.underConn.Read(b)
}
func (sf *Client) Write(b []byte) (int, error) {
return sf.underConn.Write(b)
}
func (sf *Client) Close() (err error) {
err = sf.tcpConn.Close()
if sf.underConn != nil {
err = sf.underConn.Close()
}
return
}
func (sf *Client) LocalAddr() net.Addr {
return sf.underConn.LocalAddr()
}
func (sf *Client) RemoteAddr() net.Addr {
return sf.underConn.RemoteAddr()
}
func (sf *Client) SetDeadline(t time.Time) error {
return sf.underConn.SetDeadline(t)
}
func (sf *Client) SetReadDeadline(t time.Time) error {
return sf.underConn.SetReadDeadline(t)
}
func (sf *Client) SetWriteDeadline(t time.Time) error {
return sf.underConn.SetWriteDeadline(t)
}
func (sf *Client) Dial(network, addr string) (net.Conn, error) {
if network == "tcp" {
return sf.DialTCP(network, addr)
}
if network == "udp" {
return sf.DialUDP(network, nil, addr)
}
return nil, errors.New("not support network")
}
func (sf *Client) DialTCP(network, addr string) (*Connect, error) {
conn := *sf // clone a client
_, err := net.ResolveTCPAddr(network, addr)
if err != nil {
return nil, err
}
err = conn.dialProxyServer(network)
if err != nil {
return nil, err
}
if _, err := conn.handshake(statute.CommandConnect, addr); err != nil {
conn.Close()
return nil, err
}
conn.underConn = conn.tcpConn
return &Connect{&conn}, nil
}
func (sf *Client) DialUDP(network string, laddr *net.UDPAddr, raddr string) (*Associate, error) {
conn := *sf // clone a client
remoteAddress, err := net.ResolveUDPAddr(network, raddr)
if err != nil {
return nil, err
}
err = conn.dialProxyServer("tcp")
if err != nil {
return nil, err
}
bndAddress, err := conn.handshake(statute.CommandAssociate, raddr)
if err != nil {
return nil, err
}
ra, err := net.ResolveUDPAddr(network, bndAddress)
if err != nil {
conn.Close()
return nil, err
}
if laddr == nil {
laddr = &net.UDPAddr{
IP: conn.tcpConn.LocalAddr().(*net.TCPAddr).IP,
Port: conn.tcpConn.LocalAddr().(*net.TCPAddr).Port,
Zone: conn.tcpConn.LocalAddr().(*net.TCPAddr).Zone,
}
}
udpConn, err := net.DialUDP(network, laddr, ra)
if err != nil {
conn.Close()
return nil, err
}
conn.underConn = &underUDPConn{
udpConn,
conn.bufferPool,
remoteAddress,
}
return &Associate{&conn}, nil
}
func (sf *Client) handshake(command byte, addr string) (string, error) {
methods := statute.MethodNoAuth
if sf.auth != nil {
methods = statute.MethodUserPassAuth
}
_, err := sf.tcpConn.Write(statute.NewMethodRequest(statute.VersionSocks5, []byte{methods}).Bytes())
if err != nil {
return "", err
}
reply, err := statute.ParseMethodReply(sf.tcpConn)
if err != nil {
return "", err
}
if reply.Ver != statute.VersionSocks5 {
return "", statute.ErrNotSupportVersion
}
if reply.Method != methods {
return "", statute.ErrNotSupportMethod
}
if methods == statute.MethodUserPassAuth {
_, err = sf.tcpConn.Write(statute.NewUserPassRequest(statute.UserPassAuthVersion, []byte(sf.auth.User), []byte(sf.auth.Password)).Bytes())
if err != nil {
return "", err
}
rsp, err := statute.ParseUserPassReply(sf.tcpConn)
if err != nil {
return "", err
}
if rsp.Ver != statute.UserPassAuthVersion {
return "", statute.ErrNotSupportMethod
}
if rsp.Status != statute.RepSuccess {
return "", statute.ErrUserAuthFailed
}
}
a, err := statute.ParseAddrSpec(addr)
if err != nil {
return "", err
}
reqHead := statute.Request{
Version: statute.VersionSocks5,
Command: command,
DstAddress: a,
}
if _, err := sf.tcpConn.Write(reqHead.Bytes()); err != nil {
return "", err
}
rspHead, err := statute.ParseReply(sf.tcpConn)
if err != nil {
return "", err
}
if rspHead.Response != statute.RepSuccess {
return "", errors.New("host unreachable")
}
return rspHead.BndAddress.String(), nil
}
func (sf *Client) dialProxyServer(network string) error {
conn, err := net.Dial(network, sf.proxyAddr)
if err != nil {
return err
}
sf.tcpConn = conn.(*net.TCPConn)
if sf.KeepAlivePeriod != 0 {
err = sf.tcpConn.SetKeepAlivePeriod(sf.KeepAlivePeriod)
}
if err != nil {
sf.tcpConn.Close()
return err
}
return nil
}

View File

@ -1,22 +1,30 @@
package client
package client_socks5
import (
"time"
"golang.org/x/net/proxy"
"github.com/thinkgos/go-socks5/bufferpool"
)
type Option func(c *Client)
func WithAuth(auth *proxy.Auth) Option {
return func(c *Client) {
c.Auth = auth
c.auth = auth
}
}
func WithTCPTimeout(t time.Duration) Option {
func WithBufferPool(p bufferpool.BufPool) Option {
return func(c *Client) {
c.TCPTimeout = t
c.bufferPool = p
}
}
func WithKeepAlivePeriod(t time.Duration) Option {
return func(c *Client) {
c.KeepAlivePeriod = t
}
}

View File

@ -0,0 +1,63 @@
package client_socks5
import (
"net"
"time"
"github.com/thinkgos/go-socks5/bufferpool"
"github.com/thinkgos/go-socks5/statute"
)
type underUDPConn struct {
udpConn *net.UDPConn
bufferPool bufferpool.BufPool
remoteAddress net.Addr
}
func (sf *underUDPConn) Read(b []byte) (int, error) {
b1 := sf.bufferPool.Get()
defer sf.bufferPool.Put(b1)
n, err := sf.udpConn.Read(b1[:cap(b1)])
if err != nil {
return 0, err
}
datagram, err := statute.ParseDatagram(b1[:n])
if err != nil {
return 0, err
}
n = copy(b, datagram.Data)
return n, nil
}
func (sf *underUDPConn) Write(b []byte) (int, error) {
datagram, err := statute.NewDatagram(sf.remoteAddress.String(), b)
if err != nil {
return 0, err
}
return sf.udpConn.Write(datagram.Bytes())
}
func (sf *underUDPConn) Close() error {
return sf.udpConn.Close()
}
func (sf *underUDPConn) LocalAddr() net.Addr {
return sf.udpConn.LocalAddr()
}
func (sf *underUDPConn) RemoteAddr() net.Addr {
return sf.remoteAddress
}
func (sf *underUDPConn) SetDeadline(t time.Time) error {
return sf.udpConn.SetDeadline(t)
}
func (sf *underUDPConn) SetReadDeadline(t time.Time) error {
return sf.udpConn.SetReadDeadline(t)
}
func (sf *underUDPConn) SetWriteDeadline(t time.Time) error {
return sf.udpConn.SetWriteDeadline(t)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/thinkgos/go-socks5/bufferpool"
"github.com/thinkgos/go-socks5/statute"
)
@ -49,7 +50,7 @@ func TestRequest_Connect(t *testing.T) {
rules: NewPermitAll(),
resolver: DNSResolver{},
logger: NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags)),
bufferPool: NewPool(32 * 1024),
bufferPool: bufferpool.NewPool(32 * 1024),
}
// Create the connect request
@ -106,7 +107,7 @@ func TestRequest_Connect_RuleFail(t *testing.T) {
rules: NewPermitNone(),
resolver: DNSResolver{},
logger: NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags)),
bufferPool: NewPool(32 * 1024),
bufferPool: bufferpool.NewPool(32 * 1024),
}
// Create the connect request

View File

@ -4,6 +4,8 @@ import (
"context"
"io"
"net"
"github.com/thinkgos/go-socks5/bufferpool"
)
// Option user's option
@ -11,7 +13,7 @@ type Option func(s *Server)
// WithBufferPool can be provided to implement custom buffer pool
// By default, buffer pool use size is 32k
func WithBufferPool(bufferPool BufferPool) Option {
func WithBufferPool(bufferPool bufferpool.BufPool) Option {
return func(s *Server) {
s.bufferPool = bufferPool
}

View File

@ -10,6 +10,7 @@ import (
"log"
"net"
"github.com/thinkgos/go-socks5/bufferpool"
"github.com/thinkgos/go-socks5/statute"
)
@ -48,7 +49,7 @@ type Server struct {
// Optional function for dialing out
dial func(ctx context.Context, network, addr string) (net.Conn, error)
// buffer pool
bufferPool BufferPool
bufferPool bufferpool.BufPool
// goroutine pool
gPool GPool
// user's handle
@ -62,7 +63,7 @@ func NewServer(opts ...Option) *Server {
server := &Server{
authMethods: make(map[uint8]Authenticator),
authCustomMethods: []Authenticator{&NoAuthAuthenticator{}},
bufferPool: NewPool(32 * 1024),
bufferPool: bufferpool.NewPool(32 * 1024),
resolver: DNSResolver{},
rules: NewPermitAll(),
logger: NewLogger(log.New(ioutil.Discard, "socks5: ", log.LstdFlags)),

View File

@ -100,6 +100,7 @@ func TestSOCKS5_Connect(t *testing.T) {
out := make([]byte, len(expected))
conn.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(conn, out)
conn.SetDeadline(time.Time{}) // nolint: errcheck
require.NoError(t, err)
// Ignore the port
out[12] = 0
@ -110,7 +111,7 @@ func TestSOCKS5_Connect(t *testing.T) {
func TestSOCKS5_Associate(t *testing.T) {
locIP := net.ParseIP("127.0.0.1")
// Create a local listener
lAddr := &net.UDPAddr{IP: locIP, Port: 12398}
lAddr := &net.UDPAddr{IP: locIP, Port: 12399}
l, err := net.ListenUDP("udp", lAddr)
require.NoError(t, err)
defer l.Close()
@ -173,8 +174,9 @@ func TestSOCKS5_Associate(t *testing.T) {
}
out := make([]byte, len(expected))
_ = conn.SetDeadline(time.Now().Add(time.Second))
conn.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(conn, out)
conn.SetDeadline(time.Time{}) // nolint: errcheck
require.NoError(t, err)
require.Equal(t, expected, out)
@ -183,7 +185,7 @@ func TestSOCKS5_Associate(t *testing.T) {
require.Equal(t, statute.VersionSocks5, rspHead.Version)
require.Equal(t, statute.RepSuccess, rspHead.Response)
t.Logf("proxy bind listen port: %d", rspHead.BndAddress.Port)
// t.Logf("proxy bind listen port: %d", rspHead.BndAddress.Port)
udpConn, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: locIP,
@ -246,6 +248,7 @@ func Test_SocksWithProxy(t *testing.T) {
out := make([]byte, 4)
conn.SetDeadline(time.Now().Add(time.Second)) // nolint: errcheck
_, err = io.ReadFull(conn, out)
conn.SetDeadline(time.Time{}) // nolint: errcheck
require.NoError(t, err)
require.Equal(t, []byte("pong"), out)
}