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