| 45 | } |
| 46 | |
| 47 | func NewStreamClient(network string, password []byte, src string, server net.Conn, timeout int, dst []byte) (Exchanger, error) { |
| 48 | if timeout != 0 { |
| 49 | if err := server.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)); err != nil { |
| 50 | return nil, err |
| 51 | } |
| 52 | } |
| 53 | if len(dst) > 2048-2-16-4-16 { |
| 54 | return nil, errors.New("dst too long") |
| 55 | } |
| 56 | c := &StreamClient{network: network, Server: server, Timeout: timeout, src: src, dst: socks5.ToAddress(dst[0], dst[1:len(dst)-2], dst[len(dst)-2:])} |
| 57 | |
| 58 | c.cn = x.BP12.Get().([]byte) |
| 59 | if _, err := io.ReadFull(rand.Reader, c.cn); err != nil { |
| 60 | x.BP12.Put(c.cn) |
| 61 | return nil, err |
| 62 | } |
| 63 | ck := x.BP32.Get().([]byte) |
| 64 | if _, err := io.ReadFull(hkdf.New(sha256.New, password, c.cn, ClientHKDFInfo), ck); err != nil { |
| 65 | x.BP12.Put(c.cn) |
| 66 | x.BP32.Put(ck) |
| 67 | return nil, err |
| 68 | } |
| 69 | if _, err := c.Server.Write(c.cn); err != nil { |
| 70 | x.BP12.Put(c.cn) |
| 71 | x.BP32.Put(ck) |
| 72 | return nil, err |
| 73 | } |
| 74 | cb, err := aes.NewCipher(ck) |
| 75 | if err != nil { |
| 76 | x.BP12.Put(c.cn) |
| 77 | x.BP32.Put(ck) |
| 78 | return nil, err |
| 79 | } |
| 80 | x.BP32.Put(ck) |
| 81 | c.ca, err = cipher.NewGCM(cb) |
| 82 | if err != nil { |
| 83 | x.BP12.Put(c.cn) |
| 84 | return nil, err |
| 85 | } |
| 86 | |
| 87 | c.WB = x.BP2048.Get().([]byte) |
| 88 | i := time.Now().Unix() |
| 89 | if c.network == "tcp" && i%2 != 0 { |
| 90 | i += 1 |
| 91 | } |
| 92 | if c.network == "udp" && i%2 != 1 { |
| 93 | i += 1 |
| 94 | } |
| 95 | binary.BigEndian.PutUint32(c.WB[2+16:2+16+4], uint32(i)) |
| 96 | copy(c.WB[2+16+4:2+16+4+len(dst)], dst) |
| 97 | if err := c.Write(4 + len(dst)); err != nil { |
| 98 | x.BP12.Put(c.cn) |
| 99 | x.BP2048.Put(c.WB) |
| 100 | return nil, err |
| 101 | } |
| 102 | |
| 103 | c.sn = x.BP12.Get().([]byte) |
| 104 | if _, err := io.ReadFull(c.Server, c.sn); err != nil { |