Files
gosocks5/examples/server.go
T
2015-03-26 22:07:09 +08:00

111 lines
1.8 KiB
Go

package main
import (
"github.com/ginuerzh/gosocks5"
"io"
"log"
"net"
)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
server := &gosocks5.Server{
Addr: ":9999",
Handle: handle,
}
server.Serve()
}
func handle(conn net.Conn, method uint8) error {
defer conn.Close()
req, err := gosocks5.ReadRequest(conn)
if err != nil {
log.Println(err)
return err
}
tconn, err := Connect(req.Addr.String())
if err != nil {
log.Println(err)
return err
}
defer tconn.Close()
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
if err := rep.Write(conn); err != nil {
return err
}
if err := Transport(conn, tconn); err != nil {
log.Println(err)
}
return nil
}
func Connect(addr string) (net.Conn, error) {
taddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
log.Println(err)
return nil, err
}
return net.DialTCP("tcp", nil, taddr)
}
func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
//log.Println("cp r", nr, er)
if nr > 0 {
nw, ew := dst.Write(buf[:nr])
//log.Println("cp w", nw, ew)
if nw > 0 {
written += int64(nw)
}
if ew != nil {
err = ew
break
}
/*
if nr != nw {
err = io.ErrShortWrite
break
}
*/
}
if er == io.EOF {
break
}
if er != nil {
err = er
break
}
}
return
}
func Pipe(src io.Reader, dst io.Writer, c chan<- error) {
_, err := Copy(dst, src)
c <- err
}
func Transport(conn, conn2 net.Conn) (err error) {
rChan := make(chan error, 1)
wChan := make(chan error, 1)
go Pipe(conn, conn2, wChan)
go Pipe(conn2, conn, rChan)
select {
case err = <-wChan:
//log.Println("w exit", err)
case err = <-rChan:
//log.Println("r exit", err)
}
return
}