package yu_tcp import ( yu_base64 "gogs.qqck.cn/s/tools/base64" yu_fast "gogs.qqck.cn/s/tools/fast" yu_proxy "gogs.qqck.cn/s/tools/proxy" yu_strconv "gogs.qqck.cn/s/tools/strconv" "net" "net/netip" ) type Tcp struct { host string // IP 或 域名 port int // 端口号 proxy *yu_proxy.Info sec int32 // 超时时间,单位:秒 usec int32 // 超时时间,单位:微妙 fd uintptr // socket 句柄 } // New // // @Description: 创建 Tcp 对象 func New() (t *Tcp) { t = &Tcp{} t.SetSec(30) t.SetUsec(0) t.init() return } func (t *Tcp) SetHost(value string) *Tcp { t.host = value return t } func (t *Tcp) GetHost() string { return t.host } func (t *Tcp) SetPort(value int) *Tcp { t.port = value return t } func (t *Tcp) GetPort() int { return t.port } func (t *Tcp) SetProxy(value *yu_proxy.Info) *Tcp { t.proxy = value return t } func (t *Tcp) GetProxy() *yu_proxy.Info { return t.proxy } // SetSec // // @Description: 设置超时时间,单位:秒,默认:30 ,最终的超时时间是 sec 和 usec 的总和 func (t *Tcp) SetSec(value int32) *Tcp { t.sec = value return t } func (t *Tcp) GetSec() int32 { return t.sec } // SetUsec // // @Description: 设置超时时间,单位:微秒,默认:0,最终的超时时间是 sec 和 usec 的总和 func (t *Tcp) SetUsec(value int32) *Tcp { t.usec = value return t } func (t *Tcp) GetUsec() int32 { return t.usec } func (t *Tcp) Connect() bool { if t.proxy != nil && t.proxy.IsValid() { return t.content_proxy() } return t.connect(t.host, t.port) } func (t *Tcp) content_proxy() bool { if t.proxy.IsTimeout() { return false } if !t.connect(t.proxy.Host, t.proxy.Port) { return false } var j_addr netip.Addr var j_err error var j_doamin bool if j_addr, j_err = netip.ParseAddr(t.host); j_err != nil { j_addrs, j_err := net.LookupHost(t.host) if j_err != nil || len(j_addrs) == 0 { t.Close() return false } if j_addr, j_err = netip.ParseAddr(j_addrs[0]); j_err != nil { t.Close() return false } j_doamin = true } if t.proxy.IsHttp() { j_buf := make([]byte, 0, 256) j_buf = append(j_buf, "CONNECT "...) if t.proxy.Domain { j_buf = append(j_buf, t.host...) } else if j_addr.IsValid() { if j_addr.Is4() { j_buf = append(j_buf, j_addr.String()...) } else if j_addr.Is6() { j_buf = append(j_buf, '[') j_buf = append(j_buf, j_addr.String()...) j_buf = append(j_buf, ']') } else { t.Close() return false } } else { t.Close() return false } j_buf = append(j_buf, ':') j_buf = append(j_buf, yu_strconv.FormatInt(t.port)...) j_buf = append(j_buf, " HTTP/1.1\r\n"...) j_buf = append(j_buf, "Proxy-Connection: Keep-Alive"...) j_buf = append(j_buf, 13, 10) if t.proxy.IsAuthorization() { j_buf = append(j_buf, "Proxy-Authorization: Basic "...) j_buf = append(j_buf, yu_base64.Std.EncodeS2S(t.proxy.User+":"+t.proxy.Pass)...) j_buf = append(j_buf, 13, 10) } j_buf = append(j_buf, 13, 10) if !t.send(t.fd, j_buf) { t.Close() return false } if j_buf = t.recv(t.fd, 1024); len(j_buf) == 0 { t.Close() return false } // "HTTP/1.1 200 Connection Established"、"HTTP/1.1 200 Connection established" // HTTP/1.0 200 OK if len(j_buf) < 36 || yu_fast.B2S(j_buf[9:12]) != "200" { t.Close() return false } switch yu_fast.B2S(j_buf[13:35]) { case "Connection Established", "Connection established", "connection Established", "connection established": default: t.Close() return false } return true } if t.proxy.IsSocks5() { // https://zhuanlan.zhihu.com/p/458173597?utm_id=0 // https://www.jianshu.com/p/97873541510f j_buf := make([]byte, 0, 256) j_buf = append(j_buf, 5) // VER 协议版本号 j_buf = append(j_buf, 1) // NMETHODS 客户端支持的认证方法数量 // X'00' 不需要身份验证(NO AUTHENTICATION REQUIRED) // X'01' GSSAPI // X'02' 用户密码认证(USERNAME/PASSWORD) // X'03' to X'7F' IANA ASSIGNED // X'80' to X'FE' RESERVED FOR PRIVATE METHODS if t.proxy.IsAuthorization() { j_buf = append(j_buf, 0x02) // METHODS:认证方法 } else { j_buf = append(j_buf, 0x00) // METHODS:认证方法 } if !t.send(t.fd, j_buf) { t.Close() return false } if j_buf = t.recv(t.fd, 1024); len(j_buf) == 0 { t.Close() return false } if len(j_buf) != 2 || j_buf[0] != 5 { t.Close() return false } if j_buf[1] == 0x02 { j_buf = append(j_buf[0:0], 1) // VERSION 认证子协商版本(与SOCKS协议版本的0x05无关系) j_buf = append(j_buf, byte(len(t.proxy.User))) j_buf = append(j_buf, t.proxy.User...) j_buf = append(j_buf, byte(len(t.proxy.Pass))) j_buf = append(j_buf, t.proxy.Pass...) if !t.send(t.fd, j_buf) { t.Close() return false } if j_buf = t.recv(t.fd, 1024); len(j_buf) == 0 { t.Close() return false } if len(j_buf) != 2 || (j_buf[0] != 1 && j_buf[0] != 5) || j_buf[1] != 0 { t.Close() return false } } else if j_buf[1] != 0x00 { t.Close() return false } j_buf = append(j_buf[0:0], 5) // VER 协议版本号 j_buf = append(j_buf, 0x01) // 0x01 CONNECT 连接目标服务器 j_buf = append(j_buf, 0) // RSV 保留字段 if t.proxy.Domain && j_doamin { j_buf = append(j_buf, 0x03) // 0x03 域名地址(没有打错,就是没有0x02),域名地址的第1个字节为域名长度,剩下字节为域名名称字节数组 j_buf = append(j_buf, byte(len(t.host))) j_buf = append(j_buf, t.host...) } else if j_addr.IsValid() { if j_addr.Is4() { j_buf = append(j_buf, 0x01) // 0x01 IP V4地址 } else if j_addr.Is6() { j_buf = append(j_buf, 0x04) // 0x04 IP V6地址 } else { t.Close() return false } j_buf = append(j_buf, j_addr.AsSlice()...) } else { t.Close() return false } j_buf = append(j_buf, byte(t.port>>8), byte(t.port)) if !t.send(t.fd, j_buf) { t.Close() return false } if j_buf = t.recv(t.fd, 1024); len(j_buf) == 0 { t.Close() return false } if len(j_buf) < 10 || j_buf[0] != 5 || j_buf[1] != 0 || j_buf[2] != 0 { t.Close() return false } return true } return true } func (t *Tcp) Send(buf []byte) bool { return t.send(t.fd, buf) } func (t *Tcp) Recv(size int) []byte { return t.recv(t.fd, size) } type Pack byte const ( // PackV1 头四字节包含长度信息(包含长度信息自身的四字节),长度信息为高位字序,如: 00 00 00 09 11 22 33 44 55 PackV1 Pack = iota ) func (t *Tcp) SendPack(v Pack, buf []byte) bool { switch v { case PackV1: j_buf := make([]byte, len(buf)+4) j_buf[0] = byte(len(j_buf) >> 24) j_buf[1] = byte(len(j_buf) >> 16) j_buf[2] = byte(len(j_buf) >> 8) j_buf[3] = byte(len(j_buf)) copy(j_buf[4:], buf) return t.send(t.fd, j_buf) default: return false } } // RecvPack // // @Description: 如果接收失败返回 nil ,如果接收成功但数据包体长度为 0 返回 make([]byte, 0) func (t *Tcp) RecvPack(v Pack) []byte { switch v { case PackV1: var j_buf = make([]byte, 0, 4) for len(j_buf) != cap(j_buf) { j_tmp := t.recv(t.fd, cap(j_buf)-len(j_buf)) if len(j_tmp) == 0 { return nil } j_buf = append(j_buf, j_tmp...) } j_size := int(int32(j_buf[3]) | int32(j_buf[2])<<8 | int32(j_buf[1])<<16 | int32(j_buf[0])<<24) j_size -= 4 if j_size < 0 { return nil } j_buf = make([]byte, 0, j_size) for len(j_buf) != cap(j_buf) { j_tmp := t.recv(t.fd, cap(j_buf)-len(j_buf)) if len(j_tmp) == 0 { return nil } j_buf = append(j_buf, j_tmp...) } return j_buf default: return nil } } func (t *Tcp) Close() *Tcp { t.close() return t }