goproxy/services/sps.go
arraykeys@gmail.com f1de8659b7 prepare for sps
Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
2018-03-05 18:46:19 +08:00

111 lines
2.4 KiB
Go

package services
import (
"fmt"
"log"
"net"
"runtime/debug"
"snail007/proxy/utils"
"snail007/proxy/utils/socks"
"strconv"
)
type SPS struct {
outPool utils.OutPool
cfg SPSArgs
}
func NewSPS() Service {
return &SPS{
outPool: utils.OutPool{},
cfg: SPSArgs{},
}
}
func (s *SPS) CheckArgs() {
if *s.cfg.Parent == "" {
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
}
if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp>")
}
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
}
func (s *SPS) InitService() {
}
func (s *SPS) StopService() {
if s.outPool.Pool != nil {
s.outPool.Pool.ReleaseAll()
}
}
func (s *SPS) Start(args interface{}) (err error) {
s.cfg = args.(SPSArgs)
s.CheckArgs()
log.Printf("use %s %s parent %s", *s.cfg.ParentType, *s.cfg.ParentServiceType, *s.cfg.Parent)
s.InitService()
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTCP(s.callback)
} else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
}
if err != nil {
return
}
log.Printf("%s http(s)+socks proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr())
return
}
func (s *SPS) Clean() {
s.StopService()
}
func (s *SPS) callback(inConn net.Conn) {
defer func() {
if err := recover(); err != nil {
log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack()))
}
}()
var err error
switch *s.cfg.ParentType {
case TYPE_TCP:
fallthrough
case TYPE_TLS:
err = s.OutToTCP(&inConn)
default:
err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
}
if err != nil {
log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
utils.CloseConn(&inConn)
}
}
func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
buf := make([]byte, 1024)
n, err := (*inConn).Read(buf)
header := buf[:n]
if err != nil {
log.Printf("ERR:%s", err)
utils.CloseConn(inConn)
return
}
fmt.Printf("%v", header[0])
if header[0] == socks.VERSION_V5 {
req, e := socks.NewMethodsRequest(*inConn, header)
if e != nil {
log.Printf("ERR:%s", e)
utils.CloseConn(inConn)
err = e.(error)
return
}
fmt.Printf("address:%v", req.Version())
}
return
}