github.com/chwjbn/xclash@v0.2.0/transport/ssr/obfs/random_head.go (about) 1 package obfs 2 3 import ( 4 "encoding/binary" 5 "hash/crc32" 6 "math/rand" 7 "net" 8 9 "github.com/chwjbn/xclash/common/pool" 10 ) 11 12 func init() { 13 register("random_head", newRandomHead, 0) 14 } 15 16 type randomHead struct { 17 *Base 18 } 19 20 func newRandomHead(b *Base) Obfs { 21 return &randomHead{Base: b} 22 } 23 24 type randomHeadConn struct { 25 net.Conn 26 *randomHead 27 hasSentHeader bool 28 rawTransSent bool 29 rawTransRecv bool 30 buf []byte 31 } 32 33 func (r *randomHead) StreamConn(c net.Conn) net.Conn { 34 return &randomHeadConn{Conn: c, randomHead: r} 35 } 36 37 func (c *randomHeadConn) Read(b []byte) (int, error) { 38 if c.rawTransRecv { 39 return c.Conn.Read(b) 40 } 41 buf := pool.Get(pool.RelayBufferSize) 42 defer pool.Put(buf) 43 c.Conn.Read(buf) 44 c.rawTransRecv = true 45 c.Write(nil) 46 return 0, nil 47 } 48 49 func (c *randomHeadConn) Write(b []byte) (int, error) { 50 if c.rawTransSent { 51 return c.Conn.Write(b) 52 } 53 c.buf = append(c.buf, b...) 54 if !c.hasSentHeader { 55 c.hasSentHeader = true 56 dataLength := rand.Intn(96) + 4 57 buf := pool.Get(dataLength + 4) 58 defer pool.Put(buf) 59 rand.Read(buf[:dataLength]) 60 binary.LittleEndian.PutUint32(buf[dataLength:], 0xffffffff-crc32.ChecksumIEEE(buf[:dataLength])) 61 _, err := c.Conn.Write(buf) 62 return len(b), err 63 } 64 if c.rawTransRecv { 65 _, err := c.Conn.Write(c.buf) 66 c.buf = nil 67 c.rawTransSent = true 68 return len(b), err 69 } 70 return len(b), nil 71 }