add socks5 conn

This commit is contained in:
ginuerzh
2015-05-12 03:29:43 +00:00
parent efe2d57e48
commit d091e8c10b
2 changed files with 172 additions and 70 deletions
+172
View File
@@ -0,0 +1,172 @@
package gosocks5
import (
//"log"
"net"
"io"
"sync"
"time"
)
type Config struct {
Methods []uint8
SelectMethod func(methods ...uint8) uint8
MethodSelected func(method uint8, conn net.Conn) (net.Conn, error)
}
func defaultConfig() *Config {
return &Config{}
}
type Conn struct {
c net.Conn
config *Config
method uint8
isClient bool
handshaked bool
handshakeMutex sync.Mutex
handshakeErr error
}
func ClientConn(conn net.Conn, config *Config) *Conn {
return &Conn{
c: conn,
config: config,
isClient: true,
}
}
func ServerConn(conn net.Conn, config *Config) *Conn {
return &Conn{
c: conn,
config: config,
}
}
func (conn *Conn) Handleshake() error {
conn.handshakeMutex.Lock()
defer conn.handshakeMutex.Unlock()
if err := conn.handshakeErr; err != nil {
return err
}
if conn.handshaked {
return nil
}
if conn.isClient {
conn.handshakeErr = conn.clientHandshake()
} else {
conn.handshakeErr = conn.serverHandshake()
}
return conn.handshakeErr
}
func (conn *Conn) clientHandshake() error {
if conn.config == nil {
conn.config = defaultConfig()
}
nm := len(conn.config.Methods)
if nm == 0 {
nm = 1
}
b := make([]byte, 2+nm)
b[0] = Ver5
b[1] = uint8(nm)
copy(b[2:], conn.config.Methods)
if _, err := conn.c.Write(b); err != nil {
return err
}
if _, err := io.ReadFull(conn.c, b[:2]); err != nil {
return err
}
if b[0] != Ver5 {
return ErrBadVersion
}
if conn.config.MethodSelected != nil {
c, err := conn.config.MethodSelected(b[1], conn.c)
if err != nil {
return err
}
conn.c = c
}
conn.method = b[1]
conn.handshaked = true
return nil
}
func (conn *Conn) serverHandshake() error {
if conn.config == nil {
conn.config = defaultConfig()
}
methods, err := ReadMethods(conn.c)
if err != nil {
return err
}
method := MethodNoAuth
if conn.config.SelectMethod != nil {
method = conn.config.SelectMethod(methods...)
}
if _, err := conn.c.Write([]byte{Ver5, method}); err != nil {
return err
}
if conn.config.MethodSelected != nil {
c, err := conn.config.MethodSelected(method, conn.c)
if err != nil {
return err
}
conn.c = c
}
conn.method = method
conn.handshaked = true
return nil
}
func (conn *Conn) Read(b []byte) (n int, err error) {
if err = conn.Handleshake(); err != nil {
return
}
return conn.c.Read(b)
}
func (conn *Conn) Write(b []byte) (n int, err error) {
if err = conn.Handleshake(); err != nil {
return
}
return conn.c.Write(b)
}
func (conn *Conn) Close() error {
return conn.c.Close()
}
func (conn *Conn) LocalAddr() net.Addr {
return conn.c.LocalAddr()
}
func (conn *Conn) RemoteAddr() net.Addr {
return conn.c.RemoteAddr()
}
func (conn *Conn) SetDeadline(t time.Time) error {
return conn.c.SetDeadline(t)
}
func (conn *Conn) SetReadDeadline(t time.Time) error {
return conn.c.SetReadDeadline(t)
}
func (conn *Conn) SetWriteDeadline(t time.Time) error {
return conn.c.SetWriteDeadline(t)
}
-70
View File
@@ -1,70 +0,0 @@
package gosocks5
import (
"log"
"net"
)
type Server struct {
Addr string // TCP address to listen on
SelectMethod func(methods ...uint8) uint8
MethodSelected func(method uint8, conn net.Conn) (net.Conn, error)
Handle func(conn net.Conn)
}
func (s *Server) ListenAndServe() error {
addr, err := net.ResolveTCPAddr("tcp", s.Addr)
if err != nil {
return err
}
ln, err := net.ListenTCP("tcp", addr)
if err != nil {
return err
}
defer ln.Close()
for {
conn, err := ln.AcceptTCP()
if err != nil {
log.Println("accept:", err)
continue
}
//log.Println("accept", conn.RemoteAddr())
go s.handle(conn)
}
}
func (s *Server) handle(conn net.Conn) {
defer conn.Close()
methods, err := ReadMethods(conn)
if err != nil {
log.Println(err)
return
}
method := MethodNoAuth
if s.SelectMethod != nil {
method = s.SelectMethod(methods...)
}
if _, err := conn.Write([]byte{Ver5, method}); err != nil {
log.Println(err)
return
}
if s.MethodSelected != nil {
c, err := s.MethodSelected(method, conn)
if err != nil {
log.Println(err)
return
}
conn = c
}
if s.Handle != nil {
s.Handle(conn)
}
}